/search/layout.py
Python | 155 lines | 108 code | 21 blank | 26 comment | 32 complexity | 4a2200fba25e699903d71da13b6d395e MD5 | raw file
- # layout.py
- # ---------
- # Licensing Information: Please do not distribute or publish solutions to this
- # project. You are free to use and extend these projects for educational
- # purposes. The Pacman AI projects were developed at UC Berkeley, primarily by
- # John DeNero (denero@cs.berkeley.edu) and Dan Klein (klein@cs.berkeley.edu).
- # For more info, see http://inst.eecs.berkeley.edu/~cs188/sp09/pacman.html
- from util import manhattanDistance
- from game import Grid
- import os
- import random
- VISIBILITY_MATRIX_CACHE = {}
- class Layout:
- """
- A Layout manages the static information about the game board.
- """
-
- def __init__(self, layoutText):
- self.width = len(layoutText[0])
- self.height= len(layoutText)
- self.walls = Grid(self.width, self.height, False)
- self.food = Grid(self.width, self.height, False)
- self.capsules = []
- self.agentPositions = []
- self.numGhosts = 0
- self.processLayoutText(layoutText)
- self.layoutText = layoutText
- # self.initializeVisibilityMatrix()
-
- def getNumGhosts(self):
- return self.numGhosts
-
- def initializeVisibilityMatrix(self):
- global VISIBILITY_MATRIX_CACHE
- if reduce(str.__add__, self.layoutText) not in VISIBILITY_MATRIX_CACHE:
- from game import Directions
- vecs = [(-0.5,0), (0.5,0),(0,-0.5),(0,0.5)]
- dirs = [Directions.NORTH, Directions.SOUTH, Directions.WEST, Directions.EAST]
- vis = Grid(self.width, self.height, {Directions.NORTH:set(), Directions.SOUTH:set(), Directions.EAST:set(), Directions.WEST:set(), Directions.STOP:set()})
- for x in range(self.width):
- for y in range(self.height):
- if self.walls[x][y] == False:
- for vec, direction in zip(vecs, dirs):
- dx, dy = vec
- nextx, nexty = x + dx, y + dy
- while (nextx + nexty) != int(nextx) + int(nexty) or not self.walls[int(nextx)][int(nexty)] :
- vis[x][y][direction].add((nextx, nexty))
- nextx, nexty = x + dx, y + dy
- self.visibility = vis
- VISIBILITY_MATRIX_CACHE[reduce(str.__add__, self.layoutText)] = vis
- else:
- self.visibility = VISIBILITY_MATRIX_CACHE[reduce(str.__add__, self.layoutText)]
-
- def isWall(self, pos):
- x, col = pos
- return self.walls[x][col]
-
- def getRandomLegalPosition(self):
- x = random.choice(range(self.width))
- y = random.choice(range(self.height))
- while self.isWall( (x, y) ):
- x = random.choice(range(self.width))
- y = random.choice(range(self.height))
- return (x,y)
- def getRandomCorner(self):
- poses = [(1,1), (1, self.height - 2), (self.width - 2, 1), (self.width - 2, self.height - 2)]
- return random.choice(poses)
- def getFurthestCorner(self, pacPos):
- poses = [(1,1), (1, self.height - 2), (self.width - 2, 1), (self.width - 2, self.height - 2)]
- dist, pos = max([(manhattanDistance(p, pacPos), p) for p in poses])
- return pos
-
- def isVisibleFrom(self, ghostPos, pacPos, pacDirection):
- row, col = [int(x) for x in pacPos]
- return ghostPos in self.visibility[row][col][pacDirection]
-
- def __str__(self):
- return "\n".join(self.layoutText)
-
- def deepCopy(self):
- return Layout(self.layoutText[:])
-
- def processLayoutText(self, layoutText):
- """
- Coordinates are flipped from the input format to the (x,y) convention here
-
- The shape of the maze. Each character
- represents a different type of object.
- % - Wall
- . - Food
- o - Capsule
- G - Ghost
- P - Pacman
- Other characters are ignored.
- """
- maxY = self.height - 1
- for y in range(self.height):
- for x in range(self.width):
- layoutChar = layoutText[maxY - y][x]
- self.processLayoutChar(x, y, layoutChar)
- self.agentPositions.sort()
- self.agentPositions = [ ( i == 0, pos) for i, pos in self.agentPositions]
-
- def processLayoutChar(self, x, y, layoutChar):
- if layoutChar == '%':
- self.walls[x][y] = True
- elif layoutChar == '.':
- self.food[x][y] = True
- elif layoutChar == 'o':
- self.capsules.append((x, y))
- elif layoutChar == 'P':
- self.agentPositions.append( (0, (x, y) ) )
- elif layoutChar in ['G']:
- self.agentPositions.append( (1, (x, y) ) )
- self.numGhosts += 1
- elif layoutChar in ['1', '2', '3', '4']:
- self.agentPositions.append( (int(layoutChar), (x,y)))
- self.numGhosts += 1
-
- def getLayout(name, back = 1):
- # Set the layout directory and name to check for different enviroment
- # setups
- layoutDir = ''
- layoutName = name.strip() if name.endswith('.lay') else name.strip() + '.lay'
-
- if os.path.isdir('layouts/'):
- layoutDir = 'layouts/'
- elif os.path.isdir('src/'):
- layoutDir += 'src/'
- if os.path.isdir(layoutDir+'layouts/'):
- layoutDir += 'layouts/'
-
- layout = tryToLoad(layoutDir + layoutName)
- if layout == None:
- layout = tryToLoad(layoutName)
-
- # Try again in super directory
- if layout == None and back > 0:
- curdir = os.path.abspath('.')
- os.chdir('..')
- layout = getLayout(name, back - 1)
- os.chdir(curdir)
-
- return layout
- def tryToLoad(fullname):
- if(not os.path.exists(fullname)): return None
- f = open(fullname)
- try: return Layout([line.strip() for line in f])
- finally: f.close()