def test_open_hand_and_discard_tiles_logic(): table = Table() player = table.player tiles = string_to_136_array(sou="112235589", man="23", honors="66") player.init_hand(tiles) # we don't need to call meld even if it improves our hand, # because we are aim for honitsu or pinfu tile = string_to_136_tile(man="1") meld, _ = player.try_to_call_meld(tile, False) assert meld is None # any honor tile is suitable tile = string_to_136_tile(honors="6") meld, discard_option = player.try_to_call_meld(tile, False) assert meld is not None assert tiles_to_string([discard_option.tile_to_discard_136]) == "2m" tile = 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 assert tiles_to_string([tile_to_discard]) == "1m"
def test_discard_tile_and_wrong_tiles_valuation(): """ Bot wanted to discard 5m from the first hand, because valuation for 2p was miscalculated (too high) Same issue with wrong valuation was with second hand """ table = Table() player = table.player table.add_dora_indicator(string_to_136_tile(honors="2")) tiles = string_to_136_array(man="5", pin="256678", sou="2333467") player.init_hand(tiles) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "2p" table = Table() player = table.player table.add_dora_indicator(string_to_136_tile(man="5")) tiles = string_to_136_array(man="45667", pin="34677", sou="38", honors="22") player.init_hand(tiles) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "8s"
def test_choose_correct_wait_finished_yaku(): table = Table() player = table.player player.round_step = 2 tiles = string_to_136_array(man="23478", sou="23488", pin="235") player.init_hand(tiles) player.draw_tile(string_to_136_tile(pin="4")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "5p" tiles = string_to_136_array(man="34578", sou="34588", pin="235") player.init_hand(tiles) player.draw_tile(string_to_136_tile(pin="4")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "2p" tiles = string_to_136_array(man="34578", sou="34588", pin="235") player.init_hand(tiles) player.draw_tile(string_to_136_tile(pin="4")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "2p" tiles = string_to_136_array(man="3457", sou="233445588") player.init_hand(tiles) player.draw_tile(string_to_136_tile(man="8")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "2s" tiles = string_to_136_array(man="3457", sou="223344588") player.init_hand(tiles) player.draw_tile(string_to_136_tile(man="8")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "5s"
def test_choose_better_tanki_honor(): table = Table() player = table.player player.round_step = 2 player.dealer_seat = 3 table.add_dora_indicator(string_to_136_tile(man="8")) tiles = string_to_136_array(man="11447799", sou="556", honors="45") player.init_hand(tiles) player.draw_tile(string_to_136_tile(honors="4")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "6s" tiles = string_to_136_array(man="11447799", sou="556", honors="45") player.init_hand(tiles) player.draw_tile(string_to_136_tile(honors="5")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "6s" tiles = string_to_136_array(man="11447799", sou="556", honors="45") player.init_hand(tiles) player.draw_tile(string_to_136_tile(sou="6")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "5z"
def test_open_hand_and_discard_tiles_logic_advanced(): # we should choose between one of the ryanmens to discard # in this case - discard the one that leads us to atodzuke and has less tanyao ukeire # despite the fact that general ukeire is higher table = _make_table() table.add_discarded_tile(2, string_to_136_tile(pin="4"), False) table.add_discarded_tile(2, string_to_136_tile(pin="7"), False) table.add_discarded_tile(2, string_to_136_tile(sou="4"), False) table.add_discarded_tile(2, string_to_136_tile(sou="7"), False) tiles = string_to_136_array(man="236777", sou="56", pin="22256") table.player.init_hand(tiles) meld = make_meld(MeldPrint.PON, pin="222") table.player.add_called_meld(meld) tile = string_to_136_tile(man="6") table.player.draw_tile(tile) tile_to_discard, _ = table.player.discard_tile() assert tiles_to_string([tile_to_discard]) == "2m" or tiles_to_string( [tile_to_discard]) == "3m" # now same situation, but better ryanmen is no atodzuke table = _make_table() table.add_discarded_tile(2, string_to_136_tile(pin="4"), False) table.add_discarded_tile(2, string_to_136_tile(pin="7"), False) table.add_discarded_tile(2, string_to_136_tile(sou="4"), False) table.add_discarded_tile(2, string_to_136_tile(sou="7"), False) tiles = string_to_136_array(man="346777", sou="56", pin="22256") table.player.init_hand(tiles) meld = make_meld(MeldPrint.PON, pin="222") table.player.add_called_meld(meld) tile = string_to_136_tile(man="6") table.player.draw_tile(tile) tile_to_discard, _ = table.player.discard_tile() assert (tiles_to_string([tile_to_discard]) == "5s" or tiles_to_string([tile_to_discard]) == "6s" or tiles_to_string([tile_to_discard]) == "5p" or tiles_to_string([tile_to_discard]) == "6p") # now same situation as the first one, but ryanshanten table = _make_table() table.add_discarded_tile(2, string_to_136_tile(pin="4"), False) table.add_discarded_tile(2, string_to_136_tile(pin="7"), False) table.add_discarded_tile(2, string_to_136_tile(sou="4"), False) table.add_discarded_tile(2, string_to_136_tile(sou="7"), False) table.add_discarded_tile(2, string_to_136_tile(man="5"), False) table.add_discarded_tile(2, string_to_136_tile(man="8"), False) tiles = string_to_136_array(man="2367", sou="2356", pin="22256") table.player.init_hand(tiles) meld = make_meld(MeldPrint.PON, pin="222") table.player.add_called_meld(meld) tile = string_to_136_tile(man="8") table.player.draw_tile(tile) tile_to_discard, _ = table.player.discard_tile() assert (tiles_to_string([tile_to_discard]) == "2m" or tiles_to_string([tile_to_discard]) == "3m" or tiles_to_string([tile_to_discard]) == "2s" or tiles_to_string([tile_to_discard]) == "3s")
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_discard_not_effective_tiles_first_not_honitsu(): table = Table() player = table.player player.scores = 25000 table.count_of_remaining_tiles = 100 tiles = string_to_136_array(man="33", pin="12788999", sou="5", honors="23") player.init_hand(tiles) player.draw_tile(string_to_136_tile(honors="6")) tile_to_discard, _ = player.discard_tile() # this is not really a honitsu assert tiles_to_string([tile_to_discard]) == "2z" or tiles_to_string([tile_to_discard]) == "3z"
def test_open_hand_and_not_go_for_chiitoitsu(): table = Table() player = table.player tiles = string_to_136_array(sou="1122559", honors="134557") player.init_hand(tiles) player.draw_tile(string_to_136_tile(pin="4")) tile = player.discard_tile() assert tiles_to_string([tile]) == "4p" tile = string_to_136_tile(honors="5") meld, _ = player.try_to_call_meld(tile, False) assert meld is not None assert tiles_to_string(meld.tiles) == "555z"
def test_open_hand_and_once_discarded_tile(): """ If we have valuable pair in the hand, this tile was discarded once and we have 1+ shanten let's open on this valuable pair """ table = Table() strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, table.player) tiles = string_to_136_array(sou="678", pin="14689", man="456", honors="77") table.player.init_hand(tiles) # we don't activate strategy yet assert strategy.should_activate_strategy(table.player.tiles) is False # let's skip first yakuhai early in the game tile = string_to_136_tile(honors="7") meld, _ = table.player.try_to_call_meld(tile, True) assert meld is None # now one is out table.add_discarded_tile(1, tile, False) meld, _ = table.player.try_to_call_meld(tile, True) assert meld is not None assert tiles_to_string(meld.tiles) == "777z" # but we don't need to open hand for atodzuke here tile = string_to_136_tile(pin="7") meld, _ = table.player.try_to_call_meld(tile, True) assert meld is None
def test_not_open_hand_for_not_needed_set(): """ We don't need to open hand if it is not improve the hand. There was a bug related to it. """ table = Table() player = table.player table.dora_indicators.append(string_to_136_tile(honors="7")) tiles = string_to_136_array(man="22457", sou="12234", pin="9", honors="55") player.init_hand(tiles) tile = string_to_136_array(sou="3333")[1] meld, discard_option = player.try_to_call_meld(tile, True) assert meld is not None assert tiles_to_string(meld.tiles) == "123s" # fully update hand tiles = string_to_136_array(man="22457", sou="122334", pin="9", honors="55") player.init_hand(tiles) player.add_called_meld(meld) player.discard_tile(discard_option) tile = string_to_136_array(sou="3333")[2] meld, _ = player.try_to_call_meld(tile, True) assert meld is None
def test_choose_correct_wait_yaku_potentially(): table = Table() player = table.player player.round_step = 2 tiles = string_to_136_array(man="1134578", sou="567788") player.init_hand(tiles) player.draw_tile(string_to_136_tile(man="9")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "5s" tiles = string_to_136_array(man="1134578", sou="556678") player.init_hand(tiles) player.draw_tile(string_to_136_tile(man="9")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "8s"
def test_discard_tile_based_on_second_level_ukeire_and_cost(): table = Table() player = table.player table.add_dora_indicator(string_to_136_tile(man="2")) table.add_discarded_tile(1, string_to_136_tile(man="2"), False) tiles = string_to_136_array(man="34678", pin="2356", sou="4467") tile = string_to_136_tile(sou="8") player.init_hand(tiles) player.draw_tile(tile) discarded_tile, _ = player.discard_tile() discard_correct = tiles_to_string( [discarded_tile]) == "2p" or tiles_to_string([discarded_tile]) == "3p" assert discard_correct is True
def test_dont_open_tanyao_with_good_one_shanten_hand_into_one_shanten(): table = _make_table() table.has_aka_dora = True table.add_dora_indicator(string_to_136_tile(pin="2")) tiles = string_to_136_array(man="3488", sou="3478", pin="1345") + [FIVE_RED_SOU] # aka dora table.player.init_hand(tiles) table.player.round_step = 10 # tile is not suitable to our strategy tile = string_to_136_tile(sou="9") meld, _ = table.player.try_to_call_meld(tile, True) assert meld is None # after meld we are tempai tile = string_to_136_tile(sou="6") meld, _ = table.player.try_to_call_meld(tile, True) assert meld is not None assert tiles_to_string(meld.tiles) == "678s" # we have a good one shanten and after meld we are not tempai, abort melding tile = FIVE_RED_SOU + 1 # not aka dora meld, _ = table.player.try_to_call_meld(tile, True) assert meld is None # we must still take chi when improving from 2-shanten to 1-shanten though tiles = string_to_136_array(man="34788", sou="3478", pin="135") + [FIVE_RED_SOU] # aka dora table.player.init_hand(tiles) tile = string_to_136_tile(sou="6") meld, _ = table.player.try_to_call_meld(tile, True) assert meld is not None assert tiles_to_string(meld.tiles) == "678s" tile = FIVE_RED_SOU + 1 # not aka dora meld, _ = table.player.try_to_call_meld(tile, True) assert meld is None # from 2-shanten to 2-shanten, but with clear improvement and dora pon tiles = string_to_136_array(man="2257", sou="3456899", pin="68") table.player.init_hand(tiles) tile = string_to_136_tile(man="2") meld, _ = table.player.try_to_call_meld(tile, False) assert meld is not None assert tiles_to_string(meld.tiles) == "222m"
def test_dont_count_terminal_tiles_in_ukeire(): table = _make_table() # for closed hand let's chose tile with best ukeire tiles = string_to_136_array(man="234578", sou="235", pin="2246") table.player.init_hand(tiles) table.player.draw_tile(string_to_136_tile(pin="5")) discard, _ = table.player.discard_tile() assert (tiles_to_string([discard]) == "5m" or tiles_to_string([discard]) == "2m" or tiles_to_string([discard]) == "5s") # but with opened hand we don't need to count not suitable tiles as ukeire tiles = string_to_136_array(man="234578", sou="235", pin="2246") table.player.init_hand(tiles) table.player.add_called_meld(make_meld(MeldPrint.CHI, man="234")) table.player.draw_tile(string_to_136_tile(pin="5")) discard, _ = table.player.discard_tile() assert tiles_to_string([discard]) == "8m"
def test_keep_yakuhai_in_closed_hand(): table = Table() tiles = string_to_136_array(man="14", sou="15", pin="113347", honors="777") table.player.init_hand(tiles) tile = string_to_136_tile(honors="3") table.player.draw_tile(tile) discard, _ = table.player.discard_tile() assert tiles_to_string([discard]) != "7z"
def test_dont_keep_honor_with_small_number_of_shanten(): table = Table() player = table.player tiles = string_to_136_array(sou="11445", pin="55699", man="246") player.init_hand(tiles) player.draw_tile(string_to_136_tile(honors="7")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "7z"
def test_discard_tile_with_better_wait_in_iishanten(): table = Table() player = table.player table.add_dora_indicator(string_to_136_tile(sou="4")) tiles = string_to_136_array(man="123567", pin="113788", sou="99") player.init_hand(tiles) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "8p"
def test_get_common_tempai_honro(): table = Table() tiles = string_to_136_array(man="11999", sou="112", pin="99", honors="333") table.player.init_hand(tiles) tile = string_to_136_tile(pin="9") meld, _ = table.player.try_to_call_meld(tile, False) assert meld is not None assert tiles_to_string(meld.tiles) == "999p"
def test_keep_chiitoitsu_tempai(): table = Table() player = table.player tiles = string_to_136_array(sou="113355", man="22669", pin="99") player.init_hand(tiles) player.draw_tile(string_to_136_tile(man="6")) discard, _ = player.discard_tile() assert tiles_to_string([discard]) == "6m"
def test_we_dont_need_to_discard_terminals_from_closed_hand(): table = _make_table() tiles = string_to_136_array(man="22234", sou="13588", pin="558") table.player.init_hand(tiles) tile = string_to_136_tile(pin="5") table.player.draw_tile(tile) tile_to_discard, _ = table.player.discard_tile() # our hand is closed, let's keep terminal for now assert tiles_to_string([tile_to_discard]) == "8p"
def test_discard_tile_with_max_ukeire_second_level(): table = Table() player = table.player table.add_dora_indicator(string_to_136_tile(sou="4")) tiles = string_to_136_array(sou="11367", pin="45", man="344778") player.init_hand(tiles) player.draw_tile(string_to_136_tile(pin="6")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "3s"
def test_prefer_valuable_tiles_with_almost_same_ukeire(): table = Table() player = table.player table.add_dora_indicator(string_to_136_tile(sou="4")) tiles = string_to_136_array(sou="1366", pin="123456", man="345") player.init_hand(tiles) player.draw_tile(string_to_136_tile(sou="5")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "1s"
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 test_correct_discard_agari_no_yaku(): table = _make_table() tiles = string_to_136_array(man="23567", sou="456", pin="22244") table.player.init_hand(tiles) meld = make_meld(MeldPrint.CHI, man="567") table.player.add_called_meld(meld) tile = string_to_136_tile(man="1") table.player.draw_tile(tile) discard, _ = table.player.discard_tile() assert tiles_to_string([discard]) == "1m"
def test_discard_not_effective_tiles_first(): table = Table() player = table.player player.scores = 25000 table.count_of_remaining_tiles = 100 tiles = string_to_136_array(man="33", pin="12788999", sou="5", honors="77") player.init_hand(tiles) player.draw_tile(string_to_136_tile(honors="6")) tile_to_discard = player.discard_tile() assert tiles_to_string([tile_to_discard]) == "5s"
def test_get_common_tempai_sanshoku(): table = Table() table.add_dora_indicator(string_to_136_tile(man="8")) tiles = string_to_136_array(man="13999", sou="123", pin="12899") table.player.init_hand(tiles) tile = string_to_136_tile(pin="3") meld, _ = table.player.try_to_call_meld(tile, True) assert meld is not None assert tiles_to_string(meld.tiles) == "123p"
def test_get_common_tempai_sandoko(): table = Table() table.add_dora_indicator(string_to_136_tile(man="1")) tiles = string_to_136_array(man="222", sou="2278", pin="222899") table.player.init_hand(tiles) tile = string_to_136_tile(sou="2") meld, _ = table.player.try_to_call_meld(tile, False) assert meld is not None assert tiles_to_string(meld.tiles) == "222s"
def test_choose_correct_waiting_and_first_opened_meld(): table = _make_table() tiles = string_to_136_array(man="2337788", sou="222", pin="234") table.player.init_hand(tiles) tile = string_to_136_tile(man="8") meld, tile_to_discard = table.player.try_to_call_meld(tile, False) _assert_tanyao(table.player) discard, _ = table.player.discard_tile(tile_to_discard) assert tiles_to_string([discard]) == "2m"
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_discard_tile(): table = Table() player = table.player tiles = string_to_136_array(sou="11134567", pin="159", man="45") tile = string_to_136_tile(man="9") player.init_hand(tiles) player.draw_tile(tile) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "9m" or tiles_to_string( [discarded_tile]) == "9p" assert player.ai.shanten == 2 player.draw_tile(string_to_136_tile(pin="4")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "1p" assert player.ai.shanten == 2 player.draw_tile(string_to_136_tile(pin="3")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "9p" or tiles_to_string( [discarded_tile]) == "9m" assert player.ai.shanten == 1 player.draw_tile(string_to_136_tile(man="4")) discarded_tile, _ = player.discard_tile() assert tiles_to_string([discarded_tile]) == "5m" assert player.ai.shanten == 0