示例#1
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