def __repr__(self): # type: () -> str """ :return: A concise string representation of the state in one line """ rep = "The game is in phase: {}\n".format(self.__phase) rep += "Player 1's points: {}, pending: {}\n".format(self.__p1_points, self.__p1_pending_points) rep += "Player 2's points: {}, pending: {}\n".format(self.__p2_points, self.__p2_pending_points) rep += "The trump suit is: {}\n".format(self.get_trump_suit()) rep += "Player 1's hand:" for card in self.__deck.get_player_hand(1): rank, suit = util.get_card_name(card) rep += " {}{}".format(rank, suit) rep += "\n" rep += "Player 2's hand:" for card in self.__deck.get_player_hand(2): rank, suit = util.get_card_name(card) rep += " {}{}".format(rank, suit) rep += "\n" rep += "There are {} cards in the stock\n".format(self.__deck.get_stock_size()) trick = self.__deck.get_trick() if trick[0] is not None: rep += "Player 1 has played card: {} of {}\n".format(util.get_rank(trick[0]), util.get_suit(trick[0])) if trick[1] is not None: rep += "Player 2 has played card: {} of {}\n".format(util.get_rank(trick[1]), util.get_suit(trick[1])) return rep
def test_trump_jack_non_leading(self): state = State.generate(6) me = state.whose_turn() s1 = state.clone(signature=me) trump_suit = state.get_trump_suit() jacks = [ move for move in s1.moves() if (move[0] == 4 or move[0] == 9 or move[0] == 14 or move[0] == 19) ] trump_jacks = [ move for move in jacks if util.get_suit(move[0]) == trump_suit ] self.assertEqual(len(s1.moves()), 5 + len(trump_jacks)) state = state.next(random.choice(state.moves())) s1 = state.clone(me) jacks = [ move for move in state.moves() if (move[0] == 4 or move[0] == 9 or move[0] == 14 or move[0] == 19) ] trump_jacks = [ move for move in jacks if util.get_suit(move[0]) == trump_suit ] self.assertGreater(len(trump_jacks), 0) self.assertEqual(len(state.moves()), 5)
def general_information(kb, state, index): # Loads fuzzy symbols, gives them fuzzy values and adds them to fuzzy knowledge base RV = FuzzySymbol("rv", set_fuzzyRankValue(state, util.get_rank(index))) # rank value TV = FuzzySymbol("tv", 0.01 if state.get_trump_suit() == util.get_suit(index) else 1.00) # trump value SV = FuzzySymbol("sv", set_fuzzySuitValue(state, util.get_suit(index))) # suit value kb.add_clause(RV) kb.add_clause(TV) kb.add_clause(SV)
def play( player1, player2, state, # type: State max_time=5000, # type: int verbose=True # type: bool ): """ Play a game between two given players, from the given starting state. """ pr('player1: {}'.format(player1), verbose) pr('player2: {}'.format(player2), verbose) # The game loop while not state.finished(): player = player1 if state.whose_turn() == 1 else player2 move = get_move(state, player, max_time, verbose) check(move, player) # check for common mistakes TODO if move[0] is None: pr( '* Player {} performs a trump jack exchange'.format( state.whose_turn()), verbose) else: pr( '* Player {} plays: {}{}'.format(state.whose_turn(), util.get_rank(move[0]), util.get_suit(move[0])), verbose) if move[1] is not None: pr( '* Player {} melds a marriage between {}{} and {}{}'. format(state.whose_turn(), util.get_rank(move[0]), util.get_suit(move[0]), util.get_rank(move[1]), util.get_suit(move[1])), verbose) state = state.next(move) pr(state, verbose) if not state.revoked() is None: pr( '! Player {} revoked (made illegal move), game finished.'. format(state.revoked()), verbose) if state.finished(): pr( 'Game finished. Player {} has won, receiving {} points.'.format( state.winner()[0], state.winner()[1]), verbose) else: pr('Maximum turns exceed. No winner.', verbose) return state.winner() if state.finished() else None
def best_non_trump_card(state): """ :param state: A state object :return: A move tuple representing the highest rank non-trump move available """ # All legal moves moves = state.moves() chosen_move = moves[0] lowest_suit_moves = [] #Get all moves which are not trump suit or matching the suit of the enemy's card for move in moves: if move[0] is not None and util.get_suit( move[0]) != state.get_trump_suit(): lowest_suit_moves.append(move) if len(lowest_suit_moves) == 0: lowest_suit_moves = moves # Get move with highest rank available, of the subset that we've narrowed down so far for move in lowest_suit_moves: if move[0] is not None and move[0] % 5 <= chosen_move[0] % 5: chosen_move = move return chosen_move
def get_move(self, state): # type: (State) -> tuple[int, int] """ Function that gets called every turn. This is where to implement the strategies. Be sure to make a legal move. Illegal moves, like giving an index of a card you don't own or proposing an illegal mariage, will lose you the game. TODO: add some more explanation :param State state: An object representing the gamestate. This includes a link to the states of all the cards, the trick and the points. :return: A tuple of integers or a tuple of an integer and None, indicating a move; the first indicates the card played in the trick, the second a potential spouse. """ # All legal moves moves = state.moves() # Heuristic 1 - if possible, play a mariage. for move in moves: if move[0] != None and move[1] != None: # print('forcing a mariage {}'.format(move)) if util.get_suit(move[1]) == state.get_trump_suit(): return move else: return move # Heuristic 2 - if only 1 spouse in hand (and it's partner has not been played in the previous trick), # don't play it and keep it. Unless it's the only card in hand. # check if not the only card in hand prev_trick = state.get_prev_trick() if len(moves) > 1: for move in enumerate(moves): # remove single spouses (Kings and Queens) from moves if their partners were played in the previous trick. if move[1][0] in (2, 7, 12, 17): # test if King if prev_trick[0] not in (3, 8, 13, 18): pass # if card 1 from previous trick is not a queen, pass if prev_trick[1] not in (3, 8, 13, 18): pass # if card 2 from previous trick is not a queen, pass else: # spouse detected in previous trick, remove from moves. moves.pop(move[0]) # print('previous trick --> {}'.format(prev_trick)) # print( # 'removed move {}, single spouse detected.'.format(move[1])) elif move[1][0] in (3, 8, 13, 18): # test if queen if prev_trick[0] not in (2, 7, 12, 17): pass # if card 1 from previous trick is not a king, pass if prev_trick[1] not in (2, 7, 12, 17): pass # if card 2 from previous trick is not a king, pass else: # spouse detected in previous trick, remove from moves. moves.pop(move[0]) # print('previous trick --> {}'.format(prev_trick)) # print( # 'removed move {}, single spouse detected.'.format(move[1])) # Return a random choice return random.choice(moves)
def get_move(self, state): moves = state.moves() random.shuffle(moves) trumpexmoves = [] marriagemoves = [] othermoves = [] trumpmoves = [] for move in moves: if move[0] is None: trumpexmoves.append(move) elif move[1] is not None: marriagemoves.append(move) elif util.get_suit(move[0]) == state.get_trump_suit(): trumpmoves.append(move) else: othermoves.append(move) for move in trumpexmoves: if not self.kb_consistent_trumpex(state, move): # Plays the first move that makes the kb inconsistent. We do not take # into account that there might be other valid moves according to the strategy. # Uncomment the next line if you want to see that something happens. # print("Trump Strategy Applied") return move for move in marriagemoves: if not self.kb_consistent_marriage(state, move): # into account that there might be other valid moves according to the strategy. # Uncomment the next line if you want to see that something happens. # Plays the first move that makes the kb inconsistent. We do not take # print("Marriage Strategy Applied") return move if state.get_phase() == 1: if state.get_opponents_played_card() is None: if len(trumpmoves) != 0: return highest_value(trumpmoves) else: return highest_value(moves) else: for move in moves: if check_card(state, move): # print("HIGHEST SAME SUIT MOVE") return move # print("LOWEST VALUE MOVE") return lowest_value(moves) else: if len(trumpmoves) != 0: return highest_value(trumpmoves) else: return highest_value(moves)
def lowest_winning_move(moves, opponents_card): """Returns the lowest ranking card that wins current trick against the card the opponent has played. If not possible, returns the lowest ranking card in hand. Args: moves (list): List of moves to choose from opponents_card (int): Index of card that opponent has played Returns: tuple: Schnapsen move """ higher_same_suit = [] # possible moves that are higher rank and same suit as opponent's card for move in moves: if util.get_suit(move[0]) == util.get_suit(opponents_card) and move[0] % 5 < opponents_card % 5: higher_same_suit.append(move) if len(higher_same_suit) > 0: return lowest_rank_move(higher_same_suit) else: return lowest_rank_move(moves)
def playerHeuristic(): Bonus = 0 if state.winner()[1] == 3: Bonus += 3 elif state.winner()[1] == 2: Bonus += 1 elif state.winner()[1] == 1: Bonus += 0 if phase == 2: # If game enters to the phase 2 at some point more trump cards means more points for card in phaseEnterence.moves(): if card[0] != None and util.get_suit( card[0]) == state.get_trump_suit(): Bonus += 3 for card in state.moves( ): # And this is for ending the game with almost zero trumps in either case if card[0] != None and util.get_suit( card[0]) != state.get_trump_suit(): Bonus += 3 return 1 + Bonus if state.winner()[0] == self.player else 0
def play( player1, player2, state, # type: State max_time=5000, # type: int verbose=True # type: bool ): """ Play a game between two given players, from the given starting state. """ pr('player1: {}'.format(player1), verbose) pr('player2: {}'.format(player2), verbose) # The game loop while not state.finished(): player = player1 if state.whose_turn() == 1 else player2 # We introduce a state signature which essentially obscures the deck's perfect knowledge from the player given_state = state.clone( signature=state.whose_turn()) if state.get_phase() == 1 else state move = get_move(given_state, player, max_time, verbose) if is_valid(move, player): # check for common mistakes if move[0] is None: pr( '* Player {} performs a trump jack exchange'.format( state.whose_turn()), verbose) else: pr( '* Player {} plays: {}{}'.format(state.whose_turn(), util.get_rank(move[0]), util.get_suit(move[0])), verbose) if move[1] is not None: pr( '* Player {} melds a marriage between {}{} and {}{}'. format(state.whose_turn(), util.get_rank(move[0]), util.get_suit(move[0]), util.get_rank(move[1]), util.get_suit(move[1])), verbose) state = state.next(move) pr(state, verbose) if not state.revoked() is None: pr( '! Player {} revoked (made illegal move), game finished.' .format(state.revoked()), verbose) else: state.set_to_revoked() pr( 'Game finished. Player {} has won, receiving {} points.'.format( state.winner()[0], state.winner()[1]), verbose) return state.winner()
def is_trump(state, move): return util.get_suit(move) == state.get_trump_suit() if move is not None else "None move"
def is_trump(state, move): if util.get_suit(move) == state.get_trump_suit(): return True else: return False
def check_card(state, move): if util.get_suit(move[0]) == util.get_suit(state.get_opponents_played_card()): if move[0] % 5 < state.get_opponents_played_card() % 5: return True return False
def get_move(self, state): # type: (State) -> tuple[int, int] """ Function that gets called every turn. This is where to implement the strategies. Be sure to make a legal move. Illegal moves, like giving an index of a card you don't own or proposing an illegal mariage, will lose you the game. TODO: add some more explanation :param State state: An object representing the gamestate. This includes a link to the states of all the cards, the trick and the points. :return: A tuple of integers or a tuple of an integer and None, indicating a move; the first indicates the card played in the trick, the second a potential spouse. """ # All legal moves moves = state.moves() chosen_move = moves[0] moves_trump_suit = [] # Heuristic 1 - If we have the trump jack in our hand, pick the trump jack exchange # (this makes our lowest trump card not a jack and therfore higher rank) for move in moves: if move[0] == None and move[1] != None: if move[1] in (4, 9, 14, 19): # print('forcing trump jack exchange') return move # Heuristic 2 - if possible, play a mariage. for move in moves: if move[0] != None and move[1] != None: # print('forcing a mariage {}'.format(move)) if util.get_suit(move[1]) == state.get_trump_suit(): return move else: return move # Heuristic 3 - If the opponent plays ace (highest) trump card # We play the lowest ranking card in hand (so opponent receives minimum points) opponents_card = state.get_opponents_played_card() if opponents_card is not None: # test if opponents card is a trump suit ace if opponents_card % 5 == 0 and Deck.get_suit( opponents_card) == state.get_trump_suit(): # print('opponent played a trump suit ace - {}'.format(opponents_card)) # print('test - the trump suit is: {}'.format(state.get_trump_suit())) for index, move in enumerate(moves): if move[0] is not None and move[0] % 5 > chosen_move[0] % 5: # print('move {} is worth less then {}'.format( # move, chosen_move)) # print('playing move {}'.format(move)) chosen_move = move return chosen_move # Get all trump suit moves available for index, move in enumerate(moves): if move[0] is not None and Deck.get_suit( move[0]) == state.get_trump_suit(): moves_trump_suit.append(move) if len(moves_trump_suit) > 0: chosen_move = moves_trump_suit[0] return chosen_move # If the opponent has played a card/./. if state.get_opponents_played_card() is not None: moves_same_suit = [] # Get all moves of the same suit as the opponent's played card for index, move in enumerate(moves): if move[0] is not None and Deck.get_suit( move[0]) == Deck.get_suit( state.get_opponents_played_card()): moves_same_suit.append(move) if len(moves_same_suit) > 0: chosen_move = moves_same_suit[0] return chosen_move # Get move with highest rank available, of any suit for index, move in enumerate(moves): if move[0] is not None and move[0] % 5 <= chosen_move[0] % 5: chosen_move = move return chosen_move
def get_move(self, state): moves = state.moves() random.shuffle(moves) marriage_moves = [] trumpex_moves = [] other_moves = [] trump_moves = [] for move in moves: if move[0] is None: trumpex_moves.append(move) elif move[1] is not None: marriage_moves.append(move) elif is_trump(state, move[0]): trump_moves.append(move) else: other_moves.append(move) for move in trumpex_moves: if not self.kb_consistent(state, move, 0): # print("Trump Strategy Applied") return move for move in marriage_moves: if not self.kb_consistent(state, move, 1): # print("Marriage Strategy Applied") return move if state.get_phase() == 1: # print("phase 1") if state.get_opponents_played_card() is None: # print("phase 1, leading, play lowest non trump") return lowest_value(other_moves) else: # print("not leading") if is_trump(state, state.get_opponents_played_card()) is False and \ (state.get_opponents_played_card() % 5 == 0 or state.get_opponents_played_card() % 5 == 1): if len(trump_moves) != 0: # print("phase1, following, lowest trump card") return lowest_value(trump_moves) else: # print("phase 1, following, lowest non trump") return lowest_value(other_moves) elif is_trump(state, state.get_opponents_played_card()): # print("phase 1, following, lowest non trump") return lowest_value(other_moves) else: same_suit = [] for move in other_moves: if util.get_suit(move[0]) == util.get_suit( state.get_opponents_played_card()): same_suit.append(move) # print("phase 1, following, same suit highest") if len(same_suit) != 0: highest_same_suit = highest_value(same_suit) # print(highest_same_suit, state.get_opponents_played_card()) if highest_same_suit[ 0] % 5 < state.get_opponents_played_card() % 5: return highest_same_suit else: return lowest_value(other_moves) else: return lowest_value(other_moves) else: # print("phase 2") if state.get_opponents_played_card() is None: # print("leading") if len(trump_moves) != 0: # print("phase 2, leading, highest trump") return highest_value(trump_moves) else: # print("phase 2, leading, highest non-trump") return highest_value(other_moves) else: # print("following") if len(trump_moves) != 0: # print("phase 2, following, highest trump card") return highest_value(trump_moves) else: # print("phase 2, following, play random card") return random.choice(moves)