def alphabeta(self, rnd: PlayerRoundCheating, last_card: int, alpha: (int, int), beta: (int, int), maximizingPlayer: bool) -> Move: """ Returns the best card to play, based on the minimax algorithm Args: rnd: For the first call this is the current round. For further calls inside the recursion this ist the round that is being simulated last_card: the last Card that has been played maximizingPlayer: if you need to maximize or minimize Returns: the best card to play, int encoded :param maximizingPlayer: :param last_card: :param rnd: :param beta: :param alpha: """ if rnd.nr_cards_in_trick > 3: rule = RuleSchieber() points = rule.calc_points(rnd.current_trick, rnd.nr_played_cards == 36, rnd.trump) winner = rule.calc_winner(rnd.current_trick, rnd.trick_first_player[rnd.nr_tricks], rnd.trump) if winner == NORTH or winner == SOUTH: bestCard = Move(last_card, points) else: bestCard = Move(last_card, -points) return bestCard elif maximizingPlayer: cardsToPlay = np.flatnonzero(rnd.get_valid_cards()) for card in cardsToPlay: newRound = self.fake_move(rnd, card) alpha = max(alpha, self.alphabeta(newRound, card, alpha, beta, False)) if beta <= alpha: break return alpha else: cardsToPlay = np.flatnonzero(rnd.get_valid_cards()) for card in cardsToPlay: newRound = self.fake_move(rnd, card) beta = min(beta, self.alphabeta(newRound, card, alpha, beta, True)) if beta <= alpha: break return beta return bestCard
def expandNode(self, node: Node, rnd: PlayerRoundCheating): validCards = np.flatnonzero(rnd.get_valid_cards()) for card in validCards: newNode = Node() newNode.setParent(node) newNode.getAction().setRound(rnd) newNode.getAction().setPlayerNr(node.getAction().getRound().player) newNode.getAction().setCard(card) node.addChild(newNode)
def play_card(self, rnd: PlayerRoundCheating) -> int: """ Player returns a card to play based on the given round information. Args: rnd: current round Returns: card to play, int encoded """ playerRound = PlayerRoundCheating() playerRound.set_from_round(rnd) cardToPlay = self.alphabeta(playerRound, 0, Move(0, -sys.maxsize), Move(0, sys.maxsize), True) return cardToPlay.get_card()
def __expand_node(self, node: Node, round: PlayerRoundCheating): valid_cards = np.flatnonzero(round.get_valid_cards()) for card in valid_cards: newNode = Node() newNode.set_parent(node) newNode.getNodeMCTSInformation().setRound(round) newNode.getNodeMCTSInformation().setPlayerNr(node.getNodeMCTSInformation().getRound().player) newNode.getNodeMCTSInformation().setCard(card) node.addChild(newNode)
def fake_move(self, rnd: PlayerRoundCheating, cardToPlay: int) -> PlayerRoundCheating: nextRound = PlayerRoundCheating() nextRound.set_from_round(rnd) nextRound.current_trick[rnd.nr_cards_in_trick] = cardToPlay nextRound.hands[nextRound.player, cardToPlay] = 0 nextRound.nr_cards_in_trick = nextRound.nr_cards_in_trick + 1 nextRound.nr_played_cards = nextRound.nr_played_cards + 1 nextRound.player = (nextRound.player - 1) % 4 nextRound.hand = nextRound.hands[nextRound.player] return nextRound
def simulateRound(self, node: Node): rnd = get_round_from_player_round(node.getAction().getRound(), node.getAction().getRound().hands) rnd.action_play_card(node.getAction().getCard()) cards = rnd.nr_played_cards randomPlayer = RandomPlayerSchieber() while cards < 36: player_rnd = PlayerRoundCheating() player_rnd.set_from_round(rnd) card_action = randomPlayer.play_card(player_rnd) rnd.action_play_card(card_action) cards += 1 myPoints = rnd.points_team_0 pointsEnemy = rnd.points_team_1 maxPoints = myPoints + pointsEnemy if myPoints > pointsEnemy: return (myPoints - 0) / (maxPoints - 0) else: return 0
def __simulate_round(self, node: Node): # Random walk round = get_round_from_player_round(node.getNodeMCTSInformation().getRound(), node.getNodeMCTSInformation().getRound().hands) round.action_play_card(node.getNodeMCTSInformation().getCard()) cards = round.nr_played_cards random_player = MyPlayer() while cards < 36: player_round = PlayerRoundCheating() player_round.set_from_round(round) card_action = random_player.play_card(player_round) round.action_play_card(card_action) cards += 1 myPoints = round.points_team_0 pointsEnemy = round.points_team_1 maxPoints = myPoints + pointsEnemy if myPoints > pointsEnemy: return (myPoints - 0) / (maxPoints - 0) else: return 0