def test_taboo_cells(n): problem_file = "./warehouses/warehouse_%s.txt" % str(n) wh = Warehouse() wh.read_warehouse_file(problem_file) answer = taboo_cells(wh) print(set(find_2D_iterator(answer.split('\n'), "X"))) print(answer)
def actions(self, state): """ Return the list of actions that can be executed in the given state. As specified in the header comment of this class, the attributes 'self.allow_taboo_push' and 'self.macro' should be tested to determine what type of list of actions is to be returned. """ warehouse = sokoban.Warehouse() warehouse.extract_locations(state.splitlines()) # print(warehouse) # print(state) taboo = set( sokoban.find_2D_iterator( taboo_cells(str(warehouse)).splitlines(), "X")) for box in warehouse.boxes: for move in movement: worker_position = (box[0] - move[0], box[1] - move[1]) box_after_pushed = (box[0] + move[0], box[1] + move[1]) # print(taboo) if (can_go_there(warehouse, worker_position) and box_after_pushed not in taboo and box_after_pushed not in warehouse.walls and box_after_pushed not in warehouse.boxes): yield (box, direction(move))
def __init__(self, warehouse, macro=False, allow_taboo_push=False, push_costs=None): """ initialisation function stores the state as a tuple of (worker, frozenset((box, cost), ...) and any other necessary information for performing the a* graph search algorithm @param warehouse: the warehouse object @param macro: default False, whether to use macro actions @param allow_taboo_push: default False, whether to allow boxes to be pushed onto taboo cells @push_costs: default None, list of integer costs following the same order of warehouse.boxes """ self.initial = (warehouse.worker, frozenset(zip(warehouse.boxes, push_costs))) \ if push_costs is not None \ else (warehouse.worker, frozenset((box, 0) for box in warehouse.boxes)) # custom variable inputs self.push_costs = push_costs self.macro = macro self.allow_taboo_push = allow_taboo_push # helpers self.taboo_cells = set( sokoban.find_2D_iterator( taboo_cells(warehouse).split(sep='\n'), "X")) self.walls = set(warehouse.walls) self.goal = set(warehouse.targets) # for macro actions can_go_there purposes self.warehouse = warehouse
def __init__(self, warehouse, push_costs=None): self.warehouse = warehouse self.initial = (warehouse.worker, tuple(warehouse.boxes)) self.goal = warehouse.targets self.walls = warehouse.walls self.push_costs = push_costs self.taboo = sokoban.find_2D_iterator( taboo_cells(self.warehouse).split('\n'), 'X')
def __init__(self, warehouse): self.warehouse = warehouse self.initial = (warehouse.worker, tuple(warehouse.boxes)) self.goal = warehouse.targets self.walls = warehouse.walls # by default does not allow push of boxes on taboo cells self.allow_taboo_push = False # use elementary actions if self.macro == False self.macro = False self.taboo = sokoban.find_2D_iterator( taboo_cells(self.warehouse).split('\n'), 'X')
def actions(self, state): warehouse = sokoban.Warehouse() warehouse.extract_locations(state.splitlines()) taboo = set(sokoban.find_2D_iterator(taboo_cells(str(warehouse)), "X")) for box in warehouse.boxes: for move in movement: worker_position = (box[0] - move[0], box[1] - move[1]) box_after_pushed = (box[0] + move[0], box[1] + move[1]) if (can_go_there(warehouse, worker_position) and box_after_pushed not in taboo and box_after_pushed not in warehouse.walls and box_after_pushed not in warehouse.boxes): yield (box, direction(move))
def __init__(self, warehouse, initial=None, goal=None): self.warehouse = warehouse self.taboo = list(sokoban.find_2D_iterator(taboo_cells(warehouse).split(sep='\n'), "X")) self.walls = warehouse.walls self.targets = warehouse.targets if initial is not None: self.initial = initial else: self.initial = (self.warehouse.worker,tuple(self.warehouse.boxes)) if goal is not None: self.goal = goal else: self.goal = self.warehouse.targets assert set(self.goal) == set(warehouse.targets)
def taboo_reader(taboo_cells_str): # reference from from_lines lines = taboo_cells_str.split(sep='\n') first_row, first_col = None, None for row, line in enumerate(lines): brick_column = line.find('#') if brick_column >= 0: if first_row is None: first_row = row if first_col is None: first_col = brick_column else: first_col = min(first_col, brick_column) if first_col is None: raise ValueError('Warehouse with no walls!') canonical_lines = [ line[first_col:] for line in lines[first_row:] if line.find('#') >= 0 ] return list(sokoban.find_2D_iterator(canonical_lines, "X"))
def actions(self, state): """ Returns the list of actions that can be executed in the given state. """ #Warehouse current state the_warehouse = sokoban.Warehouse() #Positional information of boxes, worker, targets and walls extracted the_warehouse.extract_locations(state[1].split(sep="\n")) #If allow_taboo_push is True, return all legal moves including the box on a taboo cell if self.allow_taboo_push: #Find bad cell spots is_cell_taboo = set( find_2D_iterator(taboo_cells(the_warehouse), "X")) #find directions for the box for box in the_warehouse.boxes: for offset in worker_offsets: offset = offset_of_direction(offset) b_position = add_coordinates(box, offset) ppos1 = (box[0] + offset[0] * -1) ppos0 = (box[1] + offset[1] * -1) p_position = (ppos1, ppos0) p_position = flip_coordinates(p_position) if can_go_there(the_warehouse, p_position): if b_position not in is_cell_taboo: if b_position not in the_warehouse.boxes: if b_position not in the_warehouse.walls: yield (box, direction_of_offset(offset)) #if allow_taboo_push is False, taboo and shouldn't be included in list of moves. elif not self.allow_taboo_push: #find directions for the box for box in the_warehouse.boxes: for offset in worker_offsets: b_position = add_coordinates(box, offset) p_position = flip_coordinates((box[0] + offset[0] * -1), (box[1] + offset[1] * -1)) if can_go_there(the_warehouse, p_position): if b_position not in the_warehouse.boxes: if b_position not in the_warehouse.walls: yield (box, direction_of_offset(offset))
def actions_macro(self, state): ''' return action as a direction in the (x, y) coordinate for macro @param state: coordinate of the worker and boxes ''' state_Of_Worker = state[0] state_Of_Boxes = list(state[1]) Directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] directions_In_Words = ['Left', 'Right', 'Up', 'Down'] actions = [] for boxState in state_Of_Boxes: taboo_cells_list = sokoban.find_2D_iterator( taboo_cells(self.warehouse).split('\n'), 'X') for dId, direction in enumerate(Directions): # moves boxes in the before state before_box_x = boxState[0] + direction[0] before_box_y = boxState[1] + direction[1] before_box_state = (before_box_x, before_box_y) # moves boxes in the after state after_box_x = boxState[0] - direction[0] after_box_y = boxState[1] - direction[1] after_box_state = (after_box_x, after_box_y) if after_box_state in self.warehouse.walls or before_box_state in self.warehouse.walls: continue if after_box_state in state_Of_Boxes or before_box_state in state_Of_Boxes: continue if not self.allow_taboo_push: if after_box_state in taboo_cells_list: continue temp_warehouse = self.warehouse.copy(state_Of_Worker, state_Of_Boxes) if can_go_there(temp_warehouse, (before_box_state[1], before_box_state[0])): actions.append( ((boxState[1], boxState[0]), directions_In_Words[dId])) search return actions
def read_taboo_cells(taboo_cells_str): ''' Parameters ---------- taboo_cells_str : string A warehouse string version onyl with taboo and walls. Raises ------ ValueError When wall is empty raise error. Returns ------- list A list that represent taboo position exmaple :[[x,y]...[xn,yn]]. ''' lines = taboo_cells_str.split(sep='\n') first_row_brick, first_column_brick = None, None for row, line in enumerate(lines): brick_column = line.find('#') if brick_column >= 0: if first_row_brick is None: first_row_brick = row # found first row with a brick if first_column_brick is None: first_column_brick = brick_column else: first_column_brick = min(first_column_brick, brick_column) if first_row_brick is None: raise ValueError('Warehouse with no walls!') # compute the canonical representation # keep only the lines that contain walls canonical_lines = [ line[first_column_brick:] for line in lines[first_row_brick:] if line.find('#') >= 0 ] return list(sokoban.find_2D_iterator(canonical_lines, "X"))
def actions(self, state): # Extract the warehouse from the current state. current_warehouse = sokoban.Warehouse() current_warehouse.extract_locations(state[1].split(sep="\n")) global bad_cells if bad_cells is None: # If taboo cells haven't been computed, compute them. # This is done once for optimisation purposes. bad_cells = set( find_2D_iterator( taboo_cells(current_warehouse).split("\n"), "X")) # Find every box, and every direction it can be pushed. for box in current_warehouse.boxes: for offset in offset_states: player_position = flip_tuple( (box[0] + (offset[0] * -1), box[1] + (offset[1] * -1))) new_box_position = add_tuples(box, offset) if can_go_there(current_warehouse, player_position) \ and new_box_position not in bad_cells \ and new_box_position not in current_warehouse.walls \ and new_box_position not in current_warehouse.boxes: yield (box, offset_to_direction(offset))
def extract_taboo(lines): taboo = list(sokoban.find_2D_iterator(lines, "X")) # taboo_cells return taboo
def actions(self, state): """ Return the list of actions that can be executed in the given state. As specified in the header comment of this class, the attributes 'self.allow_taboo_push' and 'self.macro' should be tested to determine what type of list of actions is to be returned. """ # These are in (y, x) format moveLeft = (-1, 0) moveRight = (1, 0) moveUp = (0, -1) moveDown = (0, 1) possibleMoves = [moveLeft, moveRight, moveUp, moveDown] nodeAsString = state.split('\n') warehouseObject = sokoban.Warehouse() warehouseObject.extract_locations(nodeAsString) justTabooCells = taboo_cells(warehouseObject) tabooCells = list(sokoban.find_2D_iterator(justTabooCells.split('\n'), 'X')) \ if not self.allow_taboo_push else [] currentWalls = warehouseObject.walls currentBoxes = warehouseObject.boxes currentWorker = warehouseObject.worker if self.macro: for box in currentBoxes: for move in possibleMoves: testNewBoxPosition = box[0] + move[0], box[1] + move[1] # Need to reverse the tuple to be in a (x,y) format testNewPlayerPosition = box[1] + (move[1] * -1), box[0] + ( move[0] * -1) canIGetThere = can_go_there(warehouseObject, testNewPlayerPosition) if canIGetThere and testNewBoxPosition not in currentWalls \ and testNewBoxPosition not in currentBoxes \ and testNewBoxPosition not in tabooCells: revBox = box[1], box[0] if move == moveLeft: yield (revBox, "Left") elif move == moveRight: yield (revBox, "Right") elif move == moveUp: yield (revBox, "Up") elif move == moveDown: yield (revBox, "Down") else: for move in possibleMoves: # Need to reverse the tuple to be in a (x,y) format testNewPlayerPosition = currentWorker[0] + move[ 0], currentWorker[1] + move[1] if testNewPlayerPosition not in currentWalls: if testNewPlayerPosition not in currentBoxes: if move == moveLeft: yield ("Left") elif move == moveRight: yield ("Right") elif move == moveUp: yield ("Up") elif move == moveDown: yield ("Down") else: # If there is a box in the way, make sure the box can legally be moved newBoxPosition = testNewPlayerPosition[0] + move[ 0], testNewPlayerPosition[1] + move[1] if newBoxPosition not in currentWalls and \ newBoxPosition not in currentBoxes and \ newBoxPosition not in tabooCells: if move == moveLeft: yield ("Left") elif move == moveRight: yield ("Right") elif move == moveUp: yield ("Up") elif move == moveDown: yield ("Down")