def test_discard_tile(self): table = Table() player = table.player tiles = self._string_to_136_array(sou='11134567', pin='159', man='45') tile = self._string_to_136_tile(man='9') player.init_hand(tiles) player.draw_tile(tile) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '9m') self.assertEqual(player.ai.previous_shanten, 2) player.draw_tile(self._string_to_136_tile(pin='4')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '1p') self.assertEqual(player.ai.previous_shanten, 2) player.draw_tile(self._string_to_136_tile(pin='3')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '9p') self.assertEqual(player.ai.previous_shanten, 1) player.draw_tile(self._string_to_136_tile(man='4')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '5m') self.assertEqual(player.ai.previous_shanten, 0)
def test_should_activate_strategy(self): table = Table() player = table.player strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) tiles = self._string_to_136_array(sou='12355689', man='89', honors='123') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False) tiles = self._string_to_136_array(sou='12355689', man='89', honors='44') player.init_hand(tiles) player.dealer_seat = 1 self.assertEqual(strategy.should_activate_strategy(), True) tiles = self._string_to_136_array(sou='12355689', man='89', honors='666') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), True) # with chitoitsu-like hand we don't need to go for yakuhai tiles = self._string_to_136_array(sou='1235566', man='8899', honors='66') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False)
def test_suitable_tiles(self): table = Table() player = table.player strategy = TanyaoStrategy(BaseStrategy.TANYAO, player) tile = self._string_to_136_tile(man='1') self.assertEqual(strategy.is_tile_suitable(tile), False) tile = self._string_to_136_tile(pin='1') self.assertEqual(strategy.is_tile_suitable(tile), False) tile = self._string_to_136_tile(sou='9') self.assertEqual(strategy.is_tile_suitable(tile), False) tile = self._string_to_136_tile(honors='1') self.assertEqual(strategy.is_tile_suitable(tile), False) tile = self._string_to_136_tile(honors='6') self.assertEqual(strategy.is_tile_suitable(tile), False) tile = self._string_to_136_tile(man='2') self.assertEqual(strategy.is_tile_suitable(tile), True) tile = self._string_to_136_tile(pin='5') self.assertEqual(strategy.is_tile_suitable(tile), True) tile = self._string_to_136_tile(sou='8') self.assertEqual(strategy.is_tile_suitable(tile), True)
def test_wrong_shanten_improvements_detection(self): """ With hand 2345s1p11z bot wanted to open set on 2s, so after opened set we will get 25s1p11z it is not correct logic, because we ruined our hand :return: """ table = Table() player = table.player tiles = self._string_to_136_array(sou='2345999', honors='114446') player.init_hand(tiles) meld = self._make_meld(Meld.PON, self._string_to_136_array(sou='999')) player.add_called_meld(meld) meld = self._make_meld(Meld.PON, self._string_to_136_array(honors='444')) player.add_called_meld(meld) # to rebuild all caches player.draw_tile(self._string_to_136_tile(pin='2')) player.discard_tile() tile = self._string_to_136_tile(sou='2') meld, _ = table.player.try_to_call_meld(tile, True) self.assertEqual(meld, None)
def test_should_activate_strategy_and_already_completed_sided_set(self): table = Table() player = table.player strategy = TanyaoStrategy(BaseStrategy.TANYAO, player) tiles = self._string_to_136_array(sou='123234', man='3459', pin='234') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False) tiles = self._string_to_136_array(sou='234789', man='3459', pin='234') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False) tiles = self._string_to_136_array(sou='234', man='1233459', pin='234') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False) tiles = self._string_to_136_array(sou='234', man='3457899', pin='234') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False) tiles = self._string_to_136_array(sou='234', man='3459', pin='122334') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False) tiles = self._string_to_136_array(sou='234', man='3459', pin='234789') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False) tiles = self._string_to_136_array(sou='223344', man='3459', pin='234') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), True)
def test_open_hand_and_discard_tiles_logic(self): table = Table() player = table.player tiles = self._string_to_136_array(sou='112235589', man='24', honors='22') player.init_hand(tiles) # we don't need to call meld even if it improves our hand, # because we are collecting honitsu tile = self._string_to_136_tile(man='1') meld, _ = player.try_to_call_meld(tile, False) self.assertEqual(meld, None) # any honor tile is suitable tile = self._string_to_136_tile(honors='2') meld, _ = player.try_to_call_meld(tile, False) self.assertNotEqual(meld, None) tile = self._string_to_136_tile(man='1') player.draw_tile(tile) tile_to_discard = player.discard_tile() # we are in honitsu mode, so we should discard man suits self.assertEqual(self._to_string([tile_to_discard]), '1m')
def test_should_activate_strategy(self): table = Table() player = table.player strategy = HonitsuStrategy(BaseStrategy.HONITSU, player) tiles = self._string_to_136_array(sou='12355', man='12389', honors='123') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False) tiles = self._string_to_136_array(sou='12355', man='238', honors='11234') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), True) # with hand without pairs we not should go for honitsu, # because it is far away from tempai tiles = self._string_to_136_array(sou='12358', man='238', honors='12345') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False) # with chitoitsu-like hand we don't need to go for honitsu tiles = self._string_to_136_array(pin='77', man='3355677899', sou='11') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False)
def test_open_hand_and_discard_tiles_logic(self): table = Table() player = table.player # 2345779m1p256s44z tiles = self._string_to_136_array(man='22345', sou='238', pin='256', honors='44') player.init_hand(tiles) # if we are in tanyao # we need to discard terminals and honors tile = self._string_to_136_tile(sou='4') meld, discard_option = player.try_to_call_meld(tile, True) discarded_tile = table.player.discard_tile(discard_option) self.assertNotEqual(meld, None) self.assertEqual(self._to_string([discarded_tile]), '4z') tile = self._string_to_136_tile(pin='5') player.draw_tile(tile) tile_to_discard = player.discard_tile() # we are in tanyao, so we should discard honors and terminals self.assertEqual(self._to_string([tile_to_discard]), '4z')
def test_should_activate_strategy_and_chitoitsu_like_hand(self): table = Table() player = table.player strategy = TanyaoStrategy(BaseStrategy.TANYAO, player) tiles = self._string_to_136_array(sou='223388', man='3344', pin='6687') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False)
def test_suitable_tiles(self): table = Table() player = table.player strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) # for yakuhai we can use any tile for tile in range(0, 136): self.assertEqual(strategy.is_tile_suitable(tile), True)
def test_open_hand_with_yakuhai_pair_in_hand(self): table = Table() player = table.player tiles = self._string_to_136_array(sou='123678', pin='25899', honors='44') tile = self._string_to_136_tile(honors='4') player.init_hand(tiles) # we don't need to open hand with not our wind meld, _ = player.try_to_call_meld(tile, False) self.assertEqual(meld, None) # with dragon pair in hand let's open our hand tiles = self._string_to_136_array(sou='1689', pin='2358', man='1', honors='4455') tile = self._string_to_136_tile(honors='4') player.init_hand(tiles) meld, _ = player.try_to_call_meld(tile, False) self.assertNotEqual(meld, None) player.add_called_meld(meld) player.tiles.append(tile) self.assertEqual(meld.type, Meld.PON) self.assertEqual(self._to_string(meld.tiles), '444z') self.assertEqual(len(player.closed_hand), 11) self.assertEqual(len(player.tiles), 14) player.discard_tile() tile = self._string_to_136_tile(honors='5') meld, _ = player.try_to_call_meld(tile, False) self.assertNotEqual(meld, None) player.add_called_meld(meld) player.tiles.append(tile) self.assertEqual(meld.type, Meld.PON) self.assertEqual(self._to_string(meld.tiles), '555z') self.assertEqual(len(player.closed_hand), 8) self.assertEqual(len(player.tiles), 14) player.discard_tile() tile = self._string_to_136_tile(sou='7') # we can call chi only from left player meld, _ = player.try_to_call_meld(tile, False) self.assertEqual(meld, None) meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(meld, None) player.add_called_meld(meld) player.tiles.append(tile) self.assertEqual(meld.type, Meld.CHI) self.assertEqual(self._to_string(meld.tiles), '678s') self.assertEqual(len(player.closed_hand), 5) self.assertEqual(len(player.tiles), 14)
def test_chose_right_set_to_open_hand(self): """ Different test cases to open hand and chose correct set to open hand. Based on real examples of incorrect opened hands """ table = Table() player = table.player tiles = self._string_to_136_array(man='23455', pin='3445678', honors='1') tile = self._string_to_136_tile(man='5') player.init_hand(tiles) meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(meld, None) self.assertEqual(meld.type, Meld.PON) self.assertEqual(self._to_string(meld.tiles), '555m') table = Table() player = table.player tiles = self._string_to_136_array(man='335666', pin='22', sou='345', honors='55') player.init_hand(tiles) tile = self._string_to_136_tile(man='4') meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(meld, None) self.assertEqual(meld.type, Meld.CHI) self.assertEqual(self._to_string(meld.tiles), '345m') table = Table() player = table.player tiles = self._string_to_136_array(man='23557', pin='556788', honors='22') player.init_hand(tiles) tile = self._string_to_136_tile(pin='5') meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(meld, None) self.assertEqual(meld.type, Meld.PON) self.assertEqual(self._to_string(meld.tiles), '555p')
def test_opened_kan(self): table = Table() player = table.player tiles = self._string_to_136_array(man='299', sou='111456', pin='1', honors='111') player.init_hand(tiles) # to rebuild all caches player.draw_tile(self._string_to_136_tile(pin='9')) player.discard_tile() # our hand is closed, we don't need to call opened kan here tile = self._string_to_136_tile(sou='1') self.assertEqual(player.can_call_kan(tile, True), None) player.add_called_meld( self._make_meld(Meld.PON, self._string_to_136_array(honors='111'))) # our hand is open, but it is not tempai # we don't need to open kan here tile = self._string_to_136_tile(sou='1') self.assertEqual(player.can_call_kan(tile, True), None) table = Table() player = table.player tiles = self._string_to_136_array(man='2399', sou='111456', honors='111') player.init_hand(tiles) player.add_called_meld( self._make_meld(Meld.PON, self._string_to_136_array(honors='111'))) # to rebuild all caches player.draw_tile(self._string_to_136_tile(pin='9')) player.discard_tile() # our hand is open, in tempai and with a good wait tile = self._string_to_136_tile(sou='1') self.assertEqual(player.can_call_kan(tile, True), Meld.KAN)
def test_dont_call_kan_in_defence_mode(self): table = Table() tiles = self._string_to_136_array(man='12589', sou='111459', pin='12') table.player.init_hand(tiles) table.add_called_riichi(1) tile = self._string_to_136_tile(sou='1') self.assertEqual(table.player.can_call_kan(tile, False), None)
def test_go_to_the_defence_mode(self): table = Table() defence = Defence(table) self.assertFalse(defence.go_to_defence_mode()) table.players[1].in_riichi = True self.assertTrue(defence.go_to_defence_mode()) table.players[0].in_riichi = True self.assertFalse(defence.go_to_defence_mode())
def test_dont_keep_honor_with_small_number_of_shanten(self): table = Table() player = table.player tiles = self._string_to_136_array(sou='11445', pin='55699', man='246') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(honors='7')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '7z')
def test_detect_enemy_tempai_and_riichi(self): table = Table() self.assertEqual(table.get_player(1).in_tempai, False) self.assertEqual(table.get_player(1).is_threatening, False) table.add_called_riichi(1) self.assertEqual(table.get_player(1).in_tempai, True) self.assertEqual(table.get_player(1).is_threatening, True)
def test_is_dora(self): table = Table() table.init_round(0, 0, 0, 0, 0, []) table.dora_indicators = [self._string_to_136_tile(sou='1')] self.assertTrue(table.is_dora(self._string_to_136_tile(sou='2'))) table.dora_indicators = [self._string_to_136_tile(sou='9')] self.assertTrue(table.is_dora(self._string_to_136_tile(sou='1'))) table.dora_indicators = [self._string_to_136_tile(pin='9')] self.assertTrue(table.is_dora(self._string_to_136_tile(pin='1'))) table.dora_indicators = [self._string_to_136_tile(man='9')] self.assertTrue(table.is_dora(self._string_to_136_tile(man='1'))) table.dora_indicators = [self._string_to_136_tile(man='5')] self.assertTrue(table.is_dora(self._string_to_136_tile(man='6'))) table.dora_indicators = [self._string_to_136_tile(honors='1')] self.assertTrue(table.is_dora(self._string_to_136_tile(honors='2'))) table.dora_indicators = [self._string_to_136_tile(honors='2')] self.assertTrue(table.is_dora(self._string_to_136_tile(honors='3'))) table.dora_indicators = [self._string_to_136_tile(honors='3')] self.assertTrue(table.is_dora(self._string_to_136_tile(honors='4'))) table.dora_indicators = [self._string_to_136_tile(honors='4')] self.assertTrue(table.is_dora(self._string_to_136_tile(honors='1'))) table.dora_indicators = [self._string_to_136_tile(honors='5')] self.assertTrue(table.is_dora(self._string_to_136_tile(honors='6'))) table.dora_indicators = [self._string_to_136_tile(honors='6')] self.assertTrue(table.is_dora(self._string_to_136_tile(honors='7'))) table.dora_indicators = [self._string_to_136_tile(honors='7')] self.assertTrue(table.is_dora(self._string_to_136_tile(honors='5'))) table.dora_indicators = [self._string_to_136_tile(pin='1')] self.assertFalse(table.is_dora(self._string_to_136_tile(sou='2'))) settings.FIVE_REDS = True # red five man self.assertTrue(table.is_dora(FIVE_RED_MAN)) # red five pin self.assertTrue(table.is_dora(FIVE_RED_PIN)) # red five sou self.assertTrue(table.is_dora(FIVE_RED_SOU)) settings.FIVE_REDS = False
def test_prefer_valuable_tiles_with_almost_same_tiles_count(self): table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(sou='4')) tiles = self._string_to_136_array(sou='1366', pin='123456', man='345') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(sou='5')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '1s')
def test_set_scores(self): table = Table() table.init_round(0, 0, 0, 0, 0, []) scores = [230, 110, 55, 405] table.set_players_scores(scores) self.assertEqual(table.get_player(0).scores, 23000) self.assertEqual(table.get_player(1).scores, 11000) self.assertEqual(table.get_player(2).scores, 5500) self.assertEqual(table.get_player(3).scores, 40500)
def test_dont_open_hand_with_not_suitable_melds(self): table = Table() player = table.player tiles = self._string_to_136_array(man='33355788', sou='3479', honors='3') tile = self._string_to_136_tile(sou='8') player.init_hand(tiles) meld, _ = player.try_to_call_meld(tile, False) self.assertEqual(meld, None)
def test_not_open_hand_in_riichi(self): table = Table() player = table.player player.in_riichi = True tiles = self._string_to_136_array(sou='12368', pin='2358', honors='4455') tile = self._string_to_136_tile(honors='5') player.init_hand(tiles) meld, _ = player.try_to_call_meld(tile, False) self.assertEqual(meld, None)
def test_dont_go_for_honitsu_with_ryanmen_in_other_suit(self): table = Table() player = table.player strategy = HonitsuStrategy(BaseStrategy.HONITSU, player) tiles = self._string_to_136_array(man='14489', sou='45', pin='67', honors='44456') player.init_hand(tiles) self.assertEqual(strategy.should_activate_strategy(), False)
def test_discard_not_valuable_honor_first(self): table = Table() player = table.player tiles = self._string_to_136_array(sou='123456', pin='123456', man='9', honors='2') player.init_hand(tiles) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '2z')
def test_calculate_safe_tiles_to_discard(self): table = Table() table.get_main_player().init_hand([3, 5, 6, 7, 8]) defence = Defence(table) table.players[1].in_riichi = True table.players[1].add_discarded_tile(2) tile = defence.calculate_safe_tile_against_riichi() # 0, 1, 2, 3 - is a same tile self.assertEqual(tile, 3)
def test_get_more_yakuhai_sets_in_hand(self): table = Table() tiles = self._string_to_136_array(sou='1378', pin='67', man='68', honors='5566') table.player.init_hand(tiles) tile = self._string_to_136_tile(honors='5') meld, discard_option = table.player.try_to_call_meld(tile, False) self.assertNotEqual(meld, None) table.add_called_meld(0, meld) table.player.tiles.append(tile) table.player.discard_tile(discard_option) tile = self._string_to_136_tile(honors='6') meld, _ = table.player.try_to_call_meld(tile, False) self.assertNotEqual(meld, None) table = Table() tiles = self._string_to_136_array(sou='234', pin='788', man='567', honors='5566') table.player.init_hand(tiles) tile = self._string_to_136_tile(honors='5') meld, discard_option = table.player.try_to_call_meld(tile, False) self.assertNotEqual(meld, None) table.add_called_meld(0, meld) table.player.tiles.append(tile) table.player.discard_tile(discard_option) tile = self._string_to_136_tile(honors='6') meld, _ = table.player.try_to_call_meld(tile, False) self.assertEqual(meld, None)
def test_choose_correct_waiting(self): table = Table() player = table.player tiles = self._string_to_136_array(man='234678', sou='234', pin='3588') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(pin='2')) # discard 5p and riichi discard = player.discard_tile() self.assertEqual(self._to_string([discard]), '5p') table = Table() player = table.player meld = self._make_meld(Meld.CHI, self._string_to_136_array(man='234')) player.add_called_meld(meld) tiles = self._string_to_136_array(man='234678', sou='234', pin='3588') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(pin='2')) # it is not a good idea to wait on 1-4, since we can't win on 1 with open hand # so let's continue to wait on 4 only discard = player.discard_tile() self.assertEqual(self._to_string([discard]), '2p') table = Table() player = table.player meld = self._make_meld(Meld.CHI, self._string_to_136_array(man='234')) player.add_called_meld(meld) tiles = self._string_to_136_array(man='234678', sou='234', pin='2388') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(sou='7')) # we can wait only on 1-4, so let's do it even if we can't get yaku on 1 discard = player.discard_tile() self.assertEqual(self._to_string([discard]), '7s')
def test_force_yakuhai_pair_waiting_for_tempai_hand(self): """ If hand shanten = 1 don't open hand except the situation where is we have tempai on yakuhai tile after open set """ table = Table() player = table.player tiles = self._string_to_136_array(sou='123', pin='678', man='34468', honors='66') player.init_hand(tiles) # we will not get tempai on yakuhai pair with this hand, so let's skip this call tile = self._string_to_136_tile(man='5') meld, _ = player.try_to_call_meld(tile, False) self.assertEqual(meld, None) # but here we will have atodzuke tempai tile = self._string_to_136_tile(man='7') meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(meld, None) self.assertEqual(meld.type, Meld.CHI) self.assertEqual(self._to_string(meld.tiles), '678m') table = Table() player = table.player # we can open hand in that case tiles = self._string_to_136_array(man='44556', sou='366789', honors='77') player.init_hand(tiles) tile = self._string_to_136_tile(honors='7') meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(meld, None) self.assertEqual(self._to_string(meld.tiles), '777z')
def test_slide_set_to_keep_dora_in_hand(self): table = Table() table.dora_indicators = [self._string_to_136_tile(pin='9')] player = table.player tiles = self._string_to_136_array(sou='123456', pin='23478', man='99') tile = self._string_to_136_tile(pin='1') player.init_hand(tiles) player.draw_tile(tile) # 2p is a dora, we had to keep it discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '4p')
def test_call_riichi_and_penchan_wait(self): table = Table() table.count_of_remaining_tiles = 60 player = table.player player.scores = 25000 tiles = self._string_to_136_array(sou='11223', pin='234567', man='66') tile = self._string_to_136_tile(man='9') player.init_hand(tiles) player.draw_tile(tile) player.discard_tile() self.assertEqual(player.can_call_riichi(), True)