Skip to content

Commit

Permalink
Move pathfinding to separate file.
Browse files Browse the repository at this point in the history
  • Loading branch information
Francis Herne committed Apr 4, 2015
1 parent 0de10e0 commit 8dda6a3
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 55 deletions.
59 changes: 7 additions & 52 deletions MGO/Bear.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import images
import coords
import config
import pathfind
import terrain
import BaseMGO

Expand All @@ -14,67 +15,21 @@ def __init__(self, position, cellmap):
super(Bear, self).__init__(position, cellmap)
self.direction = -1 # Left
self.speed = 0.7 # Chance of moving per turn, max 1, min 0
self.pfmapsize = 32
self.detectionrange = 18
self.pfmapsize = 16
self.detectionrange = 16
self.maxcost = 32 # Max path cost before giving up.
self.hunting = None

def mindistto(self, position):
return coords.mindist(position, self.position, self.cellmap.size[0])

def directiontoplayer(self, playerpos):
"""Find the best direction to move towards the player"""

if (any(ax > self.pfmapsize for ax in self.mindistto(playerpos))):
# Player is outside pathfinder area
return False

def mapcoord(pfcoord):
"""Get map coordinate from pathfinder one"""
return coords.modsum(self.position, pfcoord, (-self.pfmapsize,)*2, self.cellmap.size)

foundtarget = False
dijkstramap = [[[0, (self.pfmapsize,)*2, False] for x in xrange(2*self.pfmapsize)] for x in xrange(2*self.pfmapsize)]
import heapq
openlist = []
heapq.heappush(openlist, (0, (self.pfmapsize,)*2))
curpos = None
while openlist:
curnode = heapq.heappop(openlist)
curdist = curnode[0]
if curdist > self.maxcost:
# Give up if player is painfully unreachable.
break
curpos = curnode[1]
if mapcoord(curpos) == tuple(playerpos):
foundtarget = True
break
if dijkstramap[curpos[0]][curpos[1]][2] == True:
continue
else:
dijkstramap[curpos[0]][curpos[1]][2] = True
for nbrpos in coords.neighbours(curpos):
if (nbrpos[0] < 0 or nbrpos[1] < 0 or
nbrpos[0] >= 2*self.pfmapsize or nbrpos[1] >= 2*self.pfmapsize or
nbrpos == (self.pfmapsize, self.pfmapsize)):
continue
cellcost = Bear.terraincost(self.cellmap[mapcoord(nbrpos)])
newdist = curdist+cellcost
if ((dijkstramap[nbrpos[0]][nbrpos[1]][0] <= newdist and dijkstramap[nbrpos[0]][nbrpos[1]][0] != 0) or
self.cellmap[mapcoord(nbrpos)]['solid'] or cellcost > 8):
continue
dijkstramap[nbrpos[0]][nbrpos[1]] = [newdist, curpos, False]
heapq.heappush(openlist, (newdist, nbrpos))
if not foundtarget:
return False
while dijkstramap[curpos[0]][curpos[1]][1] != (self.pfmapsize, self.pfmapsize):
curpos = dijkstramap[curpos[0]][curpos[1]][1]
return coords.sum(curpos, (-self.pfmapsize,)*2)
return pathfind.firstmove(self.position, playerpos, Bear.terraincost,
self.cellmap, self.pfmapsize, self.maxcost)

def update(self, world):
def chaseplayer(playerpos):
"""Decide whether to chase the player"""
if (sum(ax**2 for ax in self.mindistto(playerpos)) > self.detectionrange**2):
playerdist = coords.mindist(self.position, playerpos, self.cellmap.size)
if (sum(ax**2 for ax in playerdist) > self.detectionrange**2):
# Can't see/smell/hear (?) player
return False
if random.random() > self.speed:
Expand Down
6 changes: 3 additions & 3 deletions coords.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ def neighbours(a):

def mindist(a, b, size):
"""Distance per axis between two points accounting for world wrapping"""
return tuple([min((eb-ea)%size, (ea-eb)%size) for ea, eb in zip(a, b)])
return tuple([min((eb-ea)%es, (ea-eb)%es) for ea, eb, es in zip(a, b, size)])

def tileoffset(a, b, size):
"""Offset of b from a, accounting for wrapping of world size"""
offset = [0, 0]
for axis in [0, 1]:
subtract = b[axis] - a[axis]
absubtract = abs(subtract)
if absubtract*2 <= size:
if absubtract*2 <= size[axis]:
offset[axis] = subtract
else:
offset[axis] = (size-absubtract) * cmp(0, subtract)
offset[axis] = (size[axis]-absubtract) * cmp(0, subtract)
return offset
50 changes: 50 additions & 0 deletions pathfind.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import coords

def firstmove(startpos, destpos, costs, cellmap, pfmapsize=15, maxcost=40):
"""Find the best direction to move towards the destination"""

if (any(ax > pfmapsize for ax in coords.mindist(startpos, destpos, cellmap.size))):
# Player is outside pathfinder area
return False

def mapcoord(pfcoord):
"""Get map coordinate from pathfinder one"""
return coords.modsum(startpos, pfcoord, (-pfmapsize,)*2, cellmap.size)

foundtarget = False
dijkstramap = [[[0, (pfmapsize,)*2, False] for x in xrange(2*pfmapsize)] for x in xrange(2*pfmapsize)]
import heapq
openlist = []
heapq.heappush(openlist, (0, (pfmapsize,)*2))
curpos = None
while openlist:
curnode = heapq.heappop(openlist)
curdist = curnode[0]
if curdist > maxcost:
# Give up if player is painfully unreachable.
break
curpos = curnode[1]
if mapcoord(curpos) == tuple(destpos):
foundtarget = True
break
if dijkstramap[curpos[0]][curpos[1]][2] == True:
continue
else:
dijkstramap[curpos[0]][curpos[1]][2] = True
for nbrpos in coords.neighbours(curpos):
if (nbrpos[0] < 0 or nbrpos[1] < 0 or
nbrpos[0] >= 2*pfmapsize or nbrpos[1] >= 2*pfmapsize or
nbrpos == (pfmapsize, pfmapsize)):
continue
cellcost = costs(cellmap[mapcoord(nbrpos)])
newdist = curdist+cellcost
if ((dijkstramap[nbrpos[0]][nbrpos[1]][0] <= newdist and dijkstramap[nbrpos[0]][nbrpos[1]][0] != 0) or
cellmap[mapcoord(nbrpos)]['solid'] or cellcost > 8):
continue
dijkstramap[nbrpos[0]][nbrpos[1]] = [newdist, curpos, False]
heapq.heappush(openlist, (newdist, nbrpos))
if not foundtarget:
return False
while dijkstramap[curpos[0]][curpos[1]][1] != (pfmapsize, pfmapsize):
curpos = dijkstramap[curpos[0]][curpos[1]][1]
return coords.sum(curpos, (-pfmapsize,)*2)

0 comments on commit 8dda6a3

Please sign in to comment.