def __init__(self, available, sub_boxes, sup_boxes, storages, storekeeper, storekeepers=None, sub_full=None, storekeeper_goal=None, multi_component=None): h, w = available.shape self.height = h - 2 self.width = w - 2 self.available = available self.sub_boxes = sub_boxes self.sup_boxes = sup_boxes self.storages = storages self.storekeeper = storekeeper self.storekeeper_goal = storekeeper_goal if storekeepers is None: multi_component = False self.storekeepers = get_component(available & ~sub_boxes, [storekeeper]) else: self.storekeepers = storekeepers if multi_component is not None: self.multi_component = multi_component else: sub_comp = get_component(self.storekeepers, positions_true(self.storekeepers)[:1]) self.multi_component = (sub_comp != self.storekeepers).any() if sub_full is not None: self.sub_full = sub_full else: self.sub_full = (np.sum(sub_boxes) == np.sum(storages))
def level_to_dual_state(level): size_bord = level.height + 2, level.width + 2 available = np.zeros(size_bord, dtype=bool) available[1:-1, 1:-1] = ~level.walls storages = np.zeros(size_bord, dtype=bool) storages[1:-1, 1:-1] = level.boxes boxes = np.zeros(size_bord, dtype=bool) boxes[1:-1, 1:-1] = level.storages storekeepers_ini = np.zeros_like(available) for d in directions: storekeepers_ini |= dir_shift_array(d, boxes) storekeepers = get_component(available & ~boxes, positions_true(storekeepers_ini)) max_component = max((comp for pos, comp in component_split(storekeepers)), key=np.sum) storekeeper = positions_true(storekeepers_ini & max_component)[0] return SokoState(available, boxes, available, storages, storekeeper=storekeeper, storekeepers=storekeepers, sub_full=True, storekeeper_goal=level.storekeeper)
def deadlock_blocks_gen(deadlock_data): max_index = 0 dl_list = [] cur_block = [] for index, storekeeper, boxes, blocked, action_data in deadlock_data: assert index == len(dl_list), (index, last_index) available = np.array(base_state.available) for box in boxes: available[box] = False sk_component = get_component(available, storekeeper) deadlock = Deadlock(boxes, blocked, sk_component) deadlock.full_index = index dl_list.append(deadlock) cur_block.append((deadlock, action_data)) max_cur = max((desc for _, desc in action_data), default=max_index) max_index = max(max_cur, max_index) if max_index == index: max_index += 1 for deadlock, action_data in cur_block: deadlock.descendants = { action: dl_list[i] for action, i in action_data } #deadlock.check_dependencies(base_state) yield [dl for dl, _ in cur_block] cur_block = [] assert not cur_block
def generalize(self, sub_boxes, sup_boxes, storekeepers=None): assert (sub_boxes <= self.sub_boxes).all() if not self.sub_full: assert (self.sup_boxes <= sup_boxes).all() if storekeepers is None: if (self.sub_boxes == sub_boxes).all(): storekeepers = self.storekeepers else: storekeepers = get_component(self.available & ~sub_boxes, positions_true(self.storekeepers)) return SokoState( self.available, sub_boxes, sup_boxes, self.storages, storekeepers=storekeepers, storekeeper=self.storekeeper, storekeeper_goal=self.storekeeper_goal, multi_component=self.multi_component, )
def _find_next_lock(self, next_state): ori_lock = self.cur_lock if ori_lock.check_state(next_state): return ori_lock ori_state = None if not self.state.multi_component: if next_state.storekeepers[self.state.storekeeper]: ori_state = self.state elif self.state.storekeepers[next_state.storekeeper]: ori_state = self.state if ori_state is None: sk_intersect = get_component( next_state.available & ~next_state.sub_boxes & ~self.state.sub_boxes, positions_true(next_state.storekeepers), ) if (self.state.storekeepers <= sk_intersect).all(): ori_state = self.state return self.deadlocks.dl_set.find_by_state(next_state, ori_state=ori_state)