Esempio n. 1
0
 def _win_selections_in_tiles(self, hand: TileSet, max_used_tiles_count, ignore_4counts, current_state: WinPattern,
                              borrow_limits: TileSet, searching_start: List[Tile]):
     if sum((-hand).values()) > max_used_tiles_count:
         return
     if ignore_4counts and not all(cnt >= borrow_limits[tile] for tile, cnt in hand.items()):
         return
     if current_state.has_win():
         yield [], TileSet(-hand)
     if current_state.need_count() > sum((+hand).values()) + max_used_tiles_count:
         return
     hand = hand.copy()
     for tile in searching_start.copy():
         for unit, state in current_state.next_states(tile):
             hand_temp = hand.copy()
             hand_temp.subtract(unit)
             yield from (([unit] + tail, remains) for tail, remains in
                         self._win_selections_in_tiles(hand_temp, max_used_tiles_count, ignore_4counts, state,
                                                       borrow_limits, searching_start.copy()))
         if hand[tile] >= 0:
             del hand[tile]
         searching_start.remove(tile)
Esempio n. 2
0
    def _win_selections_in_tiles(self, hand: TileSet, ignore_4counts, current_state: WinPattern,
                                 borrow_limits: TileSet, searching_group: List[List[Tile]], borrowed_stage,
                                 waiting_step_pruning):
        # if borrowed_tile_count(hand) > self.max_used_tiles:
        #     return
        if ignore_4counts and not all(cnt >= borrow_limits[tile] for tile, cnt in hand.items()):
            return
        if current_state.has_win():
            borrowed = TileSet(-hand)
            borrowed_count = sum(borrowed.values())
            self.max_used_tiles = borrowed_count - waiting_step_pruning
            logging.debug("found borrowing %s", borrowed)
            yield borrowed_count, [], borrowed
            return
        # if current_state.need_count() > sum((+hand).values()) + self.max_used_tiles:
        #     return

        hand = hand.copy()
        basic_hand_borrowed = borrowed_tile_count(hand)

        for can_borrowed in range(borrowed_stage, current_state.max_unit_length() + 1):
            min_used_tiles = current_state.need_units() * can_borrowed
            searching_round_old = searching_group[can_borrowed]
            searching_round = searching_round_old.copy()
            temp_searching_group = searching_group.copy()
            temp_searching_group[can_borrowed] = searching_round
            hand_round = hand
            for tile in searching_round.copy():
                for unit, state in current_state.next_states(tile):
                    if basic_hand_borrowed + min_used_tiles <= self.max_used_tiles:
                        logging.debug("test %s in %s at borrow stage %d", unit, hand, can_borrowed)
                        hand_temp = hand_round.copy()
                        hand_temp.subtract(unit)
                        borrowed_new = borrowed_tile_count(hand_temp)
                        if borrowed_new - basic_hand_borrowed == can_borrowed:
                            logging.debug("search %s in %s borrowed %s", unit, hand, TileSet(-hand))
                            yield from ((cnt, [unit] + patterns, borrowed) for cnt, patterns, borrowed in
                                        self._win_selections_in_tiles(hand_temp, ignore_4counts, state,
                                                                      borrow_limits,
                                                                      temp_searching_group, can_borrowed,
                                                                      waiting_step_pruning))
                    else:
                        logging.debug("%s plan to borrowing out of range %d",
                                      hand,
                                      self.max_used_tiles - basic_hand_borrowed)
                        return
                searching_round.remove(tile)
Esempio n. 3
0
def need_to_borrow(hand: TileSet, unit: TileSet):
    hand = hand.copy()
    hand.subtract(unit)
    return borrowed_tile_count(hand)