Exemplo n.º 1
0
def test_tenhou_reasoning(hand, ans):
    answer = [
        sorted(tile_set_from_string(x) for x in selection.split(','))
        for selection in ans.split(';')
    ]
    answer.sort()
    assert sorted(NormalTypeWin().unique_win_selections(
        tile_set_from_string(hand))) == answer
def discard_reasoning(discard_event, hand_state, invisible_tiles_state, player, player_meld_state):
    invisible_player_perspective = invisible_tiles_state.value - set(hand_state.value)
    meld_count = sum(1 for meld in player_meld_state.value if not isinstance(meld, Kita))
    hand = TileSet(tile_from_tenhou(index) for index in hand_state.value)
    logger.info("reasoning {}", hand)
    win_types = [NormalTypeWin(melds=4 - meld_count)]
    reasoning_names = ["normal_reasonings", "seven_pair_reasonings"]
    if meld_count == 0:
        win_types.append(UniquePairs())
    win_reasonings = all_win_type_reasoning(hand, invisible_player_perspective, win_types)
    merged_win_reasonings = [
        reasoning_merge(list(reasoning_same_discard), invisible_player_perspective)
        for reasoning_same_discard in zip(*win_reasonings)
    ]
    merged_win_reasonings.sort(key=reasoning_key)
    _, expected_reasonings = next(groupby(merged_win_reasonings, key=reasoning_key))
    expected_reasonings = list(expected_reasonings)
    your_choice_tile = tile_from_tenhou(player.discard_tile_index(discard_event))
    your_choice_reasoning = reasoning_merge(
        [reasoning_discards(hand, invisible_player_perspective, your_choice_tile, win)
         for win in win_types
         ], invisible_player_perspective
    )
    # find_in_list(merged_win_reasonings,
    #                                  key=lambda x: x.discard_tile == your_choice_tile)
    for win_reasoning in win_reasonings:
        win_reasoning.sort(key=reasoning_key)
    # TODO add wrong rate for reason display.
    expect_shanten, expect_counts = reasoning_key(expected_reasonings[0])
    your_shanten, your_counts = reasoning_key(your_choice_reasoning)
    expect_counts = -expect_counts
    your_counts = -your_counts
    shanten_sequence_count = len(invisible_player_perspective) ** (your_shanten - expect_shanten)
    base = expect_counts * shanten_sequence_count
    # print("base=", base, "expect_counts=", expect_counts, "your_counts=", your_counts)

    correct_rate = your_counts / base
    wrong_rate = 1 - correct_rate
    # print("correct=", correct_rate, "wrong=", wrong_rate)

    your_choice_reasoning.norm()
    for item in expected_reasonings:
        item.norm()
    for item in merged_win_reasonings:
        item.norm()

    hand_str = join_tiles(to_plain_tile(x) for x in hand.tiles())
    meld_strs = [
        join_tiles(to_plain_tile(tile_from_tenhou(x))
                   for x in list(meld.self_tiles) + list(meld.borrowed_tiles))
        for meld in player_meld_state.value

    ]
    round_reasoning = RoundReasoning(
        hand_str, meld_strs,
        your_choice_reasoning, expected_reasonings, merged_win_reasonings,
        wrong_rate, False
    )

    logger.info("reasoned {}", hand)

    for name, win_reason in zip(reasoning_names, win_reasonings):
        for item in win_reason:
            item.norm()
        setattr(round_reasoning, name, win_reason)
    return round_reasoning
Exemplo n.º 3
0
def test_useful_tiles(hand, useful):
    assert TileSet(BruteForceWaiting(NormalTypeWin()).useful_tiles(tile_set_from_string(hand))) \
           == tile_set_from_string(useful)
Exemplo n.º 4
0
def test_waiting_step(hand, shanten):
    assert BruteForceWaiting(NormalTypeWin()).before_waiting_step(tile_set_from_string(hand)) \
           == shanten
Exemplo n.º 5
0
def main():
    input_hand = tile_set_from_string(input('Input hand:'))
    while len(input_hand) != 14:
        print("Input hand should be 14 tiles, e.g. 123m067p9s1234567z. " +
              "You have input %s legal tiles" % len(input_hand))
        input_hand = tile_set_from_string(input('Input hand:'))
    remain_tiles = TileSet(TileDistribution.ALL_TILES * 4) - input_hand
    remain_tile_distribution = StaticWall(remain_tiles)
    possible_discard = {tile: input_hand - TileSet([tile]) for tile in input_hand}
    remain_draw_count = int(input('Remain times for drawing tiles:'))
    win_counter = Counter()
    condition_win_counter = defaultdict(Counter)
    try_count = input('Experiment times (default 1000):')
    try_count = 1000 if try_count.strip() == '' else int(try_count)
    normal_win = NormalTypeWin()
    seven_pair = UniquePairs()
    win_patterns = [normal_win, seven_pair]
    avg_win_counter = Counter()
    total_win_count = 0
    elapsed_time = 0
    start = perf_counter()
    task_start_time = start
    for i in range(try_count):
        sample_wall = TileSet(remain_tile_distribution.sample(remain_draw_count))

        possible_win_set = set()

        for tile, hand in possible_discard.items():
            total_hand = hand + sample_wall
            for win_pattern in win_patterns:
                if win_pattern.match(total_hand):
                    win_counter.update([tile])
                    total_win_count += 1
                    possible_win_set.add(tile)
                    break

        for tile in possible_win_set:
            avg_win_counter[tile] += 1 / len(possible_win_set)

        for no_win_tile in set(possible_discard.keys()) - possible_win_set:
            for tile in possible_win_set:
                condition_win_counter[no_win_tile][tile] += 1 / len(possible_win_set)

        interval = perf_counter() - start
        if interval > 1:
            start = perf_counter()
            elapsed_time = start - task_start_time
            done = i + 1
            eta = elapsed_time / done * try_count - elapsed_time
            print("Experiments %d/%d with %.1fs, ETA %.1fs" % (done, try_count, elapsed_time, eta))
    solution_count = len(possible_discard)
    print("Done in %.1fs!" % (perf_counter() - task_start_time))
    solution_tiles = list(possible_discard.keys())
    min_rate = 1 / try_count
    condition_matrix = np.full((solution_count, solution_count), min_rate, dtype=np.double)
    for condition_index, condition_tile in enumerate(solution_tiles):
        self_transfer_rate = avg_win_counter[condition_tile] / total_win_count
        # self_transfer_rate = 0
        for transfer_index, transfer_tile in enumerate(solution_tiles):
            transfer_count = condition_win_counter[condition_tile][transfer_tile]
            condition_count = win_counter[transfer_tile]
            if transfer_count > 0 and condition_count > 0:
                condition_matrix[transfer_index][condition_index] = transfer_count
        condition_matrix[:, condition_index] *= ((1 - self_transfer_rate) / sum(condition_matrix[:, condition_index]))
        condition_matrix[condition_index][condition_index] = self_transfer_rate
    # FIXME: add regularization of Markov possibilities matrix (column sum equals 1).
    # FIXME: define proper self retain possibilities.
    condition_matrix = np.matrix(condition_matrix)
    unbiased_distribution = np.full((solution_count,), 1 / solution_count)
    rough_pick = condition_matrix * (unbiased_distribution.reshape(1, -1).transpose())
    rough_pick = np.array(rough_pick).reshape(-1)
    eigenvalues, eigenvectors = LA.eig(condition_matrix)
    nearest_one_index = abs(eigenvalues - 1).argmin()
    infinite_pick = eigenvectors[:, nearest_one_index]
    infinite_pick = np.array(infinite_pick).reshape(-1)
    infinite_pick /= sum(infinite_pick)
    pick_rank_map = {tile: (rough, infinite) for tile, rough, infinite in
                     zip(solution_tiles, rough_pick, infinite_pick)}
    # results = sorted(win_counter.items(), key=lambda tup: tup[1], reverse=True)
    results = sorted(pick_rank_map.items(), key=lambda tup: tup[1][1], reverse=True)
    print("for input hand <%s>, remain %d draws:" % (input_hand, remain_draw_count))
    for tile, (rough, infinite) in results:
        # rough, infinite = pick_rank_map[tile]
        win_count = win_counter[tile]
        print("discard %s: %.2f%% win rate (%d/%d), %.2f%% rough pick rate, %.2f%% accurate pick rate" %
              (tile,
               win_count * 100 / try_count,
               win_count, try_count
               , rough * 100, infinite * 100))
    os.system('pause')
Exemplo n.º 6
0
 def test_multi_win_selections(self):
     assert counting(NormalTypeWin().unique_win_selections(
         tile_set_from_string("111123456s55567p8p"))) == 3
Exemplo n.º 7
0
 def test_reversed_win_selections(self):
     hand = tile_set_from_string("654321111s76555p")
     item = next(NormalTypeWin().win_selections(hand))
     answer = ["111s", "123s", "456s", "55p", "567p"]
     assert sorted(item) == sorted(tile_set_from_string(x) for x in answer)
Exemplo n.º 8
0
 def test_not_ordered_win_selections(self):
     hand = tile_set_from_string("11s555p1123456s67p")
     item = next(NormalTypeWin().win_selections(hand))
     answer = ["111s", "123s", "456s", "55p", "567p"]
     assert sorted(item) == sorted(tile_set_from_string(x) for x in answer)
Exemplo n.º 9
0
def test_pattern_useful_tiles(hand, useful):
    assert TileSet(PatternMatchWaiting(NormalTypeWin()).useful_tiles(tile_set_from_string(hand))) \
           == tile_set_from_string(useful)
Exemplo n.º 10
0
def test_pattern_waiting_step(hand, shanten):
    assert PatternMatchWaiting(NormalTypeWin
                               ()).before_waiting_step(tile_set_from_string(hand)) \
           == shanten
def test_batch_convert(hand_rec):
    hand, record_map = hand_rec
    for tile, step, useful in HeuristicPatternMatchWaiting(NormalTypeWin()).batch_waiting_and_useful_tiles(hand):
        assert record_map[tile] == TileSet(useful)