def test_update_balance_should_update_the_player_balance_with_the_parameter_value( self, ): behaviour = Demanding() player = Player(behaviour=behaviour, balance=300) player.update_balance(50) expected = 350 result = player.balance self.assertEqual(expected, result, "message")
def test_player_pay_rent_should_update_player_balance_when_location_has_owner( self, ): behaviour = Demanding() player = Player(behaviour=behaviour, balance=300) player2 = Player(behaviour=behaviour, balance=300) location = Location(cost_of_sale=150, cost_of_rent=50) location.update_owner(player2) player_expected_balance = 250 player2_expected_balance = 350 player.pay_rent(location) self.assertEqual(player.balance, player_expected_balance) self.assertEqual(player2.balance, player2_expected_balance)
def test_remove_owner_should_set_location_owner_value_to_none(self): behaviour = Demanding() player = Player(behaviour=behaviour, balance=300) location = Location(cost_of_sale=150, cost_of_rent=50) location.update_owner(player) location.remove_owner() self.assertIsNone(location.owner)
def test_demanding_behaviour_buy_should_keep_player_balance_when_player_balance_when_location_already_have_a_owner( self, ): player2 = Player(behaviour=self.behaviour, balance=300) location = Location(cost_of_sale=150, cost_of_rent=55) location.owner = player2 self.player.buy(location) expected = 300 result = self.player.balance
class TestCautiousBehaviour(TestCase): def setUp(self): self.behaviour = Cautious() self.player = Player(behaviour=self.behaviour, balance=300) def test_cautious_behaviour_should_keep_balance_unchanged_when_player_balance_less_location_cost_of_sale_result_lesser_than_80( self, ): location = Location(cost_of_sale=250, cost_of_rent=49) self.player.buy(location) expected = 300 result = self.player.balance self.assertEqual(expected, result) def test_cautious_behaviour_repr_should_return_Cautious(self): expected = "Cautious" result = repr(self.behaviour) self.assertEqual(expected, result, "message")
def test_update_owner_should_set_player_as_location_owner_value(self): behaviour = Demanding() player = Player(behaviour=behaviour, balance=300) location = Location(cost_of_sale=150, cost_of_rent=50) location.update_owner(player) result = location.owner expected = player self.assertEqual(expected, result, "message")
def test_repr_should_return_a_string_with_player_info_and_location_cost_of_sale_and_location_cost_of_rent( self, ): behaviour = Demanding() player = Player(behaviour=behaviour, balance=300) location = Location(cost_of_sale=150, cost_of_rent=50) location.update_owner(player) expected = "300 - Demanding - 150 - 50" result = repr(location) self.assertEqual(expected, result)
def test_impulsive_behaviour_buy_should_keep_balance_attribute_when_a_property_already_have_a_owner( self, ): player2 = Player(behaviour=self.behaviour, balance=300) location = Location(cost_of_sale=150, cost_of_rent=150) location.owner = player2 expected = 300 self.player.buy(location) result = self.player.balance self.assertEqual(expected, result, "message")
def test_transfer(): p1 = Player(10) p2 = Player(0) p2.receive(p1.pay(10)) assert p1.balance == 0 assert p2.balance == 10
class TestImpulsiveBehaviour(TestCase): def setUp(self): self.behaviour = Impulsive() self.player = Player(behaviour=self.behaviour, balance=300) def test_impulsive_behaviour_buy_should_return_true_when_player_balance_is_greater_than_location_cost_of_sale_and_location_has_no_owner( self, ): location = Location(cost_of_sale=150, cost_of_rent=150) self.player.buy(location) result = self.player.balance expected_balance = 150 self.assertEqual(expected_balance, result, "message") def test_impulsive_behaviour_buy_should_keep_balance_attribute_when_a_property_already_have_a_owner( self, ): player2 = Player(behaviour=self.behaviour, balance=300) location = Location(cost_of_sale=150, cost_of_rent=150) location.owner = player2 expected = 300 self.player.buy(location) result = self.player.balance self.assertEqual(expected, result, "message") def test_impulsive_behaviour_buy_should_keep_balance_attribute_when_a_property_cost_of_sale_is_greater_than_player_balance( self, ): location = Location(cost_of_sale=150, cost_of_rent=150) expected = 150 self.player.buy(location) result = self.player.balance self.assertEqual(expected, result, "message")
class TestDemandingBehaviour(TestCase): def setUp(self): self.behaviour = Demanding() self.player = Player(behaviour=self.behaviour, balance=300) def test_demanding_behaviour_buy_should_update_player_balance_when_location_cost_of_saler_lesser_than_player_balance_and_location_cost_of_rent_greater_than_50( self, ): location = Location(cost_of_sale=150, cost_of_rent=51) expected = 150 self.player.buy(location) result = self.player.balance self.assertEqual(expected, result, "message") def test_demanding_behaviour_buy_should_keep_player_balance_when_location_cost_of_rent_lesser_than_50( self, ): location = Location(cost_of_sale=150, cost_of_rent=49) expected = 300 self.player.buy(location) result = self.player.balance self.assertEqual(expected, result) def test_demanding_behaviour_buy_should_keep_player_balance_when_player_balance_when_location_already_have_a_owner( self, ): player2 = Player(behaviour=self.behaviour, balance=300) location = Location(cost_of_sale=150, cost_of_rent=55) location.owner = player2 self.player.buy(location) expected = 300 result = self.player.balance
class TestRandomBehaviour(TestCase): def setUp(self): self.behaviour = Random() self.player = Player(behaviour=self.behaviour, balance=300) @mock.patch("monopoly.behaviour.choice", return_value=True) def test_random_behaviour_buy_should_update_player_balance_when_random_value_is_true( self, mocked_choice): location = Location(cost_of_sale=150, cost_of_rent=49) self.player.buy(location) expected = 150 result = self.player.balance self.assertEqual(expected, result) @mock.patch("monopoly.behaviour.choice", return_value=False) def test_random_behaviour_buy_should_keep_player_balance_unchanged_when_random_value_is_false( self, mocked_choice): location = Location(cost_of_sale=150, cost_of_rent=49) self.player.buy(location) expected = 300 result = self.player.balance self.assertEqual(expected, result)
def test_invest_without_money(): p = Player(10) with pytest.raises(NotEnoughMoney): p.invest(price=100, rent=10)
def setUp(self): self.behaviour = Demanding() self.player = Player(behaviour=self.behaviour, balance=300)
def test_init(): p = Player(300) assert p assert p.balance == 300 assert isinstance(p.strategy, Impulsive)
def test_invest_gambler_abort(mocker): p = Player(100, strategy=Gambler()) mocker.patch('random.choice', return_value=False) with pytest.raises(AbortInvestment): p.invest(price=100, rent=10)
def test_invest_impulsive(): p = Player(100) assert p.invest(price=100, rent=10) == 100 assert p.balance == 0
def setUp(self): self.behaviour = Random() self.player = Player(behaviour=self.behaviour, balance=300)
def test_invest_cautious(): p = Player(180, strategy=Cautious()) assert p.invest(price=100, rent=51) == 100 assert p.balance == 80
def test_outofmoney(): p = Player(0) with pytest.raises(OutOfMoney): p.pay(1)
def test_player_roll_the_dices_should_return_6(self, mocked_choice): behaviour = Demanding() player = Player(behaviour=behaviour, balance=300) result = player.roll_the_dices() expected = 6 self.assertEqual(expected, result, "message")
def test_invest_cautious_abort(): p = Player(100, strategy=Cautious()) with pytest.raises(AbortInvestment): p.invest(price=100, rent=10)
def run(self): config.verbose = {key: False for key in config.verbose} get_epsilon = lambda episode: np.exp(-episode * self.e_decay) for eps in range(self.episodes + 1): full_games_counter = 0 game_copy = None storage1 = self.storage_class() storage2 = self.storage_class() if self.train_on_fixed: self.policy.train_on_fixed = True print('---STARTING SIMULATIONS') for n_game in tqdm(range(self.n_games)): n_opps_agents = 1 n_rl_agents = 1 players = [] rl_agents = [ Player(policy=self.policy, player_id=str(idx) + '_rl', storage=storage1) for idx in range(n_rl_agents) ] if self.policy.policy_name == 'dqn': self.policy.policy.update_epsilon(get_epsilon(eps)) if not self.self_play: opp_agents = [ Player(policy=FixedAgent(high=350, low=150, jail=100), player_id=str(idx) + '_fixed', storage=self.storage_class()) for idx in range(n_opps_agents) ] else: opp_agents = [ Player(policy=self.policy, player_id=str(idx + 1) + '_rl', storage=storage2) for idx in range(n_rl_agents) ] players.extend(rl_agents) players.extend(opp_agents) # shuffle(players) # print('----- Players: {} fixed, {} rl'.format(n_fixed_agents, n_rl_agents)) game = Game(players=players, max_rounds=self.n_rounds) game_copy = game for player in players: player.set_game(game, n_game) game_finished = False for n_round in range(self.n_rounds): if game_finished: break game.update_round() for player in game.players: if not game.is_game_active(): # stopping rounds loop player.won() game_finished = True break # player.reset_mortgage_buy() if player.is_bankrupt: # must change it. do it two times because some players can go bankrupt when must pay bank interest game.remove_player( player) # other player's mortgaged spaces break game.pass_dice() while True: if not game.is_game_active( ): # stopping players loop break player.optional_actions() # player.reset_mortgage_buy() game.dice.roll() if player.is_in_jail(): stay_in_jail = player.jail_strategy( dice=game.dice) if stay_in_jail: player.optional_actions() break if player.is_bankrupt: game.remove_player(player) break if game.dice.double_counter == 3: player.go_to_jail() break player.move(game.dice.roll_sum) if player.position == 30: player.go_to_jail() break # TODO: add card go to jail space = game.board[player.position] player.act(space) if player.is_bankrupt: game.remove_player(player) break if game.dice.double: continue # end turn break if game.players_left == 1: full_games_counter += 1 else: for player in game.players: player.draw() losses = [] for player in game_copy.players: if 'rl' in player.id: self.update(player, losses) for player in game_copy.lost_players: if 'rl' in player.id: self.update(player, losses) if eps % self.target_update == 0: self.target_policy.load_state_dict(self.policy.state_dict()) rewards = [] for player in game_copy.players: if 'rl' in player.id: rewards.append(player.storage.get_mean_reward()) for player in game_copy.lost_players: if 'rl' in player.id: rewards.append(player.storage.get_mean_reward()) with open(self.file_metrics, 'a') as metrics: metrics.write('{},{},{}\n'.format(eps, n_rl_agents, np.average(losses))) if eps % self.verbose_eval == 0: if self.train_on_fixed: self.policy.train_on_fixed = False print('------Arena') arena = Arena( n_games=self.n_eval_games, n_rounds=self.n_rounds, verbose=0 ) # add 3 types of logging. 0 - only show win rates. print('--------RL vs Random') winrate_random = arena.fight(agent=self.target_policy, opponent=RandomAgent(), opp_id='random') print('--------RL vs Fixed') winrate_fixed = arena.fight(agent=self.target_policy, opponent=FixedAgent(high=350, low=150, jail=100), opp_id='fixed') with open(self.file_winrates, 'a') as winrates: winrates.write('{},{},{}\n'.format(eps, winrate_random, winrate_fixed)) if eps % self.checkpoint_step == 0: torch.save(self.target_policy, os.path.join('models', 'model-{}.pt'.format(eps))) print('---Full games {} / {}'.format(full_games_counter, self.n_games))
def test_str(): p = Player(0) assert str(p) == 'Impulsive'
def test_invest_demanding_abort(): p = Player(100, strategy=Demanding()) with pytest.raises(AbortInvestment): p.invest(price=100, rent=50)
def test_invest_demanding(): p = Player(100, strategy=Demanding()) assert p.invest(price=100, rent=51) == 100 assert p.balance == 0
def setUp(self): self.behaviour = Impulsive() self.player = Player(behaviour=self.behaviour, balance=300)
def fight(self, agent, opponent, agent_id='rl', opp_id='opp', log_rewards=False): if self.verbose == 0: config.verbose = {key: False for key in config.verbose} config.verbose['stats'] = True if self.verbose == 1: config.verbose = {key: True for key in config.verbose} win_stats = {agent_id: 0, opp_id: 0} full_games_counter = 0 for n_game in tqdm(range(self.n_games)): if config.verbose['game_start']: logger.info('----------------STARTING GAME {}----------------\n\n'.format(n_game)) players = [] players.append(Player(policy=agent, player_id=agent_id, storage=StorageDQN())) players.append(Player(policy=opponent, player_id=opp_id, storage=StorageDQN())) # shuffle(players) game = Game(players=players, max_rounds=self.n_rounds) for player in players: player.set_game(game, n_game) game_finished = False for n_round in range(self.n_rounds): if game_finished: break if config.verbose['round']: logger.info('-----------ROUND {}-----------\n\n'.format(n_round)) game.update_round() for player in game.players: if not game.is_game_active(): # stopping players loop player.won() game_finished = True break if config.verbose['player']: logger.info('-----------PLAYER idx={}, id={}-----------\n\n'.format(player.index, player.id)) player.reset_mortgage_buy() if player.is_bankrupt: # must change it. do it two times because some players can go bankrupt when must pay bank interest game.remove_player(player) # other player's mortgaged spaces break game.pass_dice() while True: if config.verbose['player_properties']: player.show() if not game.is_game_active(): # stopping players loop player.won() game_finished = True break player.optional_actions() player.reset_mortgage_buy() game.dice.roll() if player.is_in_jail(): stay_in_jail = player.jail_strategy(dice=game.dice) if stay_in_jail: player.optional_actions() break if player.is_bankrupt: game.remove_player(player) break if game.dice.double_counter == 3: player.go_to_jail() break player.move(game.dice.roll_sum) if player.position == 30: player.go_to_jail() # the same here break # TODO: add card go to jail space = game.board[player.position] player.act(space) if player.is_bankrupt: game.remove_player(player) break if game.dice.double: continue if config.verbose['player_properties']: player.show() break # print('SAMPLES:', len(players[0].storage.rewards)) if game.players_left != 1: leaderboard = game.get_leaderboard() win_stats[str(leaderboard[0].id)] += 1 if config.verbose['not_full_game_result']: for i, player in enumerate(leaderboard): print('Player {} is on the {} place. Total wealth {}'.format(player.id, i + 1, player.total_wealth)) player.show() if len(game.lost_players) != 0: for i, player in enumerate(game.lost_players): print('Player {} is on the {} place'.format(player.id, i + 1 + len(leaderboard))) player.show() else: win_stats[str(game.players[0].id)] += 1 full_games_counter += 1 if config.verbose['full_game_result']: print('Player {} is on the 1 place'.format(game.players[0].id)) game.players[0].show() for i, player in enumerate(game.lost_players): print('Player {} is on the {} place '.format(player.id, i + 2)) player.show() if log_rewards: p1 = game.players[0] if len(game.players) == 1: p2 = game.lost_players[0] else: p2 = game.players[1] filename1 = 'rewards_' + p1.id + '.csv' filename2 = 'rewards_' + p2.id + '.csv' for r in p1.storage.rewards: with open(filename1, 'a') as f: f.write(str(r.item()) + '\n') for r in p2.storage.rewards: with open(filename2, 'a') as f: f.write(str(r.item()) + '\n') winrate_return = 0 if config.verbose['stats']: for key in win_stats: winrate = np.round(win_stats[key] / self.n_games * 100, 3) print('----------Player {} won {} / {}'.format(key, win_stats[key], self.n_games)) print('-------------Win rate is {} %'.format(winrate)) if key == agent_id: winrate_return = winrate print('---Full games {} / {}'.format(full_games_counter, self.n_games)) return winrate_return
def setUp(self): self.behaviour = Cautious() self.player = Player(behaviour=self.behaviour, balance=300)
def test_invest_gambler(mocker): mocker.patch('random.choice', return_value=True) p = Player(100, strategy=Gambler()) assert p.invest(price=100, rent=51) == 100 assert p.balance == 0