Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
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