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.totalFood = len(self.food.asList()) # 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
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.totalFood = len(self.food.asList()) # 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
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.numPacmen = 0 # TODO If already has more than total, need to remove? # Should be fine # if fillRandom: # # Randomly adds more ghosts and pacmen # self.fillWithType(layoutText, numPacmen, 'P') # self.fillWithType(layoutText, numGhosts, 'G') # # if generateFood: # numWalls = sum([line.count('%') for line in layoutText]) # numFood = (self.width * self.height - numWalls - numPacmen - numGhosts) * foodDensity # numFood = int(numFood) # self.fillWithType(layoutText, numFood, '.') self.processLayoutText(layoutText) self.layoutText = layoutText self.totalFood = len(self.food.asList()) # self.initializeVisibilityMatrix() def fillWithType(self, layoutText, total, type): assert type == 'P' or type == 'G' or type == '.' def replace_char(string, c, index): c_arr = list(string) c_arr[index] = c return "".join(c_arr) count = sum([line.count(type) for line in layoutText]) if count < total: for _ in range(total - count): while True: x = random.randint(0, len(layoutText) - 1) y = random.randint(0, len(layoutText[0]) - 1) if layoutText[x][y] not in ['P', 'G', '%', '.']: layoutText[x] = replace_char(layoutText[x], type, y) break def getNumGhosts(self): return self.numGhosts def getNumPacmen(self): return self.numPacmen 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))) self.numPacmen += 1 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 outputToFile(self, filename): with open('layouts/tests/' + filename + '.lay', 'w') as f: for i, line in enumerate(self.layoutText): if i < len(self.layoutText) - 1: f.write(line + '\n') else: f.write(line)
class Layout: 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.totalFood = len(self.food.asList()) 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): """ Labirentin şekli. Her karakter farklı bir nesne türünü temsil eder. % - Duvar . - Gıda o - Kapsül G - Hayalet 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
class Layout: """ A Layout manages the static information about the game board. """ def __init__(self, layoutText): layoutText = self.mirror(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.transport = defaultdict(list) self.processLayoutText(layoutText) self.layoutText = layoutText self.totalFood = len(self.food.asList()) for char in self.transport.keys(): posList = self.transport[char] self.transport[posList[0]] = posList[1] self.transport[posList[1]] = posList[0] del self.transport[char] # self.initializeVisibilityMatrix() def mirrorChar(self, char): mirror_dict = { 'A': 'B', 'B': 'A', 'C': 'D', 'D': 'C', 'E': 'F', 'F': 'E', '1': '2', '2': '1', '3': '4', '4': '3', '5': '6', '6': '5', '(': ']', ']': '(', '{': '>', '>': '{', ')': '[', '[': ')', '}': '<', '<': '}', 'r': 'b', 'b': 'r' } if char in mirror_dict: return mirror_dict[char] else: return char def mirror(self, layoutText): for y in range(len(layoutText) - 1, -1, -1): next_str = '' for char in reversed(layoutText[y]): next_str += self.mirrorChar(char) layoutText.append(next_str) return layoutText def getNumGhosts(self): return len(self.agentPositions) / 2 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 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): # layout = Layout() # layout.witdh = self.width # layout.height = self.height # layout.walls = self.walls # layout.food = self.food # layout.capsules = self.capsules # layout.agentPositions = self.agentPositions # layout.transport = self.transport # # self.processLayoutText(layoutText) # self.layoutText = layoutText # self.totalFood = len(self.food.asList()) # # # for char in self.transport.keys(): # posList = self.transport[char] # self.transport[posList[0]]=posList[1] # self.transport[posList[1]]=posList[0] # del self.transport[char] # return Layout(self.layoutText[:self.height / 2]) # return self 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 F - Flag 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 <= '6', pos) for i, pos in self.agentPositions] def processLayoutChar(self, x, y, layoutChar): if layoutChar == '%': self.walls[x][y] = True elif layoutChar in ['r', 'b']: self.walls[x][y] = layoutChar elif layoutChar == '.': self.food[x][y] = 10 elif layoutChar == '+': self.food[x][y] = 50 elif layoutChar == 'o': self.capsules.append((x, y)) # A~F: ghosts elif layoutChar in ['A', 'B', 'C', 'D', 'E', 'F']: self.agentPositions.append((layoutChar, (x, y))) # 1~6: pacmans elif layoutChar in ['1', '2', '3', '4', '5', '6']: self.agentPositions.append((layoutChar, (x, y))) elif layoutChar in ['(', ')', '[', ']', '{', '}', '<', '>']: self.transport[layoutChar].append((x, y))