예제 #1
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