Ejemplo n.º 1
0
    def test_get_rent_by_name_railroads(self):
        # Resetting property instance
        Properties.properties = _init_properties()

        railroad_1 = Properties.get_property_by_name('Reading Railroad')
        railroad_2 = Properties.get_property_by_name('Pennsylvania Railroad')
        railroad_3 = Properties.get_property_by_name('B. & O. Railroad')
        railroad_4 = Properties.get_property_by_name('Short Line')

        self.assertEqual(Properties.get_rent(property_name='Reading Railroad'), 0,
                         'Bank owns property, rent should be 0')

        # Note: DO NOT JUST MANUALLY CHANGE OWNER IN ANY OTHER INSTANCE BESIDES TESTING!
        railroad_1.property_owner = 'Car'
        self.assertEqual(Properties.get_rent(property_name='Reading Railroad'), 25,
                         'One railroad owned, rent should be 25')

        railroad_2.property_owner = 'Car'
        self.assertEqual(Properties.get_rent(property_name='Reading Railroad'), 50,
                         'Two railroads owned, rent should be 50')

        railroad_3.property_owner = 'Car'
        self.assertEqual(Properties.get_rent(property_name='Reading Railroad'), 100,
                         'Three railroads owned, rent should be 100')

        railroad_4.property_owner = 'Car'
        self.assertEqual(Properties.get_rent(property_name='Reading Railroad'), 200,
                         'Three railroads owned, rent should be 200')
Ejemplo n.º 2
0
 def __str__(self):
     properties = ', '.join(
         Properties.get_property_names_by_owner(self.game_piece))
     if properties:
         return f'{self.game_piece}: ${self.cash} cash, owns properties {properties}.'
     else:
         return f'{self.game_piece}: ${self.cash} cash, owns no properties.'
Ejemplo n.º 3
0
    def _get_property_repair_amount(self, card_type):
        # Here, we need 'Chance' or 'Community Chest' for card type, as they drive different values.
        amount_to_pay = 0
        price_per_house = 0
        price_per_hotel = 0

        if card_type == 'Chance':
            # For each house pay $25, for each hotel (num_houses =  5) pay $100
            price_per_house = 25
            price_per_hotel = 100
        if card_type == 'Community Chest':
            # For each house pay $40, for each hotel (num_houses =  5) pay $115
            price_per_house = 40
            price_per_hotel = 115

        properties_owned = Properties.get_properties_by_owner(
            owner_name=self.game_piece, tile_type=TileType.PROPERTY)
        for p in properties_owned:
            if 0 < p.num_houses < 5:
                amount_to_pay += price_per_house * p.num_houses

            if p.num_houses == 5:
                amount_to_pay += price_per_hotel

        return amount_to_pay
Ejemplo n.º 4
0
    def _pay_income_tax(self):
        # Player shall pay 10% of total assets or $200, whichever is less.
        props = Properties.get_properties_by_owner(owner_name=self.game_piece)

        # Get all property values
        sum_prop_values = 0
        sum_house_values = 0
        for prop in props:
            # Get all the property values
            if prop.is_mortgaged:
                sum_prop_values += prop.mortgage_value
            else:
                sum_prop_values += prop.property_value

            # For each property, get all house values
            if prop.tile_type == TileType.PROPERTY:
                sum_house_values += prop.num_houses * prop.cost_per_house

        # Add all assets together
        sum_assets = sum_prop_values + sum_house_values + self.cash

        # Get 10% of assets
        sum_assets = int(sum_assets * 0.1)

        # If 10% of the assets < 200, pay assets
        if sum_assets < 200:
            amount_paid = self._pay_money(sum_assets)
        else:
            amount_paid = self._pay_money(200)

        return amount_paid
Ejemplo n.º 5
0
    def test_get_property_by_name(self):
        # Resetting property instance
        Properties.properties = _init_properties()

        prop = Properties.get_property_by_name('Boardwalk')
        self.assertEqual(prop.name, 'Boardwalk', 'Property name should be Boardwalk')
        self.assertIsInstance(prop, TileProperty, 'Should be TileProperty class')
Ejemplo n.º 6
0
    def test_get_rent_by_name_color_properties(self):
        # Resetting property instance
        Properties.properties = _init_properties()

        boardwalk = Properties.get_property_by_name('Boardwalk')
        park_place = Properties.get_property_by_name('Park Place')

        self.assertEqual(Properties.get_rent(property_name='Boardwalk'), 0, 'Bank owns property, rent should be 0')

        # Note: DO NOT JUST MANUALLY CHANGE OWNER IN ANY OTHER INSTANCE BESIDES TESTING!
        boardwalk.property_owner = 'Battleship'
        self.assertEqual(Properties.get_rent(property_name='Boardwalk'), 50,
                         'Boardwalk is owned, rent should be 50')

        park_place.property_owner = 'Battleship'
        self.assertEqual(Properties.get_rent(property_name='Boardwalk'), 100,
                         'All properties of same color are owned, rent should be 100')

        boardwalk.num_houses = 1

        self.assertEqual(Properties.get_rent(property_name='Boardwalk'), 200,
                         'Boardwalk rent with 1 house should be 200')

        self.assertEqual(Properties.get_rent(property_name='Park Place'), 70,
                         'Park Place rent should be 70 which is doubled still')
Ejemplo n.º 7
0
    def test_get_rent_by_name_utilities(self):
        # Resetting property instance
        Properties.properties = _init_properties()

        utility_1 = Properties.get_property_by_name('Electric Company')
        utility_2 = Properties.get_property_by_name('Water Works')

        self.assertEqual(Properties.get_rent(property_name='Electric Company', dice_roll=12), 0,
                         'Bank owns property, rent should be 0')

        # Note: DO NOT JUST MANUALLY CHANGE OWNER IN ANY OTHER INSTANCE BESIDES TESTING!
        utility_1.property_owner = 'Iron'
        self.assertEqual(Properties.get_rent(property_name='Electric Company', dice_roll=12), 48,
                         'Dice roll 12, one utility owned, 12 * 4 = 48')

        utility_2.property_owner = 'Iron'
        self.assertEqual(Properties.get_rent(property_name='Electric Company', dice_roll=12), 120,
                         'Dice roll 12, two utilities owned, 12 * 10 = 120')
Ejemplo n.º 8
0
    def test_property_repair(self):
        # Resetting property instance
        Properties.properties = _init_properties()

        # Resetting game pieces
        Player._game_pieces = [
            'battleship', 'dog', 'iron', 'shoe', 'thimble', 'top hat',
            'wheelbarrow'
        ]
        self.player = Player()

        # Some shopping money
        self.player.action(Actions.RECEIVE_MONEY, 100000)

        self.player.action(Actions.BUY_PROPERTY, 'Boardwalk')
        self.player.action(Actions.BUY_PROPERTY, 'Park Place')

        self.player.action(Actions.BUY_HOUSE, 'Boardwalk')
        self.player.action(Actions.BUY_HOUSE, 'Park Place')
        self.player.action(Actions.BUY_HOUSE, 'Boardwalk')
        self.player.action(Actions.BUY_HOUSE, 'Park Place')
        self.player.action(Actions.BUY_HOUSE, 'Boardwalk')
        self.player.action(Actions.BUY_HOUSE, 'Park Place')
        self.player.action(Actions.BUY_HOUSE, 'Boardwalk')
        self.player.action(Actions.BUY_HOUSE, 'Park Place')
        self.player.action(Actions.BUY_HOUSE, 'Boardwalk')

        self.assertEqual(
            Properties.get_property_by_name('Boardwalk').num_houses, 5,
            'Boardwalk should be hotel status')

        self.assertEqual(
            Properties.get_property_by_name('Park Place').num_houses, 4,
            'Park Place should have 4 houses')

        # Chance:  4 houses = 25 per house = 100, 1 hotel = 100, total = $200
        # CC: 4 houses = 40 per house = 160, 1 hotel = 115, total = $275
        repair_amount = self.player.action(Actions.PROPERTY_REPAIR, 'Chance')
        self.assertEqual(repair_amount, 200, 'Chance repairs should be 200')

        repair_amount = self.player.action(Actions.PROPERTY_REPAIR,
                                           'Community Chest')
        self.assertEqual(repair_amount, 275,
                         'Community Chest repairs should be 275')
Ejemplo n.º 9
0
    def _pay_money(self, amount):
        if self.cash > amount:
            # We have enough cash to pay.
            self.cash -= amount
            logging.info(
                f'{self.game_piece} paid ${amount}, now has ${self.cash}')

            return amount

        # If we reached this far, it means there's not enough cash to pay.
        # Find if there are any houses to sell
        properties_owned = Properties.get_properties_by_owner(self.game_piece)
        for p in properties_owned:
            # Check if we got enough cash from selling houses.
            if self.cash > amount:
                break

            if p.num_houses > 0:
                # Found a house. We'll need to make sure we're keeping houses evenly distributed across the group.
                properties_in_same_color = [
                    g for g in properties_owned if g.color == p.color
                ]
                # Start with the property with the most houses
                properties_in_same_color.sort(key=lambda l: l.num_houses,
                                              reverse=True)
                # Sell some properties
                for i in properties_in_same_color:
                    self.cash += i.mortgage_house()
                    # Check after each house sold to see if we got enough cash
                    if self.cash > amount:
                        break

        # See if we can bow out of this action after selling houses
        if self.cash > amount:
            self.cash -= amount
            return amount

        # If we reached this far, it means we didn't have enough houses to sell. Start mortgaging properties.
        for p in properties_owned:
            if self.cash > amount:
                break

            self.cash += p.mortgage_property()

        # Finally see if we have enough money to pay up.
        # If we have enough cash, return the full amount.
        # If there wasn't enough, just send whatever cash is available.
        # This will indicate the player is out and should be removed from the game.
        if self.cash > amount:
            self.cash -= amount
            return amount
        else:
            available_cash = self.cash
            self.cash = 0
            return available_cash
Ejemplo n.º 10
0
    def test_pay_money(self):
        # Resetting property instance
        Properties.properties = _init_properties()

        # Resetting game pieces
        Player._game_pieces = [
            'battleship', 'dog', 'iron', 'shoe', 'thimble', 'top hat',
            'wheelbarrow'
        ]
        self.player = Player()

        self.player.action(Actions.BUY_PROPERTY, 'Boardwalk')
        self.player.action(Actions.BUY_PROPERTY, 'Park Place')

        # Should have 750 at this point
        self.player.action(Actions.BUY_HOUSE, 'Boardwalk')
        self.assertEqual(
            self.player.cash, 550,
            'Started at 750, bought a house for 200, should be 550 cash')
        self.assertEqual(
            Properties.get_property_by_name('Boardwalk').num_houses, 1,
            'Num houses should be 1')

        # Paying 1 dollar more than we have in cash. Will have to sell house.
        self.player.action(Actions.PAY_MONEY, 551)
        self.assertEqual(self.player.cash, 99,
                         'Had 1300, sell house for 100, left with 99')
        self.assertEqual(
            Properties.get_property_by_name('Boardwalk').num_houses, 0,
            'Num houses should be 0')

        # cash = 99
        # mortgage Park Place = 350 / 2 = 175
        # mortgage Boardwalk = 400 / 2 = 200
        # total = $474
        money = self.player.action(Actions.PAY_MONEY, 1000)
        self.assertEqual(
            money, 474,
            'Player did not have enough money. The function returned amount of cash on hand'
        )
Ejemplo n.º 11
0
    def test_buy_properties(self):
        # Resetting property instance
        Properties.properties = _init_properties()

        # Resetting game pieces
        Player._game_pieces = [
            'battleship', 'dog', 'iron', 'shoe', 'thimble', 'top hat',
            'wheelbarrow'
        ]
        self.player = Player()

        self.player.action(Actions.BUY_PROPERTY, 'Boardwalk')
        self.assertEqual(self.player.cash, 1100,
                         'Bought Boardwalk, should have 1100 leftover')

        boardwalk = Properties.get_property_by_name('Boardwalk')
        self.assertEqual(boardwalk.property_owner, self.player.game_piece,
                         'New owner should be player')
Ejemplo n.º 12
0
    def _buy_property(self, property_name):
        logging.info(
            f'{self.game_piece} is attempting to buy the property {property_name}.'
        )
        property_to_buy = Properties.get_property_by_name(property_name)
        current_owner = property_to_buy.property_owner

        if self.cash > property_to_buy.property_value and current_owner == 'Bank':
            self.cash -= property_to_buy.property_value
            property_to_buy.update_property_owner(self.game_piece)

            logging.info(
                f'{self.game_piece} bought property {property_name} '
                f'for ${property_to_buy.property_value}, has ${self.cash} left.'
            )
            return True

        logging.info(
            f'{self.game_piece} did not buy property {property_name}, has ${self.cash} left.'
        )
        return False
Ejemplo n.º 13
0
    def test_buy_houses(self):
        # Resetting property instance
        Properties.properties = _init_properties()

        # Resetting game pieces
        Player._game_pieces = [
            'battleship', 'dog', 'iron', 'shoe', 'thimble', 'top hat',
            'wheelbarrow'
        ]
        self.player = Player()

        self.player.action(Actions.BUY_PROPERTY, 'Boardwalk')
        self.player.action(Actions.BUY_PROPERTY, 'Park Place')

        # Should have 750 cash at this point
        self.player.action(Actions.BUY_HOUSE, 'Boardwalk')
        self.assertEqual(
            Properties.get_property_by_name('Boardwalk').num_houses, 1,
            'Got a house on Boardwalk')
        self.assertEqual(self.player.cash, 550,
                         'Had 750, house cost 200, should now have 550')
Ejemplo n.º 14
0
    def player_action(self, tile):
        current_player = self.get_current_player()
        curr = current_player.game_piece
        logging.info(f'{curr} landed on tile {tile[0]}.')

        if tile[1] in [TileType.PROPERTY, TileType.UTILITY, TileType.RAILROAD]:
            property_owner = Properties.get_property_owner_by_name(tile[0])

            if property_owner == curr:
                # Player already owns property. Do nothing.
                logging.info(
                    f'{curr} already owns property {tile[0]}. No action taken.'
                )
                return

            if property_owner == 'Bank':
                # nobody owns property. Player can choose to buy or auction
                # TODO: buy or auction
                did_player_buy_property = current_player.action(
                    Actions.BUY_PROPERTY, tile[0])
                if not did_player_buy_property:
                    # Chose not to buy house, or not enough money to buy house. Auction it!
                    # TODO: Auction house
                    return
                return

            # If we're here, that means another player owns the property and current player needs to pay rent.
            landlord_player = self.get_player(property_owner)
            amount_owed = Properties.get_rent(tile[0], self.dice)
            logging.info(
                f'{curr} owes {landlord_player.game_piece} ${amount_owed}')

            amount_paid = current_player.action(Actions.PAY_MONEY, amount_owed)
            landlord_player.action(Actions.RECEIVE_MONEY, amount_paid)

            if amount_owed != amount_paid:
                # Player could not pay the amount owed and has gone bankrupt.
                self.remove_player_from_game(curr)
            else:
                logging.info(
                    f'{curr} has paid the full ${amount_paid}, has ${current_player.cash} left.'
                )

        if tile[1] == TileType.LUXURY_TAX:
            logging.info(f'{curr} owes $75 luxury tax.')
            amount_owed = 75
            amount_paid = current_player.action(Actions.PAY_MONEY, amount_owed)
            if amount_paid != amount_owed:
                # Player could not pay the amount owed and has gone bankrupt.
                self.remove_player_from_game(curr)
            else:
                logging.info(
                    f'{curr} has paid the full ${amount_paid}, has ${current_player.cash} left.'
                )

        if tile[1] == TileType.INCOME_TAX:
            amount_paid = current_player.action(Actions.PAY_INCOME_TAX, None)
            logging.info(
                f'{curr} has paid income tax of {amount_paid}, has ${current_player.cash} left.'
            )

        if tile[1] == TileType.GO_TO_JAIL:
            current_player.action(Actions.MOVE_DIRECTLY_TO_TILE_DO_NOT_PASS_GO,
                                  10)
            logging.info(f'{curr} will go directly to jail.')

        if tile[1] == TileType.CHANCE:
            # TODO: implement Actions.PAY_MONEY_TO_EACH_PLAYER and Actions.RECEIVE_MONEY_FROM_EACH_PLAYER
            chance_card = self.board.chance_cards.draw()
            logging.info(f'{curr} drew Chance card: {chance_card.name}')
            current_player.action(chance_card.action, chance_card.amount)

        if tile[1] == TileType.COMMUNITY_CHEST:
            cc_card = self.board.community_chest_cards.draw()
            logging.info(f'{curr} drew Community Chest card: {cc_card.name}')
            current_player.action(cc_card.action, cc_card.amount)

        # GO, Jail (Just Visiting), and Free Parking do nothing.
        if tile[1] in [TileType.GO, TileType.JAIL, TileType.FREE_PARKING]:
            logging.info(f'{curr} takes no action.')

        return
Ejemplo n.º 15
0
    def _buy_house(self, property_name):
        logging.info(
            f'{self.game_piece} is attempting to buy a house on {property_name}.'
        )
        properties_owned = Properties.get_properties_by_owner(
            self.game_piece, TileType.PROPERTY)

        if properties_owned:
            if property_name not in [p.name for p in properties_owned]:
                e = 'Property' + property_name + ' not owned by player.'
                logging.error(e)
                raise Exception(e)

        # Get the property to put a house on.
        prop = Properties.get_property_by_name(property_name)

        # Make sure we're dealing with the right type of property first...
        if prop.tile_type != TileType.PROPERTY:
            return 0

        # See if player can afford to buy a house.
        if self.cash < prop.cost_per_house:
            logging.warning(
                f'{self.game_piece} could not afford a house on {property_name}. '
                f'Still has {prop.num_houses} houses.')
            return prop.num_houses

        # Verifying player owns all the properties of that color before buying houses.
        properties_owned_in_same_color = Properties.get_properties_by_owner(
            owner_name=self.game_piece,
            tile_type=prop.tile_type,
            color=prop.color)

        prop_colors = Properties.get_properties_by_color(prop.color)

        if len(properties_owned_in_same_color) != len(prop_colors):
            logging.warning(
                f'{self.game_piece} does not own all properties of the same color '
                f'and cannot purchase a house. Still has {prop.num_houses} houses.'
            )
            return prop.num_houses

        # We also need to verify we don't own too many houses on one property.
        min_houses_in_same_color = min(
            [p.num_houses for p in properties_owned_in_same_color])
        if prop.num_houses > min_houses_in_same_color:
            logging.warning(
                f'{self.game_piece} cannot put a house on this property '
                f'before putting houses on the other properties first.')
            return prop.num_houses

        # If we made it this far, we are eligible to purchase a house on this property.
        # prop.add_house() will make sure we don't add more than 5 properties.
        house_count = prop.add_house()
        if house_count != -1:
            self.cash -= prop.cost_per_house
            logging.info(
                f'{self.game_piece} added a house to'
                f' property {property_name} and now has {prop.num_houses} '
                f'houses for {prop.cost_per_house}, has ${self.cash} left.')
        else:
            logging.warning(
                f'{self.game_piece} tried adding a house but already has too many.'
            )
        return prop.num_houses