示例#1
0
文件: AscSokoban.py 项目: TAEB/roomba
 def auto_command_finish(self):
     # If the traceback does not exist then it means the bot has not found a path.
     if not self.traceback:
         return False
     new_player, old_player = self.traceback[-1]
     if self.player_location == old_player:
         # Push the boulder.
         proximal = new_player
         self.traceback.pop()
     else:
         # Move next to the boulder.
         slow_neighbor_transition = SlowNeighborTransition(self, self)
         loc_to_dist = AscDP.measure_all_targets([old_player], [self.player_location], slow_neighbor_transition)
         assert self.player_location in loc_to_dist, error_message
         path = AscDP.get_path(self.player_location, slow_neighbor_transition, loc_to_dist)
         assert len(path) > 1, error_message
         proximal = path[1]
     row, col = self.player_location
     nrow, ncol = proximal
     drow = nrow - row
     dcol = ncol - col
     delta = (drow, dcol)
     move_result = self.move_player(delta)
     if not self.traceback:
         self.invalidate()
     return move_result
示例#2
0
文件: AscSokoban.py 项目: TAEB/roomba
def do_curses_demo(stdscr):
    # do not wait for a keypress when using getch()
    stdscr.nodelay(1)
    # create the subscreen to leave room at the top for a message
    sokoban_screen = stdscr.subpad(1, 0)
    # solve each level
    for level_string, level_name in all_level_strings_and_names:
        # load the list of boulder pushes from the file
        push_list = load_push_sequence(level_name)
        # all of the soko files should exist when this function is called
        assert push_list
        # load the level
        level = SokoMap(level_string, level_name)
        # show the level name on the top row
        stdscr.addstr(0, 0, level_name)
        stdscr.refresh()
        # play the level automatically
        push_index = 0
        while True:
            # quit if a key is pressed during the demo
            # note that getch() usually waits for a keypress,
            # but this has been disabled on stdscr by the nodelay(1) call.
            if stdscr.getch() != -1:
                return
            # show the initial move or the result of the last move
            level.draw_to_curses_screen(sokoban_screen)
            sokoban_screen.refresh()
            # pause between animation frames
            time.sleep(.1)
            # if we win then go to the next level
            if level.is_solved():
                break
            # are we at the square that allows us to push yet?
            rowa, cola, rowb, colb = push_list[push_index]
            drow = rowb - rowa
            dcol = colb - cola
            target_player_location = (rowa, cola)
            player_location = level.player_location
            if player_location == target_player_location:
                # push the boulder
                delta = (drow, dcol)
                level.move_player(delta)
                push_index += 1
            else:
                # move the player in the direction of the target player location
                slow_neighbor_transition = SlowNeighborTransition(level, level)
                loc_to_dist = AscDP.measure_all_targets([target_player_location], [level.player_location], slow_neighbor_transition)
                path = AscDP.get_path(level.player_location, slow_neighbor_transition, loc_to_dist)
                best_loc = path[1]
                row, col = player_location
                nrow, ncol = best_loc
                delta = (nrow - row, ncol - col)
                level.move_player(delta)
        # clear the screen to prepare to show the new level map and map name
        stdscr.clear()
        stdscr.refresh()
示例#3
0
文件: AscSelect.py 项目: TAEB/roomba
 def get_best_action(self, location, targets):
     """
     @param location: current location
     @param targets: an iterable container of equally desirable target locations
     @return: the first action in the shortest path
     """
     best_actions = AscDP.get_best_actions(location, targets, self.transition_table.backwards, self.transition_table.forwards)
     if best_actions:
         return list(best_actions)[0]
示例#4
0
文件: AscSokoban.py 项目: TAEB/roomba
 def __call__(self, source):
     """
     Interesting moves include pushing the boulder and moving to a different side of the boulder to push it.
     """
     boulder_location, player_location = source
     # Keep a set of the next states to return at the end of the function.
     next_states = set()
     # Make sure that the state is valid.
     assert self.rect.is_inbounds(boulder_location)
     assert self.rect.is_inbounds(player_location)
     assert self.level[boulder_location] not in '0-|^', (boulder_location, self.level[boulder_location])
     assert self.level[player_location] not in '0-|^', (player_location, self.leve[player_location])
     # Put the boulder on the floor.
     self.level[boulder_location] = '0'
     # Keep a set of the locations we want to visit to push the boulder in a different direction.
     target_locations = set()
     # This set includes all target locations and may include the current location.
     all_desirable_sides = set()
     for back, front in self.location_to_back_front_pairs[boulder_location]:
         # You cannot push a boulder while standing on a trap or solid object.
         if self.level[back] in '0^':
             continue
         # You cannot push a boulder into a solid object
         if self.level[front] == '0':
             continue
         # At this point the boulder is pushable if we can get behind it.
         all_desirable_sides.add(back)
         if player_location == back:
             # If we are already behind it then add a boulder push to the list of next states.
             next_states.add((front, boulder_location))
         else:
             # Otherwise add the location behind the boulder to a list of places we want to reach.
             target_locations.add(back)
     # See which of the target locations we can reach while the boulder is on the floor.
     if target_locations:
         reachable_desirable_sides = self.side_cache.get(source, None)
         if not reachable_desirable_sides:
             reachable_desirable_sides = AscDP.flood_all_targets([player_location], all_desirable_sides, self.manhattan_transition)
         for back in reachable_desirable_sides:
             adjacent_state = (boulder_location, back)
             self.side_cache[adjacent_state] = reachable_desirable_sides
             if adjacent_state != source:
                 next_states.add(adjacent_state)
     # Take the boulder back off of the floor.
     self.level[boulder_location] = '.'
     return next_states
示例#5
0
文件: AscSokoban.py 项目: TAEB/roomba
 def invalidate(self):
     """
     A boulder has been moved so the traceback must be recalculated.
     """
     # calling this function means something has caused the old traceback to become invalid
     self.traceback = None
     # see where the boulders are
     boulder_locations = [loc for loc, c in self.level.items() if c == '0']
     # create solvers associated with boulder locations
     pq = []
     distance_solver_location_triples = []
     for boulder_location in boulder_locations:
         self.level[boulder_location] = '.'
         boulder_transition = BoulderTransition(self, self.level, self.floor_neighbors, self.location_to_back_front_pairs)
         boulder_heuristic = BoulderTransitionHeuristic(self, self.level, self.location_to_back_front_pairs)
         initial_state = (boulder_location, self.player_location)
         solver = AscDP.MeasureInformedTraceback([initial_state], boulder_transition, boulder_heuristic)
         solver.step()
         self.level[boulder_location] = '0'
         distance = solver.get_distance()
         if distance is not None:
             heappush(pq, (distance, solver, boulder_location))
     # Keep going until a solver has finished or until they have all failed to find a solution.
     best_path = None
     while pq:
         distance, solver, boulder_location = heappop(pq)
         solution = solver.get_solution()
         if solution:
             best_path = AscDP.traceback_to_path(*solution)
             break
         self.level[boulder_location] = '.'
         solver.step()
         self.level[boulder_location] = '0'
         distance = solver.get_distance()
         if distance is not None:
             heappush(pq, (distance, solver, boulder_location))
     # Set the path if one was found.
     if best_path:
         # Convert the path to boulder pushes.
         assert len(best_path) > 1
         self.traceback = []
         for (new_boulder, new_player), (old_boulder, old_player) in zip(best_path[0:-1], best_path[1:]):
             if new_boulder != old_boulder:
                 self.traceback.append((new_player, old_player))
示例#6
0
文件: AscSokoban.py 项目: TAEB/roomba
 def __init__(self, rect, level, location_to_back_front_pairs):
     relaxed_reverse_transition = RelaxedBoulderReverseTransition(rect, level, location_to_back_front_pairs)
     relaxed_targets = set(loc for loc, c in level.items() if c == '^')
     self.boulder_location_to_lower_bound = AscDP.measure_all_states(relaxed_targets, relaxed_reverse_transition)