Beispiel #1
0
 def test_play_poacher_with_empty_supply_piles(self):
     for num_empty_supply_piles in (1, 2, 3):
         cards_in_supply = [CopperCard, SilverCard, GoldCard]
         starting_deck = [CopperCard] * 20
         game_state = self.create_game_state(
             starting_deck, supply=UnorderedCardStack(cards_in_supply))
         p1_agent = TestAgent('p1')
         p2_agent = TestAgent('p2')
         game_state.set_agents([p1_agent, p2_agent])
         supply = game_state.get_location(
             Location(None, LocationName.SUPPLY))
         # empty supply piles
         for i in range(num_empty_supply_piles):
             supply.extract([cards_in_supply[i]])
         player = game_state.get_current_player_name()
         start_hand_size = 5
         game_state.draw(start_hand_size)
         PoacherCard.play(game_state)
         hand = game_state.get_location(Location(player, LocationName.HAND))
         self.assertEqual(
             hand.size(), start_hand_size + 1 - num_empty_supply_piles,
             'Player should draw 1 card and then discard one for each empty supply pile.'
         )
         discard = game_state.get_location(
             Location(player, LocationName.DISCARD))
         self.assertEqual(
             discard.size(), num_empty_supply_piles,
             'Player should have discarded 1 card for each empty supply pile.'
         )
         self.assertEqual(
             game_state.get_counter(CounterId(None, CounterName.COINS)), 1,
             'Poacher should give the player one extra coin.')
         self.assertEqual(
             game_state.get_counter(CounterId(None, CounterName.ACTIONS)),
             1, 'Poacher should give the player one extra action.')
Beispiel #2
0
 def play(cls, game_state):
     game_state.draw(1)
     game_state.update_counter(counter_id=CounterId(None,
                                                    CounterName.ACTIONS),
                               delta=1)
     game_state.update_counter(counter_id=CounterId(None,
                                                    CounterName.COINS),
                               delta=1)
     game_state.update_counter(counter_id=CounterId(None, CounterName.BUYS),
                               delta=1)
Beispiel #3
0
    def take_buy_action(self, player, card):
        """
        Params:
          player_name: string
          card: Card class

        Moves card from supply to player discard pile
        """
        cost = card.cost(self.game_state)
        self.game_state.update_counter(CounterId(None, CounterName.BUYS), -1)
        self.game_state.update_counter(CounterId(None, CounterName.COINS),
                                       0 - cost)
        self.game_state.gain(card)
Beispiel #4
0
 def play(cls, game_state):
     game_state.draw(1)
     game_state.update_counter(counter_id=CounterId(None, CounterName.ACTIONS), delta=1)
     game_state.update_counter(counter_id=CounterId(None, CounterName.COINS), delta=1)
     supply = game_state.get_location(Location(None, LocationName.SUPPLY))
     cards_to_counts = supply.distribution.cards_to_counts()
     empty_supply_piles = list(cards_to_counts.values()).count(0)
     if empty_supply_piles == 0:
         return
     decision = PoacherDecision(game_state, empty_supply_piles)
     player = game_state.get_current_player_name()
     agent = game_state.get_agent(player)
     choice = agent.make_decision(decision)
     assert decision.is_valid(choice)
     game_state.discard(choice)
Beispiel #5
0
 def play(cls, game_state):
     """
     +2 cards
     +1 action
     """
     game_state.draw(2)
     game_state.update_counter(counter_id=CounterId(None, CounterName.ACTIONS), delta=1)
Beispiel #6
0
    def play(cls, game_state):
        """
        +1 card
        +1 action
        Look through your discard pile. You may put that card on top of your deck
        """
        game_state.draw(1)
        game_state.update_counter(counter_id=CounterId(None,
                                                       CounterName.ACTIONS),
                                  delta=1)

        decision = HarbingerDecision(game_state)
        agent = game_state.get_agent(game_state.get_current_player_name())
        chosen_cards = agent.make_decision(decision)
        assert decision.is_valid(chosen_cards)
        if chosen_cards:
            game_state.move(cards=chosen_cards,
                            number=None,
                            from_location=Location(agent.name(),
                                                   LocationName.DISCARD),
                            from_position=None,
                            to_location=Location(agent.name(),
                                                 LocationName.DRAW_PILE),
                            to_position=StackPosition.TOP,
                            event_type=CardEventType.MOVE)
Beispiel #7
0
 def _create_counters(self, player_names):
     """
     Create a dict of `CounterId` -> int for all game state counters
     in a starting game state given the list of player names.
     """
     counters = {}
     for counter_name in GLOBAL_COUNTERS:
         counters[CounterId(None, counter_name)] = 0
     return counters
Beispiel #8
0
 def play(cls, game_state):
     decision = MoneyLenderDecision(game_state)
     agent = game_state.get_agent(game_state.get_current_player_name())
     # No coppers to trash
     if decision.there_is_no_choice():
         return
     choice = agent.make_decision(decision)
     if choice == [CopperCard]:
         game_state.trash(CopperCard)
         game_state.update_counter(counter_id=CounterId(
             None, CounterName.COINS),
                                   delta=3)
Beispiel #9
0
 def test_play_poacher_no_empty_supply_piles(self):
     starting_deck = [CopperCard] * 12
     game_state = self.create_game_state(starting_deck,
                                         supply=UnorderedCardStack(
                                             [PoacherCard, CopperCard]))
     player = game_state.get_current_player_name()
     PoacherCard.play(game_state)
     hand = game_state.get_location(Location(player, LocationName.HAND))
     self.assertEqual(hand.size(), 1,
                      'Poacher should have the player draw a card.')
     discard = game_state.get_location(
         Location(player, LocationName.DISCARD))
     self.assertEqual(
         discard.size(), 0,
         'If no empty supply piles no cards should be discarded.')
     self.assertEqual(
         game_state.get_counter(CounterId(None, CounterName.COINS)), 1,
         'Poacher should give the player one extra coin.')
     self.assertEqual(
         game_state.get_counter(CounterId(None, CounterName.ACTIONS)), 1,
         'Poacher should give the player one extra action.')
Beispiel #10
0
    def play(cls, game_state):
        """
        Discard any number of cards, then draw that many
        +1 action
        """
        game_state.update_counter(counter_id=CounterId(None,
                                                       CounterName.ACTIONS),
                                  delta=1)
        decision = CellarDecision(game_state)
        agent = game_state.get_agent(game_state.get_current_player_name())
        chosen_cards = agent.make_decision(decision)
        assert decision.is_valid(chosen_cards)

        game_state.discard(chosen_cards)
        game_state.draw(len(chosen_cards))
Beispiel #11
0
    def run(self):
        """
        Main control loop for game play
        """
        #################
        # Initialization
        #################

        starting_supply = self.get_starting_supply()
        starting_deck = self.get_starting_deck()
        self.game_state = GameState(
            list(map(lambda x: x.name(), self.players)), starting_supply,
            starting_deck, self.log)
        # TODO: inform Players of initial state for learning agents
        self.game_state.set_agents(self.players)
        for player in self.players:
            # shuffle player decks
            self.game_state.shuffle(
                Location(player.name(), LocationName.DRAW_PILE))
            # draw starting hands
            self.game_state.draw(NUM_CARDS_IN_HAND, player.name())

        #################
        # Gameplay loop
        #################
        turn_number = 1
        while not self.game_over():
            # Fetch the next player
            player = self.players[self.player_index]
            ### Setup Phase
            self.game_state.reset_counters_for_new_turn()

            ### Action phase

            while (self.actions_left() > 0
                   and len(self.action_cards_in_hand(player)) > 0):
                decision = self.generate_action_decision(player)
                choices = self.give_decision(decision, player)
                action_card = choices[0] if choices else None
                # TODO: validate choice legality
                if not action_card:
                    break
                self.game_state.update_counter(
                    CounterId(None, CounterName.ACTIONS), -1)
                self.game_state.play(action_card)
                action_card.play(self.game_state)

            ### Buy phase
            decision = self.generate_play_treasures_decision(player)
            treasures = self.give_decision(decision, player)
            self.play_treasures(player, treasures)

            while self.buys_left() > 0:
                decision = self.generate_buy_decision(player)
                choices = self.give_decision(decision, player)
                choice = choices[0] if choices else None
                # TODO: validate choice legality
                if not choice:
                    break
                self.take_buy_action(player, choice)

            ### Discard cards in play and in hand
            self.game_state.discard_location(
                Location(player.name(), LocationName.IN_PLAY))
            self.game_state.discard_location(
                Location(player.name(), LocationName.HAND))

            ### Draw next hand
            self.game_state.draw(NUM_CARDS_IN_HAND, player.name())

            # TODO: inform Players of after turn state for learning agents

            # rotate player index
            self.player_index = self.increment_player_turn_index()
            turn_number += 1
            # Safety to avoid bots getting stuck in infinite game.
            if turn_number > MAX_TURNS:
                break

        #################
        # Resolve game
        #################
        print('\nGAME OVER on Turn %d\n-----------------\n' %
              (turn_number / 2))
        for name, vp in self.player_name_to_vp().items():
            print('%s: %d' % (name, vp))
        winners = self.get_winners()
        if len(winners) == 1:
            print('Winner: ' + winners[0])
        elif len(winners) == 2:
            tied_player_names = ' and '.join(winners)
            print('Tie between %s' % tied_player_names)
        return winners
Beispiel #12
0
 def _print_coins(self, known_state):
     if known_state is None:
         return
     num_coins = known_state.counters[CounterId(None, CounterName.COINS)]
     print('Coins: %d' % num_coins)
Beispiel #13
0
 def money_in_play(self):
     return self.game_state.get_counter(CounterId(None, CounterName.COINS))
Beispiel #14
0
 def buys_left(self):
     return self.game_state.get_counter(CounterId(None, CounterName.BUYS))
Beispiel #15
0
 def actions_left(self):
     return self.game_state.get_counter(CounterId(None,
                                                  CounterName.ACTIONS))
Beispiel #16
0
 def reset_counters_for_new_turn(self):
     """
     Updates all counters for the beginning of a new turn.
     """
     for counter_name, value in COUNTER_VALUES_AT_TURN_START.items():
         self.set_counter(CounterId(None, counter_name), value)
Beispiel #17
0
	def play(cls, game_state):
	    game_state.update_counter(
	    	counter_id=CounterId(None, CounterName.COINS), delta=cls.base_treasure_value
	    )