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.')
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')
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, [])
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')