def _get_triple_moves(self): moves = [] for core_card in self._cards: if self._cards[core_card] >= 3: hand_without_triple = self.remove(Counter({core_card: 3})) # no kickers moves.append( SpecificMove(RankedMoveType(MoveType.TRIPLE, core_card), Counter({core_card: 3}))) # look for single kickers for move in hand_without_triple._get_single_moves(): # kicker isn't the same as the core kicker = move.rank() if kicker != core_card: moves.append( SpecificMove( RankedMoveType(MoveType.TRIPLE_SINGLE_KICKER, core_card), Counter({ core_card: 3, kicker: 1 }))) for move in hand_without_triple._get_pair_moves(): kicker = move.rank() if kicker != core_card: moves.append( SpecificMove( RankedMoveType(MoveType.TRIPLE_PAIR_KICKER, core_card), Counter({ core_card: 3, kicker: 2 }))) return moves
def _get_quad_moves(self): moves = [] for core_card in self._cards: if self._cards[core_card] == 4: hand_without_core = self.remove(Counter({core_card: 4})) # just as bomb moves.append( SpecificMove(RankedMoveType(MoveType.BOMB, core_card), Counter({core_card: 4}))) # two single kickers for kicker1, kicker2 in hand_without_core._get_two_kickers(): moves.append( SpecificMove( RankedMoveType(MoveType.QUAD_SINGLE_KICKERS, core_card), Counter({ core_card: 4, kicker1: 1, kicker2: 1 }))) for kicker1, kicker2 in hand_without_core._get_two_kickers( kicker_n=2): moves.append( SpecificMove( RankedMoveType(MoveType.QUAD_SINGLE_KICKERS, core_card), Counter({ core_card: 4, kicker1: 2, kicker2: 2 }))) return moves
def _get_airplanes(self): # checking only 2-consecutive moves = [] for i, card in enumerate(LandlordDeck.NORMAL_CARD_TYPES): if self._cards[card] >= 3 and card.next( ) is not None and self._cards[card.next()] >= 3: airplane_cards = Counter({card: 3, card.next(): 3}) hand_without_core = self.remove(airplane_cards) for kicker1, kicker2 in hand_without_core._get_two_kickers(): specific_cards = airplane_cards + Counter({ kicker1: 1, kicker2: 1 }) moves.append( SpecificMove( RankedMoveType(MoveType.AIRPLANE_SINGLE_KICKER, card.next()), specific_cards)) for kicker1, kicker2 in hand_without_core._get_two_kickers( kicker_n=2): specific_cards = airplane_cards + Counter({ kicker1: 2, kicker2: 2 }) moves.append( SpecificMove( RankedMoveType(MoveType.AIRPLANE_PAIR_KICKER, card.next()), specific_cards)) return moves
def _get_single_moves(self): moves = [] for card in self._cards: moves.append( SpecificMove(RankedMoveType(MoveType.SINGLE, card), Counter({card: 1}))) return moves
def test_setup(self): players = [LearningPlayer('v1', None)] * 3 game = LandlordGame(players=players) hands = { TurnPosition.FIRST: [Card.ACE] * 4 + [Card.KING] * 4 + [Card.QUEEN] * 4 + [Card.JACK] * 4 + [Card.THREE], TurnPosition.SECOND: [Card.TEN] * 4 + [Card.NINE] * 4 + [Card.EIGHT] * 4 + [Card.SEVEN] * 4 + [Card.THREE], TurnPosition.THIRD: [Card.FIVE] * 4 + [Card.FOUR] * 4 + [Card.SIX] * 4 + [Card.TWO] * 4 + [Card.THREE] * 2 + [Card.LITTLE_JOKER] + [Card.BIG_JOKER] } game._betting_complete = True game.force_setup(TurnPosition.THIRD, hands, 2) self.assertTrue(game.get_current_position() == TurnPosition.THIRD) game.play_move(None) self.assertTrue( game.get_current_position() == TurnPosition.THIRD.next()) self.assertTrue(len(game.get_move_logs()) == 1) self.assertTrue(game.get_move_logs()[0][1] is None) game.play_move( SpecificMove(RankedMoveType(MoveType.BOMB, Card.KING), cards=Counter({Card.KING: 4}))) self.assertTrue(game.get_current_position() == TurnPosition.SECOND) feature_matrix = players[1]._derive_features(game) self.assertTrue(feature_matrix[0][-6] == 1) self.assertTrue(feature_matrix[0][-2] == 1) self.assertTrue(feature_matrix[1][10] == 4) self.assertTrue(np.sum(feature_matrix) == 7)
def test_hand_vector_v2(self): players = [ LearningPlayer_v2(name='random', estimation_mode=LearningPlayer.ACTUAL_Q) for _ in range(3) ] game = LandlordGame(players=players) hands = { TurnPosition.FIRST: [Card.ACE] * 4, TurnPosition.SECOND: [Card.TEN] * 3 + [Card.THREE], TurnPosition.THIRD: [Card.FIVE] * 3 + [Card.THREE] + [Card.FOUR] } game._betting_complete = True game.force_setup(TurnPosition.SECOND, hands, 3) best_move = SpecificMove(RankedMoveType(MoveType.TRIPLE_SINGLE_KICKER, Card.TEN), cards=Counter({ Card.TEN: 3, Card.THREE: 1 })) move_vector = players[1].compute_move_vector( TurnPosition.SECOND, game.get_landlord_position(), best_move) remaining_hand_vector = players[1].compute_remaining_hand_vector( game, move_vector, TurnPosition.SECOND)[:-3] self.assertEqual(np.sum(remaining_hand_vector), 0)
def _get_pair_moves(self): moves = [] for card in self._cards: if self._cards[card] >= 2: moves.append( SpecificMove(RankedMoveType(MoveType.PAIR, card), Counter({card: 2}))) return moves
def test_landlord_game_ending(self): players = [LearningPlayer('v1')] * 3 game = LandlordGame(players=players) hands = { TurnPosition.FIRST: [Card.ACE] * 4, TurnPosition.SECOND: [Card.TEN] * 4, TurnPosition.THIRD: [Card.FIVE] * 4 } game._betting_complete = True game.force_setup(TurnPosition.THIRD, hands, 2) self.assertTrue( game.move_ends_game( SpecificMove(RankedMoveType(MoveType.BOMB, Card.FIVE), Counter({Card.FIVE: 4})))) self.assertFalse( game.move_ends_game( SpecificMove(RankedMoveType(MoveType.BOMB, Card.TEN), Counter({Card.TEN: 4}))))
def test_human(self): human = HumanPlayer(name='human') self.assertTrue( human.parse_input('nine nine nine six six'), SpecificMove(RankedMoveType(MoveType.TRIPLE_PAIR_KICKER, Card.NINE), cards=Counter({ Card.NINE: 3, Card.SIX: 2 }))) self.assertRaises(TypoError, human.parse_input, 'ni') self.assertRaises(InvalidMoveError, human.parse_input, 'nine 10')
def _get_special_moves(self): # rocket moves = [] if self._cards[Card.LITTLE_JOKER] == 1 and self._cards[ Card.BIG_JOKER] == 1: moves.append( SpecificMove( RankedMoveType(MoveType.BOMB, Card.BIG_JOKER), Counter({ Card.LITTLE_JOKER: 1, Card.BIG_JOKER: 1 }))) return moves
def test_landlord_bombing(self): players = [LearningPlayer('v1')] * 3 game = LandlordGame(players=players) hands = { TurnPosition.FIRST: [Card.ACE] * 4 + [Card.THREE], TurnPosition.SECOND: [Card.TEN] * 4 + [Card.THREE], TurnPosition.THIRD: [Card.FIVE] * 4 + [Card.THREE] } game._betting_complete = True game.force_setup(TurnPosition.THIRD, hands, 2) game.play_move( SpecificMove(RankedMoveType(MoveType.BOMB, Card.FIVE), Counter({Card.FIVE: 4}))) self.assertTrue(game._bet_amount == 4)
def test_sweep(self): players = [LearningPlayer('v1')] * 3 game = LandlordGame(players=players) hands = { TurnPosition.FIRST: [Card.ACE] * LandlordGame.DEAL_SIZE, TurnPosition.SECOND: [Card.TEN] * LandlordGame.DEAL_SIZE, TurnPosition.THIRD: [Card.FIVE] * 4 } game._betting_complete = True game.force_setup(TurnPosition.THIRD, hands, 2) game.play_move( SpecificMove(RankedMoveType(MoveType.BOMB, Card.FIVE), Counter({Card.FIVE: 4}))) self.assertTrue(game.peasants_have_no_plays()) self.assertTrue(game.get_scores()[TurnPosition.THIRD] == 2 * 2 * 2 * LandlordGame.SWEEP_MULTIPLIER) self.assertEqual(game.get_r(), 24) self.assertEqual(game.get_winbased_r(), 1)
def test_player_move(self): players = [LearningPlayer(name='random')] * 3 game = LandlordGame(players=players) hands = { TurnPosition.FIRST: [Card.ACE] * 4 + [Card.KING] * 4 + [Card.QUEEN] * 4 + [Card.JACK] * 4 + [Card.THREE], TurnPosition.SECOND: [Card.TEN] * 4 + [Card.NINE] * 4 + [Card.EIGHT] * 4 + [Card.SEVEN] * 4 + [Card.THREE], TurnPosition.THIRD: [Card.FIVE] * 4 + [Card.FOUR] * 4 + [Card.SIX] * 4 + [Card.TWO] * 4 + [Card.THREE] * 2 + [Card.LITTLE_JOKER] + [Card.BIG_JOKER] } game._betting_complete = True game.force_setup(TurnPosition.THIRD, hands, 3) game2 = copy(game) game.play_move( SpecificMove(RankedMoveType(MoveType.BOMB, Card.FIVE), Counter({Card.FIVE: 4}))) self.assertNotEqual(game2.get_hand(TurnPosition.THIRD), game.get_hand(TurnPosition.THIRD))
def _get_straights_from(self, card, num_cards=1): consecutives_required = 5 if num_cards == 1 else 3 moves = [] consecutive = 1 cards_included = Counter({card: num_cards}) while card.next() is not None: if self._cards[card.next()] >= num_cards: consecutive += 1 cards_included[card.next()] = num_cards card = card.next() else: break if consecutive >= consecutives_required: assert (len(cards_included) == consecutive) moves.append( SpecificMove( RankedMoveType( MoveType.get_straight_of_length( consecutive, num_cards), card), cards_included.copy())) return moves
def test_betting(self): players = [LearningPlayer('v1')] * 3 game = LandlordGame(players=players) game.force_current_position(TurnPosition.SECOND) game.force_kitty([Card.LITTLE_JOKER, Card.BIG_JOKER, Card.THREE]) game._make_bet_move(BetMove(2)) game._make_bet_move(None) self.assertEqual(game.get_last_played(), BetMove(2)) game._make_bet_move(BetMove(3)) hands = { TurnPosition.FIRST: [Card.ACE] * 4 + [Card.KING] * 4 + [Card.QUEEN] * 4 + [Card.JACK] * 4 + [Card.THREE], TurnPosition.SECOND: [Card.TEN] * 4 + [Card.NINE] * 4 + [Card.EIGHT] * 4 + [Card.SEVEN] * 4 + [Card.THREE], TurnPosition.THIRD: [Card.FIVE] * 4 + [Card.FOUR] * 4 + [Card.SIX] * 4 + [Card.TWO] * 4 + [Card.THREE] * 1 } game.force_setup(TurnPosition.FIRST, hands, 2) game.play_move( SpecificMove(RankedMoveType(MoveType.BOMB, Card.ACE), cards=Counter({Card.ACE: 4}))) feature_matrix = players[1]._derive_features(game) self.assertTrue(feature_matrix[0][-3] == 2) self.assertTrue(np.sum(players[1]._derive_features(game)) == 16)
def test_move(self): self.assertTrue( RankedMoveType(MoveType.CHAIN_PAIR_4, Card.KING).beats( RankedMoveType(MoveType.CHAIN_PAIR_4, Card.QUEEN))) self.assertFalse( RankedMoveType(MoveType.BOMB, Card.KING).beats( RankedMoveType(MoveType.BOMB, Card.BIG_JOKER))) self.assertTrue( RankedMoveType(MoveType.BOMB, Card.THREE).beats( RankedMoveType(MoveType.TRIPLE_PAIR_KICKER, Card.FIVE))) self.assertTrue( RankedMoveType(MoveType.PAIR, Card.ACE).beats( RankedMoveType(MoveType.PAIR, Card.JACK))) self.assertFalse( RankedMoveType(MoveType.PAIR, Card.ACE).beats( RankedMoveType(MoveType.PAIR, Card.ACE))) self.assertFalse( RankedMoveType(MoveType.TRIPLE_PAIR_KICKER, Card.FOUR).beats( RankedMoveType(MoveType.TRIPLE_SINGLE_KICKER, Card.TEN))) self.assertTrue( RankedMoveType(MoveType.SINGLE, Card.FOUR).beats( RankedMoveType(MoveType.SINGLE, Card.THREE)))