class MinimaxPlayer(Player): """Minimax player attempts to play with minimax rules.""" THRESHOLD = 0.8 def __init__(self, name, depth = 2, breadth = 3): Player.__init__(self, name) self.depth = depth self.breadth = breadth self.predictor = Predictor(self.THRESHOLD) def round_start(self, game_state): self.predictor.reset(game_state) def choose_card(self, game_state): self.predictor.refresh(game_state, self) players = self.predictor.players turn_index = players.index(self) def utility(pred, trick): total_tricks = len(pred.deck.cards) / whist.NUM_PLAYERS played = [card for card, player in pred.plays.items() if player == self] tricks_remaining = total_tricks - len(played) not_played = [card for card in self.cards if card not in played] win_thresh = (tricks_remaining * len(ranks)) / total_tricks score = 0 for card in not_played: if ranks.index(card.rank) >= win_thresh: score += 1 else: score -= 1 return score def vopt(pred, trick, depth): if depth == 0: return utility(pred, trick) score = 0 turn = (players.index(trick.play_order[-1]) + 1) % whist.NUM_PLAYERS # first we calculate the score if possible if not trick.left_to_play: # all players have played if game_state.are_partners(self.name, trick.winning_player().name): score = 1 else: score = -1 turn = players.index(trick.winning_player()) if not players[turn].cards: # game complete return score trick = Trick(players, game_state.trump) depth = depth - 1 cards = util.get_legal_cards(pred.predict(players[turn]), trick.suit_led) cards = cards if len(cards) < self.breadth else random.sample(cards, self.breadth) plays = [] # next we attempt to play cards if not cards: # this branch cannot be satisified, prune it return 0 for card in cards: trick.play_card(players[turn], card) pred.try_play(players[turn], card) plays.append(score + vopt(pred, trick, depth)) pred.revert_play(players[turn], card) trick.revert_play(players[turn], card) # finally we return the highest score if game_state.are_partners(self.name, players[turn].name): # max return max(plays) else: # min return min(plays) # make best play legal_cards = util.get_legal_cards(self.cards, game_state.trick.suit_led) trick = game_state.trick choices = [] max_score = float("-inf") pred = self.predictor for card in legal_cards: trick.play_card(self, card) pred.try_play(self, card) score = vopt(pred, trick, self.depth) pred.revert_play(self, card) trick.revert_play(self, card) print "Predict %s: %d" % (card, score) choices.append((score, card)) if score > max_score: max_score = score choices = [card for score, card in choices if score == max_score] max_card = random.choice(choices) pred.learn(self, max_card) return max_card def observe_play(self, game_state, player, card): self.predictor.refresh(game_state, self) self.predictor.learn(player, card)