Add timeout to pathfinding, optimize

This commit is contained in:
Tanner Collin 2020-05-20 17:57:22 -06:00
parent 948dd64221
commit ccdd51aad3
2 changed files with 46 additions and 12 deletions

View File

@ -183,12 +183,12 @@ NON_SOLID = [
]
SINGLE_SNOW = 3919
NON_SOLID_IDS = [SINGLE_SNOW]
NON_SOLID_IDS = set([SINGLE_SNOW])
for block_name in NON_SOLID:
for state in BLOCKS[block_name]['states']:
NON_SOLID_IDS.append(state['id'])
NON_SOLID_IDS.add(state['id'])
AVOID_IDS = []
AVOID_IDS = set()
for block_name in AVOID:
for state in BLOCKS[block_name]['states']:
AVOID_IDS.append(state['id'])
AVOID_IDS.add(state['id'])

50
bot.py
View File

@ -1,5 +1,6 @@
import os
import time
import functools
from math import ceil, floor, hypot
import blocks
@ -11,6 +12,9 @@ from minecraft.networking.packets import Packet, clientbound, serverbound
from minecraft.compat import input
from minecraft.managers import ChunksManager
class AStarTimeout(Exception):
pass
class DataManager:
def __init__(self):
self.blocks_states = {}
@ -107,19 +111,41 @@ PARKOUR = [
PARKOUR_WEST,
]
HYPOT_LUT = {
(0, -1): 1.0,
(0, 1): 1.0,
(1, 0): 1.0,
(-1, 0): 1.0,
(1, -1): 1.414,
(-1, -1): 1.414,
(1, 1): 1.414,
(-1, 1): 1.414,
(0, 2): 2.0,
(-2, 0): 2.0,
(2, 0): 2.0,
(0, -2): 2.0,
}
def padd(p1, p2):
return (p1[0] + p2[0], p1[1] + p2[1], p1[2] + p2[2])
def pint(p):
return (int(p[0]), int(p[1]), int(p[2]))
# larger started being slower
BLOCK_CACHE_SIZE = 2**14
class MazeSolver(AStar):
def __init__(self, chunks):
self.chunks = chunks
self.start_time = time.time()
@functools.lru_cache(maxsize=BLOCK_CACHE_SIZE)
def bair(self, p):
return self.chunks.get_block_at(*p) in blocks.NON_SOLID_IDS
@functools.lru_cache(maxsize=BLOCK_CACHE_SIZE)
def bavoid(self, p):
return self.chunks.get_block_at(*p) in blocks.AVOID_IDS
@ -225,18 +251,19 @@ class MazeSolver(AStar):
return True
def check_parkour(self, node, offset):
if not self.check_ascend(node, offset):
return False
dest = padd(node, offset)
half_offset = tuple(int(0.5*x) for x in offset)
half_offset = (int(offset[0]/2), offset[1], int(offset[2]/2))
middle = padd(node, half_offset)
middle_head = padd(middle, BLOCK_ABOVE)
# dont jump if we can walk instead
if not self.bair(padd(middle, BLOCK_BELOW)):
return False
if not self.check_ascend(node, offset):
return False
middle_head = padd(middle, BLOCK_ABOVE)
if not self.bair(middle_head):
return False
@ -270,12 +297,16 @@ class MazeSolver(AStar):
if self.check_parkour(node, offset):
results.append(padd(node, offset))
if not results:
if time.time() - self.start_time > 2.0:
raise(AStarTimeout)
return results
def distance_between(self, n1, n2):
(x1, y1, z1) = n1
(x2, y2, z2) = n2
return hypot(x2 - x1, z2 - z1)
return HYPOT_LUT[x2 - x1, z2 - z1]
def heuristic_cost_estimate(self, n1, n2):
(x1, y1, z1) = n1
@ -407,10 +438,13 @@ def main(connection, player_info):
s['goal'] = LPoint3f(x=p.location[0], y=p.location[1], z=p.location[2])
print('new waypoint:', s['goal'])
start = time.time()
solution = MazeSolver(player_info.chunks).astar(pint(player_info.pos), pint(s['goal']))
if solution:
s['path'] = list(solution)
print(s['path'])
solution = list(solution)
s['path'] = solution
print(len(solution))
print(round(time.time() - start, 3), 'seconds')
else:
packet = serverbound.play.ChatPacket()
packet.message = 'No path found'