def run_game(num_players=2, validate=True, ai_player_indices=[1]): state = GameState(players=num_players, init_game=True, validate=False) ai = H50AI_TDlam(restore=True, stepsize=0, prob_factor=100, num_players=2) while True: print_game_state(state, player_index=0, ai=ai) if validate: state.verify_state() if state.current_player_index == 0: winners = check_winner(state) if winners is not None: print(Style.BRIGHT + Fore.WHITE) if len(winners) == 1: print('Player {} wins with {} points'.format( winners[0] + 1, state.players[winners[0]].score)) else: print( 'Players {} win with {} points and {} cards'.format( [w + 1 for w in winners], state.players[winner[0]].score, len(state.players[winner[0]].cards_played))) exit(0) if state.current_player_index in ai_player_indices: move, move_info = ai.make_move(state) state.make_move(move) else: do_player_move(state, ai) # If the player has too many gems, discard some discard_to_ten_gems(state)
def run_game(self, verbose=True): # print('===') state = GameState(players=self.num_players, init_game=True, validate=self.validate) self.state = state state_vectors = [] # Add the judgement of the first state vector ai = self.ais[0] if isinstance(ai, H50AI_TDlam): state_vector = state.get_state_vector(0).reshape((1, -1)) current_value = ai.session.run(ai.softmax_output, {ai.input_state: state_vector})[0] else: state_vector = np.zeros(5) current_value = np.zeros(2) # current_grads = ai.session.run(ai.grads, feed_dict={ai.input_state: state_vector}) # state_vectors.append((state.get_state_vector(0), current_value, state_vector, current_grads)) game_round = 1 state = state while True: if state.current_player_index == 0: scores = np.array([player.score for player in state.players]) if np.any(scores >= self.end_score): # game has ended max_score = np.max(scores) num_cards = [] for i, player in enumerate(state.players): if player.score == max_score: num_cards.append(len(player.cards_played)) min_num_cards = np.min(num_cards) winning_players = [] for i, player in enumerate(state.players): if player.score == max_score and len( player.cards_played) == min_num_cards: winning_players.append((i, player)) assert len(winning_players) >= 1 print('## players {} win with {} points after {} rounds'. format([p[0] for p in winning_players], max_score, game_round)) try: state.verify_state() except AssertionError: import traceback traceback.print_exc() import ipdb ipdb.set_trace() if len(winning_players) > 1: print('Draw!') return FinishedGameInfo(None, None, state_vectors=state_vectors) winner_index = winning_players[0][0] winner_num_bought = len( state.players[winner_index].cards_played) winner_value = np.zeros(self.num_players) winner_value[winner_index] = 1. for player_index in range(state.num_players): #pass #print(np.roll(winner_value, -1 * player_index)) #print(state_vectors[-1].post_move_values[player_index]) #print(state_vectors[-1]) state_vectors[-1].post_move_values[ player_index] = np.roll(winner_value, -1 * player_index) # assert ((winner_index + 1) % state.num_players) == state.current_player_index winner_t1 = len([ c for c in state.players[winner_index].cards_played if c.tier == 1 ]) winner_t2 = len([ c for c in state.players[winner_index].cards_played if c.tier == 2 ]) winner_t3 = len([ c for c in state.players[winner_index].cards_played if c.tier == 3 ]) return FinishedGameInfo(game_round, winner_index, winner_num_t1_bought=winner_t1, winner_num_t2_bought=winner_t2, winner_num_t3_bought=winner_t3, state_vectors=state_vectors) # return game_round, i, winner_num_bought, state_vectors if state.current_player_index == 0: game_round += 1 if verbose: print('Round {}: {}'.format(game_round, state.get_scores())) if game_round > 50: print('Stopped after 50 rounds') return FinishedGameInfo(None, None, state_vectors=state_vectors) # return game_round, None, None, state_vectors # scores = state.get_scores() # if any([score >= self.end_score for score in scores]): # break # game end for tier in range(1, 4): state.generator.shuffle(state.cards_in_deck(tier)) current_player_index = state.current_player_index move, move_info = self.ais[state.current_player_index].make_move( state) # print(state.current_player_index, move, values[:-1]) if verbose: print('P{}: {}, value {}'.format(state.current_player_index, move, values)) last_player = state.current_player_index state.make_move(move) # new_state_vector = state.get_state_vector(current_player_index) state_vectors.append(move_info)
class GameScreen(Screen): num_players = NumericProperty(2) validate = BooleanProperty(False) tier_1_cards = ListProperty([]) tier_2_cards = ListProperty([]) tier_3_cards = ListProperty([]) supply_white = NumericProperty(0) supply_blue = NumericProperty(0) supply_green = NumericProperty(0) supply_red = NumericProperty(0) supply_black = NumericProperty(0) supply_gold = NumericProperty(0) p1_white = NumericProperty(0) p1_blue = NumericProperty(0) p1_green = NumericProperty(0) p1_red = NumericProperty(0) p1_black = NumericProperty(0) p1_gold = NumericProperty(0) p2_white = NumericProperty(0) p2_blue = NumericProperty(0) p2_green = NumericProperty(0) p2_red = NumericProperty(0) p2_black = NumericProperty(0) p2_gold = NumericProperty(0) p1_white_cards = NumericProperty(0) p1_blue_cards = NumericProperty(0) p1_green_cards = NumericProperty(0) p1_red_cards = NumericProperty(0) p1_black_cards = NumericProperty(0) p1_gold_cards = NumericProperty(0) p2_white_cards = NumericProperty(0) p2_blue_cards = NumericProperty(0) p2_green_cards = NumericProperty(0) p2_red_cards = NumericProperty(0) p2_black_cards = NumericProperty(0) p2_gold_cards = NumericProperty(0) scores = ListProperty([]) player_hand_cards = ListProperty([]) round_number = NumericProperty(0) last_move_info = StringProperty('') nobles_text = StringProperty('') current_value_text = StringProperty('') player_types = ListProperty([ 'player:1', 'player:2' ]) #H50AI_TDlam(restore=True, prob_factor=20, num_players=2)]) current_player_index = NumericProperty(0) selected_card = ObjectProperty(None, allownone=True) can_buy_selected = BooleanProperty(False) can_reserve_selected = BooleanProperty(False) ai_autoplay = BooleanProperty(False) def __init__(self, **kwargs): super().__init__(**kwargs) self.ai = H50AI_TDlam(restore=True, stepsize=0, prob_factor=100, num_players=2) self.init_game_state() def init_game_state(self): self.state = GameState(players=self.num_players, init_game=True, validate=self.validate) Clock.schedule_once(self.sync_with_game_state, 0) def sync_with_game_state(self, *args): self.state.verify_state() self.current_player_index = self.state.current_player_index self.tier_1_cards = self.state.cards_in_market(1) self.tier_2_cards = self.state.cards_in_market(2) self.tier_3_cards = self.state.cards_in_market(3) self.player_hand_cards = self.state.players[0].cards_in_hand for colour in colours + ['gold']: setattr(self, 'supply_' + colour, self.state.num_gems_available(colour)) for i, player in enumerate(self.state.players): setattr(self, 'p{}_{}'.format(i + 1, colour), player.num_gems(colour)) setattr(self, 'p{}_{}_cards'.format(i + 1, colour), player.num_cards_of_colour(colour)) self.round_number = self.state.round_number self.scores = [player.score for player in self.state.players] if self.state.moves: last_move = self.state.moves[-1] if last_move[0] == 'gems': self.last_move_info = 'gained gems ' + str(last_move[1]) elif last_move[0].startswith('buy_'): previous_player_index = (self.current_player_index - 1) % len( self.state.players) card = self.state.players[previous_player_index].cards_played[ -1] self.last_move_info = 'bought {}'.format(card) elif last_move[0] == 'reserve': self.last_move_info = 'reserved from tier {}'.format( last_move[1]) else: import ipdb ipdb.set_trace() raise ValueError('Unrecognised move') else: self.last_move_info = '---' self.nobles_text = 'nobles: {}\nP1 nobles: {} P2 nobles: {}'.format( format_nobles(self.state.nobles), format_nobles(self.state.players[0].nobles), format_nobles(self.state.players[1].nobles)) values = self.ai.evaluate(self.state) text = 'P1: {:.03f} {:.03f}\nP2: {:.03f} {:.03f}'.format( values[0, 0], values[1, 1], values[0, 1], values[1, 0]) self.current_value_text = text self.unselect_card() self.ids.gems_chooser.reset_changes() if self.ai_autoplay and self.state.current_player_index != 0: self.do_ai_move() def on_ai_autoplay(self, instance, value): self.sync_with_game_state() def unselect_card(self): if self.selected_card is not None: self.selected_card.selected = False self.selected_card = None def buy_selected_card(self): card = self.selected_card.card player = self.state.players[self.state.current_player_index] move_index = None move_type = None move_tier = None for tier in range(1, 4): market = self.state.cards_in_market(tier) for i, market_card in enumerate(market): if market_card is card: move_tier = tier move_index = i move_type = 'buy_available' break if move_type is None: for i, hand_card in enumerate(player.cards_in_hand): if hand_card is card: move_type = 'buy_reserved' move_index = i if move_type is None or move_index is None: raise ValueError('Card not found in market or hand') can_afford, cost = player.can_afford(card) assert can_afford cost = {key: -1 * value for key, value in cost.items()} if move_type == 'buy_available': move = (move_type, move_tier, move_index, cost) else: move = (move_type, move_index, cost) self.state.make_move(move) self.sync_with_game_state() def reserve_selected_card(self): card = self.selected_card.card player = self.state.players[self.state.current_player_index] move_tier = None move_index = None for tier in range(1, 4): market = self.state.cards_in_market(tier) for i, market_card in enumerate(market): if market_card is card: move_tier = tier move_index = i break if move_tier is None or move_index is None: raise ValueError('Card not found in market or hands') num_gold_available = self.state.num_gems_available('gold') gems_dict = {'gold': min(1, num_gold_available)} move = ('reserve', move_tier, move_index, gems_dict) self.state.make_move(move) self.sync_with_game_state() def take_gems(self): gems_dict = {} for colour in colours: number = getattr(self.ids.gems_chooser, '{}_change'.format(colour)) gems_dict[colour] = number move = ('gems', gems_dict) self.state.make_move(move) self.sync_with_game_state() def do_ai_move(self): move, move_info = self.ai.make_move(self.state) self.state.make_move(move) self.sync_with_game_state() def reset_game(self): self.init_game_state() def on_selected_card(self, instance, card): if card is None: self.can_buy_selected = False self.can_reserve_selected = False return current_player = self.state.players[self.state.current_player_index] if current_player.can_afford(card.card)[0]: self.can_buy_selected = True else: self.can_buy_selected = False if len(current_player.cards_in_hand) < 3: self.can_reserve_selected = True else: self.can_reserve_selected = False