Module pacai.core.layout
Expand source code
import os
import random
from pacai.core.distance import manhattan
from pacai.core.grid import Grid
# By default, the layout directory is adjacent to this file.
DEFAULT_LAYOUT_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'layouts')
GHOST_NUMS = ['1', '2', '3', '4']
class Layout(object):
"""
A Layout manages the static information about the game board.
"""
def __init__(self, layoutText, maxGhosts = None):
self.width = len(layoutText[0])
self.height = len(layoutText)
self.walls = Grid(self.width, self.height, initialValue = False)
self.food = Grid(self.width, self.height, initialValue = False)
self.capsules = []
self.agentPositions = []
self.numGhosts = 0
self.layoutText = layoutText
self.processLayoutText(layoutText, maxGhosts)
def getNumGhosts(self):
return self.numGhosts
def isWall(self, pos):
x, col = pos
return self.walls[x][col]
def getHeight(self):
return self.height
def getWidth(self):
return self.width
def getRandomLegalPosition(self):
x = random.choice(list(range(self.width)))
y = random.choice(list(range(self.height)))
while self.isWall((x, y)):
x = random.choice(list(range(self.width)))
y = random.choice(list(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([(manhattan(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, maxGhosts):
"""
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, maxGhosts)
self.agentPositions.sort()
self.agentPositions = [(i == 0, pos) for i, pos in self.agentPositions]
def processLayoutChar(self, x, y, layoutChar, maxGhosts):
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'] and (maxGhosts is None or self.numGhosts < maxGhosts)):
self.agentPositions.append((1, (x, y)))
self.numGhosts += 1
elif (layoutChar in GHOST_NUMS and (maxGhosts is None or self.numGhosts < maxGhosts)):
self.agentPositions.append((int(layoutChar), (x, y)))
self.numGhosts += 1
def getLayout(name, layout_dir = DEFAULT_LAYOUT_DIR, maxGhosts = None):
if (not name.endswith('.lay')):
name += '.lay'
path = os.path.join(layout_dir, name)
if (not os.path.isfile(path)):
raise Exception("Could not locate layout file: '%s'." % (path))
rows = []
with open(path, 'r') as file:
for line in file:
line = line.strip()
if (line != ''):
rows.append(line)
return Layout(rows, maxGhosts)
Functions
def getLayout(name, layout_dir='/home/eriq/code/pacman/pacai/core/layouts', maxGhosts=None)
-
Expand source code
def getLayout(name, layout_dir = DEFAULT_LAYOUT_DIR, maxGhosts = None): if (not name.endswith('.lay')): name += '.lay' path = os.path.join(layout_dir, name) if (not os.path.isfile(path)): raise Exception("Could not locate layout file: '%s'." % (path)) rows = [] with open(path, 'r') as file: for line in file: line = line.strip() if (line != ''): rows.append(line) return Layout(rows, maxGhosts)
Classes
class Layout (layoutText, maxGhosts=None)
-
A Layout manages the static information about the game board.
Expand source code
class Layout(object): """ A Layout manages the static information about the game board. """ def __init__(self, layoutText, maxGhosts = None): self.width = len(layoutText[0]) self.height = len(layoutText) self.walls = Grid(self.width, self.height, initialValue = False) self.food = Grid(self.width, self.height, initialValue = False) self.capsules = [] self.agentPositions = [] self.numGhosts = 0 self.layoutText = layoutText self.processLayoutText(layoutText, maxGhosts) def getNumGhosts(self): return self.numGhosts def isWall(self, pos): x, col = pos return self.walls[x][col] def getHeight(self): return self.height def getWidth(self): return self.width def getRandomLegalPosition(self): x = random.choice(list(range(self.width))) y = random.choice(list(range(self.height))) while self.isWall((x, y)): x = random.choice(list(range(self.width))) y = random.choice(list(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([(manhattan(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, maxGhosts): """ 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, maxGhosts) self.agentPositions.sort() self.agentPositions = [(i == 0, pos) for i, pos in self.agentPositions] def processLayoutChar(self, x, y, layoutChar, maxGhosts): 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'] and (maxGhosts is None or self.numGhosts < maxGhosts)): self.agentPositions.append((1, (x, y))) self.numGhosts += 1 elif (layoutChar in GHOST_NUMS and (maxGhosts is None or self.numGhosts < maxGhosts)): self.agentPositions.append((int(layoutChar), (x, y))) self.numGhosts += 1
Methods
def deepCopy(self)
-
Expand source code
def deepCopy(self): return Layout(self.layoutText[:])
def getFurthestCorner(self, pacPos)
-
Expand source code
def getFurthestCorner(self, pacPos): poses = [ (1, 1), (1, self.height - 2), (self.width - 2, 1), (self.width - 2, self.height - 2) ] dist, pos = max([(manhattan(p, pacPos), p) for p in poses]) return pos
def getHeight(self)
-
Expand source code
def getHeight(self): return self.height
def getNumGhosts(self)
-
Expand source code
def getNumGhosts(self): return self.numGhosts
def getRandomCorner(self)
-
Expand source code
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 getRandomLegalPosition(self)
-
Expand source code
def getRandomLegalPosition(self): x = random.choice(list(range(self.width))) y = random.choice(list(range(self.height))) while self.isWall((x, y)): x = random.choice(list(range(self.width))) y = random.choice(list(range(self.height))) return (x, y)
def getWidth(self)
-
Expand source code
def getWidth(self): return self.width
def isVisibleFrom(self, ghostPos, pacPos, pacDirection)
-
Expand source code
def isVisibleFrom(self, ghostPos, pacPos, pacDirection): row, col = [int(x) for x in pacPos] return ghostPos in self.visibility[row][col][pacDirection]
def isWall(self, pos)
-
Expand source code
def isWall(self, pos): x, col = pos return self.walls[x][col]
def processLayoutChar(self, x, y, layoutChar, maxGhosts)
-
Expand source code
def processLayoutChar(self, x, y, layoutChar, maxGhosts): 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'] and (maxGhosts is None or self.numGhosts < maxGhosts)): self.agentPositions.append((1, (x, y))) self.numGhosts += 1 elif (layoutChar in GHOST_NUMS and (maxGhosts is None or self.numGhosts < maxGhosts)): self.agentPositions.append((int(layoutChar), (x, y))) self.numGhosts += 1
def processLayoutText(self, layoutText, maxGhosts)
-
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.
Expand source code
def processLayoutText(self, layoutText, maxGhosts): """ 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, maxGhosts) self.agentPositions.sort() self.agentPositions = [(i == 0, pos) for i, pos in self.agentPositions]