def test_atodzuke_dont_open_no_yaku_tempai():
    # make sure yakuhai strategy is activated by adding 3 doras to the hand
    table = Table()
    player = table.player
    table.add_dora_indicator(string_to_136_tile(man="9"))

    tiles = string_to_136_array(man="111445", sou="567", pin="56", honors="77")
    player.init_hand(tiles)

    meld = make_meld(MeldPrint.PON, man="111")
    player.add_called_meld(meld)

    # 6 man is bad meld, we lose our second pair and so is 4 man
    tile = string_to_136_tile(man="6")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is None

    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)
    assert strategy.should_activate_strategy(player.tiles) is True

    tile = string_to_136_tile(man="4")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is None

    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)
    assert strategy.should_activate_strategy(player.tiles) is True

    # 7 pin is a good meld, we get to tempai keeping yakuhai wait
    tile = string_to_136_tile(pin="7")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None

    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)
    assert strategy.should_activate_strategy(player.tiles) is True
def test_dont_activate_strategy_if_we_dont_have_enough_tiles_in_the_wall():
    table = Table()
    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, table.player)

    table.dora_indicators.append(string_to_136_tile(honors="7"))
    tiles = string_to_136_array(man="59", sou="1235", pin="12789", honors="55")
    table.player.init_hand(tiles)

    assert strategy.should_activate_strategy(table.player.tiles) is True

    table.add_discarded_tile(3, string_to_136_tile(honors="5"), False)
    table.add_discarded_tile(3, string_to_136_tile(honors="5"), False)

    # we can't complete yakuhai, because there is not enough honor tiles
    assert strategy.should_activate_strategy(table.player.tiles) is False
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_atodzuke_dont_destroy_second_pair():
    # make sure yakuhai strategy is activated by adding 3 doras to the hand
    table = Table()
    player = table.player
    table.add_dora_indicator(string_to_136_tile(man="9"))

    tiles = string_to_136_array(man="111445", sou="468", pin="56", honors="77")
    player.init_hand(tiles)

    meld = make_meld(MeldPrint.PON, man="111")
    player.add_called_meld(meld)

    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)
    assert strategy.should_activate_strategy(player.tiles) is True

    # 6 man is bad meld, we lose our second pair and so is 4 man
    tile = string_to_136_tile(man="6")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is None

    tile = string_to_136_tile(man="4")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is None

    # but if we have backup pair it's ok
    tiles = string_to_136_array(man="111445", sou="468", pin="88", honors="77")
    player.init_hand(tiles)

    meld = make_meld(MeldPrint.PON, man="111")
    player.add_called_meld(meld)

    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)
    assert strategy.should_activate_strategy(player.tiles) is True

    # 6 man is bad meld, we lose our second pair and so is 4 man
    tile = string_to_136_tile(man="6")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None

    tile = string_to_136_tile(man="4")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
def test_should_activate_strategy():
    table = Table()
    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, table.player)

    tiles = string_to_136_array(sou="12355689", man="89", honors="123")
    table.player.init_hand(tiles)
    assert strategy.should_activate_strategy(table.player.tiles) is False

    table.dora_indicators.append(string_to_136_tile(honors="7"))
    tiles = string_to_136_array(sou="12355689", man="899", honors="55")
    table.player.init_hand(tiles)
    assert strategy.should_activate_strategy(table.player.tiles) is True

    # with chitoitsu-like hand we don't need to go for yakuhai
    tiles = string_to_136_array(sou="1235566", man="8899", honors="66")
    table.player.init_hand(tiles)
    assert strategy.should_activate_strategy(table.player.tiles) is False

    # don't count tile discarded by other player as our pair
    tiles = string_to_136_array(sou="12355689", man="899", honors="25")
    table.player.init_hand(tiles)
    tiles = string_to_136_array(sou="12355689", man="899", honors="255")
    assert strategy.should_activate_strategy(tiles) is False
def test_open_hand_when_yakuhai_already_in_the_hand():
    # make sure yakuhai strategy is activated by adding 3 doras to the hand
    table = Table()
    player = table.player
    table.add_dora_indicator(string_to_136_tile(honors="5"))

    tiles = string_to_136_array(man="46", pin="4679", sou="1348", honors="666")
    player.init_hand(tiles)

    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)
    assert strategy.should_activate_strategy(player.tiles) is True

    tile = string_to_136_tile(sou="2")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
def test_keep_only_yakuhai_pon():
    # make sure yakuhai strategy is activated by adding 3 doras to the hand
    table = Table()
    player = table.player
    table.add_dora_indicator(string_to_136_tile(man="9"))
    table.add_dora_indicator(string_to_136_tile(man="3"))

    tiles = string_to_136_array(man="11144", sou="567", pin="56", honors="777")
    player.init_hand(tiles)

    meld = make_meld(MeldPrint.PON, man="111")
    player.add_called_meld(meld)

    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)
    assert strategy.should_activate_strategy(player.tiles) is True

    player.draw_tile(string_to_136_tile(man="4"))
    discarded_tile, _ = player.discard_tile()
    assert tiles_to_string([discarded_tile]) != "7z"
def test_atodzuke_choose_hidden_syanpon():
    # make sure yakuhai strategy is activated by adding 3 doras to the hand
    table = Table()
    player = table.player
    table.add_dora_indicator(string_to_136_tile(man="9"))

    tiles = string_to_136_array(man="111678", sou="56678", honors="77")
    player.init_hand(tiles)

    meld = make_meld(MeldPrint.PON, man="111")
    player.add_called_meld(meld)

    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)
    assert strategy.should_activate_strategy(player.tiles) is True

    for _ in range(0, 4):
        table.add_discarded_tile(1, string_to_136_tile(sou="9"), False)

    player.draw_tile(string_to_136_tile(sou="6"))
    discarded_tile, _ = player.discard_tile()
    assert tiles_to_string([discarded_tile]) != "6s"
    assert tiles_to_string([discarded_tile]) == "5s" or tiles_to_string([discarded_tile]) == "8s"
def test_atodzuke_keep_yakuhai_wait():
    # make sure yakuhai strategy is activated by adding 3 doras to the hand
    table = Table()
    player = table.player
    table.add_dora_indicator(string_to_136_tile(man="9"))

    tiles = string_to_136_array(man="11144", sou="567", pin="567", honors="77")
    player.init_hand(tiles)

    meld = make_meld(MeldPrint.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, string_to_136_tile(man="4"), False)
    table.add_discarded_tile(1, string_to_136_tile(man="4"), False)

    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)
    assert strategy.should_activate_strategy(player.tiles) is True

    player.draw_tile(string_to_136_tile(man="2"))
    discarded_tile, _ = player.discard_tile()
    assert tiles_to_string([discarded_tile]) == "2m"
def test_force_yakuhai_pair_waiting_for_tempai_hand():
    """
    If hand shanten = 1 don't open hand except the situation where is
    we have tempai on yakuhai tile after open set
    """
    table = Table()

    table.dora_indicators.append(string_to_136_tile(man="3"))
    tiles = string_to_136_array(sou="123", pin="678", man="34468", honors="66")
    table.player.init_hand(tiles)

    # we will not get tempai on yakuhai pair with this hand, so let's skip this call
    tile = string_to_136_tile(man="5")
    meld, _ = table.player.try_to_call_meld(tile, False)
    assert meld is None

    # but here we will have atodzuke tempai
    tile = string_to_136_tile(man="7")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "678m"

    table = Table()
    # we can open hand in that case
    table.dora_indicators.append(string_to_136_tile(sou="5"))
    tiles = string_to_136_array(man="44556", sou="366789", honors="77")
    table.player.init_hand(tiles)

    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, table.player)
    assert strategy.should_activate_strategy(table.player.tiles) is True

    tile = string_to_136_tile(honors="7")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is not None
    assert tiles_to_string(meld.tiles) == "777z"