/search/layout.py

https://github.com/sumeetsk/aiclass
Python | 155 lines | 108 code | 21 blank | 26 comment | 32 complexity | 4a2200fba25e699903d71da13b6d395e MD5 | raw file
  1. # layout.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. from util import manhattanDistance
  9. from game import Grid
  10. import os
  11. import random
  12. VISIBILITY_MATRIX_CACHE = {}
  13. class Layout:
  14. """
  15. A Layout manages the static information about the game board.
  16. """
  17. def __init__(self, layoutText):
  18. self.width = len(layoutText[0])
  19. self.height= len(layoutText)
  20. self.walls = Grid(self.width, self.height, False)
  21. self.food = Grid(self.width, self.height, False)
  22. self.capsules = []
  23. self.agentPositions = []
  24. self.numGhosts = 0
  25. self.processLayoutText(layoutText)
  26. self.layoutText = layoutText
  27. # self.initializeVisibilityMatrix()
  28. def getNumGhosts(self):
  29. return self.numGhosts
  30. def initializeVisibilityMatrix(self):
  31. global VISIBILITY_MATRIX_CACHE
  32. if reduce(str.__add__, self.layoutText) not in VISIBILITY_MATRIX_CACHE:
  33. from game import Directions
  34. vecs = [(-0.5,0), (0.5,0),(0,-0.5),(0,0.5)]
  35. dirs = [Directions.NORTH, Directions.SOUTH, Directions.WEST, Directions.EAST]
  36. vis = Grid(self.width, self.height, {Directions.NORTH:set(), Directions.SOUTH:set(), Directions.EAST:set(), Directions.WEST:set(), Directions.STOP:set()})
  37. for x in range(self.width):
  38. for y in range(self.height):
  39. if self.walls[x][y] == False:
  40. for vec, direction in zip(vecs, dirs):
  41. dx, dy = vec
  42. nextx, nexty = x + dx, y + dy
  43. while (nextx + nexty) != int(nextx) + int(nexty) or not self.walls[int(nextx)][int(nexty)] :
  44. vis[x][y][direction].add((nextx, nexty))
  45. nextx, nexty = x + dx, y + dy
  46. self.visibility = vis
  47. VISIBILITY_MATRIX_CACHE[reduce(str.__add__, self.layoutText)] = vis
  48. else:
  49. self.visibility = VISIBILITY_MATRIX_CACHE[reduce(str.__add__, self.layoutText)]
  50. def isWall(self, pos):
  51. x, col = pos
  52. return self.walls[x][col]
  53. def getRandomLegalPosition(self):
  54. x = random.choice(range(self.width))
  55. y = random.choice(range(self.height))
  56. while self.isWall( (x, y) ):
  57. x = random.choice(range(self.width))
  58. y = random.choice(range(self.height))
  59. return (x,y)
  60. def getRandomCorner(self):
  61. poses = [(1,1), (1, self.height - 2), (self.width - 2, 1), (self.width - 2, self.height - 2)]
  62. return random.choice(poses)
  63. def getFurthestCorner(self, pacPos):
  64. poses = [(1,1), (1, self.height - 2), (self.width - 2, 1), (self.width - 2, self.height - 2)]
  65. dist, pos = max([(manhattanDistance(p, pacPos), p) for p in poses])
  66. return pos
  67. def isVisibleFrom(self, ghostPos, pacPos, pacDirection):
  68. row, col = [int(x) for x in pacPos]
  69. return ghostPos in self.visibility[row][col][pacDirection]
  70. def __str__(self):
  71. return "\n".join(self.layoutText)
  72. def deepCopy(self):
  73. return Layout(self.layoutText[:])
  74. def processLayoutText(self, layoutText):
  75. """
  76. Coordinates are flipped from the input format to the (x,y) convention here
  77. The shape of the maze. Each character
  78. represents a different type of object.
  79. % - Wall
  80. . - Food
  81. o - Capsule
  82. G - Ghost
  83. P - Pacman
  84. Other characters are ignored.
  85. """
  86. maxY = self.height - 1
  87. for y in range(self.height):
  88. for x in range(self.width):
  89. layoutChar = layoutText[maxY - y][x]
  90. self.processLayoutChar(x, y, layoutChar)
  91. self.agentPositions.sort()
  92. self.agentPositions = [ ( i == 0, pos) for i, pos in self.agentPositions]
  93. def processLayoutChar(self, x, y, layoutChar):
  94. if layoutChar == '%':
  95. self.walls[x][y] = True
  96. elif layoutChar == '.':
  97. self.food[x][y] = True
  98. elif layoutChar == 'o':
  99. self.capsules.append((x, y))
  100. elif layoutChar == 'P':
  101. self.agentPositions.append( (0, (x, y) ) )
  102. elif layoutChar in ['G']:
  103. self.agentPositions.append( (1, (x, y) ) )
  104. self.numGhosts += 1
  105. elif layoutChar in ['1', '2', '3', '4']:
  106. self.agentPositions.append( (int(layoutChar), (x,y)))
  107. self.numGhosts += 1
  108. def getLayout(name, back = 1):
  109. # Set the layout directory and name to check for different enviroment
  110. # setups
  111. layoutDir = ''
  112. layoutName = name.strip() if name.endswith('.lay') else name.strip() + '.lay'
  113. if os.path.isdir('layouts/'):
  114. layoutDir = 'layouts/'
  115. elif os.path.isdir('src/'):
  116. layoutDir += 'src/'
  117. if os.path.isdir(layoutDir+'layouts/'):
  118. layoutDir += 'layouts/'
  119. layout = tryToLoad(layoutDir + layoutName)
  120. if layout == None:
  121. layout = tryToLoad(layoutName)
  122. # Try again in super directory
  123. if layout == None and back > 0:
  124. curdir = os.path.abspath('.')
  125. os.chdir('..')
  126. layout = getLayout(name, back - 1)
  127. os.chdir(curdir)
  128. return layout
  129. def tryToLoad(fullname):
  130. if(not os.path.exists(fullname)): return None
  131. f = open(fullname)
  132. try: return Layout([line.strip() for line in f])
  133. finally: f.close()