Register
Login
Resources
Docs Blog Datasets Glossary Case Studies Tutorials & Webinars
Product
Data Engine LLMs Platform Enterprise
Pricing Explore
Connect to our Discord channel

pacman.py 26 KB

You have to be logged in to leave a comment. Sign In
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
  1. # pacman.py
  2. # ---------
  3. # Licensing Information: Please do not distribute or publish solutions to this
  4. # project. You are free to use and extend these projects for educational
  5. # purposes. The Pacman AI projects were developed at UC Berkeley, primarily by
  6. # John DeNero (denero@cs.berkeley.edu) and Dan Klein (klein@cs.berkeley.edu).
  7. # For more info, see http://inst.eecs.berkeley.edu/~cs188/sp09/pacman.html
  8. """
  9. Pacman.py holds the logic for the classic pacman game along with the main
  10. code to run a game. This file is divided into three sections:
  11. (i) Your interface to the pacman world:
  12. Pacman is a complex environment. You probably don't want to
  13. read through all of the code we wrote to make the game runs
  14. correctly. This section contains the parts of the code
  15. that you will need to understand in order to complete the
  16. project. There is also some code in game.py that you should
  17. understand.
  18. (ii) The hidden secrets of pacman:
  19. This section contains all of the logic code that the pacman
  20. environment uses to decide who can move where, who dies when
  21. things collide, etc. You shouldn't need to read this section
  22. of code, but you can if you want.
  23. (iii) Framework to start a game:
  24. The final section contains the code for reading the command
  25. you use to set up the game, then starting up a new game, along with
  26. linking in all the external parts (agent functions, graphics).
  27. Check this section out to see all the options available to you.
  28. To play your first game, type 'python pacman.py' from the command line.
  29. The keys are 'a', 's', 'd', and 'w' to move (or arrow keys). Have fun!
  30. """
  31. from utilities.game import GameStateData
  32. from utilities.game import Game
  33. from utilities.game import Directions
  34. from utilities.game import Actions
  35. from utilities.util import nearestPoint
  36. from utilities.util import manhattanDistance
  37. from utilities import layout
  38. import sys, random, os
  39. ###################################################
  40. # YOUR INTERFACE TO THE PACMAN WORLD: A GameState #
  41. ###################################################
  42. class GameState:
  43. """
  44. A GameState specifies the full game state, including the food, capsules,
  45. agent configurations and score changes.
  46. GameStates are used by the Game object to capture the actual state of the game and
  47. can be used by agents to reason about the game.
  48. Much of the information in a GameState is stored in a GameStateData object. We
  49. strongly suggest that you access that data via the accessor methods below rather
  50. than referring to the GameStateData object directly.
  51. Note that in classic Pacman, Pacman is always agent 0.
  52. """
  53. ####################################################
  54. # Accessor methods: use these to access state data #
  55. ####################################################
  56. def getLegalActions(self, agentIndex=0):
  57. """
  58. Returns the legal actions for the agent specified.
  59. """
  60. if self.isWin() or self.isLose(): return []
  61. if agentIndex == 0: # Pacman is moving
  62. return PacmanRules.getLegalActions(self)
  63. else:
  64. return GhostRules.getLegalActions(self, agentIndex)
  65. def generateSuccessor(self, agentIndex, action):
  66. """
  67. Returns the successor state after the specified agent takes the action.
  68. """
  69. # Check that successors exist
  70. if self.isWin() or self.isLose(): raise Exception(
  71. 'Can\'t generate a successor of a terminal state.')
  72. # Copy current state
  73. state = GameState(self)
  74. # Let agent's logic deal with its action's effects on the board
  75. if agentIndex == 0: # Pacman is moving
  76. state.data._eaten = [False for i in range(state.getNumAgents())]
  77. PacmanRules.applyAction(state, action)
  78. else: # A ghost is moving
  79. GhostRules.applyAction(state, action, agentIndex)
  80. # Time passes
  81. if agentIndex == 0:
  82. state.data.scoreChange += -TIME_PENALTY # Penalty for waiting around
  83. else:
  84. GhostRules.decrementTimer(state.data.agentStates[agentIndex])
  85. # Resolve multi-agent effects
  86. GhostRules.checkDeath(state, agentIndex)
  87. # Book keeping
  88. state.data._agentMoved = agentIndex
  89. state.data.score += state.data.scoreChange
  90. # print(state.data.score)
  91. return state
  92. def getLegalPacmanActions(self):
  93. return self.getLegalActions(0)
  94. def generatePacmanSuccessor(self, action):
  95. """
  96. Generates the successor state after the specified pacman move
  97. """
  98. return self.generateSuccessor(0, action)
  99. def getPacmanState(self):
  100. """
  101. Returns an AgentState object for pacman (in game.py)
  102. state.pos gives the current position
  103. state.direction gives the travel vector
  104. """
  105. return self.data.agentStates[0].copy()
  106. def getPacmanPosition(self):
  107. return self.data.agentStates[0].getPosition()
  108. def getGhostStates(self):
  109. return self.data.agentStates[1:]
  110. def getGhostState(self, agentIndex):
  111. if agentIndex == 0 or agentIndex >= self.getNumAgents():
  112. raise Exception("Invalid index passed to getGhostState")
  113. return self.data.agentStates[agentIndex]
  114. def getGhostPosition(self, agentIndex):
  115. if agentIndex == 0:
  116. raise Exception("Pacman's index passed to getGhostPosition")
  117. return self.data.agentStates[agentIndex].getPosition()
  118. def getGhostPositions(self):
  119. return [s.getPosition() for s in self.getGhostStates()]
  120. def getNumAgents(self):
  121. return len(self.data.agentStates)
  122. def getScore(self):
  123. return self.data.score
  124. def getCapsules(self):
  125. """
  126. Returns a list of positions (x,y) of the remaining capsules.
  127. """
  128. return self.data.capsules
  129. def getNumFood(self):
  130. return self.data.food.count()
  131. def getFood(self):
  132. """
  133. Returns a Grid of boolean food indicator variables.
  134. Grids can be accessed via list notation, so to check
  135. if there is food at (x,y), just call
  136. currentFood = state.getFood()
  137. if currentFood[x][y] == True: ...
  138. """
  139. return self.data.food
  140. def getWalls(self):
  141. """
  142. Returns a Grid of boolean wall indicator variables.
  143. Grids can be accessed via list notation, so to check
  144. if there is food at (x,y), just call
  145. walls = state.getWalls()
  146. if walls[x][y] == True: ...
  147. """
  148. return self.data.layout.walls
  149. def hasFood(self, x, y):
  150. return self.data.food[x][y]
  151. def hasWall(self, x, y):
  152. return self.data.layout.walls[x][y]
  153. def isLose(self):
  154. return self.data._lose
  155. def isWin(self):
  156. return self.data._win
  157. #############################################
  158. # Helper methods: #
  159. # You shouldn't need to call these directly #
  160. #############################################
  161. def __init__(self, prevState=None):
  162. """
  163. Generates a new state by copying information from its predecessor.
  164. """
  165. if prevState != None: # Initial state
  166. self.data = GameStateData(prevState.data)
  167. else:
  168. self.data = GameStateData()
  169. def deepCopy(self):
  170. state = GameState(self)
  171. state.data = self.data.deepCopy()
  172. return state
  173. def __eq__(self, other):
  174. """
  175. Allows two states to be compared.
  176. """
  177. if other is None:
  178. return False
  179. return self.data == other.data
  180. def __hash__(self):
  181. """
  182. Allows states to be keys of dictionaries.
  183. """
  184. return hash(self.data)
  185. def __str__(self):
  186. return str(self.data)
  187. def initialize(self, layout, numGhostAgents=1000):
  188. """
  189. Creates an initial game state from a layout array (see layout.py).
  190. """
  191. self.data.initialize(layout, numGhostAgents)
  192. ############################################################################
  193. # THE HIDDEN SECRETS OF PACMAN #
  194. # #
  195. # You shouldn't need to look through the code in this section of the file. #
  196. ############################################################################
  197. SCARED_TIME = 40 # Moves ghosts are scared
  198. COLLISION_TOLERANCE = 0.7 # How close ghosts must be to Pacman to kill
  199. TIME_PENALTY = 1 # Number of points lost each round
  200. class ClassicGameRules:
  201. """
  202. These game rules manage the control flow of a game, deciding when
  203. and how the game starts and ends.
  204. """
  205. def __init__(self, timeout=30):
  206. self.timeout = timeout
  207. def newGame(self, layout, pacmanAgent, ghostAgents, display, quiet=False,
  208. catchExceptions=False):
  209. agents = [pacmanAgent] + ghostAgents[:layout.getNumGhosts()]
  210. initState = GameState()
  211. initState.initialize(layout, len(ghostAgents))
  212. game = Game(agents, display, self, catchExceptions=catchExceptions)
  213. game.state = initState
  214. self.initialState = initState.deepCopy()
  215. self.quiet = quiet
  216. return game
  217. def process(self, state, game):
  218. """
  219. Checks to see whether it is time to end the game.
  220. """
  221. if state.isWin(): self.win(state, game)
  222. if state.isLose(): self.lose(state, game)
  223. def win(self, state, game):
  224. if not self.quiet: print("Pacman emerges victorious! Score: %d" % state.data.score)
  225. game.gameOver = True
  226. def lose(self, state, game):
  227. if not self.quiet: print("Pacman died! Score: %d" % state.data.score)
  228. game.gameOver = True
  229. def getProgress(self, game):
  230. return float(game.state.getNumFood()) / self.initialState.getNumFood()
  231. def agentCrash(self, game, agentIndex):
  232. if agentIndex == 0:
  233. print("Pacman crashed")
  234. else:
  235. print("A ghost crashed")
  236. def getMaxTotalTime(self, agentIndex):
  237. return self.timeout
  238. def getMaxStartupTime(self, agentIndex):
  239. return self.timeout
  240. def getMoveWarningTime(self, agentIndex):
  241. return self.timeout
  242. def getMoveTimeout(self, agentIndex):
  243. return self.timeout
  244. def getMaxTimeWarnings(self, agentIndex):
  245. return 0
  246. class PacmanRules:
  247. """
  248. These functions govern how pacman interacts with his environment under
  249. the classic game rules.
  250. """
  251. PACMAN_SPEED = 1
  252. def getLegalActions(state):
  253. """
  254. Returns a list of possible actions.
  255. """
  256. return Actions.getPossibleActions(state.getPacmanState().configuration,
  257. state.data.layout.walls)
  258. getLegalActions = staticmethod(getLegalActions)
  259. def applyAction(state, action):
  260. """
  261. Edits the state to reflect the results of the action.
  262. """
  263. legal = PacmanRules.getLegalActions(state)
  264. if action not in legal:
  265. raise Exception("Illegal action " + str(action))
  266. pacmanState = state.data.agentStates[0]
  267. # Update Configuration
  268. vector = Actions.directionToVector(action, PacmanRules.PACMAN_SPEED)
  269. pacmanState.configuration = pacmanState.configuration.generateSuccessor(vector)
  270. # Eat
  271. next = pacmanState.configuration.getPosition()
  272. nearest = nearestPoint(next)
  273. if manhattanDistance(nearest, next) <= 0.5:
  274. # Remove food
  275. PacmanRules.consume(nearest, state)
  276. applyAction = staticmethod(applyAction)
  277. def consume(position, state):
  278. x, y = position
  279. # Eat food
  280. if state.data.food[x][y]:
  281. state.data.scoreChange += 10
  282. state.data.food = state.data.food.copy()
  283. state.data.food[x][y] = False
  284. state.data._foodEaten = position
  285. # TODO: cache numFood?
  286. numFood = state.getNumFood()
  287. if numFood == 0 and not state.data._lose:
  288. state.data.scoreChange += 500
  289. state.data._win = True
  290. # Eat capsule
  291. if (position in state.getCapsules()):
  292. state.data.capsules.remove(position)
  293. state.data._capsuleEaten = position
  294. # Reset all ghosts' scared timers
  295. for index in range(1, len(state.data.agentStates)):
  296. state.data.agentStates[index].scaredTimer = SCARED_TIME
  297. consume = staticmethod(consume)
  298. class GhostRules:
  299. """
  300. These functions dictate how ghosts interact with their environment.
  301. """
  302. GHOST_SPEED = 1.0
  303. def getLegalActions(state, ghostIndex):
  304. """
  305. Ghosts cannot stop, and cannot turn around unless they
  306. reach a dead end, but can turn 90 degrees at intersections.
  307. """
  308. conf = state.getGhostState(ghostIndex).configuration
  309. possibleActions = Actions.getPossibleActions(conf, state.data.layout.walls)
  310. reverse = Actions.reverseDirection(conf.direction)
  311. if Directions.STOP in possibleActions:
  312. possibleActions.remove(Directions.STOP)
  313. if reverse in possibleActions and len(possibleActions) > 1:
  314. possibleActions.remove(reverse)
  315. return possibleActions
  316. getLegalActions = staticmethod(getLegalActions)
  317. def applyAction(state, action, ghostIndex):
  318. legal = GhostRules.getLegalActions(state, ghostIndex)
  319. if action not in legal:
  320. raise Exception("Illegal ghost action " + str(action))
  321. ghostState = state.data.agentStates[ghostIndex]
  322. speed = GhostRules.GHOST_SPEED
  323. if ghostState.scaredTimer > 0: speed /= 2.0
  324. vector = Actions.directionToVector(action, speed)
  325. ghostState.configuration = ghostState.configuration.generateSuccessor(vector)
  326. applyAction = staticmethod(applyAction)
  327. def decrementTimer(ghostState):
  328. timer = ghostState.scaredTimer
  329. if timer == 1:
  330. ghostState.configuration.pos = nearestPoint(ghostState.configuration.pos)
  331. ghostState.scaredTimer = max(0, timer - 1)
  332. decrementTimer = staticmethod(decrementTimer)
  333. def checkDeath(state, agentIndex):
  334. pacmanPosition = state.getPacmanPosition()
  335. if agentIndex == 0: # Pacman just moved; Anyone can kill him
  336. for index in range(1, len(state.data.agentStates)):
  337. ghostState = state.data.agentStates[index]
  338. ghostPosition = ghostState.configuration.getPosition()
  339. if GhostRules.canKill(pacmanPosition, ghostPosition):
  340. GhostRules.collide(state, ghostState, index)
  341. else:
  342. ghostState = state.data.agentStates[agentIndex]
  343. ghostPosition = ghostState.configuration.getPosition()
  344. if GhostRules.canKill(pacmanPosition, ghostPosition):
  345. GhostRules.collide(state, ghostState, agentIndex)
  346. checkDeath = staticmethod(checkDeath)
  347. def collide(state, ghostState, agentIndex):
  348. if ghostState.scaredTimer > 0:
  349. state.data.scoreChange += 200
  350. GhostRules.placeGhost(state, ghostState)
  351. ghostState.scaredTimer = 0
  352. # Added for first-person
  353. state.data._eaten[agentIndex] = True
  354. else:
  355. if not state.data._win:
  356. state.data.scoreChange -= 500
  357. state.data._lose = True
  358. collide = staticmethod(collide)
  359. def canKill(pacmanPosition, ghostPosition):
  360. return manhattanDistance(ghostPosition, pacmanPosition) <= COLLISION_TOLERANCE
  361. canKill = staticmethod(canKill)
  362. def placeGhost(state, ghostState):
  363. ghostState.configuration = ghostState.start
  364. placeGhost = staticmethod(placeGhost)
  365. #############################
  366. # FRAMEWORK TO START A GAME #
  367. #############################
  368. def default(str):
  369. return str + ' [Default: %default]'
  370. def parseAgentArgs(str):
  371. if str == None: return {}
  372. pieces = str.split(',')
  373. opts = {}
  374. for p in pieces:
  375. if '=' in p:
  376. key, val = p.split('=')
  377. else:
  378. key, val = p, 1
  379. opts[key] = val
  380. return opts
  381. def readCommand(argv):
  382. """
  383. Processes the command used to run pacman from the command line.
  384. """
  385. from optparse import OptionParser
  386. usageStr = """
  387. USAGE: python pacman.py <options>
  388. EXAMPLES: (1) python pacman.py
  389. - starts an interactive game
  390. (2) python pacman.py --layout smallClassic --zoom 2
  391. OR python pacman.py -l smallClassic -z 2
  392. - starts an interactive game on a smaller board, zoomed in
  393. """
  394. parser = OptionParser(usageStr)
  395. parser.add_option('-n', '--numGames', dest='numGames', type='int',
  396. help=default('the number of GAMES to play'), metavar='GAMES', default=1)
  397. parser.add_option('-l', '--layout', dest='layout',
  398. help=default('the LAYOUT_FILE from which to load the map layout'),
  399. metavar='LAYOUT_FILE', default='mediumClassic')
  400. parser.add_option('-p', '--pacman', dest='pacman',
  401. help=default('the agent TYPE in the pacmanAgents module to use'),
  402. metavar='TYPE', default='KeyboardAgent')
  403. parser.add_option('-t', '--textGraphics', action='store_true', dest='textGraphics',
  404. help='Display output as text only', default=False)
  405. parser.add_option('-q', '--quietTextGraphics', action='store_true', dest='quietGraphics',
  406. help='Generate minimal output and no graphics', default=False)
  407. parser.add_option('-g', '--ghosts', dest='ghost',
  408. help=default('the ghost agent TYPE in the ghostAgents module to use'),
  409. metavar='TYPE', default='RandomGhost')
  410. parser.add_option('-k', '--numghosts', type='int', dest='numGhosts',
  411. help=default('The maximum number of ghosts to use'), default=4)
  412. parser.add_option('-z', '--zoom', type='float', dest='zoom',
  413. help=default('Zoom the size of the graphics window'), default=1.0)
  414. parser.add_option('-f', '--fixRandomSeed', action='store_true', dest='fixRandomSeed',
  415. help='Fixes the random seed to always play the same game', default=False)
  416. parser.add_option('-r', '--recordActions', action='store_true', dest='record',
  417. help='Writes game histories to a file (named by the time they were played)',
  418. default=False)
  419. parser.add_option('--replay', dest='gameToReplay',
  420. help='A recorded game file (pickle) to replay', default=None)
  421. parser.add_option('-a', '--agentArgs', dest='agentArgs',
  422. help='Comma separated values sent to agent. e.g. "opt1=val1,opt2,opt3=val3"')
  423. parser.add_option('-x', '--numTraining', dest='numTraining', type='int',
  424. help=default('How many episodes are training (suppresses output)'), default=0)
  425. parser.add_option('--frameTime', dest='frameTime', type='float',
  426. help=default('Time to delay between frames; <0 means keyboard'), default=0.1)
  427. parser.add_option('-c', '--catchExceptions', action='store_true', dest='catchExceptions',
  428. help='Turns on exception handling and timeouts during games', default=False)
  429. parser.add_option('--timeout', dest='timeout', type='int',
  430. help=default(
  431. 'Maximum length of time an agent can spend computing in a single game'),
  432. default=30)
  433. options, otherjunk = parser.parse_args(argv)
  434. if len(otherjunk) != 0:
  435. raise Exception('Command line input not understood: ' + str(otherjunk))
  436. args = dict()
  437. # Fix the random seed
  438. if options.fixRandomSeed: random.seed('cs188')
  439. # Choose a layout
  440. args['layout'] = layout.getLayout(options.layout)
  441. if args['layout'] == None: raise Exception("The layout " + options.layout + " cannot be found")
  442. # Choose a Pacman agent
  443. noKeyboard = options.gameToReplay == None and (options.textGraphics or options.quietGraphics)
  444. pacmanType = loadAgent(options.pacman, noKeyboard)
  445. agentOpts = parseAgentArgs(options.agentArgs)
  446. if options.numTraining > 0:
  447. args['numTraining'] = options.numTraining
  448. if 'numTraining' not in agentOpts: agentOpts['numTraining'] = options.numTraining
  449. pacman = pacmanType(**agentOpts) # Instantiate Pacman with agentArgs
  450. args['pacman'] = pacman
  451. # Don't display training games
  452. if 'numTrain' in agentOpts:
  453. options.numQuiet = int(agentOpts['numTrain'])
  454. options.numIgnore = int(agentOpts['numTrain'])
  455. # Choose a ghost agent
  456. ghostType = loadAgent(options.ghost, noKeyboard)
  457. args['ghosts'] = [ghostType(i + 1) for i in range(options.numGhosts)]
  458. # Choose a display format
  459. if options.quietGraphics:
  460. from utilities import textDisplay
  461. args['display'] = textDisplay.NullGraphics()
  462. elif options.textGraphics:
  463. from utilities import textDisplay
  464. textDisplay.SLEEP_TIME = options.frameTime
  465. args['display'] = textDisplay.PacmanGraphics()
  466. else:
  467. from utilities import graphicsDisplay
  468. args['display'] = graphicsDisplay.PacmanGraphics(options.zoom, frameTime=options.frameTime)
  469. args['numGames'] = options.numGames
  470. args['record'] = options.record
  471. args['catchExceptions'] = options.catchExceptions
  472. args['timeout'] = options.timeout
  473. # Special case: recorded games don't use the runGames method or args structure
  474. if options.gameToReplay != None:
  475. print('Replaying recorded game %s.' % options.gameToReplay)
  476. import cPickle
  477. f = open(options.gameToReplay)
  478. try:
  479. recorded = cPickle.load(f)
  480. finally:
  481. f.close()
  482. recorded['display'] = args['display']
  483. replayGame(**recorded)
  484. sys.exit(0)
  485. return args
  486. def loadAgent(pacman, nographics):
  487. # Looks through all pythonPath Directories for the right module,
  488. # pythonPathStr = os.path.expandvars("$PYTHONPATH")
  489. # if pythonPathStr.find(';') == -1:
  490. # pythonPathDirs = pythonPathStr.split(':')
  491. # else:
  492. # pythonPathDirs = pythonPathStr.split(';')
  493. # pythonPathDirs.append('.')
  494. # Add agents from from agents folder
  495. pythonPathDirs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'agents')
  496. moduleNames = [f for f in os.listdir(pythonPathDirs) if f.endswith('gents.py')]
  497. for modulename in moduleNames:
  498. try:
  499. module = __import__('agents.' + modulename[:-3], fromlist=['*'])
  500. except ImportError:
  501. continue
  502. if pacman in dir(module):
  503. if nographics and modulename == 'keyboardAgents.py':
  504. raise Exception('Using the keyboard requires graphics (not text display)')
  505. return getattr(module, pacman)
  506. raise Exception('The agent ' + pacman + ' is not specified in any *Agents.py.')
  507. def replayGame(layout, actions, display):
  508. from agents import ghostAgents
  509. from agents import pacmanAgents
  510. rules = ClassicGameRules()
  511. agents = [pacmanAgents.GreedyAgent()] + [ghostAgents.RandomGhost(i + 1) for i in range(layout.getNumGhosts())]
  512. game = rules.newGame(layout, agents[0], agents[1:], display)
  513. state = game.state
  514. display.initialize(state.data)
  515. for action in actions:
  516. # Execute the action
  517. state = state.generateSuccessor(*action)
  518. # Change the display
  519. display.update(state.data)
  520. # Allow for game specific conditions (winning, losing, etc.)
  521. rules.process(state, game)
  522. display.finish()
  523. def runGames(layout, pacman, ghosts, display, numGames, record, numTraining=0,
  524. catchExceptions=False, timeout=30):
  525. import __main__
  526. __main__.__dict__['_display'] = display
  527. rules = ClassicGameRules(timeout)
  528. games = []
  529. for i in range(numGames):
  530. beQuiet = i < numTraining
  531. if beQuiet:
  532. # Suppress output and graphics
  533. from utilities import textDisplay
  534. gameDisplay = textDisplay.NullGraphics()
  535. rules.quiet = True
  536. else:
  537. gameDisplay = display
  538. rules.quiet = False
  539. game = rules.newGame(layout, pacman, ghosts, gameDisplay, beQuiet, catchExceptions)
  540. game.run()
  541. if not beQuiet: games.append(game)
  542. if record:
  543. import time, cPickle
  544. fname = ('recorded-game-%d' % (i + 1)) + '-'.join(
  545. [str(t) for t in time.localtime()[1:6]])
  546. f = file(fname, 'w')
  547. components = {'layout': layout, 'actions': game.moveHistory}
  548. cPickle.dump(components, f)
  549. f.close()
  550. if (numGames - numTraining) > 0:
  551. scores = [game.state.getScore() for game in games]
  552. wins = [game.state.isWin() for game in games]
  553. winRate = wins.count(True) / float(len(wins))
  554. print('Average Score:', sum(scores) / float(len(scores)))
  555. print('Scores: ', ', '.join([str(score) for score in scores]))
  556. print('Win Rate: %d/%d (%.2f)' % (wins.count(True), len(wins), winRate))
  557. print('Record: ', ', '.join([['Loss', 'Win'][int(w)] for w in wins]))
  558. return games
  559. if __name__ == '__main__':
  560. """
  561. The main function called when pacman.py is run
  562. from the command line:
  563. > python pacman.py
  564. See the usage string for more details.
  565. > python pacman.py --help
  566. """
  567. args = readCommand(sys.argv[1:]) # Get game components based on input
  568. runGames(**args)
  569. # import cProfile
  570. # cProfile.run("runGames( **args )")
  571. pass
Tip!

Press p or to see the previous file or, n or to see the next file

Comments

Loading...