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. :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] # If it is the computers turn if state.get_opponents_played_card() is not None: case = [] # Store all cards of the same suit in an array for index, move in enumerate(moves): if move[0] is not None: if Deck.get_suit(move[0]) == Deck.get_suit(state.get_opponents_played_card()): case.append(move)
def __evaluate_trick(self, trick): """ Evaluates who the winner of the specified trick is and returns it :param trick: A tuple signifying the trick which is evaluated :return: The winner's id as an integer """ if len(trick) != 2: raise RuntimeError("Incorrect trick format. List of length 2 needed.") if trick[0] is None or trick[1] is None: raise RuntimeError("An incomplete trick was attempted to be evaluated.") # If the two cards of the trick have the same suit if Deck.get_suit(trick[0]) == Deck.get_suit(trick[1]): # We only compare indices since the convention we defined in Deck # puts higher rank cards at lower indices, when considering the same color. return 1 if trick[0] < trick[1] else 2 if Deck.get_suit(trick[0]) == self.__deck.get_trump_suit(): return 1 if Deck.get_suit(trick[1]) == self.__deck.get_trump_suit(): return 2 # If the control flow has reached this point, the trick consists of two # different non-trump cards. Since the new leader is determined by the # output of this function, at this point the state object still considers # it to be the non-leading player's turn. Thus, we determine that the winner # is the other player, i.e. the leading player. Thanks: Daan Raven return util.other(self.whose_turn())
def get_move(self, state): whose_turn = state.whose_turn() leader = state.leader() trump_suit = state.get_trump_suit() if whose_turn == leader: global kb moves = state.moves() # We look for a possible trump exchange for move in moves: if move[0] is None: return move # We look for a possible marriage for move in moves: if move[1] is not None: return move # We compare the bot's points with the threshold value and decide on playing hard. if state.get_points(whose_turn) >= 50: for move in moves: if Deck.get_suit(move[0]) == trump_suit: return move random.shuffle(moves) for move in moves: if not self.kb_consistent(state, move): # print "Strategy Applied" return move if random.randint(1, 2) == 1: # We play the highest possible card if none of the cards in hand is entailed by the KB chosen_move = moves[0] 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 else: # We play the lowest possible card if none of the cards in hand is entailed by the KB lowest_card, _ = moves[0] for move in moves: candidate_card, _ = move if candidate_card != None: if Deck.get_suit(candidate_card) != trump_suit: if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card if Deck.get_suit(lowest_card) == trump_suit: for move in moves: candidate_card, _ = move if candidate_card != None: if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card return (lowest_card, None) else: return self.returnMove(state)
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 = [] moves_trump_suit = [] # 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) #Get a card with higher rank than opponent and same suit as opponent if len(moves_same_suit) > 0: for index, move in enumerate(moves_same_suit): if move[0] is not None and move[0] % 5 < ( state.get_opponents_played_card() % 5): 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 # Get move with lowest 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): # 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] move_trump_suit = [] for index, move in enumerate(moves): if move[0] is not None and Deck.get_suit(move[0]) == state.get_trump_suit(): move_trump_suit.append(move) if len(move_trump_suit) > 0 : chosen_move = move_trump_suit[0] return chosen_move if state.get_opponents_played_card() is not None : move_same_suit = [] move_lowest = [] for index, move in enumerate(moves): if Deck.get_suit(move[0]) == Deck.get_suit(state.get_opponents_played_card()): if move[0] is not None and move[0] % 5 < state.get_opponents_played_card() % 5 : move_same_suit.append(move) elif move[0] is not None and move[0] % 5 > chosen_move[0] % 5: move_lowest.append(move) if len(move_same_suit) > 0 : chosen_move = move_same_suit[0] return chosen_move elif len(move_lowest) > 0 : chosen_move = move_lowest[0] return chosen_move for index, move in enumerate(moves): if move[0] is not None and move[0] % 5 <= chosen_move[0] % 5: chosen_move = move # Return a random choice return chosen_move
def how_many_card_can_beat_it(state, myList, card) -> int: # see how many trump cards exist that are better cardsThatCanBeatMyCard = 0 for ints in myList: ints = int(ints) # print(ints,card[0]) if (ints % 5 < card[0] % 5) or \ (Deck.get_suit(card[0]) != state.get_trump_suit() and Deck.get_suit(ints) == state.get_trump_suit()): cardsThatCanBeatMyCard += 1 return cardsThatCanBeatMyCard
def returnMove(self, state): moves = state.moves() trump_suit = state.get_trump_suit() played_card = state.get_opponents_played_card() # If we are past the threshold, reply to a trump with highest trump, else trump with lowest trump if Deck.get_suit( played_card) == trump_suit: # Check if played card is trump for move in moves: candidate_card, _ = move if candidate_card != None: if Deck.get_suit( candidate_card ) == trump_suit: # Still not checking for the lowest possible trump card if candidate_card % 5 < played_card % 5: return (candidate_card, None) lowest_card, _ = moves[0] for move in moves: candidate_card, _ = move if candidate_card != None: if Deck.get_suit( candidate_card ) != trump_suit: # Logic will still give exception if nothing is present other than trump cards, which is absurd, because that is not possible (think about it) if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card return (lowest_card, None) for move in moves: # Else try to find a stronger card of same suit candidate_card, _ = move if candidate_card != None: if Deck.get_suit(candidate_card) == Deck.get_suit(played_card): if candidate_card % 5 < played_card % 5: return (candidate_card, None) for move in moves: # Else try to find a a card from trump suit candidate_card, _ = move if candidate_card != None: if Deck.get_suit(candidate_card) == trump_suit: return (candidate_card, None) lowest_card, _ = moves[0] for move in moves: # By this position, losing the trick is certain, so we try and find the lowest card candidate_card, _ = move if candidate_card != None: if Deck.get_suit(candidate_card) != trump_suit: if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card if Deck.get_suit(lowest_card) == trump_suit: for move in moves: candidate_card, _ = move if candidate_card != None: if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card return (lowest_card, None)
def get_trump_moves(state, moves): trump_moves = [] for move in moves: if move[0] is not None and Deck.get_suit( move[0]) == state.get_trump_suit(): trump_moves.append(move) return trump_moves
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() for move in moves: if move[0] != None and move[1] != None: return move elif state.get_opponents_played_card(): if state.get_opponents_played_card( ) % 5 == 1 or state.get_opponents_played_card() % 5 == 0: if Deck.get_suit(move[0]) == state.get_trump_suit(): return move #Trump exchange elif move[0] == None and move[1] != None: return move return moves[0]
def get_suit(card_index): """ Returns the suit of a card :param card_index: :return: """ return Deck.get_suit(card_index)
def eval_points(opponents_card, move): if opponents_card is None or move is None: raise RuntimeError( "An incomplete trick was attempted to be evaluated.") # If the two cards of the trick have the same suit if Deck.get_suit(opponents_card[0]) == Deck.get_suit(move[0]): # We only compare indices since the convention we defined in Deck # puts higher rank cards at lower indices, when considering the same color. return 1 if opponents_card < move else 2 if Deck.get_suit(opponents_card[0]) == self.__deck.get_trump_suit(): return 1 if Deck.get_suit(move[0]) == self.__deck.get_trump_suit(): return 2
def getTrumpMoves(self, state, moves): new_moves = copy.deepcopy(moves) trump_suit = state.get_trump_suit() for move in new_moves: card, _ = move if Deck.get_suit(card) != trump_suit: new_moves.remove(move) return new_moves
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() # starting with a random move chosen_move = random.choice(moves) # List of all legal moves, not being of a trump suit not_trump_suit = [] # Which player this bot is player = state.whose_turn() leader = state.leader # If a mariage or jack exchange is possible, play it for index, move in enumerate(moves): if move[1] != None: return move # Get all not trump suit moves for index, move in enumerate(moves): if move[0] is not None and Deck.get_suit( move[0]) != state.get_trump_suit(): not_trump_suit.append(move) # starting with a random move if len(not_trump_suit) > 0: chosen_move = random.choice(not_trump_suit) # play the highest not trump cards first if len(not_trump_suit ) > 0 and player == leader and not_trump_suit != []: for index, move in enumerate(not_trump_suit): if move[0] is not None and move[0] % 5 <= chosen_move % 5: chosen_move = move return chosen_move # if player != leader: # played_card = state.get_opponents_played_card() # suit_of_card = Deck.get_suit(played_card) # for index, move in enumerate(moves): # if move[0] is not None and Deck.get_suit(move[0]) return chosen_move
def checkForMarriage(self, state): position = None moves = state.moves() chosen_suit = [] trumpSuit = state.get_trump_suit() queens = [] kings = [] # Get all queens and kings from the possible moves for index, move in enumerate(moves): if moves[index][0] is not None and Deck.get_rank( moves[index][0]) == "Q": queens.append(move[0]) elif moves[index][0] is not None and Deck.get_rank( moves[index][0]) == "K": kings.append(move[0]) isLooping = True if len(queens) and len(kings) > 0: for index, move in enumerate(queens): for index2, move2 in enumerate(kings): # if a Queen and a King of same suit has been found return the suit of that Queen # also first prioritize the Royal Marriage if Deck.get_suit(queens[index]) == Deck.get_suit(kings[index2]) \ and Deck.get_suit(queens[index]) == trumpSuit: chosen_suit = Deck.get_suit(queens[index]) # variable used to break out of a nested loop isLooping = False break elif Deck.get_suit(queens[index]) == Deck.get_suit( kings[index2]): chosen_suit = Deck.get_suit(queens[index]) isLooping = False break if isLooping == False: break # if such a Marriage exists in the possible moves return the index of that Queen for index, move in enumerate(moves): if moves[index][0] is not None \ and Deck.get_suit(moves[index][0]) == chosen_suit \ and Deck.get_rank(moves[index][0]) == "Q": position = index return position
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] if state.get_phase() == 2: chosen_move = moves[len(moves) - 1] # 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) # Play the cheapest card in phase two if you cant beat the trick, else play the highest card if len(moves_same_suit) > 0: if state.get_phase() == 2 and ( state.get_opponents_played_card() % 5 < moves_same_suit[0][0]): return moves_same_suit[len(moves_same_suit) - 1] chosen_move = moves_same_suit[0] return chosen_move return chosen_move
def kb_consistent_matching_win(self, state, move): # type: (State,move) -> bool kb = KB() load_justabout.general_information(kb) load_justabout.strategy_knowledge(kb) opp_card = state.get_opponents_played_card() opp_card_suit = Deck.get_suit(opp_card) opp_card_rank = opp_card % 5 p_card = move[0] p_card_suit = Deck.get_suit(p_card) p_card_rank = opp_card % 5 variable_string = "wt" + str(p_card_rank) + str(opp_card_rank) + str(p_card_suit) + str(opp_card_suit) strategy_variable = Boolean(variable_string) kb.add_clause(~strategy_variable) return kb.satisfiable()
def kb_consistent_trump_win(self,state,move): # type: (State,move) -> bool kb = KB() load_justabout.general_information(kb) load_justabout.strategy_knowledge(kb) opp_card = state.get_opponents_played_card() opp_card_suit = Deck.get_suit(opp_card) opp_card_rank = opp_card & 5 p_card = move[0] p_card_suit = Deck.get_suit(p_card) p_card_rank = p_card % 5 trump_suit = state.get_trump_suit() constraint_a = Integer('me') > Integer('op') constraint_b = Integer('op') > Integer('me') if opp_card_suit == trump_suit: if p_card_suit == trump_suit: if opp_card_rank < p_card_rank: strategy_variable = constraint_b else: strategy_variable = constraint_a else: strategy_variable = constraint_b else: variable_string = "wtt" + str(p_card_suit) + str(trump_suit) strategy_variable = Boolean(variable_string) kb.add_clause(~strategy_variable) return kb.satisfiable()
def get_move(self, state): moves_trump_suit = [] if random.random() < self.__non_trump_move: # IMPLEMENT: Make the best non-trump move you can. Use the best_non_trump_card method written below. # bully bot moves = state.moves() chosen_move = moves[0] # take the 1st available #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) # find all cards same suit if len(moves_trump_suit) > 0: chosen_move = moves_trump_suit[0] # choose the 1st trump-suit card return chosen_move # No trump suit moves available: # # 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 #IMPLEMENT: Make a random move (but exclude the best non-trump move from above) moves_none_trump = list(set(state.moves()) - set(moves_trump_suit)) # Return a random choice return random.choice(moves_none_trump)
def check_marriage(self, state, moves): possible_marriages = [] for index in moves: if index[0] is not None and index[1] is not None: possible_marriages.append(index) # Check for royal marriages if possible_marriages: possible_royal_marriages = [] for index in possible_marriages: if Deck.get_suit(index[0]) == state.get_trump_suit(): possible_royal_marriages.append(index) return possible_royal_marriages return possible_marriages
def get_number_trumps_or_ace(state, Deck): moves = state.moves() util_point = 0 for move in moves: if move[0] is not None and Deck.get_suit( move[0]) == state.get_trump_suit(): util_point += 1 if move[0] is not None and move[0] % 5 == 0: util_point += 1 return util_point / len(moves)
def kb_consistent(self, state, move): # type: (State, move) -> bool index = move[0] if (Deck.get_suit(index) == state.get_trump_suit()): return True kb = self.prepareKB(state) load.strategy_knowledge(kb) variable_string = "pc" + str(index) strategy_variable = Boolean(variable_string) kb.add_clause(~strategy_variable) return kb.satisfiable()
def findLowestCardOfSameSuit(self, state): lowestRank = None position = None # All possible moves moves = state.moves() # Opponents card suit opponentsCardSuit = Deck.get_suit(state.get_opponents_played_card()) moves_suit = [] # Get all the moves available with the same suit as opponent's played card suit for index, move in enumerate(moves): if moves[index][0] is not None and Deck.get_suit( moves[index][0]) == opponentsCardSuit: moves_suit.append(move) # Check your hand for same suit cards as opponent # If opponent's card rank is '10' check for lowest value card which is 'J' if len(moves_suit) > 0: for index, move in enumerate(moves_suit): if Deck.get_rank(moves_suit[index][0]) == "J" \ and Deck.get_suit(moves_suit[index][0]) == opponentsCardSuit: lowestRank = "J" break # otherwise check for the next lowest value which is 'Q' elif Deck.get_rank(moves_suit[index][0]) == "Q" \ and Deck.get_suit(moves_suit[index][0]) == opponentsCardSuit: lowestRank = "Q" # and so forth elif Deck.get_rank(moves_suit[index][0]) == "K" \ and Deck.get_suit(moves_suit[index][0]) == opponentsCardSuit \ and lowestRank != "Q": lowestRank = "K" # also this function will not play high value cards like '10' and 'A' # becaues in our strategy we are saving the high value card for future # possible cases when we could win the hand # If there is such a card with a smaller value than the opponent's # played card and of the same suit, return the index for index, move in enumerate(moves): if Deck.get_rank(moves[index][0]) == lowestRank \ and Deck.get_suit(moves[index][0]) == opponentsCardSuit: position = index break return position
def kb_trump(self, state, move): # type: (State,move) -> bool kb = KB() load.general_information(kb) load.strategy_knowledge(kb) p_card = move[0] p_card_suit = Deck.get_suit(p_card) trump_suit = state.get_trump_suit() variable_string = "wtt" + str(p_card_suit) + str(trump_suit) strategy_variable = Boolean(variable_string) kb.add_clause(~strategy_variable) return kb.satisfiable()
def get_move(self, state): moves = state.moves() random.shuffle(moves) for move in moves: if not self.kb_consistent(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 "Strategy Applied" print(str(Deck.get_rank(move[0]) + Deck.get_suit(move[0])), " has been played") #str(Deck.get_rank(move[0]) + Deck.get_suit(move[0])) return move # If no move that is entailed by the kb is found, play random move return random.choice(moves)
def get_move(self, state): whose_turn = state.whose_turn() leader = state.leader() trump_suit = state.get_trump_suit() if whose_turn == leader: global kb moves = state.moves() # We look for a possible trump exchange for move in moves: if move[0] is None: return move # We look for a possible marriage for move in moves: if move[1] is not None: # print("+1") return move # If we are in stage 2, we give priority to playing Aces if state.get_phase() == 2: # We try to return a non-trump Ace for move in moves: if move[0] % 5 == 0 and Deck.get_suit( move[0]) != trump_suit: return move # We try to return any Ace for move in moves: if move[0] % 5 == 0: return move moves = self.saveMarriage(state) # We compare the bot's points with the threshold value and decide on playing hard. if state.get_points(whose_turn) >= 50: for move in moves: if Deck.get_suit(move[0]) == trump_suit: return move random.shuffle(moves) for move in moves: if not self.kb_consistent(state, move): # print "Strategy Applied" return move if random.randint(1, 2) == 1: # We play the highest possible card if none of the cards in hand is entailed by the KB highest_card, _ = moves[0] for move in moves: candidate_card, _ = move if candidate_card != None: if Deck.get_suit(candidate_card) != trump_suit: if candidate_card % 5 < highest_card % 5: highest_card = candidate_card if Deck.get_suit(highest_card) == trump_suit: for move in moves: candidate_card, _ = move if candidate_card != None: if candidate_card % 5 < highest_card % 5: highest_card = candidate_card return (highest_card, None) else: # We play the lowest possible card if none of the cards in hand is entailed by the KB lowest_card, _ = moves[0] for move in moves: candidate_card, _ = move if candidate_card != None: if Deck.get_suit(candidate_card) != trump_suit: if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card if Deck.get_suit(lowest_card) == trump_suit: for move in moves: candidate_card, _ = move if candidate_card != None: if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card return (lowest_card, None) else: return self.returnMove(state)
def isTrump(self, state, card): if Deck.get_suit(card) == state.get_trump_suit(): return True else: return False
def returnMove(self, state): moves = self.saveMarriage(state) trump_suit = state.get_trump_suit() played_card = state.get_opponents_played_card() if Deck.get_suit( played_card) == trump_suit: # Check if played card is trump for move in moves: candidate_card, _ = move if candidate_card != None: if Deck.get_suit( candidate_card ) == trump_suit: # Still not checking for the lowest possible trump card if candidate_card % 5 < played_card % 5: return (candidate_card, None) lowest_card, _ = moves[0] for move in moves: candidate_card, _ = move if candidate_card != None: if Deck.get_suit( candidate_card ) != trump_suit: # Logic will still give exception if nothing is present other than trump cards, which is absurd, because that is not possible (think about it) if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card return (lowest_card, None) for move in moves: # Else try to find a stronger card of same suit candidate_card, _ = move if candidate_card != None: if Deck.get_suit(candidate_card) == Deck.get_suit(played_card): if candidate_card % 5 < played_card % 5: return (candidate_card, None) # for move in moves: # Else try to find a a card from trump suit # candidate_card, _ = move # if candidate_card != None: # if Deck.get_suit(candidate_card) == trump_suit: # return (candidate_card, None) if self.getDifference(state) < THRESHOLD: trump_moves = self.getTrumpMoves(state, moves) if trump_moves: if self.isLow(played_card): lowest_card, _ = trump_moves[0] for move in trump_moves: # Else try to find a a card from trump suit candidate_card, _ = move if self.isLow(candidate_card) is True: if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card if self.isLow(lowest_card) is True: return lowest_card, _ else: if self.isHigh(played_card): highest_card, _ = trump_moves[0] for move in trump_moves: # Else try to find a a card from trump suit candidate_card, _ = move if self.isHigh(candidate_card) is True: if candidate_card % 5 < highest_card % 5: highest_card = candidate_card if self.isHigh(highest_card) is True: return highest_card, _ else: trump_moves = self.getTrumpMoves(state, moves) if trump_moves: highest_card, _ = trump_moves[0] for move in trump_moves: # Else try to find a a card from trump suit candidate_card, _ = move if candidate_card % 5 < highest_card % 5: highest_card = candidate_card return highest_card, _ lowest_card, _ = moves[0] for move in moves: # By this position, losing the trick is certain, so we try and find the lowest card candidate_card, _ = move if candidate_card != None: if Deck.get_suit(candidate_card) != trump_suit: if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card if Deck.get_suit(lowest_card) == trump_suit: for move in moves: candidate_card, _ = move if candidate_card != None: if candidate_card % 5 > lowest_card % 5: lowest_card = candidate_card return (lowest_card, None)
def findLowestPointsCardThatIsNotTrump(self, state): moves = state.moves() smallestRank = None possibleRanks = ["A", "10", "K", "Q", "J"] position = None trumpSuit = state.get_trump_suit() moves_not_trump_suit = [] # Get all trump suit moves available for index, move in enumerate(moves): if moves[index][0] is not None and Deck.get_suit( moves[index][0]) != trumpSuit: moves_not_trump_suit.append(move[0]) if len(moves_not_trump_suit) > 0: for index, move in enumerate(moves_not_trump_suit): # Iterate through all the possible moves, and # find the lowest value card in your hand that is also not a trump # Check whether 'J' is in your hand, if so play the card if Deck.get_rank( moves_not_trump_suit[index]) == possibleRanks[4]: smallestRank = possibleRanks[4] break # Otherwise check for a Queen, and keep on checking maybe the Jack will be found later elif Deck.get_rank( moves_not_trump_suit[index]) == possibleRanks[3]: smallestRank = possibleRanks[3] # and so forth elif Deck.get_rank(moves_not_trump_suit[index]) == possibleRanks[2] \ and smallestRank != possibleRanks[4] \ and smallestRank != possibleRanks[3]: smallestRank = possibleRanks[2] elif Deck.get_rank(moves_not_trump_suit[index]) == possibleRanks[1] \ and smallestRank != possibleRanks[4] \ and smallestRank != possibleRanks[3] \ and smallestRank != possibleRanks[2]: smallestRank = possibleRanks[1] elif Deck.get_rank(moves_not_trump_suit[index]) == possibleRanks[0] \ and smallestRank != possibleRanks[4] \ and smallestRank != possibleRanks[3] \ and smallestRank != possibleRanks[2] \ and smallestRank != possibleRanks[1]: smallestRank = possibleRanks[0] # Return the index of the smallest value card from all the possible moves that is also not a trump suit # if such a card is found return it's index otherwise return None for index, move in enumerate(moves): if moves[index][0] is not None and Deck.get_rank(moves[index][0]) == smallestRank \ and Deck.get_suit(moves[index][0]) != trumpSuit: position = index return position
def moves(self): """ :return: A list of all the legal moves that can be made by the player whose turn it is. A move is a tuple of length 2. There are 3 distinct cases: - (int, None): first element indicates the index of the card that is placed down. - (int, int) : first element as above, second element completes a marriage - (None, int): First element being None indicates a trump jack exchange, second element is the index of that trump jack """ hand = self.hand() if self.__signature is not None and len(hand) == 0: raise RuntimeError("\n\nGame is in phase 1. Insufficient information to derive any of the opponent's possible moves. Try to make an assumption\n") possible_moves = [] # In this case, no constraints are put on the move if self.__phase == 1 or self.whose_turn() == self.leader(): for card in hand: possible_moves.append((card, None)) # If the game is in phase 2 and it's not the leader's turn, then some constraints apply else: opponent_card = self.get_opponents_played_card() same_suit_hand = [card for card in hand if Deck.get_suit(card) == Deck.get_suit(opponent_card)] playable_cards = None if len(same_suit_hand) > 0: same_suit_hand_higher = [card for card in same_suit_hand if card < opponent_card] if len(same_suit_hand_higher) > 0: playable_cards = same_suit_hand_higher else: playable_cards = same_suit_hand elif Deck.get_suit(opponent_card) != self.__deck.get_trump_suit(): trump_hand = [card for card in hand if Deck.get_suit(card) == self.__deck.get_trump_suit()] if len(trump_hand) > 0: playable_cards = trump_hand else: playable_cards = hand else: playable_cards = hand possible_moves = [(card, None) for card in playable_cards] #Add possible trump jack exchanges and mariages to moves #Marriages and exchanges can only be made by the leading player if self.whose_turn() == self.leader(): if self.__deck.can_exchange(self.whose_turn()): possible_moves.append((None, self.__deck.get_trump_jack_index())) possible_mariages = self.__deck.get_possible_mariages(self.whose_turn()) possible_moves += possible_mariages return possible_moves
def next(self, move # type: tuple(int, int) ): """ Computes the next state based on the given move :param move: Tuple of length 2 of which each element can either be an int or None :return: Newly computed state based on current state and given move """ if self.__signature is not None and self.__signature != self.whose_turn(): raise RuntimeError('\n\nGame is in phase 1. Cannot view next state with imperfect information. Try making an assumption first.\n') if self.finished(): raise RuntimeError('Gamestate is finished. No next states exist.') # Start with a copy of the current state state = self.clone() # type: State # If we find an invalid move, we set the __revoked class variable # To the pid of the player who made the incorrect move, and return the state as is. if not state.__is_valid(move): state.__revoked = state.whose_turn() return state # If move is a trump exchange if move[0] is None: # Store the indices we need in variables trump_jack_index = move[1] trump_card_index = state.__deck.get_trump_card_index() # Perform trump jack exchange, perspective updated in function state.__exchange_trump(trump_jack_index) return state # Change turns state.__leads_turn = not state.__leads_turn #Add the given move to the trick, store the whole trick in a variable trick = state.__deck.set_trick(state.whose_turn(), move[0]) # At this point, we know that the move is not a trump jack exchange. # Check if this move is a marriage if move[1] is not None: # A marriage cannot be melded by the non-leading player if state.__leads_turn: raise RuntimeError("Marriage was attempted to be melded by non-leading player") # Update perspective since an additional card is revealed by the player who performs a marriage. state.__deck.add_to_perspective(util.other(state.whose_turn()), move[1], "P" + str(state.whose_turn()) + "H") # Trump suit marriage yields 40 points, regular yields 20, to be awarded at next trick win. if Deck.get_suit(move[1]) == state.__deck.get_trump_suit(): state.__reserve_pending_points(state.whose_turn(), 40) else: state.__reserve_pending_points(state.whose_turn(), 20) # If it is not the lead's turn, i.e. currently the trick is # incomplete and we already know it's not a trump jack exchange if not state.__leads_turn: other = state.whose_turn() state.__player1s_turn = not state.__player1s_turn state.__deck.add_to_perspective(state.whose_turn(), trick[other-1], "P" + str(other) + "H") return state # At this point we know that it is the lead's turn and that a complete # trick from the previous hand can be evaluated. # Evaluate the trick and store the winner in the leader variable leader = state.__evaluate_trick(trick) state.__allocate_trick_points(leader, trick) state.__deck.put_trick_away(leader) if state.__phase == 2 and len(state.hand()) == 0 and not state.finished(): # If all cards are exhausted, the winner of the last trick wins the game state.__set_points(leader, 66) #Draw cards from stock if state.__phase == 1: state.__deck.draw_card(leader) state.__deck.draw_card(util.other(leader)) if state.__deck.get_stock_size() == 0: state.__phase = 2 # Set player1s_turn according to the leader variable state.__player1s_turn = True if leader == 1 else False # Returns state return state