def before_waiting_step(self, hand: TileSet, ignore_4counts=True): self.max_used_tiles = sum(hand.values()) borrows = self.init_search_by_hand(hand) result_iter = self._win_selections_in_tiles(hand, ignore_4counts, self.win_pattern, borrowed_limit(hand), borrows, 0, 1) return min(v for v, _, _ in result_iter) - 1
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)