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_suitable_tiles():
    table = Table()
    strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, table.player)

    # for yakuhai we can use any tile
    for tile in range(0, 136):
        assert strategy.is_tile_suitable(tile) is True
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_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"
def test_tempai_with_open_yakuhai_meld_and_yakuhai_pair_in_the_hand():
    """
    there was a bug where bot didn't handle tempai properly
    with opened yakuhai pon and pair in the hand
    56m555p6678s55z + [777z]
    """
    table = Table()
    player = table.player

    tiles = string_to_136_array(man="56", pin="555", sou="667", honors="55777")
    player.init_hand(tiles)
    player.add_called_meld(make_meld(MeldPrint.PON, honors="777"))
    player.draw_tile(string_to_136_tile(sou="8"))

    player.ai.current_strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)

    discarded_tile, _ = player.discard_tile()
    assert tiles_to_string([discarded_tile]) == "6s"
Esempio n. 11
0
    def determine_strategy(self, tiles_136, meld_tile=None):
        # for already opened hand we don't need to give up on selected strategy
        if self.player.is_open_hand and self.current_strategy:
            return False

        old_strategy = self.current_strategy
        self.current_strategy = None

        # order is important, we add strategies with the highest priority first
        strategies = []

        if self.player.table.has_open_tanyao:
            strategies.append(TanyaoStrategy(BaseStrategy.TANYAO, self.player))

        strategies.append(YakuhaiStrategy(BaseStrategy.YAKUHAI, self.player))
        strategies.append(HonitsuStrategy(BaseStrategy.HONITSU, self.player))
        strategies.append(ChinitsuStrategy(BaseStrategy.CHINITSU, self.player))

        strategies.append(
            FormalTempaiStrategy(BaseStrategy.FORMAL_TEMPAI, self.player))
        strategies.append(
            CommonOpenTempaiStrategy(BaseStrategy.COMMON_OPEN_TEMPAI,
                                     self.player))

        for strategy in strategies:
            if strategy.should_activate_strategy(tiles_136,
                                                 meld_tile=meld_tile):
                self.current_strategy = strategy
                break

        if self.current_strategy and (
                not old_strategy
                or self.current_strategy.type != old_strategy.type):
            self.player.logger.debug(
                log.STRATEGY_ACTIVATE,
                context=self.current_strategy,
            )

        if not self.current_strategy and old_strategy:
            self.player.logger.debug(log.STRATEGY_DROP, context=old_strategy)

        return self.current_strategy and True or False
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