示例#1
0
def test_threatening_riichi_player_and_not_early_hand_bonus():
    table = Table()
    enemy_seat = 2
    discards = string_to_136_array(sou="1111222")
    for discard in discards:
        table.add_discarded_tile(enemy_seat, discard, False)
    table.add_called_riichi_step_one(enemy_seat)
    table.add_called_riichi_step_two(enemy_seat)
    table.get_player(enemy_seat).is_ippatsu = 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
示例#2
0
def test_threatening_riichi_player_middle_tiles_bonus():
    table = Table()
    enemy_seat = 2
    table.add_called_riichi_step_one(enemy_seat)
    table.add_called_riichi_step_two(enemy_seat)
    table.get_player(enemy_seat).is_ippatsu = False

    # +1 scale 456 tiles
    threatening_player = table.player.ai.defence.get_threatening_players()[0]
    assert threatening_player.enemy.seat == enemy_seat

    # +1 scale 456 tiles
    assert threatening_player.get_assumed_hand_cost(
        string_to_136_tile(man="4"), can_be_used_for_ryanmen=True) == 3900
    assert threatening_player.get_assumed_hand_cost(
        string_to_136_tile(man="5"), can_be_used_for_ryanmen=True) == 3900
    assert threatening_player.get_assumed_hand_cost(
        string_to_136_tile(man="6"), can_be_used_for_ryanmen=True) == 3900
    assert threatening_player.get_assumed_hand_cost(
        string_to_136_tile(man="5"), can_be_used_for_ryanmen=False) == 3900

    # +1 scare for 2378 tiles that could be used in ryanmen
    assert threatening_player.get_assumed_hand_cost(
        string_to_136_tile(pin="2"), can_be_used_for_ryanmen=True) == 3900
    assert threatening_player.get_assumed_hand_cost(
        string_to_136_tile(pin="2"), can_be_used_for_ryanmen=False) == 2000
    assert threatening_player.get_assumed_hand_cost(
        string_to_136_tile(sou="7"), can_be_used_for_ryanmen=True) == 3900
    assert threatening_player.get_assumed_hand_cost(
        string_to_136_tile(sou="7"), can_be_used_for_ryanmen=False) == 2000

    # not middle tiles
    assert threatening_player.get_assumed_hand_cost(
        string_to_136_tile(man="1"), can_be_used_for_ryanmen=True) == 2000
    assert threatening_player.get_assumed_hand_cost(
        string_to_136_tile(pin="9"), can_be_used_for_ryanmen=True) == 2000
示例#3
0
    def reproduce(self, player, wind, honba, needed_tile, action,
                  tile_number_to_stop):
        player_position = self._find_player_position(player)
        round_content = self._find_needed_round(wind, honba)

        draw_tags = ["T", "U", "V", "W"]
        discard_tags = ["D", "E", "F", "G"]

        player_draw = draw_tags[player_position]

        player_draw_regex = re.compile(r"^<[{}]+\d*".format(
            "".join(player_draw)))
        discard_regex = re.compile(r"^<[{}]+\d*".format("".join(discard_tags)))

        draw_regex = re.compile(r"^<[{}]+\d*".format("".join(draw_tags)))
        last_draws = {0: None, 1: None, 2: None, 3: None}

        table = Table()
        # TODO get this info from log content
        table.has_aka_dora = True
        table.has_open_tanyao = True
        table.player.init_logger(self.logger)

        players = {}
        for round_item in self.rounds:
            for tag in round_item:
                if "<UN" in tag:
                    players_temp = self.decoder.parse_names_and_ranks(tag)
                    if players_temp:
                        for x in players_temp:
                            players[x["seat"]] = x

        draw_tile_seen_number = 0
        enemy_discard_seen_number = 0
        for tag in round_content:
            if player_draw_regex.match(tag) and "UN" not in tag:
                tile = self.decoder.parse_tile(tag)
                table.count_of_remaining_tiles -= 1

                # is it time to stop reproducing?
                found_tile = TilesConverter.to_one_line_string(
                    [tile]) == needed_tile
                if action == "draw" and found_tile:
                    draw_tile_seen_number += 1
                    if draw_tile_seen_number == tile_number_to_stop:
                        self.logger.info("Stop on player draw")

                        discard_result = None
                        with_riichi = False
                        table.player.draw_tile(tile)

                        table.player.should_call_kan(
                            tile,
                            open_kan=False,
                            from_riichi=table.player.in_riichi)

                        if not table.player.in_riichi:
                            discard_result = table.player.discard_tile()
                            with_riichi = table.player.can_call_riichi()

                        return discard_result, with_riichi

                table.player.draw_tile(tile)

            if "INIT" in tag:
                values = self.decoder.parse_initial_values(tag)

                shifted_scores = []
                for x in range(0, 4):
                    shifted_scores.append(
                        values["scores"][self._normalize_position(
                            player_position, x)])

                table.init_round(
                    values["round_wind_number"],
                    values["count_of_honba_sticks"],
                    values["count_of_riichi_sticks"],
                    values["dora_indicator"],
                    self._normalize_position(values["dealer"],
                                             player_position),
                    shifted_scores,
                )

                hands = [
                    [
                        int(x) for x in self.decoder.get_attribute_content(
                            tag, "hai0").split(",")
                    ],
                    [
                        int(x) for x in self.decoder.get_attribute_content(
                            tag, "hai1").split(",")
                    ],
                    [
                        int(x) for x in self.decoder.get_attribute_content(
                            tag, "hai2").split(",")
                    ],
                    [
                        int(x) for x in self.decoder.get_attribute_content(
                            tag, "hai3").split(",")
                    ],
                ]

                table.player.init_hand(hands[player_position])
                table.player.name = players[player_position]["name"]

                self.logger.info("Init round info")
                self.logger.info(table.player.name)
                self.logger.info(f"Scores: {table.player.scores}")
                self.logger.info(
                    f"Wind: {DISPLAY_WINDS[table.player.player_wind]}")

            if "DORA hai" in tag:
                table.add_dora_indicator(
                    int(self._get_attribute_content(tag, "hai")))

            if draw_regex.match(tag) and "UN" not in tag:
                tile = self.decoder.parse_tile(tag)
                player_sign = tag.upper()[1]
                player_seat = self._normalize_position(
                    draw_tags.index(player_sign), player_position)
                last_draws[player_seat] = tile

            if discard_regex.match(tag) and "DORA" not in tag:
                tile = self.decoder.parse_tile(tag)
                player_sign = tag.upper()[1]
                player_seat = self._normalize_position(
                    discard_tags.index(player_sign), player_position)

                if player_seat == 0:
                    table.player.discard_tile(tile, force_tsumogiri=True)
                else:
                    # is it time to stop?
                    found_tile = TilesConverter.to_one_line_string(
                        [tile]) == needed_tile
                    is_kamicha_discard = player_seat == 3

                    if action == "enemy_discard" and found_tile:
                        enemy_discard_seen_number += 1
                        if enemy_discard_seen_number == tile_number_to_stop:
                            self.logger.info("Stop on enemy discard")
                            self._rebuild_bot_shanten_cache(table.player)
                            table.player.should_call_kan(tile,
                                                         open_kan=True,
                                                         from_riichi=False)
                            return table.player.try_to_call_meld(
                                tile, is_kamicha_discard)

                    is_tsumogiri = last_draws[player_seat] == tile
                    table.add_discarded_tile(player_seat,
                                             tile,
                                             is_tsumogiri=is_tsumogiri)

            if "<N who=" in tag:
                meld = self.decoder.parse_meld(tag)
                player_seat = self._normalize_position(meld.who,
                                                       player_position)
                table.add_called_meld(player_seat, meld)

                if player_seat == 0:
                    if meld.type != MeldPrint.KAN and meld.type != MeldPrint.SHOUMINKAN:
                        table.player.draw_tile(meld.called_tile)

            if "<REACH" in tag and 'step="1"' in tag:
                who_called_riichi = self._normalize_position(
                    self.decoder.parse_who_called_riichi(tag), player_position)
                table.add_called_riichi_step_one(who_called_riichi)

            if "<REACH" in tag and 'step="2"' in tag:
                who_called_riichi = self._normalize_position(
                    self.decoder.parse_who_called_riichi(tag), player_position)
                table.add_called_riichi_step_two(who_called_riichi)