def test_choose_better_tanki_honor(self): table = Table() player = table.player player.round_step = 2 player.dealer_seat = 3 table.add_dora_indicator(self._string_to_136_tile(man='8')) tiles = self._string_to_136_array(man='11447799', sou='556', honors='45') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(honors='4')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '6s') tiles = self._string_to_136_array(man='11447799', sou='556', honors='45') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(honors='5')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '6s') tiles = self._string_to_136_array(man='11447799', sou='556', honors='45') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(sou='6')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '5z') tiles = self._string_to_136_array(man='11447799', sou='556', honors='34') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(sou='6')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '3z')
def test_find_dealer_tile_to_discard(self): dealer = 2 dora = self._string_to_136_tile(honors='3') table = Table() table.init_round(0, 0, 0, dora, dealer, []) tiles = self._string_to_136_array(sou='2234678', pin='34', man='45789') table.player.init_hand(tiles) table.add_discarded_tile(1, self._string_to_136_tile(man='4'), False) table.add_discarded_tile(1, self._string_to_136_tile(man='5'), False) table.add_discarded_tile(2, self._string_to_136_tile(man='8'), False) table.add_discarded_tile(2, self._string_to_136_tile(man='9'), False) table.add_called_riichi(1) table.add_called_riichi(2) # for this test we don't need temporary_safe_tiles table.get_player(1).temporary_safe_tiles = [] table.get_player(2).temporary_safe_tiles = [] result = table.player.discard_tile() # second player is a dealer, let's fold against him self.assertEqual(self._to_string([result]), '9m') tiles = self._string_to_136_array(sou='234567', pin='348', man='234', honors='23') table.player.init_hand(tiles) result = table.player.discard_tile() # there is no safe tiles against dealer, so let's fold against other players self.assertEqual(table.player.ai.in_defence, True) self.assertEqual(self._to_string([result]), '4m')
def test_discard_tile_force_tsumogiri(self): table = Table() table.has_aka_dora = True player = table.player tiles = self._string_to_136_array(sou='11134567', pin='456', man='45') # 6p tile = 57 player.init_hand(tiles) player.draw_tile(tile) discarded_tile = player.discard_tile() self.assertEqual(discarded_tile, tile) # add not red five pin tiles = self._string_to_136_array(sou='11134567', pin='46', man='45') + [53] tile = FIVE_RED_PIN player.init_hand(tiles) player.draw_tile(tile) discarded_tile = player.discard_tile() # WE DON'T NEED TO DISCARD RED FIVE self.assertNotEqual(discarded_tile, tile)
def test_atodzuke_dont_open_no_yaku_tempai(self): # make sure yakuhai strategy is activated by adding 3 doras to the hand table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(man='9')) tiles = self._string_to_136_array(man='111445', sou='567', pin='56', honors='77') player.init_hand(tiles) meld = self._make_meld(Meld.PON, man='111') player.add_called_meld(meld) # 6 man is bad meld, we lose our second pair and so is 4 man tile = self._string_to_136_tile(man='6') meld, _ = player.try_to_call_meld(tile, True) self.assertEqual(meld, None) strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) self.assertEqual(strategy.should_activate_strategy(player.tiles), True) tile = self._string_to_136_tile(man='4') meld, _ = player.try_to_call_meld(tile, True) self.assertEqual(meld, None) strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) self.assertEqual(strategy.should_activate_strategy(player.tiles), True) # 7 pin is a good meld, we get to tempai keeping yakuhai wait tile = self._string_to_136_tile(pin='7') meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(meld, None) strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) self.assertEqual(strategy.should_activate_strategy(player.tiles), True)
def test_discard_tile_with_better_wait_in_iishanten(self): table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(sou='4')) tiles = self._string_to_136_array(man='123567', pin='113788', sou='99') player.init_hand(tiles) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '8p')
def test_detect_enemy_tempai_and_riichi(self): table = Table() self.assertEqual(EnemyAnalyzer(table.get_player(1)).in_tempai, False) self.assertEqual(EnemyAnalyzer(table.get_player(1)).is_threatening, False) table.add_called_riichi(1) self.assertEqual(EnemyAnalyzer(table.get_player(1)).in_tempai, True) self.assertEqual(EnemyAnalyzer(table.get_player(1)).is_threatening, True)
def test_discard_tile_with_max_ukeire_second_level(self): table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(sou='4')) tiles = self._string_to_136_array(sou='11367', pin='45', man='344778') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(pin='6')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '3s')
def test_prefer_valuable_tiles_with_almost_same_ukeire(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_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 _choose_tanki_with_kabe_helper(self, tiles, kabe_tiles, tile_to_draw, tile_to_discard_str): table = Table() player = table.player player.round_step = 2 player.dealer_seat = 3 for tile in kabe_tiles: for _ in range(0, 4): table.add_discarded_tile(1, tile, False) player.init_hand(tiles) player.draw_tile(tile_to_draw) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), tile_to_discard_str)
def test_find_suji_tiles_to_discard_for_one_player(self): table = Table() tiles = self._string_to_136_array(sou='2345678', pin='12789', man='55') table.player.init_hand(tiles) table.add_discarded_tile(1, self._string_to_136_tile(man='2'), False) table.add_discarded_tile(1, self._string_to_136_tile(man='8'), False) table.add_called_riichi(1) result = table.player.discard_tile() self.assertEqual(self._to_string([result]), '5m')
def test_keep_aka_dora_in_hand(self): table = Table() table.dora_indicators = [self._string_to_136_tile(pin='1')] table.has_aka_dora = True player = table.player tiles = self._string_to_136_array(sou='12346', pin='34578', man='99') # five sou, we can't get it from string (because from string it is always aka dora) tiles += [89] player.init_hand(tiles) player.draw_tile(FIVE_RED_SOU) # we had to keep red five and discard just 5s discarded_tile = player.discard_tile() self.assertNotEqual(discarded_tile, FIVE_RED_SOU)
def test_open_hand_when_yakuhai_already_in_the_hand(self): # make sure yakuhai strategy is activated by adding 3 doras to the hand table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(honors='5')) tiles = self._string_to_136_array(man='46', pin='4679', sou='1348', honors='666') player.init_hand(tiles) strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) self.assertEqual(strategy.should_activate_strategy(player.tiles), True) tile = self._string_to_136_tile(sou='2') meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(meld, None)
def test_call_riichi_with_bad_wait_against_other_player_riichi(self): table = Table() table.count_of_remaining_tiles = 60 table.player.scores = 25000 tiles = self._string_to_136_array(sou='11223', pin='234678', man='55') table.player.init_hand(tiles) table.player.draw_tile(self._string_to_136_tile(man='9')) table.add_called_riichi(3) discard = table.player.discard_tile() self.assertEqual(self._to_string([discard]), '9m') self.assertEqual(table.player.ai.in_defence, True) self.assertEqual(table.player.can_call_riichi(), False)
def test_find_common_suji_tiles_to_discard_for_multiple_players(self): table = Table() tiles = self._string_to_136_array(sou='2345678', pin='12789', man='55') table.player.init_hand(tiles) table.add_discarded_tile(1, self._string_to_136_tile(pin='4'), False) table.add_discarded_tile(2, self._string_to_136_tile(pin='4'), False) table.add_called_riichi(1) table.add_called_riichi(2) result = table.player.discard_tile() self.assertEqual(self._to_string([result]), '1p')
def test_discard_tile_based_on_second_level_ukeire_and_cost(self): table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(man='2')) table.add_discarded_tile(1, self._string_to_136_tile(man='2'), False) tiles = self._string_to_136_array(man='34678', pin='2356', sou='4467') tile = self._string_to_136_tile(sou='8') player.init_hand(tiles) player.draw_tile(tile) discarded_tile = player.discard_tile() discard_correct = self._to_string([discarded_tile]) == '2p' or self._to_string([discarded_tile]) == '3p' self.assertEqual(discard_correct, True)
def test_try_to_discard_less_valuable_tiles_first_in_defence_mode(self): table = Table() tiles = self._string_to_136_array(sou='234678', pin='6789', man='55', honors='13') table.player.init_hand(tiles) table.add_discarded_tile(1, self._string_to_136_tile(pin='7'), False) table.add_discarded_tile(1, self._string_to_136_tile(sou='2'), False) table.add_called_riichi(1) result = table.player.discard_tile() # discard of 2s will do less damage to our hand shape than 7p discard self.assertEqual(table.player.ai.in_defence, True) self.assertEqual(self._to_string([result]), '2s')
def _choose_furiten_over_karaten_helper(self, tiles, furiten_tile, karaten_tile, tile_to_draw, tile_to_discard_str): table = Table() player = table.player player.round_step = 2 player.dealer_seat = 3 player.init_hand(tiles) player.add_discarded_tile(Tile(furiten_tile, True)) for _ in range(0, 3): table.add_discarded_tile(1, karaten_tile, False) player.draw_tile(tile_to_draw) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), tile_to_discard_str)
def test_choose_1_shanten_with_cost_possibility_draw(self): table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(sou='4')) tiles = self._string_to_136_array(man='557', pin='468', sou='55577', honors='66') player.init_hand(tiles) meld = self._make_meld(Meld.PON, sou='555') player.add_called_meld(meld) tile = self._string_to_136_tile(sou='7') player.draw_tile(tile) discarded_tile = player.discard_tile() self.assertNotEqual(player.ai.current_strategy, None) self.assertEqual(player.ai.current_strategy.type, BaseStrategy.YAKUHAI) self.assertEqual(self._to_string([discarded_tile]), '7m')
def test_should_go_for_defence_and_bad_hand(self): """ When we have 13 tiles in hand and someone declared a riichi """ table = Table() tiles = self._string_to_136_array(sou='1259', pin='12348', honors='3456') table.player.init_hand(tiles) table.player.draw_tile(self._string_to_136_tile(man='6')) # discard here to reinit shanten number in AI table.player.discard_tile() self.assertEqual(table.player.ai.defence.should_go_to_defence_mode(), False) table.add_called_riichi(3) # our hand is pretty bad, there is no sense to push it against riichi self.assertEqual(table.player.ai.defence.should_go_to_defence_mode(), True)
def test_add_safe_tile_after_discard(self): table = Table() table.add_called_riichi(3) table.add_discarded_tile(1, self._string_to_136_tile(man='3'), False) table.add_discarded_tile(0, self._string_to_136_tile(man='4'), False) self.assertEqual(len(table.get_player(1).discards), 1) self.assertEqual(len(table.get_player(2).discards), 0) self.assertEqual(len(table.get_player(3).discards), 0) self.assertEqual(len(table.get_player(1).safe_tiles), 1) self.assertEqual(len(table.get_player(2).safe_tiles), 0) self.assertEqual(len(table.get_player(3).safe_tiles), 2) # "2" is 3 man self.assertEqual(table.get_player(1).safe_tiles, [2]) self.assertEqual(table.get_player(3).safe_tiles, [2, 3])
def test_5_pairs_yakuhai_not_chiitoitsu(self): table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(sou='9')) table.add_dora_indicator(self._string_to_136_tile(sou='1')) tiles = self._string_to_136_array(sou='112233', pin='16678', honors='66') player.init_hand(tiles) tile = self._string_to_136_tile(honors='6') meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(player.ai.current_strategy.type, BaseStrategy.CHIITOITSU) self.assertEqual(player.ai.current_strategy.type, BaseStrategy.YAKUHAI) self.assertNotEqual(meld, None)
def test_choose_best_option_with_melds(self): table = Table() player = table.player table.has_aka_dora = False tiles = self._string_to_136_array(sou='245666789', honors='2266') player.init_hand(tiles) meld = self._make_meld(Meld.PON, sou='666') player.add_called_meld(meld) meld = self._make_meld(Meld.CHI, sou='789') player.add_called_meld(meld) player.draw_tile(self._string_to_136_tile(sou='5')) discarded_tile = player.discard_tile() # we should discard best ukeire option here - 2s self.assertEqual(self._to_string([discarded_tile]), '2s')
def test_priority_of_players_safe_tiles(self): table = Table() tiles = self._string_to_136_array(man='789', pin='2789', sou='23789', honors='1') table.player.init_hand(tiles) table.player.draw_tile(self._string_to_136_tile(sou='1')) table.add_discarded_tile(1, self._string_to_136_tile(sou='7'), False) table.add_discarded_tile(1, self._string_to_136_tile(honors='1'), False) table.add_called_riichi(1) table.add_discarded_tile(2, self._string_to_136_tile(honors='1'), False) result = table.player.discard_tile() self.assertEqual(self._to_string([result]), '1z')
def test_should_go_for_defence_and_good_hand_with_drawn_tile(self): """ When we have 14 tiles in hand and someone declared a riichi """ table = Table() table.has_aka_dora = True tiles = self._string_to_136_array(sou='2223457899', honors='666') table.player.init_hand(tiles) table.player.draw_tile(self._string_to_136_tile(man='8')) table.player.add_called_meld(self._make_meld(Meld.PON, sou='222')) table.player.add_called_meld(self._make_meld(Meld.PON, honors='666')) self.assertEqual(table.player.ai.defence.should_go_to_defence_mode(), False) table.add_called_riichi(3) result = table.player.discard_tile() self.assertEqual(self._to_string([result]), '8m')
def test_keep_only_yakuhai_pon(self): # make sure yakuhai strategy is activated by adding 3 doras to the hand table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(man='9')) table.add_dora_indicator(self._string_to_136_tile(man='3')) tiles = self._string_to_136_array(man='11144', sou='567', pin='56', honors='777') player.init_hand(tiles) meld = self._make_meld(Meld.PON, man='111') player.add_called_meld(meld) strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) self.assertEqual(strategy.should_activate_strategy(player.tiles), True) player.draw_tile(self._string_to_136_tile(man='4')) discarded_tile = player.discard_tile() self.assertNotEqual(self._to_string([discarded_tile]), '7z')
def test_set_scores_and_uma(self): table = Table() table.init_round(0, 0, 0, 0, 0, []) scores = [230, 110, 55, 405] uma = [-17, 3, 48, -34] table.set_players_scores(scores, uma) self.assertEqual(table.get_player(0).scores, 23000) self.assertEqual(table.get_player(0).uma, -17) self.assertEqual(table.get_player(1).scores, 11000) self.assertEqual(table.get_player(1).uma, 3) self.assertEqual(table.get_player(2).scores, 5500) self.assertEqual(table.get_player(2).uma, 48) self.assertEqual(table.get_player(3).scores, 40500) self.assertEqual(table.get_player(3).uma, -34)
def test_atodzuke_dont_destroy_second_pair(self): # make sure yakuhai strategy is activated by adding 3 doras to the hand table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(man='9')) tiles = self._string_to_136_array(man='111445', sou='468', pin='56', honors='77') player.init_hand(tiles) meld = self._make_meld(Meld.PON, man='111') player.add_called_meld(meld) strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) self.assertEqual(strategy.should_activate_strategy(player.tiles), True) # 6 man is bad meld, we lose our second pair and so is 4 man tile = self._string_to_136_tile(man='6') meld, _ = player.try_to_call_meld(tile, True) self.assertEqual(meld, None) tile = self._string_to_136_tile(man='4') meld, _ = player.try_to_call_meld(tile, True) self.assertEqual(meld, None) # but if we have backup pair it's ok tiles = self._string_to_136_array(man='111445', sou='468', pin='88', honors='77') player.init_hand(tiles) meld = self._make_meld(Meld.PON, man='111') player.add_called_meld(meld) strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) self.assertEqual(strategy.should_activate_strategy(player.tiles), True) # 6 man is bad meld, we lose our second pair and so is 4 man tile = self._string_to_136_tile(man='6') meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(meld, None) tile = self._string_to_136_tile(man='4') meld, _ = player.try_to_call_meld(tile, True) self.assertNotEqual(meld, None)
def test_tempai_without_yaku(): table = Table() tiles = string_to_136_array(sou="678", pin="12355", man="456", honors="77") table.player.init_hand(tiles) tile = string_to_136_tile(pin="5") table.player.draw_tile(tile) meld = make_meld(MeldPrint.CHI, sou="678") table.player.add_called_meld(meld) discard = table.player.discard_tile() assert tiles_to_string([discard]) != "7z"
def test_player_called_meld_and_closed_hand(self): table = Table() player = table.player tiles = self._string_to_136_array(sou='123678', pin='3599', honors='555') player.init_hand(tiles) self.assertEqual(len(player.closed_hand), 13) player.add_called_meld(self._make_meld(Meld.PON, honors='555')) self.assertEqual(len(player.closed_hand), 10)
def test_discard_not_valuable_honor_first(): table = Table() player = table.player tiles = string_to_136_array(sou="123456", pin="123455", man="9", honors="2") player.init_hand(tiles) discarded_tile = player.discard_tile() assert tiles_to_string([discarded_tile]) == "2z"
def _make_table(self, dora_indicators=None): self.table = Table() self.table.count_of_remaining_tiles = 60 self.player = self.table.player self.player.scores = 25000 # with that we don't have daburi anymore self.player.round_step = 1 if dora_indicators: for x in dora_indicators: self.table.add_dora_indicator(x)
def test_find_impossible_waits_and_honor_tiles(self): table = Table() tiles = self._string_to_136_array(honors='1133', man='123', sou='456', pin='999') table.player.init_hand(tiles) table.player.add_called_meld(self._make_meld(Meld.CHI, man='123')) table.player.add_called_meld(self._make_meld(Meld.CHI, sou='456')) table.player.add_called_meld(self._make_meld(Meld.PON, pin='999')) table.add_discarded_tile(1, self._string_to_136_tile(honors='1'), False) table.add_discarded_tile(1, self._string_to_136_tile(honors='3'), False) table.add_called_riichi(2) table.player.ai.defence.hand_34 = self._to_34_array(table.player.tiles) table.player.ai.defence.closed_hand_34 = self._to_34_array(table.player.closed_hand) result = table.player.ai.defence.impossible_wait.find_tiles_to_discard([]) # dora is not safe against tanki wait, so let's hold it self.assertEqual([x.value for x in result], [EAST, WEST])
def test_try_to_discard_not_needed_tiles_first_in_defence_mode(self): table = Table() tiles = self._string_to_136_array(sou='2345678', pin='789', man='55', honors='12') table.player.init_hand(tiles) table.add_discarded_tile(1, self._string_to_136_tile(man='5'), False) table.add_discarded_tile(1, self._string_to_136_tile(honors='1'), False) table.add_called_riichi(1) result = table.player.discard_tile() self.assertEqual(self._to_string([result]), '1z')
def test_dont_call_riichi_with_tanki_wait(self): table = Table() table.count_of_remaining_tiles = 60 player = table.player player.scores = 25000 tiles = self._string_to_136_array(sou='123456', pin='123456', man='3') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(man='4')) player.discard_tile() self.assertEqual(player.can_call_riichi(), False) table = Table() table.count_of_remaining_tiles = 60 player = table.player player.scores = 25000 tiles = self._string_to_136_array(sou='1133557799', pin='113') tile = self._string_to_136_tile(pin='6') player.init_hand(tiles) player.draw_tile(tile) player.discard_tile() # for chitoitsu it is ok to have a pair wait self.assertEqual(player.can_call_riichi(), True)
def test_keep_only_yakuhai_pair(self): # make sure yakuhai strategy is activated by adding 3 doras to the hand table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(man='9')) table.add_dora_indicator(self._string_to_136_tile(man='3')) table.add_discarded_tile(1, self._string_to_136_tile(honors='7'), False) tiles = self._string_to_136_array(man='11144', sou='567', pin='156', honors='77') player.init_hand(tiles) meld = self._make_meld(Meld.PON, man='111') player.add_called_meld(meld) strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) self.assertEqual(strategy.should_activate_strategy(player.tiles), True) player.draw_tile(self._string_to_136_tile(pin='1')) discarded_tile = player.discard_tile() self.assertNotEqual(self._to_string([discarded_tile]), '7z')
def test_atodzuke_keep_yakuhai_wait(self): # make sure yakuhai strategy is activated by adding 3 doras to the hand table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(man='9')) tiles = self._string_to_136_array(man='11144', sou='567', pin='567', honors='77') player.init_hand(tiles) meld = self._make_meld(Meld.PON, man='111') player.add_called_meld(meld) # two of 4 man tiles are already out, so it would seem our wait is worse, but we know # we must keep two pairs in order to be atodzuke tempai table.add_discarded_tile(1, self._string_to_136_tile(man='4'), False) table.add_discarded_tile(1, self._string_to_136_tile(man='4'), False) strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player) self.assertEqual(strategy.should_activate_strategy(player.tiles), True) player.draw_tile(self._string_to_136_tile(man='2')) discarded_tile = player.discard_tile() self.assertEqual(self._to_string([discarded_tile]), '2m')
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_discard_less_valuable_isolated_tile_first(self): table = Table() player = table.player table.add_dora_indicator(self._string_to_136_tile(sou='4')) tiles = self._string_to_136_array(sou='2456', pin='129', man='234458') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(sou='7')) discarded_tile = player.discard_tile() # we have a choice what to discard: 9p or 8m # 9p is less valuable self.assertEqual(self._to_string([discarded_tile]), '9p') table.dora_indicators.append(self._string_to_136_tile(pin='8')) tiles = self._string_to_136_array(sou='2456', pin='129', man='234458') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(sou='7')) discarded_tile = player.discard_tile() # but if 9p is dora # let's discard 8m instead self.assertEqual(self._to_string([discarded_tile]), '8m')
def chiitoitsu_tanyao_tempai(self): table = Table() player = table.player tiles = self._string_to_136_array(sou='223344', pin='788', man='4577') player.init_hand(tiles) player.draw_tile(self._string_to_136_tile(man='4')) discard = player.discard_tile() discard_correct = self._to_string( [discard]) == '7p' or self._to_string([discard]) == '5m' self.assertEqual(discard_correct, True)
def test_discard_less_valuable_isolated_tile_first(): table = Table() player = table.player table.add_dora_indicator(string_to_136_tile(sou="4")) tiles = string_to_136_array(sou="2456", pin="129", man="234458") player.init_hand(tiles) player.draw_tile(string_to_136_tile(sou="7")) discarded_tile, _ = player.discard_tile() # we have a choice what to discard: 9p or 8m # 9p is less valuable assert tiles_to_string([discarded_tile]) == "9p" table.dora_indicators.append(string_to_136_tile(pin="8")) tiles = string_to_136_array(sou="2456", pin="129", man="234458") player.init_hand(tiles) player.draw_tile(string_to_136_tile(sou="7")) discarded_tile, _ = player.discard_tile() # but if 9p is dora # let's discard 8m instead assert tiles_to_string([discarded_tile]) == "8m"
def test_calculate_honor_tiles_value(): table = Table() player = table.player player.dealer_seat = 3 table.has_aka_dora = False # valuable honor, wind of the round option = DiscardOption(player, EAST * 4, 0, [], 0) assert option.valuation == 120 # valuable honor, wind of the player option = DiscardOption(player, SOUTH * 4, 0, [], 0) assert option.valuation == 120 # not valuable wind option = DiscardOption(player, WEST * 4, 0, [], 0) assert option.valuation == 100 # not valuable wind option = DiscardOption(player, NORTH * 4, 0, [], 0) assert option.valuation == 100 # valuable dragon option = DiscardOption(player, HAKU * 4, 0, [], 0) assert option.valuation == 120 # valuable dragon option = DiscardOption(player, HATSU * 4, 0, [], 0) assert option.valuation == 120 # valuable dragon option = DiscardOption(player, CHUN * 4, 0, [], 0) assert option.valuation == 120 player.dealer_seat = 0 # double wind option = DiscardOption(player, EAST * 4, 0, [], 0) assert option.valuation == 140
def chiitoitsu_tanyao_tempai(): table = Table() player = table.player tiles = string_to_136_array(sou="223344", pin="788", man="4577") player.init_hand(tiles) player.draw_tile(string_to_136_tile(man="4")) discard = player.discard_tile() discard_correct = tiles_to_string([discard]) == "7p" or tiles_to_string( [discard]) == "5m" assert discard_correct is True
def test_placement_evaluation(): table = Table() player = table.player # very comfortable first player.scores = 82000 for enemy in table.players: if enemy != player: enemy.scores = 6000 placement = player.ai.placement._get_placement_evaluation( player.ai.placement.get_current_placement()) assert placement == Placement.VERY_COMFORTABLE_FIRST
def test_closed_kan_and_not_necessary_call(): """ Bot tried to call closed kan with 568m669p1478999s + 9s hand """ table = Table() player = table.player tiles = string_to_136_array(man="568", sou="1478999", pin="669") player.init_hand(tiles) tile = string_to_136_tile(sou="9") player.draw_tile(tile) assert player.should_call_kan(tile, False) is 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_mark_dora_as_dangerous_tile_for_suji(self): table = Table() table.add_dora_indicator(self._string_to_136_tile(man='8')) tiles = self._string_to_136_array(man='112235', pin='4557788') table.player.init_hand(tiles) # 9 man is dora! table.player.draw_tile(self._string_to_136_tile(man='9')) table.add_discarded_tile(1, self._string_to_136_tile(man='6'), False) table.add_called_riichi(1) result = table.player.discard_tile() self.assertEqual(self._to_string([result]), '3m')
def test_threatening_riichi_player_and_not_visible_dora(): table = Table() enemy_seat = 2 table.add_called_riichi_step_one(enemy_seat) table.add_dora_indicator(string_to_136_tile(sou="2")) table.has_aka_dora = True discards = string_to_136_array(sou="33") for discard in discards: table.add_discarded_tile(enemy_seat, discard, False) # +1 scale for riichi on 6+ turn threatening_player = table.player.ai.defence.get_threatening_players()[0] assert threatening_player.enemy.seat == enemy_seat assert threatening_player.get_assumed_hand_cost( string_to_136_tile(man="2")) == 3900 # on dora discard, enemy hand will be on average more expensive assert threatening_player.get_assumed_hand_cost( string_to_136_tile(sou="3")) == 5200
def test_can_call_riichi_and_tempai(): table = Table() player = table.player player.in_tempai = False player.in_riichi = False player.scores = 2000 player.table.count_of_remaining_tiles = 40 assert player.formal_riichi_conditions() is False player.in_tempai = True assert player.formal_riichi_conditions() is True
def test_correct_discard_agari_no_yaku(): table = Table() player = table.player tiles = string_to_136_array(man="111234677889", sou="1", pin="") player.init_hand(tiles) meld = make_meld(MeldPrint.CHI, man="789") player.add_called_meld(meld) tile = string_to_136_tile(sou="1") player.draw_tile(tile) discard, _ = player.discard_tile() assert tiles_to_string([discard]) == "1s"
def test_discard_tile_force_tsumogiri(self): table = Table() table.has_aka_dora = True player = table.player tiles = self._string_to_136_array(sou='11134567', pin='456', man='45') tile = 57 # 6p player.init_hand(tiles) player.draw_tile(tile) discarded_tile = player.discard_tile() self.assertEqual(discarded_tile, tile) tiles = self._string_to_136_array(sou='11134567', pin='46', man='45') + [53] # simple five pin tile = FIVE_RED_PIN player.init_hand(tiles) player.draw_tile(tile) discarded_tile = player.discard_tile() # WE DON'T NEED TO DISCARD RED FIVE self.assertNotEqual(discarded_tile, tile)
def test_correct_discard_agari_no_yaku(self): table = Table() player = table.player tiles = self._string_to_136_array(man='111234677889', sou='1', pin='') player.init_hand(tiles) meld = self._make_meld(Meld.CHI, man='789') player.add_called_meld(meld) tile = self._string_to_136_tile(sou='1') player.draw_tile(tile) discard = player.discard_tile() self.assertEqual(self._to_string([discard]), '1s')
def test_is_threatening_and_riichi(): table = Table() threatening_players = table.player.ai.defence.get_threatening_players() assert len(threatening_players) == 0 enemy_seat = 2 enemy_called_riichi_helper(table, enemy_seat) threatening_players = table.player.ai.defence.get_threatening_players() assert len(threatening_players) == 1 assert threatening_players[0].enemy.seat == enemy_seat assert threatening_players[0].threat_reason[ "id"] == EnemyDanger.THREAT_RIICHI["id"]
def test_threatening_riichi_player_with_dora_kan(): table = Table() enemy_seat = 2 table.add_called_riichi_step_one(enemy_seat) table.add_dora_indicator(string_to_136_tile(man="2")) table.add_called_meld(enemy_seat, make_meld(MeldPrint.KAN, is_open=False, man="3333")) # we have to do it manually in test # normally tenhou client would do that table._add_revealed_tile(string_to_136_tile(man="3")) # non dealer threatening_player = table.player.ai.defence.get_threatening_players()[0] assert threatening_player.enemy.seat == enemy_seat assert threatening_player.get_assumed_hand_cost( string_to_136_tile(man="2")) == 12000 # dealer threatening_player.enemy.dealer_seat = enemy_seat assert threatening_player.get_assumed_hand_cost( string_to_136_tile(man="2")) == 18000
def test_can_call_riichi_and_remaining_tiles(self): table = Table() player = table.player player.in_tempai = True player.in_riichi = False player.scores = 2000 player.table.count_of_remaining_tiles = 3 self.assertEqual(player.formal_riichi_conditions(), False) player.table.count_of_remaining_tiles = 5 self.assertEqual(player.formal_riichi_conditions(), True)
def test_player_wind(self): table = Table() player = table.player self.assertEqual(player.player_wind, EAST) player = Player(table, 0, 1) self.assertEqual(player.player_wind, NORTH) player = Player(table, 0, 2) self.assertEqual(player.player_wind, WEST) player = Player(table, 0, 3) self.assertEqual(player.player_wind, SOUTH)
def test_choose_1_shanten_with_cost_possibility_meld(): table = Table() player = table.player table.add_dora_indicator(string_to_136_tile(sou="4")) tiles = string_to_136_array(man="557", pin="468", sou="55577", honors="66") player.init_hand(tiles) meld = make_meld(MeldPrint.PON, sou="555") player.add_called_meld(meld) tile = string_to_136_tile(sou="7") meld, discard_option = player.try_to_call_meld(tile, False) assert meld is not None assert meld.type == MeldPrint.PON assert tiles_to_string(meld.tiles) == "777s" assert player.ai.current_strategy is not None assert player.ai.current_strategy.type == BaseStrategy.YAKUHAI discarded_tile = discard_option.tile_to_discard_136 assert tiles_to_string([discarded_tile]) == "7m"
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() table.has_open_tanyao = True 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() table.has_open_tanyao = True 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')