class Monopoly: def __init__(self, num_players): self.board = Board() self.draw = Draw() self.blockchain = BlockChain() self.banker = Bank() self.num_players = num_players self.players = [] for player_index in range(num_players): name = input('Enter Player {}\'s Name: '.format(player_index + 1)) self.players.append(Player(name, player_index + 1)) # Initialize the accounts of all players with 1500 Monopoly Coin self.blockchain.initialize_accounts(self.players) # Initialize all properties. By default the owner of all properties is the bank self.blockchain.initialize_properties(self.board.get_all_properties()) @staticmethod def roll_dice(): return random.randint(1, 6), random.randint(1, 6) def play_game(self, automatic=True): if automatic: while not self.game_over(): for player in self.players: self.serve_turn(player, 0) else: game_ended = False while not game_ended: for player in self.players: cont = input('\nContinue? Y/N: ') if cont == 'Y' or cont == 'y': self.serve_turn(player, 0) else: winner = None highest_assets = 0 for player in self.players: if not player.state == PlayerState.DONE: assets = player.add_assets( self.blockchain, self.board) if highest_assets < assets: winner = player highest_assets = assets game_ended = True print('Winner is {}. Game Ended. Bye!'.format(winner)) # ---------- Serving Methods ------------ def serve_turn(self, player, num_doubles): if num_doubles == 0: print('\n{} is up! Starting balance: ${}'.format( str(player), player.get_balance(self.blockchain))) roll = self.roll_dice() print('{} rolled: {}'.format(str(player), roll)) if num_doubles == 2 and roll[0] == roll[1]: self.go_to_jail(player) elif player.in_jail: self.serve_jail(player, roll) else: trade = input('Would you like to make a trade? Y/N: ') if trade == 'Y' or trade == 'y': self.serve_trade(player) edit = input('Would you like to edit properties? Y/N: ') if edit == 'Y' or edit == 'y': self.serve_prop_edit(player) self.serve_normally(player, roll) if roll[0] == roll[1]: self.serve_turn(player, num_doubles + 1) if num_doubles == 0: print('{}\'s turn is over! Ending balance: ${}'.format( str(player), player.get_balance(self.blockchain))) def serve_normally(self, player, roll): position = (player.position + roll[0] + roll[1]) % 40 space = self.board.get_property_at_index(position) print('{} landed on: {}'.format(str(player), space.name)) self.move_player_to(player, position) if space.type == 'Draw': self.serve_draw(player, space) elif space.type == 'Special': self.serve_special_space(player, space) else: self.serve_property(player, space) def serve_jail(self, player, roll): player.jail_rolls += 1 if roll[0] == roll[1] or player.jail_rolls == 3: print('{} got out of Jail!'.format(str(player))) player.jail_rolls = 0 player.in_jail = False self.serve_normally(player, roll) else: print('{} is still in Jail!'.format(str(player))) def serve_draw(self, player, space): draw = self.draw.draw_card(space.draw_type) print('{} drew: {}'.format(str(player), draw.description)) if draw.type == 'Pay': player.pay(self.banker, draw.amount, self.blockchain) elif draw.type == 'Pay All': for player_ in self.players: if player_ != player: player.pay(player_, draw.amount, self.blockchain) elif draw.type == 'Receive': self.banker.pay(player, draw.amount, self.blockchain) elif draw.type == 'Receive All': for player_ in self.players: if player_ != player: player_.pay(player, draw.amount, self.blockchain) elif draw.type == 'Move': if draw.name != 'Go to Jail': move_space = self.board.get_property_at_index(draw.index) print('{} moved to: {}'.format(str(player), str(move_space))) self.move_player_to(player, move_space.index) if move_space.type != 'Draw' and move_space.type != 'Special': self.serve_property(player, move_space) else: self.go_to_jail(player) elif draw.type == 'Special': if draw.name == 'Street Repairs' or draw.name == 'Property Repairs': houses = 0 hotels = 0 for index in self.blockchain.get_all_properties(player): houses += self.blockchain.get_houses(index) hotels += self.blockchain.get_hotel(index) print( '{} has {} houses and {} hotels and must pay ${}.'.format( player, houses, hotels, houses * draw.house_amount + hotels * draw.hotel_amount)) player.pay( self.banker, houses * draw.house_amount + hotels * draw.hotel_amount, self.blockchain) elif draw.name == 'Advance to Utility': if abs(player.position - 12) >= abs(player.position - 28): index = 28 else: index = 12 self.move_player_to(player, index) print('{} moved to: {}'.format( player, self.board.get_property_at_index(index).name)) self.serve_property(player, self.board.get_property_at_index(index), draw.name) elif draw.name == 'Advance to Railroad 1' or draw.name == 'Advance to Railroad 2': if player.position == 7: index = 5 elif player.position == 22: index = 25 else: index = 35 self.move_player_to(player, index) print('{} moved to: {}'.format( player, self.board.get_property_at_index(index).name)) self.serve_property(player, self.board.get_property_at_index(index), draw.multiplier) def serve_special_space(self, player, space): if space.name == 'Income Tax': decision = input( 'Pay 10% of assets or $200: Y for 10%, N for $200: ') if decision == 'Y' or decision == 'y': player.pay( self.banker, player.add_assets(self.blockchain, self.board) // 10, self.blockchain) else: player.pay(self.banker, 200, self.blockchain) elif space.name == 'Luxury Tax': print('Pay $75 for Luxury Tax') player.pay(self.banker, 75, self.blockchain) def serve_property(self, player, space, multiplier=1): owner_address = self.blockchain.get_property_owner(space.index) if owner_address == self.blockchain.get_account(self.banker): self.serve_banker(owner_address, player, space) elif owner_address == self.blockchain.get_account(player): print('Welcome back home {}!'.format(player)) else: self.serve_other_owner(multiplier, owner_address, player, space) def serve_banker(self, owner_address, player, space): decision = input( '{} is unowned! It costs ${}. Want to see a description? Y/N: '. format(space, space.price)) if decision == 'Y' or decision == 'y': self.describe_property(space) decision = input( 'Current Balance: ${}. Would you like to buy it? Y/N: '.format( player.get_balance(self.blockchain))) if decision == 'Y' or decision == 'y': if self.blockchain.change_ownership(owner_address, player, space.index, space.price): print('Congrats! You bought {}!'.format(space)) else: print('Couldn\'t buy {}... :('.format(space)) def serve_other_owner(self, multiplier, owner_address, player, space): owner = None for player_ in self.players: if self.blockchain.get_account(player_) == owner_address: owner = player_ break if not self.blockchain.get_mortgage(space.index): if space.type == 'Utility': other_utility = 28 if space.index == 12 else 12 if owner_address == self.blockchain.get_property_owner( other_utility) or multiplier == 10: rent = sum(self.roll_dice()) * 10 else: rent = sum(self.roll_dice()) * 4 elif space.type == 'Station': rent = space.standard_rent other_stations = [ s for s in [5, 15, 25, 35] if s != space.index ] for station_index in other_stations: if owner_address == self.blockchain.get_property_owner( station_index): rent += space.standard_rent else: rent = space.standard_rent layout = (self.blockchain.get_houses(space.index), self.blockchain.get_hotel(space.index)) if layout[0]: if layout[0] == 1: rent = space.one_house_rent elif layout[0] == 2: rent = space.two_house_rent elif layout[0] == 3: rent = space.three_house_rent else: rent = space.four_house_rent elif layout[1]: rent = space.hotel_rent else: other_properties = [ s for s in self.board.monopolies[space.group] if s != space.index ] monopoly = True for index in other_properties: if self.blockchain.get_property_owner( index) != owner_address: monopoly = False break if monopoly: rent *= 2 print('Uh oh. You owe {} ${}.'.format(owner, rent * multiplier)) player.pay(owner, rent * multiplier, self.blockchain, critical=True, board=self.board) else: print('You lucky duck, {} is mortgaged. Enjoy your free stay!'. format(space)) def serve_trade(self, player): all_properties = player.describe_all_properties( self.blockchain, self.board) # Prints all properties as well keep_trading = True while keep_trading: trade_index = int(input('Index to trade: ')) if trade_index in all_properties: buyer = int(input('Enter player number to trade with: ')) if buyer - 1 < len(self.players) and buyer > 0: buyer = self.players[buyer - 1] sell_property = self.board.get_property_at_index( trade_index) price = int(input('Enter amount to offer: ')) buyer_decision = input( 'Would {} like to buy {} for ${}? Y/N: '.format( buyer, sell_property, price)) if buyer_decision == 'Y' or buyer_decision == 'y': player.sell_property(buyer, sell_property, price, self.blockchain) else: print('{} rejected the offer.'.format(buyer)) else: print('{} is not a valid player index, try again.'.format( buyer)) else: print('{} is not an index you can trade, try again tiger.'. format(trade_index)) decision = input('Continue trading? Y/N: ') if not decision == 'Y' and not decision == 'y': keep_trading = False def serve_prop_edit(self, player): all_properties = player.describe_all_properties( self.blockchain, self.board) # Prints all properties as well keep_editing = True while keep_editing: edit_index = int(input('Index to edit: ')) if edit_index in all_properties: player.edit_property(self.blockchain, self.board, edit_index) decision = input('Continue editing? Y/N: ') if not decision == 'Y' and not decision == 'y': keep_editing = False # Describes a property's rent and mortgage @staticmethod def describe_property(space): if space.type == 'Utility': print( ' If one utility is owned rent is 4 times amount shown on dice.\n' + ' If both utilities are owned rent is 10 times amount shown on dice.' ) elif space.type == 'Station': print(' Rent ${}\n'.format(space.standard_rent) + ' If 2 stations are owned ${}\n'.format( space.standard_rent * 2) + ' If 3 stations are owned ${}\n'.format( space.standard_rent * 3) + ' If 4 stations are owned ${}'.format( space.standard_rent * 4)) else: print(' Color Group: {}\n'.format(space.group) + ' Rent ${}\n'.format(space.standard_rent) + ' With 1 House ${}\n'.format(space.one_house_rent) + ' With 2 Houses ${}\n'.format(space.two_house_rent) + ' With 3 Houses ${}\n'.format(space.three_house_rent) + ' With 4 Houses ${}\n'.format(space.four_house_rent) + ' With Hotel ${}'.format(space.hotel_rent)) print(' Mortgage Value: ${}'.format(space.mortgage)) # Moves a player to the given index. If at 30, the player goes to jail def move_player_to(self, player, index): if index < player.position: print('{} passed Go!'.format(str(player))) self.banker.pay(player, 200, self.blockchain) if index == 30: self.go_to_jail(player) else: player.position = index @staticmethod def go_to_jail(player): print('{} went to Jail!'.format(player)) player.in_jail = True player.position = 10 def game_over(self): finished_players = 0 for player in self.players: if player.state == PlayerState.DONE: finished_players += 1 if finished_players - 1 == len(self.players): return True else: return False