Module pacai.core.distanceCalculator
Expand source code
import sys
from pacai.core.distance import manhattan
from pacai.util import priorityQueue
DEFAULT_DISTANCE = 10000
class Distancer(object):
"""
A class for computing and caching the shortest path between any two points in a given maze.
Example:
```
distancer = Distancer(gameState.getInitialLayout())
distancer.getDistance((1, 1), (10, 10))
```
"""
def __init__(self, layout):
self._distances = None
self.dc = DistanceCalculator(layout, self)
def getMazeDistances(self):
self.dc.run()
def getDistance(self, pos1, pos2):
"""
The only function you will need after you create the object.
"""
if (self._distances is None):
return manhattan(pos1, pos2)
if isInt(pos1) and isInt(pos2):
return self.getDistanceOnGrid(pos1, pos2)
pos1Grids = getGrids2D(pos1)
pos2Grids = getGrids2D(pos2)
bestDistance = DEFAULT_DISTANCE
for pos1Snap, snap1Distance in pos1Grids:
for pos2Snap, snap2Distance in pos2Grids:
gridDistance = self.getDistanceOnGrid(pos1Snap, pos2Snap)
distance = gridDistance + snap1Distance + snap2Distance
if bestDistance > distance:
bestDistance = distance
return bestDistance
def getDistanceOnGrid(self, pos1, pos2):
key = (pos1, pos2)
if key in self._distances:
return self._distances[key]
raise Exception("Position not in grid: " + str(key))
def isReadyForMazeDistance(self):
return (self._distances is not None)
def isInt(pos):
x, y = pos
return x == int(x) and y == int(y)
def getGrids2D(pos):
grids = []
for x, xDistance in getGrids1D(pos[0]):
for y, yDistance in getGrids1D(pos[1]):
grids.append(((x, y), xDistance + yDistance))
return grids
def getGrids1D(x):
intX = int(x)
if x == int(x):
return [(x, 0)]
return [(intX, x - intX), (intX + 1, intX + 1 - x)]
##########################################
# MACHINERY FOR COMPUTING MAZE DISTANCES #
##########################################
distanceMap = {}
class DistanceCalculator:
def __init__(self, layout, distancer):
self.layout = layout
self.distancer = distancer
self.cache = {}
def run(self):
if self.layout.walls not in self.cache:
self.cache[self.layout.walls] = computeDistances(self.layout)
self.distancer._distances = self.cache[self.layout.walls]
def computeDistances(layout):
"""
Runs UCS to all other positions from each position.
"""
distances = {}
allNodes = layout.walls.asList(False)
for source in allNodes:
dist = {}
closed = {}
for node in allNodes:
dist[node] = sys.maxsize
queue = priorityQueue.PriorityQueue()
queue.push(source, 0)
dist[source] = 0
while not queue.isEmpty():
node = queue.pop()
if node in closed:
continue
closed[node] = True
nodeDist = dist[node]
adjacent = []
x, y = node
if not layout.isWall((x, y + 1)):
adjacent.append((x, y + 1))
if not layout.isWall((x, y - 1)):
adjacent.append((x, y - 1))
if not layout.isWall((x + 1, y)):
adjacent.append((x + 1, y))
if not layout.isWall((x - 1, y)):
adjacent.append((x - 1, y))
for other in adjacent:
if other not in dist:
continue
oldDist = dist[other]
newDist = nodeDist + 1
if newDist < oldDist:
dist[other] = newDist
queue.push(other, newDist)
for target in allNodes:
distances[(target, source)] = dist[target]
return distances
def getDistanceOnGrid(distances, pos1, pos2):
key = (pos1, pos2)
if key in distances:
return distances[key]
return DEFAULT_DISTANCE
Functions
def computeDistances(layout)
-
Runs UCS to all other positions from each position.
Expand source code
def computeDistances(layout): """ Runs UCS to all other positions from each position. """ distances = {} allNodes = layout.walls.asList(False) for source in allNodes: dist = {} closed = {} for node in allNodes: dist[node] = sys.maxsize queue = priorityQueue.PriorityQueue() queue.push(source, 0) dist[source] = 0 while not queue.isEmpty(): node = queue.pop() if node in closed: continue closed[node] = True nodeDist = dist[node] adjacent = [] x, y = node if not layout.isWall((x, y + 1)): adjacent.append((x, y + 1)) if not layout.isWall((x, y - 1)): adjacent.append((x, y - 1)) if not layout.isWall((x + 1, y)): adjacent.append((x + 1, y)) if not layout.isWall((x - 1, y)): adjacent.append((x - 1, y)) for other in adjacent: if other not in dist: continue oldDist = dist[other] newDist = nodeDist + 1 if newDist < oldDist: dist[other] = newDist queue.push(other, newDist) for target in allNodes: distances[(target, source)] = dist[target] return distances
def getDistanceOnGrid(distances, pos1, pos2)
-
Expand source code
def getDistanceOnGrid(distances, pos1, pos2): key = (pos1, pos2) if key in distances: return distances[key] return DEFAULT_DISTANCE
def getGrids1D(x)
-
Expand source code
def getGrids1D(x): intX = int(x) if x == int(x): return [(x, 0)] return [(intX, x - intX), (intX + 1, intX + 1 - x)]
def getGrids2D(pos)
-
Expand source code
def getGrids2D(pos): grids = [] for x, xDistance in getGrids1D(pos[0]): for y, yDistance in getGrids1D(pos[1]): grids.append(((x, y), xDistance + yDistance)) return grids
def isInt(pos)
-
Expand source code
def isInt(pos): x, y = pos return x == int(x) and y == int(y)
Classes
class DistanceCalculator (layout, distancer)
-
Expand source code
class DistanceCalculator: def __init__(self, layout, distancer): self.layout = layout self.distancer = distancer self.cache = {} def run(self): if self.layout.walls not in self.cache: self.cache[self.layout.walls] = computeDistances(self.layout) self.distancer._distances = self.cache[self.layout.walls]
Methods
def run(self)
-
Expand source code
def run(self): if self.layout.walls not in self.cache: self.cache[self.layout.walls] = computeDistances(self.layout) self.distancer._distances = self.cache[self.layout.walls]
class Distancer (layout)
-
A class for computing and caching the shortest path between any two points in a given maze.
Example:
distancer = Distancer(gameState.getInitialLayout()) distancer.getDistance((1, 1), (10, 10))
Expand source code
class Distancer(object): """ A class for computing and caching the shortest path between any two points in a given maze. Example: ``` distancer = Distancer(gameState.getInitialLayout()) distancer.getDistance((1, 1), (10, 10)) ``` """ def __init__(self, layout): self._distances = None self.dc = DistanceCalculator(layout, self) def getMazeDistances(self): self.dc.run() def getDistance(self, pos1, pos2): """ The only function you will need after you create the object. """ if (self._distances is None): return manhattan(pos1, pos2) if isInt(pos1) and isInt(pos2): return self.getDistanceOnGrid(pos1, pos2) pos1Grids = getGrids2D(pos1) pos2Grids = getGrids2D(pos2) bestDistance = DEFAULT_DISTANCE for pos1Snap, snap1Distance in pos1Grids: for pos2Snap, snap2Distance in pos2Grids: gridDistance = self.getDistanceOnGrid(pos1Snap, pos2Snap) distance = gridDistance + snap1Distance + snap2Distance if bestDistance > distance: bestDistance = distance return bestDistance def getDistanceOnGrid(self, pos1, pos2): key = (pos1, pos2) if key in self._distances: return self._distances[key] raise Exception("Position not in grid: " + str(key)) def isReadyForMazeDistance(self): return (self._distances is not None)
Methods
def getDistance(self, pos1, pos2)
-
The only function you will need after you create the object.
Expand source code
def getDistance(self, pos1, pos2): """ The only function you will need after you create the object. """ if (self._distances is None): return manhattan(pos1, pos2) if isInt(pos1) and isInt(pos2): return self.getDistanceOnGrid(pos1, pos2) pos1Grids = getGrids2D(pos1) pos2Grids = getGrids2D(pos2) bestDistance = DEFAULT_DISTANCE for pos1Snap, snap1Distance in pos1Grids: for pos2Snap, snap2Distance in pos2Grids: gridDistance = self.getDistanceOnGrid(pos1Snap, pos2Snap) distance = gridDistance + snap1Distance + snap2Distance if bestDistance > distance: bestDistance = distance return bestDistance
def getDistanceOnGrid(self, pos1, pos2)
-
Expand source code
def getDistanceOnGrid(self, pos1, pos2): key = (pos1, pos2) if key in self._distances: return self._distances[key] raise Exception("Position not in grid: " + str(key))
def getMazeDistances(self)
-
Expand source code
def getMazeDistances(self): self.dc.run()
def isReadyForMazeDistance(self)
-
Expand source code
def isReadyForMazeDistance(self): return (self._distances is not None)