623 lines
25 KiB
Python
623 lines
25 KiB
Python
# logicAgents.py
|
|
# --------------
|
|
# Licensing Information: You are free to use or extend these projects for
|
|
# educational purposes provided that (1) you do not distribute or publish
|
|
# solutions, (2) you retain this notice, and (3) you provide clear
|
|
# attribution to UC Berkeley, including a link to http://ai.berkeley.edu.
|
|
#
|
|
# Attribution Information: The Pacman AI projects were developed at UC Berkeley.
|
|
# The core projects and autograders were primarily created by John DeNero
|
|
# (denero@cs.berkeley.edu) and Dan Klein (klein@cs.berkeley.edu).
|
|
# Student side autograding was added by Brad Miller, Nick Hay, and
|
|
# Pieter Abbeel (pabbeel@cs.berkeley.edu).
|
|
|
|
|
|
"""
|
|
This file contains all of the agents that can be selected to control Pacman. To
|
|
select an agent, use the '-p' option when running pacman.py. Arguments can be
|
|
passed to your agent using '-a'. For example, to load a LogicAgent that uses
|
|
logicPlan.positionLogicPlan, run the following command:
|
|
|
|
> python pacman.py -p LogicAgent -a fn=positionLogicPlan
|
|
|
|
Commands to invoke other planning methods can be found in the project
|
|
description.
|
|
|
|
You should NOT change code in this file
|
|
|
|
Good luck and happy planning!
|
|
"""
|
|
|
|
from game import Directions
|
|
from game import Agent
|
|
from game import Actions
|
|
from game import Grid
|
|
from graphicsUtils import *
|
|
import graphicsDisplay
|
|
import util
|
|
import time
|
|
import warnings
|
|
import logicPlan
|
|
import random
|
|
|
|
class GoWestAgent(Agent):
|
|
"An agent that goes West until it can't."
|
|
|
|
def getAction(self, state):
|
|
"The agent receives a GameState (defined in pacman.py)."
|
|
if Directions.WEST in state.getLegalPacmanActions():
|
|
return Directions.WEST
|
|
else:
|
|
return Directions.STOP
|
|
|
|
#######################################################
|
|
# This portion is written for you, but will only work #
|
|
# after you fill in parts of logicPlan.py #
|
|
#######################################################
|
|
|
|
class LogicAgent(Agent):
|
|
"""
|
|
This very general logic agent finds a path using a supplied planning
|
|
algorithm for a supplied planning problem, then returns actions to follow that
|
|
path.
|
|
|
|
As a default, this agent runs positionLogicPlan on a
|
|
PositionPlanningProblem to find location (1,1)
|
|
|
|
Options for fn include:
|
|
positionLogicPlan or plp
|
|
foodLogicPlan or flp
|
|
foodGhostLogicPlan or fglp
|
|
|
|
|
|
Note: You should NOT change any code in LogicAgent
|
|
"""
|
|
|
|
def __init__(self, fn='positionLogicPlan', prob='PositionPlanningProblem', plan_mod=logicPlan):
|
|
# Warning: some advanced Python magic is employed below to find the right functions and problems
|
|
|
|
# Get the planning function from the name and heuristic
|
|
if fn not in dir(plan_mod):
|
|
raise AttributeError(fn + ' is not a planning function in logicPlan.py.')
|
|
func = getattr(plan_mod, fn)
|
|
self.planningFunction = lambda x: func(x)
|
|
|
|
# Get the planning problem type from the name
|
|
if prob not in globals().keys() or not prob.endswith('Problem'):
|
|
raise AttributeError(prob + ' is not a planning problem type in logicAgents.py.')
|
|
self.planType = globals()[prob]
|
|
self.live_checking = False
|
|
print('[LogicAgent] using problem type ' + prob)
|
|
|
|
def registerInitialState(self, state):
|
|
"""
|
|
This is the first time that the agent sees the layout of the game
|
|
board. Here, we choose a path to the goal. In this phase, the agent
|
|
should compute the path to the goal and store it in a local variable.
|
|
All of the work is done in this method!
|
|
|
|
state: a GameState object (pacman.py)
|
|
"""
|
|
if self.planningFunction == None:
|
|
raise Exception("No planning function provided for LogicAgent")
|
|
starttime = time.time()
|
|
problem = self.planType(state) # Makes a new planning problem
|
|
|
|
self.actions = [] # In case planningFunction times out
|
|
self.actions = self.planningFunction(problem) # Find a path
|
|
if self.actions == None:
|
|
raise Exception('Studenct code supplied None instead of result')
|
|
totalCost = problem.getCostOfActions(self.actions)
|
|
print('Path found with total cost of %d in %.1f seconds' % (totalCost, time.time() - starttime))
|
|
# TODO Drop
|
|
if '_expanded' in dir(problem):
|
|
print('Nodes expanded: %d' % problem._expanded)
|
|
|
|
def getAction(self, state):
|
|
"""
|
|
Returns the next action in the path chosen earlier (in
|
|
registerInitialState). Return Directions.STOP if there is no further
|
|
action to take.
|
|
|
|
state: a GameState object (pacman.py)
|
|
"""
|
|
# import ipdb; ipdb.set_trace()
|
|
if 'actionIndex' not in dir(self): self.actionIndex = 0
|
|
i = self.actionIndex
|
|
self.actionIndex += 1
|
|
if i < len(self.actions):
|
|
return self.actions[i]
|
|
else:
|
|
print('Oh no! The Pacman agent created a plan that was too short!')
|
|
print()
|
|
return None
|
|
# return Directions.STOP
|
|
|
|
class CheckSatisfiabilityAgent(LogicAgent):
|
|
def __init__(self, fn='checkLocationSatisfiability', prob='LocMapProblem', plan_mod=logicPlan):
|
|
# Warning: some advanced Python magic is employed below to find the right functions and problems
|
|
|
|
# Get the planning function from the name and heuristic
|
|
if fn not in dir(plan_mod):
|
|
raise AttributeError(fn + ' is not a planning function in logicPlan.py.')
|
|
func = getattr(plan_mod, fn)
|
|
self.planningFunction = lambda x: func(*x)
|
|
|
|
# Get the planning problem type from the name
|
|
if prob not in globals().keys() or not prob.endswith('Problem'):
|
|
raise AttributeError(prob + ' is not a planning problem type in logicAgents.py.')
|
|
self.planType = globals()[prob]
|
|
print('[LogicAgent] using problem type ' + prob)
|
|
self.live_checking = False
|
|
|
|
def registerInitialState(self, state):
|
|
if self.planningFunction == None:
|
|
raise Exception("No planning function provided for LogicAgent")
|
|
starttime = time.time()
|
|
self.problem = self.planType(state) # Makes a new planning problem
|
|
|
|
def getAction(self, state):
|
|
return "EndGame"
|
|
|
|
class LocalizeMapAgent(LogicAgent):
|
|
"""Parent class for localization, mapping, and slam"""
|
|
def __init__(self, fn='positionLogicPlan', prob='LocMapProblem', plan_mod=logicPlan, display=None, scripted_actions=[]):
|
|
# Warning: some advanced Python magic is employed below to find the right functions and problems
|
|
|
|
# Get the planning function from the name and heuristic
|
|
if fn not in dir(plan_mod):
|
|
raise AttributeError(fn + ' is not a planning function in logicPlan.py.')
|
|
func = getattr(plan_mod, fn)
|
|
self.planningFunction = lambda x, y: func(x, y)
|
|
|
|
# Get the planning problem type from the name
|
|
if prob not in globals().keys() or not prob.endswith('Problem'):
|
|
raise AttributeError(prob + ' is not a planning problem type in logicAgents.py.')
|
|
self.planType = globals()[prob]
|
|
print('[LogicAgent] using problem type ' + prob)
|
|
self.visited_states = []
|
|
self.display = display
|
|
self.scripted_actions = scripted_actions
|
|
self.live_checking = True
|
|
|
|
def resetLocation(self):
|
|
self.visited_states = []
|
|
self.state = self.problem.getStartState()
|
|
self.visited_states.append(self.state)
|
|
|
|
def addNoOp_t0(self):
|
|
self.visited_states = [self.visited_states[0]] + list(self.visited_states)
|
|
self.actions.insert(0, "Stop")
|
|
|
|
def registerInitialState(self, state):
|
|
"""
|
|
This is the first time that the agent sees the layout of the game
|
|
board. Here, we choose a path to the goal. In this phase, the agent
|
|
should compute the path to the goal and store it in a local variable.
|
|
All of the work is done in this method!
|
|
|
|
state: a GameState object (pacman.py)
|
|
"""
|
|
if self.planningFunction == None:
|
|
raise Exception("No planning function provided for LogicAgent")
|
|
starttime = time.time()
|
|
problem = self.planType(state) # Makes a new planning problem
|
|
|
|
self.problem = problem
|
|
self.state = self.problem.getStartState()
|
|
|
|
self.actions = self.scripted_actions
|
|
self.resetLocation()
|
|
self.planning_fn_output = self.planningFunction(problem, self)
|
|
# self.addNoOp_t0()
|
|
|
|
def get_known_walls_non_walls_from_known_map(self, known_map):
|
|
# map is 1 for known wall, 0 for
|
|
if known_map == None:
|
|
raise Exception('Student code supplied None instead of a 2D known map')
|
|
known_walls = [[(True if entry==1 else False) for entry in row] for row in known_map]
|
|
known_non_walls = [[(True if entry==0 else False) for entry in row] for row in known_map]
|
|
return known_walls, known_non_walls
|
|
|
|
class LocalizationLogicAgent(LocalizeMapAgent):
|
|
def __init__(self, fn='localization', prob='LocalizationProblem', plan_mod=logicPlan, display=None, scripted_actions=[]):
|
|
super(LocalizationLogicAgent, self).__init__(fn, prob, plan_mod, display, scripted_actions)
|
|
self.num_timesteps = len(scripted_actions) if scripted_actions else 5
|
|
|
|
def getAction(self, state):
|
|
"""
|
|
Returns the next action in the path chosen earlier (in
|
|
registerInitialState). Return Directions.STOP if there is no further
|
|
action to take.
|
|
|
|
state: a GameState object (pacman.py)
|
|
"""
|
|
# import ipdb; ipdb.set_trace()
|
|
if 'actionIndex' not in dir(self): self.actionIndex = 0
|
|
i = self.actionIndex
|
|
self.actionIndex += 1
|
|
|
|
planning_fn_output = None
|
|
if i < self.num_timesteps:
|
|
proposed_action = self.actions[i]
|
|
planning_fn_output = next(self.planning_fn_output)
|
|
if planning_fn_output == None:
|
|
raise Exception('Studenct code supplied None instead of result')
|
|
if isinstance(self.display, graphicsDisplay.PacmanGraphics):
|
|
self.drawPossibleStates(planning_fn_output, direction=self.actions[i])
|
|
elif i < len(self.actions):
|
|
proposed_action = self.actions[i]
|
|
else:
|
|
proposed_action = "EndGame"
|
|
|
|
return proposed_action, planning_fn_output
|
|
|
|
def moveToNextState(self, action):
|
|
oldX, oldY = self.state
|
|
dx, dy = Actions.directionToVector(action)
|
|
x, y = int(oldX + dx), int(oldY + dy)
|
|
if self.problem.walls[x][y]:
|
|
raise AssertionError("Taking an action that goes into wall")
|
|
pass
|
|
else:
|
|
self.state = (x, y)
|
|
self.visited_states.append(self.state)
|
|
|
|
def getPercepts(self):
|
|
x, y = self.state
|
|
north_iswall = self.problem.walls[x][y+1]
|
|
south_iswall = self.problem.walls[x][y-1]
|
|
east_iswall = self.problem.walls[x+1][y]
|
|
west_iswall = self.problem.walls[x-1][y]
|
|
return [north_iswall, south_iswall, east_iswall, west_iswall]
|
|
|
|
def getValidActions(self):
|
|
x, y = self.state
|
|
actions = []
|
|
if not self.problem.walls[x][y+1]: actions.append('North')
|
|
if not self.problem.walls[x][y-1]: actions.append('South')
|
|
if not self.problem.walls[x+1][y]: actions.append('East')
|
|
if not self.problem.walls[x-1][y]: actions.append('West')
|
|
return actions
|
|
|
|
def drawPossibleStates(self, possibleLocations=None, direction="North", pacman_position=None):
|
|
import __main__
|
|
self.display.clearExpandedCells() # Erase previous colors
|
|
self.display.colorCircleCells(possibleLocations, direction=direction, pacman_position=pacman_position)
|
|
|
|
class MappingLogicAgent(LocalizeMapAgent):
|
|
def __init__(self, fn='mapping', prob='MappingProblem', plan_mod=logicPlan, display=None, scripted_actions=[]):
|
|
super(MappingLogicAgent, self).__init__(fn, prob, plan_mod, display, scripted_actions)
|
|
self.num_timesteps = len(scripted_actions) if scripted_actions else 10
|
|
|
|
def getAction(self, state):
|
|
"""
|
|
Returns the next action in the path chosen earlier (in
|
|
registerInitialState). Return Directions.STOP if there is no further
|
|
action to take.
|
|
|
|
state: a GameState object (pacman.py)
|
|
"""
|
|
if 'actionIndex' not in dir(self): self.actionIndex = 0
|
|
i = self.actionIndex
|
|
self.actionIndex += 1
|
|
|
|
planning_fn_output = None
|
|
if i < self.num_timesteps:
|
|
proposed_action = self.actions[i]
|
|
planning_fn_output = next(self.planning_fn_output)
|
|
if isinstance(self.display, graphicsDisplay.PacmanGraphics):
|
|
self.drawWallBeliefs(planning_fn_output, self.actions[i], self.visited_states[:i])
|
|
elif i < len(self.actions):
|
|
proposed_action = self.actions[i]
|
|
else:
|
|
proposed_action = "EndGame"
|
|
|
|
return proposed_action, planning_fn_output
|
|
|
|
def moveToNextState(self, action):
|
|
oldX, oldY = self.state
|
|
dx, dy = Actions.directionToVector(action)
|
|
x, y = int(oldX + dx), int(oldY + dy)
|
|
if self.problem.walls[x][y]:
|
|
raise AssertionError("Taking an action that goes into wall")
|
|
pass
|
|
else:
|
|
self.state = (x, y)
|
|
self.visited_states.append(self.state)
|
|
|
|
def getPercepts(self):
|
|
x, y = self.state
|
|
north_iswall = self.problem.walls[x][y+1]
|
|
south_iswall = self.problem.walls[x][y-1]
|
|
east_iswall = self.problem.walls[x+1][y]
|
|
west_iswall = self.problem.walls[x-1][y]
|
|
return [north_iswall, south_iswall, east_iswall, west_iswall]
|
|
|
|
def getValidActions(self):
|
|
x, y = self.state
|
|
actions = []
|
|
if not self.problem.walls[x][y+1]: actions.append('North')
|
|
if not self.problem.walls[x][y-1]: actions.append('South')
|
|
if not self.problem.walls[x+1][y]: actions.append('East')
|
|
if not self.problem.walls[x-1][y]: actions.append('West')
|
|
return actions
|
|
|
|
def drawWallBeliefs(self, known_map=None, direction="North", visited_states_to_render=[]):
|
|
import random
|
|
import __main__
|
|
from graphicsUtils import draw_background, refresh
|
|
known_walls, known_non_walls = self.get_known_walls_non_walls_from_known_map(known_map)
|
|
wallGrid = Grid(self.problem.walls.width, self.problem.walls.height, initialValue=False)
|
|
wallGrid.data = known_walls
|
|
allTrueWallGrid = Grid(self.problem.walls.width, self.problem.walls.height, initialValue=True)
|
|
self.display.clearExpandedCells() # Erase previous colors
|
|
self.display.drawWalls(wallGrid, formatColor(.9,0,0), allTrueWallGrid)
|
|
refresh()
|
|
|
|
class SLAMLogicAgent(LocalizeMapAgent):
|
|
def __init__(self, fn='slam', prob='SLAMProblem', plan_mod=logicPlan, display=None, scripted_actions=[]):
|
|
super(SLAMLogicAgent, self).__init__(fn, prob, plan_mod, display, scripted_actions)
|
|
self.scripted_actions = scripted_actions
|
|
self.num_timesteps = len(self.scripted_actions) if self.scripted_actions else 10
|
|
self.live_checking = True
|
|
|
|
def getAction(self, state):
|
|
"""
|
|
Returns the next action in the path chosen earlier (in
|
|
registerInitialState). Return Directions.STOP if there is no further
|
|
action to take.
|
|
|
|
state: a GameState object (pacman.py)
|
|
"""
|
|
# import ipdb; ipdb.set_trace()
|
|
if 'actionIndex' not in dir(self): self.actionIndex = 0
|
|
i = self.actionIndex
|
|
self.actionIndex += 1
|
|
pacman_loc = self.visited_states[i]
|
|
|
|
planning_fn_output = None
|
|
if i < self.num_timesteps:
|
|
proposed_action = self.actions[i]
|
|
planning_fn_output = next(self.planning_fn_output)
|
|
if planning_fn_output == None:
|
|
raise Exception('Studenct code supplied None instead of result')
|
|
if isinstance(self.display, graphicsDisplay.PacmanGraphics):
|
|
self.drawWallandPositionBeliefs(
|
|
known_map=planning_fn_output[0],
|
|
possibleLocations=planning_fn_output[1],
|
|
direction=self.actions[i])
|
|
elif i < len(self.actions):
|
|
proposed_action = self.actions[i]
|
|
else:
|
|
proposed_action = "EndGame"
|
|
|
|
# SLAM needs to handle illegal actions
|
|
if proposed_action not in self.getValidActions(pacman_loc) and proposed_action not in ["Stop", "EndGame"]:
|
|
proposed_action = "Stop"
|
|
|
|
return proposed_action, planning_fn_output
|
|
|
|
def moveToNextState(self, action):
|
|
oldX, oldY = self.state
|
|
dx, dy = Actions.directionToVector(action)
|
|
x, y = int(oldX + dx), int(oldY + dy)
|
|
if self.problem.walls[x][y]:
|
|
# raise AssertionError("Taking an action that goes into wall")
|
|
pass
|
|
else:
|
|
self.state = (x, y)
|
|
self.visited_states.append(self.state)
|
|
|
|
def getPercepts(self):
|
|
x, y = self.state
|
|
north_iswall = self.problem.walls[x][y+1]
|
|
south_iswall = self.problem.walls[x][y-1]
|
|
east_iswall = self.problem.walls[x+1][y]
|
|
west_iswall = self.problem.walls[x-1][y]
|
|
num_adj_walls = sum([north_iswall, south_iswall, east_iswall, west_iswall])
|
|
# percept format: [adj_to_>=1_wall, adj_to_>=2_wall, adj_to_>=3_wall]
|
|
percept = [num_adj_walls >= i for i in range(1, 4)]
|
|
return percept
|
|
|
|
def getValidActions(self, state=None):
|
|
if not state:
|
|
state = self.state
|
|
x, y = state
|
|
actions = []
|
|
if not self.problem.walls[x][y+1]: actions.append('North')
|
|
if not self.problem.walls[x][y-1]: actions.append('South')
|
|
if not self.problem.walls[x+1][y]: actions.append('East')
|
|
if not self.problem.walls[x-1][y]: actions.append('West')
|
|
return actions
|
|
|
|
def drawWallandPositionBeliefs(self, known_map=None, possibleLocations=None,
|
|
direction="North", visited_states_to_render=[], pacman_position=None):
|
|
import random
|
|
import __main__
|
|
from graphicsUtils import draw_background, refresh
|
|
known_walls, known_non_walls = self.get_known_walls_non_walls_from_known_map(known_map)
|
|
wallGrid = Grid(self.problem.walls.width, self.problem.walls.height, initialValue=False)
|
|
wallGrid.data = known_walls
|
|
allTrueWallGrid = Grid(self.problem.walls.width, self.problem.walls.height, initialValue=True)
|
|
|
|
# Recover list of non-wall coords:
|
|
non_wall_coords = []
|
|
for x in range(len(known_non_walls)):
|
|
for y in range(len(known_non_walls[x])):
|
|
if known_non_walls[x][y] == 1:
|
|
non_wall_coords.append((x, y))
|
|
|
|
self.display.clearExpandedCells() # Erase previous colors
|
|
|
|
self.display.drawWalls(wallGrid, formatColor(.9,0,0), allTrueWallGrid)
|
|
self.display.colorCircleSquareCells(possibleLocations, square_cells=non_wall_coords, direction=direction, pacman_position=pacman_position)
|
|
refresh()
|
|
|
|
class PositionPlanningProblem(logicPlan.PlanningProblem):
|
|
"""
|
|
A planning problem defines the state space, start state, goal test, successor
|
|
function and cost function. This planning problem can be used to find paths
|
|
to a particular point on the pacman board.
|
|
|
|
The state space consists of (x,y) positions in a pacman game.
|
|
|
|
Note: this planning problem is fully specified; you should NOT change it.
|
|
"""
|
|
|
|
def __init__(self, gameState, costFn = lambda x: 1, goal=(1,1), start=None, warn=True, visualize=True):
|
|
"""
|
|
Stores the start and goal.
|
|
|
|
gameState: A GameState object (pacman.py)
|
|
costFn: A function from a planning state (tuple) to a non-negative number
|
|
goal: A position in the gameState
|
|
"""
|
|
self.walls = gameState.getWalls()
|
|
self.startState = gameState.getPacmanPosition()
|
|
if start != None: self.startState = start
|
|
self.goal = goal
|
|
self.costFn = costFn
|
|
self.visualize = visualize
|
|
if warn and (gameState.getNumFood() != 1 or not gameState.hasFood(*goal)):
|
|
print('Warning: this does not look like a regular position planning maze')
|
|
|
|
# For display purposes
|
|
self._visited, self._visitedlist, self._expanded = {}, [], 0 # DO NOT CHANGE
|
|
|
|
def getStartState(self):
|
|
return self.startState
|
|
|
|
def getGoalState(self):
|
|
return self.goal
|
|
|
|
def getCostOfActions(self, actions):
|
|
"""
|
|
Returns the cost of a particular sequence of actions. If those actions
|
|
include an illegal move, return 999999.
|
|
|
|
This is included in the logic project solely for autograding purposes.
|
|
You should not be calling it.
|
|
"""
|
|
if actions == None: return 999999
|
|
x,y= self.getStartState()
|
|
cost = 0
|
|
for action in actions:
|
|
# Check figure out the next state and see whether it's legal
|
|
dx, dy = Actions.directionToVector(action)
|
|
x, y = int(x + dx), int(y + dy)
|
|
if self.walls[x][y]: return 999999
|
|
cost += self.costFn((x,y))
|
|
return cost
|
|
|
|
def getWidth(self):
|
|
"""
|
|
Returns the width of the playable grid (does not include the external wall)
|
|
Possible x positions for agents will be in range [1,width]
|
|
"""
|
|
return self.walls.width-2
|
|
|
|
def getHeight(self):
|
|
"""
|
|
Returns the height of the playable grid (does not include the external wall)
|
|
Possible y positions for agents will be in range [1,height]
|
|
"""
|
|
return self.walls.height-2
|
|
|
|
def manhattanHeuristic(position, problem, info={}):
|
|
"The Manhattan distance heuristic for a PositionPlanningProblem"
|
|
xy1 = position
|
|
xy2 = problem.goal
|
|
return abs(xy1[0] - xy2[0]) + abs(xy1[1] - xy2[1])
|
|
|
|
def euclideanHeuristic(position, problem, info={}):
|
|
"The Euclidean distance heuristic for a PositionPlanningProblem"
|
|
xy1 = position
|
|
xy2 = problem.goal
|
|
return ( (xy1[0] - xy2[0]) ** 2 + (xy1[1] - xy2[1]) ** 2 ) ** 0.5
|
|
|
|
class LocMapProblem:
|
|
"""Parent class for Localization, Mapping, and SLAM."""
|
|
def __init__(self, gameState, costFn = lambda x: 1, goal=(1,1), start=None, warn=True, visualize=True):
|
|
self.walls = gameState.getWalls()
|
|
self.startState = gameState.getPacmanPosition()
|
|
if start != None: self.startState = start
|
|
self._visited, self._visitedlist, self._expanded = {}, [], 0 # DO NOT CHANGE
|
|
|
|
def getStartState(self):
|
|
return self.startState
|
|
|
|
def getWidth(self):
|
|
"""
|
|
Returns the width of the playable grid (does not include the external wall)
|
|
Possible x positions for agents will be in range [1,width]
|
|
"""
|
|
return self.walls.width-2
|
|
|
|
def getHeight(self):
|
|
"""
|
|
Returns the height of the playable grid (does not include the external wall)
|
|
Possible y positions for agents will be in range [1,height]
|
|
"""
|
|
return self.walls.height-2
|
|
|
|
class LocalizationProblem(LocMapProblem):
|
|
pass
|
|
|
|
class MappingProblem(LocMapProblem):
|
|
pass
|
|
|
|
class SLAMProblem(LocMapProblem):
|
|
pass
|
|
|
|
class FoodPlanningProblem:
|
|
"""
|
|
A planning problem associated with finding the a path that collects all of the
|
|
food (dots) in a Pacman game.
|
|
|
|
A planning state in this problem is a tuple ( pacmanPosition, foodGrid ) where
|
|
pacmanPosition: a tuple (x,y) of integers specifying Pacman's position
|
|
foodGrid: a Grid (see game.py) of either True or False, specifying remaining food
|
|
"""
|
|
def __init__(self, startingGameState):
|
|
self.start = (startingGameState.getPacmanPosition(), startingGameState.getFood())
|
|
self.walls = startingGameState.getWalls()
|
|
self.startingGameState = startingGameState
|
|
self._expanded = 0 # DO NOT CHANGE
|
|
self.heuristicInfo = {} # A dictionary for the heuristic to store information
|
|
|
|
def getStartState(self):
|
|
return self.start
|
|
|
|
def getCostOfActions(self, actions):
|
|
"""Returns the cost of a particular sequence of actions. If those actions
|
|
include an illegal move, return 999999.
|
|
|
|
This is included in the logic project solely for autograding purposes.
|
|
You should not be calling it.
|
|
"""
|
|
x,y= self.getStartState()[0]
|
|
cost = 0
|
|
for action in actions:
|
|
# figure out the next state and see whether it's legal
|
|
dx, dy = Actions.directionToVector(action)
|
|
x, y = int(x + dx), int(y + dy)
|
|
if self.walls[x][y]:
|
|
return 999999
|
|
cost += 1
|
|
return cost
|
|
|
|
def getWidth(self):
|
|
"""
|
|
Returns the width of the playable grid (does not include the external wall)
|
|
Possible x positions for agents will be in range [1,width]
|
|
"""
|
|
return self.walls.width-2
|
|
|
|
def getHeight(self):
|
|
"""
|
|
Returns the height of the playable grid (does not include the external wall)
|
|
Possible y positions for agents will be in range [1,height]
|
|
"""
|
|
return self.walls.height-2
|