def simulate_game_instance(game_elements, history_log_file=None, np_seed=2): """ Simulate a game instance. :param game_elements: The dict output by set_up_board :param np_seed: The numpy seed to use to control randomness. :return: None """ logger.debug("size of board " + str(len(game_elements['location_sequence']))) np.random.seed(np_seed) np.random.shuffle(game_elements['players']) game_elements['seed'] = np_seed game_elements['card_seed'] = np_seed game_elements['choice_function'] = np.random.choice count_json = 0 # a counter to keep track of how many rounds the game has to be played before storing the current_state of gameboard to file. num_die_rolls = 0 tot_time = 0 # game_elements['go_increment'] = 100 # we should not be modifying this here. It is only for testing purposes. # One reason to modify go_increment is if your decision agent is not aggressively trying to monopolize. Since go_increment # by default is 200 it can lead to runaway cash increases for simple agents like ours. logger.debug('players will play in the following order: ' + '->'.join([p.player_name for p in game_elements['players']])) logger.debug('Beginning play. Rolling first die...') current_player_index = 0 num_active_players = 4 winner = None workbook = None if history_log_file: workbook = xlsxwriter.Workbook(history_log_file) game_elements['start_time'] = time.time() while num_active_players > 1: disable_history( game_elements ) # comment this out when you want history to stay. Currently, it has high memory consumption, we are working to solve the problem (most likely due to deep copy run-off). current_player = game_elements['players'][current_player_index] while current_player.status == 'lost': current_player_index += 1 current_player_index = current_player_index % len( game_elements['players']) current_player = game_elements['players'][current_player_index] current_player.status = 'current_move' # pre-roll for current player + out-of-turn moves for everybody else, # till we get num_active_players skip turns in a row. skip_turn = 0 if current_player.make_pre_roll_moves( game_elements) == 2: # 2 is the special skip-turn code skip_turn += 1 out_of_turn_player_index = current_player_index + 1 out_of_turn_count = 0 while skip_turn != num_active_players and out_of_turn_count <= 5: ##oot count reduced to 20 from 200 to keep the game short out_of_turn_count += 1 # print('checkpoint 1') out_of_turn_player = game_elements['players'][ out_of_turn_player_index % len(game_elements['players'])] if out_of_turn_player.status == 'lost': out_of_turn_player_index += 1 continue oot_code = out_of_turn_player.make_out_of_turn_moves(game_elements) # add to game history game_elements['history']['function'].append( out_of_turn_player.make_out_of_turn_moves) params = dict() params['self'] = out_of_turn_player params['current_gameboard'] = game_elements game_elements['history']['param'].append(params) game_elements['history']['return'].append(oot_code) if oot_code == 2: skip_turn += 1 else: skip_turn = 0 out_of_turn_player_index += 1 # now we roll the dice and get into the post_roll phase, # but only if we're not in jail. # but only if we're not in jail. logger.debug("Printing cash balance and net worth of each player: ") diagnostics.print_player_net_worths_and_cash_bal(game_elements) r = roll_die(game_elements['dies'], np.random.choice) for i in range(len(r)): game_elements['die_sequence'][i].append(r[i]) # add to game history game_elements['history']['function'].append(roll_die) params = dict() params['die_objects'] = game_elements['dies'] params['choice'] = np.random.choice game_elements['history']['param'].append(params) game_elements['history']['return'].append(r) num_die_rolls += 1 game_elements['current_die_total'] = sum(r) logger.debug('dies have come up ' + str(r)) if not current_player.currently_in_jail: check_for_go = True game_elements['move_player_after_die_roll'](current_player, sum(r), game_elements, check_for_go) # add to game history game_elements['history']['function'].append( game_elements['move_player_after_die_roll']) params = dict() params['player'] = current_player params['rel_move'] = sum(r) params['current_gameboard'] = game_elements params['check_for_go'] = check_for_go game_elements['history']['param'].append(params) game_elements['history']['return'].append(None) current_player.process_move_consequences(game_elements) # add to game history game_elements['history']['function'].append( current_player.process_move_consequences) params = dict() params['self'] = current_player params['current_gameboard'] = game_elements game_elements['history']['param'].append(params) game_elements['history']['return'].append(None) # post-roll for current player. No out-of-turn moves allowed at this point. current_player.make_post_roll_moves(game_elements) # add to game history game_elements['history']['function'].append( current_player.make_post_roll_moves) params = dict() params['self'] = current_player params['current_gameboard'] = game_elements game_elements['history']['param'].append(params) game_elements['history']['param'].append(params) game_elements['history']['return'].append(None) else: current_player.currently_in_jail = False # the player is only allowed to skip one turn (i.e. this one) if current_player.current_cash < 0: code = current_player.handle_negative_cash_balance(game_elements) # add to game history game_elements['history']['function'].append( current_player.handle_negative_cash_balance) params = dict() params['self'] = current_player params['current_gameboard'] = game_elements game_elements['history']['param'].append(params) game_elements['history']['return'].append(code) if code == flag_config_dict[ 'failure_code'] or current_player.current_cash < 0: current_player.begin_bankruptcy_proceedings(game_elements) # add to game history game_elements['history']['function'].append( current_player.begin_bankruptcy_proceedings) params = dict() params['self'] = current_player params['current_gameboard'] = game_elements game_elements['history']['param'].append(params) game_elements['history']['return'].append(None) num_active_players -= 1 diagnostics.print_asset_owners(game_elements) diagnostics.print_player_cash_balances(game_elements) if num_active_players == 1: for p in game_elements['players']: if p.status != 'lost': winner = p p.status = 'won' else: current_player.status = 'waiting_for_move' else: current_player.status = 'waiting_for_move' current_player_index = (current_player_index + 1) % len( game_elements['players']) tot_time = time.time() - game_elements['start_time'] if card_utility_actions.check_for_game_termination( game_elements, tot_time): # game terminates if check_for_game_termination returns true. # We print some diagnostics and return if any player exceeds this. diagnostics.print_asset_owners(game_elements) diagnostics.print_player_cash_balances(game_elements) logger.debug("Game ran for " + str(tot_time) + " seconds.") break #This is an example of how you may want to write out gameboard state to file. #Uncomment the following piece of code to write out the gameboard current_state to file at the "count_json" iteration. #All the data from game_elements will be written to a .json file which can be read back to intialize a new game with #those gameboard values to start the game from that point onwards. ''' if count_json == 50: outfile = '../current_gameboard_state.json' oot_code = read_write_current_state.write_out_current_state_to_file(game_elements, outfile) if oot_code == 1: print("Successfully written gameboard current state to file.") logger.debug("Successfully written gameboard current state to file.") print("Cash in hand with players when writing gameboard state to file: ") for player in game_elements['players']: print(player.player_name, " current cash=", player.current_cash) else: print("Something went wrong when trying to write gameboard state to file. " "Rest of the game will be played as normal but will not log state to file.") ''' count_json += 1 logger.debug('Liquid Cash remaining with Bank = ' + str(game_elements['bank'].total_cash_with_bank)) if workbook: write_history_to_file(game_elements, workbook) # let's print some numbers logger.debug('printing final asset owners: ') diagnostics.print_asset_owners(game_elements) logger.debug('number of dice rolls: ' + str(num_die_rolls)) logger.debug('printing final cash balances: ') diagnostics.print_player_cash_balances(game_elements) logger.debug("printing net worth of each player: ") diagnostics.print_player_net_worths(game_elements) logger.debug("Game ran for " + str(tot_time) + " seconds.") if winner: logger.debug('We have a winner: ' + winner.player_name) return winner.player_name else: winner = card_utility_actions.check_for_winner(game_elements) if winner is not None: logger.debug('We have a winner: ' + winner.player_name) return winner.player_name else: logger.debug('Game has no winner, do not know what went wrong!!!') return None # ideally should never get here
def simulate_game_instance(game_elements, history_log_file=None, np_seed=6): """ Simulate a game instance. :param game_elements: The dict output by set_up_board :param np_seed: The numpy seed to use to control randomness. :return: None """ logger.debug("size of board " + str(len(game_elements['location_sequence']))) for i in range(len(game_elements['location_sequence'])): logger.debug(game_elements['location_sequence'][i].name) logger.debug( "start pos: " + str(game_elements['location_objects']['States Avenue'].start_position) + " end pos: " + str( game_elements['location_objects']['States Avenue'].end_position)) logger.debug( "start pos: " + str(game_elements['location_objects']['Virginia Avenue'].start_position) + " end pos: " + str( game_elements['location_objects']['Virginia Avenue'].end_position)) logger.debug("start pos: " + str( game_elements['location_objects']['Pennsylvania Railroad'].start_position) + " end pos: " + str( game_elements['location_objects']['Pennsylvania Railroad'].end_position)) np.random.seed(np_seed) np.random.shuffle(game_elements['players']) game_elements['seed'] = np_seed game_elements['card_seed'] = np_seed game_elements['choice_function'] = np.random.choice num_die_rolls = 0 # game_elements['go_increment'] = 100 # we should not be modifying this here. It is only for testing purposes. # One reason to modify go_increment is if your decision agent is not aggressively trying to monopolize. Since go_increment # by default is 200 it can lead to runaway cash increases for simple agents like ours. logger.debug( 'players will play in the following order: ' + '->'.join([p.player_name for p in game_elements['players']])) logger.debug('Beginning play. Rolling first die...') current_player_index = 0 num_active_players = 4 winner = None workbook = None if history_log_file: workbook = xlsxwriter.Workbook(history_log_file) while num_active_players > 1: disable_history( game_elements) # comment this out when you want history to stay. Currently, it has high memory consumption, we are working to solve the problem (most likely due to deep copy run-off). current_player = game_elements['players'][current_player_index] while current_player.status == 'lost': current_player_index += 1 current_player_index = current_player_index % len(game_elements['players']) current_player = game_elements['players'][current_player_index] current_player.status = 'current_move' # pre-roll for current player + out-of-turn moves for everybody else, # till we get num_active_players skip turns in a row. skip_turn = 0 if current_player.make_pre_roll_moves(game_elements) == 2: # 2 is the special skip-turn code skip_turn += 1 out_of_turn_player_index = current_player_index + 1 out_of_turn_count = 0 while skip_turn != num_active_players and out_of_turn_count <= 200: out_of_turn_count += 1 # print('checkpoint 1') out_of_turn_player = game_elements['players'][out_of_turn_player_index % len(game_elements['players'])] if out_of_turn_player.status == 'lost': out_of_turn_player_index += 1 continue oot_code = out_of_turn_player.make_out_of_turn_moves(game_elements) # add to game history game_elements['history']['function'].append(out_of_turn_player.make_out_of_turn_moves) params = dict() params['self'] = out_of_turn_player params['current_gameboard'] = game_elements game_elements['history']['param'].append(params) game_elements['history']['return'].append(oot_code) if oot_code == 2: skip_turn += 1 else: skip_turn = 0 out_of_turn_player_index += 1 # now we roll the dice and get into the post_roll phase, # but only if we're not in jail. # but only if we're not in jail. r = roll_die(game_elements['dies'], np.random.choice) for i in range(len(r)): game_elements['die_sequence'][i].append(r[i]) # add to game history game_elements['history']['function'].append(roll_die) params = dict() params['die_objects'] = game_elements['dies'] params['choice'] = np.random.choice game_elements['history']['param'].append(params) game_elements['history']['return'].append(r) num_die_rolls += 1 game_elements['current_die_total'] = sum(r) logger.debug('dies have come up ' + str(r)) if not current_player.currently_in_jail: check_for_go = True move_player_after_die_roll(current_player, sum(r), game_elements, check_for_go) # add to game history game_elements['history']['function'].append(move_player_after_die_roll) params = dict() params['player'] = current_player params['rel_move'] = sum(r) params['current_gameboard'] = game_elements params['check_for_go'] = check_for_go game_elements['history']['param'].append(params) game_elements['history']['return'].append(None) current_player.process_move_consequences(game_elements) # add to game history game_elements['history']['function'].append(current_player.process_move_consequences) params = dict() params['self'] = current_player params['current_gameboard'] = game_elements game_elements['history']['param'].append(params) game_elements['history']['return'].append(None) # post-roll for current player. No out-of-turn moves allowed at this point. current_player.make_post_roll_moves(game_elements) # add to game history game_elements['history']['function'].append(current_player.make_post_roll_moves) params = dict() params['self'] = current_player params['current_gameboard'] = game_elements game_elements['history']['param'].append(params) game_elements['history']['return'].append(None) else: current_player.currently_in_jail = False # the player is only allowed to skip one turn (i.e. this one) if current_player.current_cash < 0: code = current_player.agent.handle_negative_cash_balance(current_player, game_elements) # add to game history game_elements['history']['function'].append(current_player.agent.handle_negative_cash_balance) params = dict() params['player'] = current_player params['current_gameboard'] = game_elements game_elements['history']['param'].append(params) game_elements['history']['return'].append(code) if code == -1 or current_player.current_cash < 0: current_player.begin_bankruptcy_proceedings(game_elements) # add to game history game_elements['history']['function'].append(current_player.begin_bankruptcy_proceedings) params = dict() params['self'] = current_player params['current_gameboard'] = game_elements game_elements['history']['param'].append(params) game_elements['history']['return'].append(None) num_active_players -= 1 diagnostics.print_asset_owners(game_elements) diagnostics.print_player_cash_balances(game_elements) if num_active_players == 1: for p in game_elements['players']: if p.status != 'lost': winner = p p.status = 'won' else: current_player.status = 'waiting_for_move' current_player_index = (current_player_index + 1) % len(game_elements['players']) if diagnostics.max_cash_balance( game_elements) > 300000: # this is our limit for runaway cash for testing purposes only. # We print some diagnostics and return if any player exceeds this. diagnostics.print_asset_owners(game_elements) diagnostics.print_player_cash_balances(game_elements) return if workbook: write_history_to_file(game_elements, workbook) # let's print some numbers logger.debug('printing final asset owners: ') diagnostics.print_asset_owners(game_elements) logger.debug('number of dice rolls: ' + str(num_die_rolls)) logger.debug('printing final cash balances: ') diagnostics.print_player_cash_balances(game_elements) if winner: logger.debug('We have a winner: ' + winner.player_name) return winner.player_name return None
def simulate_game_instance(self, history_log_file=None, np_seed=838885): """ Simulate a game instance. :param game_elements: The dict output by set_up_board :param np_seed: The numpy seed to use to control randomness. :return: None """ logger.debug("size of board "+ str(len(self.game_elem['location_sequence']))) #for i in range(len(self.game_elem['location_sequence'])): # logger.debug(self.game_elem['location_sequence'][i].name) #logger.debug("start pos: " + str(self.game_elem['location_objects']['States Avenue'].start_position) + " end pos: " + str(self.game_elem['location_objects']['States Avenue'].end_position)) #logger.debug("start pos: " + str(self.game_elem['location_objects']['Virginia Avenue'].start_position) + " end pos: " + str(self.game_elem['location_objects']['Virginia Avenue'].end_position)) #logger.debug("start pos: " + str(self.game_elem['location_objects']['Pennsylvania Railroad'].start_position) + " end pos: " + str(self.game_elem['location_objects']['Pennsylvania Railroad'].end_position)) np.random.seed(np_seed) np.random.shuffle(self.game_elem['players']) self.game_elem['seed'] = np_seed self.game_elem['card_seed'] = np_seed self.game_elem['choice_function'] = np.random.choice num_die_rolls = 0 # game_elements['go_increment'] = 100 # we should not be modifying this here. It is only for testing purposes. # One reason to modify go_increment is if your decision agent is not aggressively trying to monopolize. Since go_increment # by default is 200 it can lead to runaway cash increases for simple agents like ours. logger.debug('players will play in the following order: '+'->'.join([p.player_name for p in self.game_elem['players']])) logger.debug('Beginning play. Rolling first die...') current_player_index = 0 num_active_players = 4 winner = None while num_active_players > 1: self.disable_history() if self.start_stop_flag==True: current_player = self.game_elem['players'][current_player_index] while current_player.status == 'lost': current_player_index += 1 current_player_index = current_player_index % len(self.game_elem['players']) current_player = self.game_elem['players'][current_player_index] current_player.status = 'current_move' # pre-roll for current player + out-of-turn moves for everybody else, # till we get num_active_players skip turns in a row. skip_turn = 0 if current_player.make_pre_roll_moves(self.game_elem) == 2: #2 is the special skip-turn code skip_turn += 1 out_of_turn_player_index = current_player_index + 1 out_of_turn_count = 0 while skip_turn != num_active_players and out_of_turn_count<=200: out_of_turn_count += 1 # print('checkpoint 1') out_of_turn_player = self.game_elem['players'][out_of_turn_player_index%len(self.game_elem['players'])] if out_of_turn_player.status == 'lost': out_of_turn_player_index += 1 continue oot_code = out_of_turn_player.make_out_of_turn_moves(self.game_elem) # add to game history self.game_elem['history']['function'].append(out_of_turn_player.make_out_of_turn_moves) params = dict() params['self']=out_of_turn_player params['current_gameboard']=self.game_elem self.game_elem['history']['param'].append(params) self.game_elem['history']['return'].append(oot_code) if oot_code == 2: skip_turn += 1 else: skip_turn = 0 out_of_turn_player_index += 1 # now we roll the dice and get into the post_roll phase, # but only if we're not in jail. r = roll_die(self.game_elem['dies'], np.random.choice) self.dice_list = r for i in range(len(r)): self.game_elem['die_sequence'][i].append(r[i]) # add to game history self.game_elem['history']['function'].append(roll_die) params = dict() params['die_objects'] = self.game_elem['dies'] params['choice'] = np.random.choice self.game_elem['history']['param'].append(params) self.game_elem['history']['return'].append(r) num_die_rolls += 1 self.game_elem['current_die_total'] = sum(r) logger.debug('dies have come up ' + str(r)) if not current_player.currently_in_jail: check_for_go = True move_player_after_die_roll(current_player, sum(r), self.game_elem, check_for_go) # add to game history self.game_elem['history']['function'].append(move_player_after_die_roll) params = dict() params['player'] = current_player params['rel_move'] = sum(r) params['current_gameboard'] = self.game_elem params['check_for_go'] = check_for_go self.game_elem['history']['param'].append(params) self.game_elem['history']['return'].append(None) current_player.process_move_consequences(self.game_elem) # add to game history self.game_elem['history']['function'].append(current_player.process_move_consequences) params = dict() params['self'] = current_player params['current_gameboard'] = self.game_elem self.game_elem['history']['param'].append(params) self.game_elem['history']['return'].append(None) # post-roll for current player. No out-of-turn moves allowed at this point. current_player.make_post_roll_moves(self.game_elem) # add to game history self.game_elem['history']['function'].append(current_player.make_post_roll_moves) params = dict() params['self'] = current_player params['current_gameboard'] = self.game_elem self.game_elem['history']['param'].append(params) self.game_elem['history']['return'].append(None) else: current_player.currently_in_jail = False # the player is only allowed to skip one turn (i.e. this one) if current_player.current_cash < 0: code = current_player.agent.handle_negative_cash_balance(current_player, self.game_elem) # add to game history self.game_elem['history']['function'].append(current_player.agent.handle_negative_cash_balance) params = dict() params['player'] = current_player params['current_gameboard'] = self.game_elem self.game_elem['history']['param'].append(params) self.game_elem['history']['return'].append(code) if code == -1 or current_player.current_cash < 0: current_player.begin_bankruptcy_proceedings(self.game_elem) # add to game history self.game_elem['history']['function'].append(current_player.begin_bankruptcy_proceedings) params = dict() params['self'] = current_player params['current_gameboard'] = self.game_elem self.game_elem['history']['param'].append(params) self.game_elem['history']['return'].append(None) num_active_players -= 1 diagnostics.print_asset_owners(self.game_elem) diagnostics.print_player_cash_balances(self.game_elem) if num_active_players == 1: for p in self.game_elem['players']: if p.status != 'lost': winner = p p.status = 'won' else: current_player.status = 'waiting_for_move' current_player_index = (current_player_index+1)%len(self.game_elem['players']) ''' The following line determines the speed of your game visualization and game. 0.1 is the default setting for this package. You can reduce it if you want the game to run faster or increase it to slow down the execution. ''' time.sleep(0.1) self.update_board() if diagnostics.max_cash_balance(self.game_elem) > 300000: # this is our limit for runaway cash for testing purposes only. # We print some diagnostics and return if any player exceeds this. diagnostics.print_asset_owners(self.game_elem) diagnostics.print_player_cash_balances(self.game_elem) return logger.debug('printing final asset owners: ') diagnostics.print_asset_owners(self.game_elem) logger.debug('number of dice rolls: '+ str(num_die_rolls)) logger.debug('printing final cash balances: ') diagnostics.print_player_cash_balances(self.game_elem) if winner: logger.debug('We have a winner: '+ winner.player_name) return