예제 #1
0
    def makeDecision(self, s: State, response: DecisionResponse):
        d: DecisionState = s.decision
        if s.phase == Phase.TreasurePhase:
            response.single_card = d.card_choices[0]
            return

        if d.type == DecisionType.DecisionSelectCards:
            cardsToPick = -1
            d.print_card_choices()
            while (cardsToPick < d.min_cards or cardsToPick > d.max_cards):
                text = ''
                while not text:
                    text = input(
                        f'Pick between {d.min_cards} and {d.max_cards} of the above cards:\n'
                    )
                cardsToPick = int(text)

            responseIdxs = []
            for i in range(cardsToPick):
                cardIdx = -1
                while (cardIdx == -1 or cardIdx in responseIdxs
                       or cardIdx >= len(d.card_choices)):
                    d.print_card_choices()
                    text = ''
                    while not text:
                        text = input('Choose another card:\n')
                    cardIdx = int(text)
                responseIdxs.append(cardIdx)
                response.cards.append(d.card_choices[cardIdx])
        elif d.type == DecisionType.DecisionDiscreteChoice:
            choice = -1
            while choice == -1 or choice > d.min_cards:
                text = ''
                while not text:
                    text = input(
                        'Please make a discrete choice from the above cards:\n'
                    )
                choice = int(text)
                d.print_card_choices()
            response.choice = choice
        else:
            logging.error(f'Player {s.player} given invalid decision type.')
예제 #2
0
    def makeDecision(self, s: State, response: DecisionResponse):
        d: DecisionState = s.decision

        # Do not allow RandomPlayer to purchase curses
        if s.phase == Phase.BuyPhase and not self.train:
            remove_first_card(Curse(), d.card_choices)

        # Ensure random player plays all treasures
        if s.phase == Phase.TreasurePhase:
            response.single_card = d.card_choices[0]
            return

        if d.type == DecisionType.DecisionSelectCards:
            cards_to_pick = d.min_cards
            if d.max_cards > d.min_cards:
                cards_to_pick = random.randint(d.min_cards, d.max_cards)

            response.cards = random.sample(d.card_choices,
                                           k=min(cards_to_pick,
                                                 len(d.card_choices)))
        elif d.type == DecisionType.DecisionDiscreteChoice:
            response.choice = random.randint(0, d.min_cards)
        else:
            logging.error('Invalid decision type')
예제 #3
0
    def test_moat_reveal(self) -> None:
        self.game.new_game()

        # Inject necessary cards into players' hands
        attack_card = Militia()
        moat_card = Moat()
        self.game.state.inject(0, attack_card)
        self.game.state.inject(1, moat_card)

        self.game.state.advance_next_decision()

        # Action Phase decision
        r = DecisionResponse([])
        r.cards = [attack_card]
        self.game.state.process_decision(r)
        self.game.state.advance_next_decision()

        # MoatReveal reaction
        r = DecisionResponse([])
        r.choice = 0
        self.game.state.process_decision(r)
        self.game.state.advance_next_decision()

        self.assertEqual(self.game.state.events, [])
예제 #4
0
 def makeBaseDecision(self, s: State, response: DecisionResponse):
     d: DecisionState = s.decision
     card = d.active_card
     player = s.decision.controlling_player
     p_state: PlayerState = s.player_states[player]
     if isinstance(card, Cellar):
         num_discarded = 0
         for c in d.card_choices:
             if isinstance(c, VictoryCard) or c.get_coin_cost() < 2:
                 response.cards.append(c)
     elif isinstance(card, Chapel):
         treasureValue = s.get_total_coin_count(player)
         trashCoppers = (treasureValue > 3)
         num_discarded = 0
         for c in d.card_choices:
             trashCoppers = (treasureValue > 3)
             if num_discarded == 4:
                 break
             if isinstance(c, Curse):
                 response.cards.append(c)
                 num_discarded += 1
             elif isinstance(c, Copper) and trashCoppers:
                 response.cards.append(c)
                 num_discarded += 1
                 treasureValue -= 1
             elif isinstance(c, Estate):
                 response.cards.append(c)
                 num_discarded += 1
             elif isinstance(c, Chapel):
                 response.cards.append(c)
                 num_discarded += 1
     elif isinstance(card, Moat):
         response.choice = 0
     elif isinstance(card, Bureaucrat):
         response.cards.append(d.card_choices[0])
     elif isinstance(card, Militia):
         self.makeDiscardDownDecision(s, response)
     elif isinstance(card, ThroneRoom):
         self.makeCopyDecision(s, response)
     elif isinstance(card, Library):
         if s.player_states[s.player].actions == 0:
             response.choice = 0
         else:
             response.choice = 1
     elif isinstance(card, Mine):
         event = s.events[-1]
         if not event.trashed_card:
             def scoringFunction(card: Card):
                 if isinstance(card, Gold) and s.supply[Gold] > 0:
                     return 20
                 if isinstance(card, Silver) and s.supply[Silver] > 0:
                     return 19
                 if isinstance(card, Copper) and s.supply[Copper] > 0:
                     return 18
                 return -card.get_coin_cost()
             response.cards = heuristic_select_cards(d.card_choices, d.min_cards, scoringFunction)
         else:
             response.cards.append(self.agenda.forceBuy(s, player, d.card_choices))
     elif isinstance(card, Harbinger):
         def scoringFunction(card: Card):
             if has_excess_actions(p_state.hand):
                 if isinstance(card, ActionCard):
                     return 100 + card.get_coin_cost()
                 else:
                     return card.get_coin_cost()
             else:
                 return card.get_coin_cost()
         response.cards = heuristic_select_cards(d.card_choices, d.min_cards, scoringFunction)
     elif isinstance(card, Artisan):
         event = s.events[-1]
         if not event.gained_card:
             response.cards.append(self.agenda.forceBuy(s, player, d.card_choices))
         else:
             self.makePutDownOnDeckDecision(s, response)
     elif isinstance(card, Poacher):
         self.makeDiscardDownDecision(s, response)
     else:
         logging.error('Unexpected decision')