Feat: hw2 done
This commit is contained in:
271
HW2_pacman/multiAgents.py
Normal file
271
HW2_pacman/multiAgents.py
Normal file
@@ -0,0 +1,271 @@
|
||||
from util import manhattanDistance
|
||||
from game import Directions
|
||||
import random, util
|
||||
from game import Agent
|
||||
|
||||
class ReflexAgent(Agent):
|
||||
"""
|
||||
A reflex agent chooses an action at each choice point by examining
|
||||
its alternatives via a state evaluation function.
|
||||
|
||||
The code below is provided as a guide. You are welcome to change
|
||||
it in any way you see fit, so long as you don't touch our method
|
||||
headers.
|
||||
"""
|
||||
|
||||
def getAction(self, gameState):
|
||||
"""
|
||||
You do not need to change this method, but you're welcome to.
|
||||
|
||||
getAction chooses among the best options according to the evaluation function.
|
||||
|
||||
Just like in the previous project, getAction takes a GameState and returns
|
||||
some Directions.X for some X in the set {NORTH, SOUTH, WEST, EAST, STOP}
|
||||
"""
|
||||
# Collect legal moves and child states
|
||||
legalMoves = gameState.getLegalActions()
|
||||
|
||||
# Choose one of the best actions
|
||||
scores = [self.evaluationFunction(gameState, action) for action in legalMoves]
|
||||
bestScore = max(scores)
|
||||
bestIndices = [index for index in range(len(scores)) if scores[index] == bestScore]
|
||||
chosenIndex = random.choice(bestIndices) # Pick randomly among the best
|
||||
|
||||
return legalMoves[chosenIndex]
|
||||
|
||||
def evaluationFunction(self, currentGameState, action):
|
||||
"""
|
||||
The evaluation function takes in the current and proposed child
|
||||
GameStates (pacman.py) and returns a number, where higher numbers are better.
|
||||
|
||||
The code below extracts some useful information from the state, like the
|
||||
remaining food (newFood) and Pacman position after moving (newPos).
|
||||
newScaredTimes holds the number of moves that each ghost will remain
|
||||
scared because of Pacman having eaten a power pellet.
|
||||
"""
|
||||
# Useful information you can extract from a GameState (pacman.py)
|
||||
childGameState = currentGameState.getPacmanNextState(action)
|
||||
newPos = childGameState.getPacmanPosition()
|
||||
newFood = childGameState.getFood()
|
||||
newGhostStates = childGameState.getGhostStates()
|
||||
newScaredTimes = [ghostState.scaredTimer for ghostState in newGhostStates]
|
||||
|
||||
minGhostDistance = min([manhattanDistance(newPos, state.getPosition()) for state in newGhostStates])
|
||||
|
||||
scoreDiff = childGameState.getScore() - currentGameState.getScore()
|
||||
|
||||
pos = currentGameState.getPacmanPosition()
|
||||
nearestFoodDistance = min([manhattanDistance(pos, food) for food in currentGameState.getFood().asList()])
|
||||
newFoodsDistances = [manhattanDistance(newPos, food) for food in newFood.asList()]
|
||||
newNearestFoodDistance = 0 if not newFoodsDistances else min(newFoodsDistances)
|
||||
isFoodNearer = nearestFoodDistance - newNearestFoodDistance
|
||||
|
||||
direction = currentGameState.getPacmanState().getDirection()
|
||||
if minGhostDistance <= 1 or action == Directions.STOP:
|
||||
return 0
|
||||
if scoreDiff > 0:
|
||||
return 8
|
||||
elif isFoodNearer > 0:
|
||||
return 4
|
||||
elif action == direction:
|
||||
return 2
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
def scoreEvaluationFunction(currentGameState):
|
||||
"""
|
||||
This default evaluation function just returns the score of the state.
|
||||
The score is the same one displayed in the Pacman GUI.
|
||||
|
||||
This evaluation function is meant for use with adversarial search agents
|
||||
(not reflex agents).
|
||||
"""
|
||||
return currentGameState.getScore()
|
||||
|
||||
|
||||
class MultiAgentSearchAgent(Agent):
|
||||
"""
|
||||
This class provides some common elements to all of your
|
||||
multi-agent searchers. Any methods defined here will be available
|
||||
to the MinimaxPacmanAgent, AlphaBetaPacmanAgent & ExpectimaxPacmanAgent.
|
||||
|
||||
You *do not* need to make any changes here, but you can if you want to
|
||||
add functionality to all your adversarial search agents. Please do not
|
||||
remove anything, however.
|
||||
|
||||
Note: this is an abstract class: one that should not be instantiated. It's
|
||||
only partially specified, and designed to be extended. Agent (game.py)
|
||||
is another abstract class.
|
||||
"""
|
||||
|
||||
def __init__(self, evalFn = 'scoreEvaluationFunction', depth = '2'):
|
||||
self.index = 0 # Pacman is always agent index 0
|
||||
self.evaluationFunction = util.lookup(evalFn, globals())
|
||||
self.depth = int(depth)
|
||||
|
||||
|
||||
class MinimaxAgent(MultiAgentSearchAgent):
|
||||
"""
|
||||
Your minimax agent (Part 1)
|
||||
"""
|
||||
|
||||
def getAction(self, gameState):
|
||||
"""
|
||||
Returns the minimax action from the current gameState using self.depth
|
||||
and self.evaluationFunction.
|
||||
|
||||
Here are some method calls that might be useful when implementing minimax.
|
||||
|
||||
gameState.getLegalActions(agentIndex):
|
||||
Returns a list of legal actions for an agent
|
||||
agentIndex=0 means Pacman, ghosts are >= 1
|
||||
|
||||
gameState.getNextState(agentIndex, action):
|
||||
Returns the child game state after an agent takes an action
|
||||
|
||||
gameState.getNumAgents():
|
||||
Returns the total number of agents in the game
|
||||
|
||||
gameState.isWin():
|
||||
Returns whether or not the game state is a winning state
|
||||
|
||||
gameState.isLose():
|
||||
Returns whether or not the game state is a losing state
|
||||
"""
|
||||
# Begin your code (Part 1)
|
||||
def minimax(s, d, agent):
|
||||
if s.isWin() or s.isLose() or d == 0:
|
||||
return self.evaluationFunction(s), None
|
||||
|
||||
nxt = (agent + 1) % s.getNumAgents()
|
||||
d2 = d - 1 if nxt == 0 else d
|
||||
actions = s.getLegalActions(agent)
|
||||
|
||||
if agent == 0:
|
||||
best = (float('-inf'), None)
|
||||
for a in actions:
|
||||
v = minimax(s.getNextState(agent, a), d2, nxt)[0]
|
||||
if v > best[0]:
|
||||
best = (v, a)
|
||||
return best
|
||||
else:
|
||||
best = (float('inf'), None)
|
||||
for a in actions:
|
||||
v = minimax(s.getNextState(agent, a), d2, nxt)[0]
|
||||
if v < best[0]:
|
||||
best = (v, a)
|
||||
return best
|
||||
|
||||
return minimax(gameState, self.depth, 0)[1]
|
||||
# End your code (Part 1)
|
||||
|
||||
|
||||
class AlphaBetaAgent(MultiAgentSearchAgent):
|
||||
"""
|
||||
Your minimax agent with alpha-beta pruning (Part 2)
|
||||
"""
|
||||
|
||||
def getAction(self, gameState):
|
||||
"""
|
||||
Returns the minimax action using self.depth and self.evaluationFunction
|
||||
"""
|
||||
# Begin your code (Part 2)
|
||||
def ab(s, d, agent, a, b):
|
||||
if s.isWin() or s.isLose() or d == 0:
|
||||
return self.evaluationFunction(s), None
|
||||
|
||||
nxt = (agent + 1) % s.getNumAgents()
|
||||
d2 = d - 1 if nxt == 0 else d
|
||||
actions = s.getLegalActions(agent)
|
||||
|
||||
if agent == 0:
|
||||
best = (float('-inf'), None)
|
||||
for act in actions:
|
||||
v = ab(s.getNextState(agent, act), d2, nxt, a, b)[0]
|
||||
if v > best[0]:
|
||||
best = (v, act)
|
||||
if best[0] > b:
|
||||
return best
|
||||
a = max(a, best[0])
|
||||
return best
|
||||
else:
|
||||
best = (float('inf'), None)
|
||||
for act in actions:
|
||||
v = ab(s.getNextState(agent, act), d2, nxt, a, b)[0]
|
||||
if v < best[0]:
|
||||
best = (v, act)
|
||||
if best[0] < a:
|
||||
return best
|
||||
b = min(b, best[0])
|
||||
return best
|
||||
|
||||
return ab(gameState, self.depth, 0, float('-inf'), float('inf'))[1]
|
||||
# End your code (Part 2)
|
||||
|
||||
|
||||
class ExpectimaxAgent(MultiAgentSearchAgent):
|
||||
"""
|
||||
Your expectimax agent (Part 3)
|
||||
"""
|
||||
|
||||
def getAction(self, gameState):
|
||||
"""
|
||||
Returns the expectimax action using self.depth and self.evaluationFunction
|
||||
|
||||
All ghosts should be modeled as choosing uniformly at random from their
|
||||
legal moves.
|
||||
"""
|
||||
# Begin your code (Part 3)
|
||||
def expmax(s, d, agent):
|
||||
if s.isWin() or s.isLose() or d == 0:
|
||||
return self.evaluationFunction(s), None
|
||||
|
||||
nxt = (agent + 1) % s.getNumAgents()
|
||||
d2 = d - 1 if nxt == 0 else d
|
||||
actions = s.getLegalActions(agent)
|
||||
|
||||
if agent == 0:
|
||||
best = (float('-inf'), None)
|
||||
for a in actions:
|
||||
v = expmax(s.getNextState(agent, a), d2, nxt)[0]
|
||||
if v > best[0]:
|
||||
best = (v, a)
|
||||
return best
|
||||
else:
|
||||
vals = [expmax(s.getNextState(agent, a), d2, nxt)[0] for a in actions]
|
||||
return sum(vals) / len(vals), None
|
||||
|
||||
return expmax(gameState, self.depth, 0)[1]
|
||||
# End your code (Part 3)
|
||||
|
||||
|
||||
def betterEvaluationFunction(currentGameState):
|
||||
"""
|
||||
Your extreme ghost-hunting, pellet-nabbing, food-gobbling, unstoppable
|
||||
evaluation function (Part 4).
|
||||
"""
|
||||
# Begin your code (Part 4)
|
||||
pos = currentGameState.getPacmanPosition()
|
||||
foodList = currentGameState.getFood().asList()
|
||||
ghosts = currentGameState.getGhostStates()
|
||||
|
||||
score = currentGameState.getScore()
|
||||
score -= 10 * len(foodList)
|
||||
score -= 20 * len(currentGameState.getCapsules())
|
||||
|
||||
if foodList:
|
||||
score += 1.0 / min(manhattanDistance(pos, f) for f in foodList)
|
||||
|
||||
for g in ghosts:
|
||||
d = manhattanDistance(pos, g.getPosition())
|
||||
if g.scaredTimer > 0:
|
||||
score += 200 / (d + 1)
|
||||
else:
|
||||
score -= 10000 / (10 ** d)
|
||||
|
||||
return score
|
||||
# End your code (Part 4)
|
||||
|
||||
# Abbreviation
|
||||
better = betterEvaluationFunction
|
||||
Reference in New Issue
Block a user