getting right starter files

This commit is contained in:
Arjun Patel
2019-02-20 15:24:24 -08:00
parent 48d11417be
commit ade293719f
358 changed files with 8770 additions and 4878 deletions
+194 -140
View File
@@ -4,7 +4,7 @@
# 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
# ([email protected]) and Dan Klein ([email protected]).
@@ -45,13 +45,19 @@ from game import Directions
from game import Actions
from util import nearestPoint
from util import manhattanDistance
import util, layout
import sys, types, time, random, os
import util
import layout
import sys
import types
import time
import random
import os
###################################################
# YOUR INTERFACE TO THE PACMAN WORLD: A GameState #
###################################################
class GameState:
"""
A GameState specifies the full game state, including the food, capsules,
@@ -73,30 +79,33 @@ class GameState:
# static variable keeps track of which states have had getLegalActions called
explored = set()
def getAndResetExplored():
tmp = GameState.explored.copy()
GameState.explored = set()
return tmp
getAndResetExplored = staticmethod(getAndResetExplored)
def getLegalActions( self, agentIndex=0 ):
def getLegalActions(self, agentIndex=0):
"""
Returns the legal actions for the agent specified.
"""
# GameState.explored.add(self)
if self.isWin() or self.isLose(): return []
if self.isWin() or self.isLose():
return []
if agentIndex == 0: # Pacman is moving
return PacmanRules.getLegalActions( self )
return PacmanRules.getLegalActions(self)
else:
return GhostRules.getLegalActions( self, agentIndex )
return GhostRules.getLegalActions(self, agentIndex)
def generateSuccessor( self, agentIndex, action):
def generateSuccessor(self, agentIndex, action):
"""
Returns the successor state after the specified agent takes the action.
"""
# Check that successors exist
if self.isWin() or self.isLose(): raise Exception('Can\'t generate a successor of a terminal state.')
if self.isWin() or self.isLose():
raise Exception('Can\'t generate a successor of a terminal state.')
# Copy current state
state = GameState(self)
@@ -104,18 +113,18 @@ class GameState:
# Let agent's logic deal with its action's effects on the board
if agentIndex == 0: # Pacman is moving
state.data._eaten = [False for i in range(state.getNumAgents())]
PacmanRules.applyAction( state, action )
PacmanRules.applyAction(state, action)
else: # A ghost is moving
GhostRules.applyAction( state, action, agentIndex )
GhostRules.applyAction(state, action, agentIndex)
# Time passes
if agentIndex == 0:
state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around
state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around
else:
GhostRules.decrementTimer( state.data.agentStates[agentIndex] )
GhostRules.decrementTimer(state.data.agentStates[agentIndex])
# Resolve multi-agent effects
GhostRules.checkDeath( state, agentIndex )
GhostRules.checkDeath(state, agentIndex)
# Book keeping
state.data._agentMoved = agentIndex
@@ -124,16 +133,16 @@ class GameState:
GameState.explored.add(state)
return state
def getLegalPacmanActions( self ):
return self.getLegalActions( 0 )
def getLegalPacmanActions(self):
return self.getLegalActions(0)
def generatePacmanSuccessor( self, action ):
def generatePacmanSuccessor(self, action):
"""
Generates the successor state after the specified pacman move
"""
return self.generateSuccessor( 0, action )
return self.generateSuccessor(0, action)
def getPacmanState( self ):
def getPacmanState(self):
"""
Returns an AgentState object for pacman (in game.py)
@@ -142,18 +151,18 @@ class GameState:
"""
return self.data.agentStates[0].copy()
def getPacmanPosition( self ):
def getPacmanPosition(self):
return self.data.agentStates[0].getPosition()
def getGhostStates( self ):
def getGhostStates(self):
return self.data.agentStates[1:]
def getGhostState( self, agentIndex ):
def getGhostState(self, agentIndex):
if agentIndex == 0 or agentIndex >= self.getNumAgents():
raise Exception("Invalid index passed to getGhostState")
return self.data.agentStates[agentIndex]
def getGhostPosition( self, agentIndex ):
def getGhostPosition(self, agentIndex):
if agentIndex == 0:
raise Exception("Pacman's index passed to getGhostPosition")
return self.data.agentStates[agentIndex].getPosition()
@@ -161,10 +170,10 @@ class GameState:
def getGhostPositions(self):
return [s.getPosition() for s in self.getGhostStates()]
def getNumAgents( self ):
return len( self.data.agentStates )
def getNumAgents(self):
return len(self.data.agentStates)
def getScore( self ):
def getScore(self):
return float(self.data.score)
def getCapsules(self):
@@ -173,7 +182,7 @@ class GameState:
"""
return self.data.capsules
def getNumFood( self ):
def getNumFood(self):
return self.data.food.count()
def getFood(self):
@@ -206,10 +215,10 @@ class GameState:
def hasWall(self, x, y):
return self.data.layout.walls[x][y]
def isLose( self ):
def isLose(self):
return self.data._lose
def isWin( self ):
def isWin(self):
return self.data._win
#############################################
@@ -217,37 +226,37 @@ class GameState:
# You shouldn't need to call these directly #
#############################################
def __init__( self, prevState = None ):
def __init__(self, prevState=None):
"""
Generates a new state by copying information from its predecessor.
"""
if prevState != None: # Initial state
if prevState != None: # Initial state
self.data = GameStateData(prevState.data)
else:
self.data = GameStateData()
def deepCopy( self ):
state = GameState( self )
def deepCopy(self):
state = GameState(self)
state.data = self.data.deepCopy()
return state
def __eq__( self, other ):
def __eq__(self, other):
"""
Allows two states to be compared.
"""
return hasattr(other, 'data') and self.data == other.data
def __hash__( self ):
def __hash__(self):
"""
Allows states to be keys of dictionaries.
"""
return hash( self.data )
return hash(self.data)
def __str__( self ):
def __str__(self):
return str(self.data)
def initialize( self, layout, numGhostAgents=1000 ):
def initialize(self, layout, numGhostAgents=1000):
"""
Creates an initial game state from a layout array (see layout.py).
"""
@@ -259,22 +268,25 @@ class GameState:
# You shouldn't need to look through the code in this section of the file. #
############################################################################
SCARED_TIME = 40 # Moves ghosts are scared
COLLISION_TOLERANCE = 0.7 # How close ghosts must be to Pacman to kill
TIME_PENALTY = 1 # Number of points lost each round
COLLISION_TOLERANCE = 0.7 # How close ghosts must be to Pacman to kill
TIME_PENALTY = 1 # Number of points lost each round
class ClassicGameRules:
"""
These game rules manage the control flow of a game, deciding when
and how the game starts and ends.
"""
def __init__(self, timeout=30):
self.timeout = timeout
def newGame( self, layout, pacmanAgent, ghostAgents, display, quiet = False, catchExceptions=False):
def newGame(self, layout, pacmanAgent, ghostAgents, display, quiet=False, catchExceptions=False):
agents = [pacmanAgent] + ghostAgents[:layout.getNumGhosts()]
initState = GameState()
initState.initialize( layout, len(ghostAgents) )
initState.initialize(layout, len(ghostAgents))
game = Game(agents, display, self, catchExceptions=catchExceptions)
game.state = initState
self.initialState = initState.deepCopy()
@@ -285,15 +297,19 @@ class ClassicGameRules:
"""
Checks to see whether it is time to end the game.
"""
if state.isWin(): self.win(state, game)
if state.isLose(): self.lose(state, game)
if state.isWin():
self.win(state, game)
if state.isLose():
self.lose(state, game)
def win( self, state, game ):
if not self.quiet: print("Pacman emerges victorious! Score: %d" % state.data.score)
def win(self, state, game):
if not self.quiet:
print("Pacman emerges victorious! Score: %d" % state.data.score)
game.gameOver = True
def lose( self, state, game ):
if not self.quiet: print("Pacman died! Score: %d" % state.data.score)
def lose(self, state, game):
if not self.quiet:
print("Pacman died! Score: %d" % state.data.score)
game.gameOver = True
def getProgress(self, game):
@@ -320,44 +336,46 @@ class ClassicGameRules:
def getMaxTimeWarnings(self, agentIndex):
return 0
class PacmanRules:
"""
These functions govern how pacman interacts with his environment under
the classic game rules.
"""
PACMAN_SPEED=1
PACMAN_SPEED = 1
def getLegalActions( state ):
def getLegalActions(state):
"""
Returns a list of possible actions.
"""
return Actions.getPossibleActions( state.getPacmanState().configuration, state.data.layout.walls )
getLegalActions = staticmethod( getLegalActions )
return Actions.getPossibleActions(state.getPacmanState().configuration, state.data.layout.walls)
getLegalActions = staticmethod(getLegalActions)
def applyAction( state, action ):
def applyAction(state, action):
"""
Edits the state to reflect the results of the action.
"""
legal = PacmanRules.getLegalActions( state )
legal = PacmanRules.getLegalActions(state)
if action not in legal:
raise Exception("Illegal action " + str(action))
pacmanState = state.data.agentStates[0]
# Update Configuration
vector = Actions.directionToVector( action, PacmanRules.PACMAN_SPEED )
pacmanState.configuration = pacmanState.configuration.generateSuccessor( vector )
vector = Actions.directionToVector(action, PacmanRules.PACMAN_SPEED)
pacmanState.configuration = pacmanState.configuration.generateSuccessor(
vector)
# Eat
next = pacmanState.configuration.getPosition()
nearest = nearestPoint( next )
if manhattanDistance( nearest, next ) <= 0.5 :
nearest = nearestPoint(next)
if manhattanDistance(nearest, next) <= 0.5:
# Remove food
PacmanRules.consume( nearest, state )
applyAction = staticmethod( applyAction )
PacmanRules.consume(nearest, state)
applyAction = staticmethod(applyAction)
def consume( position, state ):
x,y = position
def consume(position, state):
x, y = position
# Eat food
if state.data.food[x][y]:
state.data.scoreChange += 10
@@ -370,70 +388,76 @@ class PacmanRules:
state.data.scoreChange += 500
state.data._win = True
# Eat capsule
if( position in state.getCapsules() ):
state.data.capsules.remove( position )
if(position in state.getCapsules()):
state.data.capsules.remove(position)
state.data._capsuleEaten = position
# Reset all ghosts' scared timers
for index in range( 1, len( state.data.agentStates ) ):
for index in range(1, len(state.data.agentStates)):
state.data.agentStates[index].scaredTimer = SCARED_TIME
consume = staticmethod( consume )
consume = staticmethod(consume)
class GhostRules:
"""
These functions dictate how ghosts interact with their environment.
"""
GHOST_SPEED=1.0
def getLegalActions( state, ghostIndex ):
GHOST_SPEED = 1.0
def getLegalActions(state, ghostIndex):
"""
Ghosts cannot stop, and cannot turn around unless they
reach a dead end, but can turn 90 degrees at intersections.
"""
conf = state.getGhostState( ghostIndex ).configuration
possibleActions = Actions.getPossibleActions( conf, state.data.layout.walls )
reverse = Actions.reverseDirection( conf.direction )
conf = state.getGhostState(ghostIndex).configuration
possibleActions = Actions.getPossibleActions(
conf, state.data.layout.walls)
reverse = Actions.reverseDirection(conf.direction)
if Directions.STOP in possibleActions:
possibleActions.remove( Directions.STOP )
if reverse in possibleActions and len( possibleActions ) > 1:
possibleActions.remove( reverse )
possibleActions.remove(Directions.STOP)
if reverse in possibleActions and len(possibleActions) > 1:
possibleActions.remove(reverse)
return possibleActions
getLegalActions = staticmethod( getLegalActions )
getLegalActions = staticmethod(getLegalActions)
def applyAction( state, action, ghostIndex):
def applyAction(state, action, ghostIndex):
legal = GhostRules.getLegalActions( state, ghostIndex )
legal = GhostRules.getLegalActions(state, ghostIndex)
if action not in legal:
raise Exception("Illegal ghost action " + str(action))
ghostState = state.data.agentStates[ghostIndex]
speed = GhostRules.GHOST_SPEED
if ghostState.scaredTimer > 0: speed /= 2.0
vector = Actions.directionToVector( action, speed )
ghostState.configuration = ghostState.configuration.generateSuccessor( vector )
applyAction = staticmethod( applyAction )
if ghostState.scaredTimer > 0:
speed /= 2.0
vector = Actions.directionToVector(action, speed)
ghostState.configuration = ghostState.configuration.generateSuccessor(
vector)
applyAction = staticmethod(applyAction)
def decrementTimer( ghostState):
def decrementTimer(ghostState):
timer = ghostState.scaredTimer
if timer == 1:
ghostState.configuration.pos = nearestPoint( ghostState.configuration.pos )
ghostState.scaredTimer = max( 0, timer - 1 )
decrementTimer = staticmethod( decrementTimer )
ghostState.configuration.pos = nearestPoint(
ghostState.configuration.pos)
ghostState.scaredTimer = max(0, timer - 1)
decrementTimer = staticmethod(decrementTimer)
def checkDeath( state, agentIndex):
def checkDeath(state, agentIndex):
pacmanPosition = state.getPacmanPosition()
if agentIndex == 0: # Pacman just moved; Anyone can kill him
for index in range( 1, len( state.data.agentStates ) ):
if agentIndex == 0: # Pacman just moved; Anyone can kill him
for index in range(1, len(state.data.agentStates)):
ghostState = state.data.agentStates[index]
ghostPosition = ghostState.configuration.getPosition()
if GhostRules.canKill( pacmanPosition, ghostPosition ):
GhostRules.collide( state, ghostState, index )
if GhostRules.canKill(pacmanPosition, ghostPosition):
GhostRules.collide(state, ghostState, index)
else:
ghostState = state.data.agentStates[agentIndex]
ghostPosition = ghostState.configuration.getPosition()
if GhostRules.canKill( pacmanPosition, ghostPosition ):
GhostRules.collide( state, ghostState, agentIndex )
checkDeath = staticmethod( checkDeath )
if GhostRules.canKill(pacmanPosition, ghostPosition):
GhostRules.collide(state, ghostState, agentIndex)
checkDeath = staticmethod(checkDeath)
def collide( state, ghostState, agentIndex):
def collide(state, ghostState, agentIndex):
if ghostState.scaredTimer > 0:
state.data.scoreChange += 200
GhostRules.placeGhost(state, ghostState)
@@ -444,36 +468,40 @@ class GhostRules:
if not state.data._win:
state.data.scoreChange -= 500
state.data._lose = True
collide = staticmethod( collide )
collide = staticmethod(collide)
def canKill( pacmanPosition, ghostPosition ):
return manhattanDistance( ghostPosition, pacmanPosition ) <= COLLISION_TOLERANCE
canKill = staticmethod( canKill )
def canKill(pacmanPosition, ghostPosition):
return manhattanDistance(ghostPosition, pacmanPosition) <= COLLISION_TOLERANCE
canKill = staticmethod(canKill)
def placeGhost(state, ghostState):
ghostState.configuration = ghostState.start
placeGhost = staticmethod( placeGhost )
placeGhost = staticmethod(placeGhost)
#############################
# FRAMEWORK TO START A GAME #
#############################
def default(str):
return str + ' [Default: %default]'
def parseAgentArgs(str):
if str == None: return {}
if str == None:
return {}
pieces = str.split(',')
opts = {}
for p in pieces:
if '=' in p:
key, val = p.split('=')
else:
key,val = p, 1
key, val = p, 1
opts[key] = val
return opts
def readCommand( argv ):
def readCommand(argv):
"""
Processes the command used to run pacman from the command line.
"""
@@ -491,18 +519,21 @@ def readCommand( argv ):
parser.add_option('-n', '--numGames', dest='numGames', type='int',
help=default('the number of GAMES to play'), metavar='GAMES', default=1)
parser.add_option('-l', '--layout', dest='layout',
help=default('the LAYOUT_FILE from which to load the map layout'),
help=default(
'the LAYOUT_FILE from which to load the map layout'),
metavar='LAYOUT_FILE', default='mediumClassic')
parser.add_option('-p', '--pacman', dest='pacman',
help=default('the agent TYPE in the pacmanAgents module to use'),
help=default(
'the agent TYPE in the pacmanAgents module to use'),
metavar='TYPE', default='KeyboardAgent')
parser.add_option('-t', '--textGraphics', action='store_true', dest='textGraphics',
help='Display output as text only', default=False)
parser.add_option('-q', '--quietTextGraphics', action='store_true', dest='quietGraphics',
help='Generate minimal output and no graphics', default=False)
parser.add_option('-g', '--ghosts', dest='ghost',
help=default('the ghost agent TYPE in the ghostAgents module to use'),
metavar = 'TYPE', default='RandomGhost')
help=default(
'the ghost agent TYPE in the ghostAgents module to use'),
metavar='TYPE', default='RandomGhost')
parser.add_option('-k', '--numghosts', type='int', dest='numGhosts',
help=default('The maximum number of ghosts to use'), default=4)
parser.add_option('-z', '--zoom', type='float', dest='zoom',
@@ -513,7 +544,7 @@ def readCommand( argv ):
help='Writes game histories to a file (named by the time they were played)', default=False)
parser.add_option('--replay', dest='gameToReplay',
help='A recorded game file (pickle) to replay', default=None)
parser.add_option('-a','--agentArgs',dest='agentArgs',
parser.add_option('-a', '--agentArgs', dest='agentArgs',
help='Comma separated values sent to agent. e.g. "opt1=val1,opt2,opt3=val3"')
parser.add_option('-x', '--numTraining', dest='numTraining', type='int',
help=default('How many episodes are training (suppresses output)'), default=0)
@@ -530,20 +561,24 @@ def readCommand( argv ):
args = dict()
# Fix the random seed
if options.fixRandomSeed: random.seed('cs188')
if options.fixRandomSeed:
random.seed('cs188')
# Choose a layout
args['layout'] = layout.getLayout( options.layout )
if args['layout'] == None: raise Exception("The layout " + options.layout + " cannot be found")
args['layout'] = layout.getLayout(options.layout)
if args['layout'] == None:
raise Exception("The layout " + options.layout + " cannot be found")
# Choose a Pacman agent
noKeyboard = options.gameToReplay == None and (options.textGraphics or options.quietGraphics)
noKeyboard = options.gameToReplay == None and (
options.textGraphics or options.quietGraphics)
pacmanType = loadAgent(options.pacman, noKeyboard)
agentOpts = parseAgentArgs(options.agentArgs)
if options.numTraining > 0:
args['numTraining'] = options.numTraining
if 'numTraining' not in agentOpts: agentOpts['numTraining'] = options.numTraining
pacman = pacmanType(**agentOpts) # Instantiate Pacman with agentArgs
if 'numTraining' not in agentOpts:
agentOpts['numTraining'] = options.numTraining
pacman = pacmanType(**agentOpts) # Instantiate Pacman with agentArgs
args['pacman'] = pacman
# Don't display training games
@@ -553,7 +588,7 @@ def readCommand( argv ):
# Choose a ghost agent
ghostType = loadAgent(options.ghost, noKeyboard)
args['ghosts'] = [ghostType( i+1 ) for i in range( options.numGhosts )]
args['ghosts'] = [ghostType(i+1) for i in range(options.numGhosts)]
# Choose a display format
if options.quietGraphics:
@@ -565,7 +600,8 @@ def readCommand( argv ):
args['display'] = textDisplay.PacmanGraphics()
else:
import graphicsDisplay
args['display'] = graphicsDisplay.PacmanGraphics(options.zoom, frameTime = options.frameTime)
args['display'] = graphicsDisplay.PacmanGraphics(
options.zoom, frameTime=options.frameTime)
args['numGames'] = options.numGames
args['record'] = options.record
args['catchExceptions'] = options.catchExceptions
@@ -575,15 +611,18 @@ def readCommand( argv ):
if options.gameToReplay != None:
print('Replaying recorded game %s.' % options.gameToReplay)
import pickle
f = open(options.gameToReplay, 'rb')
try: recorded = pickle.load(f)
finally: f.close()
f = open(options.gameToReplay)
try:
recorded = pickle.load(f)
finally:
f.close()
recorded['display'] = args['display']
replayGame(**recorded)
sys.exit(0)
return args
def loadAgent(pacman, nographics):
# Looks through all pythonPath Directories for the right module,
pythonPathStr = os.path.expandvars("$PYTHONPATH")
@@ -594,8 +633,10 @@ def loadAgent(pacman, nographics):
pythonPathDirs.append('.')
for moduleDir in pythonPathDirs:
if not os.path.isdir(moduleDir): continue
moduleNames = [f for f in os.listdir(moduleDir) if f.endswith('gents.py')]
if not os.path.isdir(moduleDir):
continue
moduleNames = [f for f in os.listdir(
moduleDir) if f.endswith('gents.py')]
for modulename in moduleNames:
try:
module = __import__(modulename[:-3])
@@ -603,36 +644,42 @@ def loadAgent(pacman, nographics):
continue
if pacman in dir(module):
if nographics and modulename == 'keyboardAgents.py':
raise Exception('Using the keyboard requires graphics (not text display)')
raise Exception(
'Using the keyboard requires graphics (not text display)')
return getattr(module, pacman)
raise Exception('The agent ' + pacman + ' is not specified in any *Agents.py.')
raise Exception('The agent ' + pacman +
' is not specified in any *Agents.py.')
def replayGame( layout, actions, display ):
import pacmanAgents, ghostAgents
def replayGame(layout, actions, display):
import pacmanAgents
import ghostAgents
rules = ClassicGameRules()
agents = [pacmanAgents.GreedyAgent()] + [ghostAgents.RandomGhost(i+1) for i in range(layout.getNumGhosts())]
game = rules.newGame( layout, agents[0], agents[1:], display )
agents = [pacmanAgents.GreedyAgent()] + [ghostAgents.RandomGhost(i+1)
for i in range(layout.getNumGhosts())]
game = rules.newGame(layout, agents[0], agents[1:], display)
state = game.state
display.initialize(state.data)
for action in actions:
# Execute the action
state = state.generateSuccessor( *action )
state = state.generateSuccessor(*action)
# Change the display
display.update( state.data )
display.update(state.data)
# Allow for game specific conditions (winning, losing, etc.)
rules.process(state, game)
display.finish()
def runGames( layout, pacman, ghosts, display, numGames, record, numTraining = 0, catchExceptions=False, timeout=30 ):
def runGames(layout, pacman, ghosts, display, numGames, record, numTraining=0, catchExceptions=False, timeout=30):
import __main__
__main__.__dict__['_display'] = display
rules = ClassicGameRules(timeout)
games = []
for i in range( numGames ):
for i in range(numGames):
beQuiet = i < numTraining
if beQuiet:
# Suppress output and graphics
@@ -642,14 +689,18 @@ def runGames( layout, pacman, ghosts, display, numGames, record, numTraining = 0
else:
gameDisplay = display
rules.quiet = False
game = rules.newGame( layout, pacman, ghosts, gameDisplay, beQuiet, catchExceptions)
game = rules.newGame(layout, pacman, ghosts,
gameDisplay, beQuiet, catchExceptions)
game.run()
if not beQuiet: games.append(game)
if not beQuiet:
games.append(game)
if record:
import time, pickle
fname = ('recorded-game-%d' % (i + 1)) + '-'.join([str(t) for t in time.localtime()[1:6]])
f = open(fname, 'wb')
import time
import pickle
fname = ('recorded-game-%d' % (i + 1)) + \
'-'.join([str(t) for t in time.localtime()[1:6]])
f = file(fname, 'w')
components = {'layout': layout, 'actions': game.moveHistory}
pickle.dump(components, f)
f.close()
@@ -657,14 +708,17 @@ def runGames( layout, pacman, ghosts, display, numGames, record, numTraining = 0
if (numGames-numTraining) > 0:
scores = [game.state.getScore() for game in games]
wins = [game.state.isWin() for game in games]
winRate = wins.count(True)/ float(len(wins))
winRate = wins.count(True) / float(len(wins))
print('Average Score:', sum(scores) / float(len(scores)))
print('Scores: ', ', '.join([str(score) for score in scores]))
print('Win Rate: %d/%d (%.2f)' % (wins.count(True), len(wins), winRate))
print('Record: ', ', '.join([ ['Loss', 'Win'][int(w)] for w in wins]))
print('Win Rate: %d/%d (%.2f)' %
(wins.count(True), len(wins), winRate))
print('Record: ', ', '.join(
[['Loss', 'Win'][int(w)] for w in wins]))
return games
if __name__ == '__main__':
"""
The main function called when pacman.py is run
@@ -676,8 +730,8 @@ if __name__ == '__main__':
> python pacman.py --help
"""
args = readCommand( sys.argv[1:] ) # Get game components based on input
runGames( **args )
args = readCommand(sys.argv[1:]) # Get game components based on input
runGames(**args)
# import cProfile
# cProfile.run("runGames( **args )")