Fix lumberjack bugs

This commit is contained in:
Tanner Collin 2020-05-24 21:55:38 -06:00
parent 4e2efeb604
commit d37f55a2db

140
bot.py
View File

@ -217,8 +217,11 @@ def padd(p1, p2):
def psub(p1, p2): def psub(p1, p2):
return (p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]) return (p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2])
def phyp(p1, p2):
return hypot(p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2])
def pint(p): def pint(p):
return (int(p[0]), int(p[1]), int(p[2])) return (floor(p[0]), floor(p[1]), floor(p[2]))
# larger started being slower # larger started being slower
BLOCK_CACHE_SIZE = 2**14 BLOCK_CACHE_SIZE = 2**14
@ -296,9 +299,6 @@ class MazeSolver(AStar):
if not self.bair(padd(node, BLOCK_ABOVE2)): if not self.bair(padd(node, BLOCK_ABOVE2)):
return False return False
if not self.bair(padd(dest, BLOCK_ABOVE2)):
return False
return True return True
def check_descend(self, node, offset): def check_descend(self, node, offset):
@ -346,6 +346,9 @@ class MazeSolver(AStar):
if not self.check_ascend(node, offset): if not self.check_ascend(node, offset):
return False return False
if not self.bair(padd(dest, BLOCK_ABOVE2)):
return False
if not self.bair(padd(middle, BLOCK_ABOVE)): if not self.bair(padd(middle, BLOCK_ABOVE)):
return False return False
@ -398,6 +401,7 @@ class MazeSolver(AStar):
def spiral(n): def spiral(n):
# return x, 0, z coords along a spiral at step n # return x, 0, z coords along a spiral at step n
# I forget where I found this
n += 1 n += 1
k = ceil((sqrt(n)-1)/2) k = ceil((sqrt(n)-1)/2)
t = 2 * k + 1 t = 2 * k + 1
@ -442,6 +446,7 @@ def break_block(connection, coords, time):
s['break_finished_packet'].face = 1 s['break_finished_packet'].face = 1
s['break_time'] = time s['break_time'] = time
s['break_timeout'] = 0.25
BLOCK_ABOVE = (0, +1, 0) BLOCK_ABOVE = (0, +1, 0)
@ -480,14 +485,21 @@ class MCWorld:
if offset[0] > distance: if offset[0] > distance:
return result return result
def find_tree(self, center, distance): def find_trees(self, center, distance):
logs = [] logs = []
for i in range(5): for i in range(5):
check = padd(center, alternate(i, 4)) check = padd(center, alternate(i, 3))
logs.extend(self.find_blocks(center, distance, blocks.LOG_IDS, 5)) logs.extend(self.find_blocks(check, distance, blocks.LOG_IDS, 50))
print(logs)
trees = []
for log in logs: for log in logs:
# crawl to the top log # crawl to the bottom log
while self.block_at(*padd(log, BLOCK_BELOW)) in blocks.LOG_IDS:
log = padd(log, BLOCK_BELOW)
# crawl to the top log to count
log_count = 1 log_count = 1
while self.block_at(*padd(log, BLOCK_ABOVE)) in blocks.LOG_IDS: while self.block_at(*padd(log, BLOCK_ABOVE)) in blocks.LOG_IDS:
log = padd(log, BLOCK_ABOVE) log = padd(log, BLOCK_ABOVE)
@ -495,15 +507,16 @@ class MCWorld:
# make sure it's a good tree # make sure it's a good tree
if self.block_at(*padd(log, BLOCK_ABOVE)) in blocks.LEAF_IDS and log_count > 2: if self.block_at(*padd(log, BLOCK_ABOVE)) in blocks.LEAF_IDS and log_count > 2:
break # crawl back to the bottom log
else: # for while self.block_at(*padd(log, BLOCK_BELOW)) in blocks.LOG_IDS:
return None log = padd(log, BLOCK_BELOW)
trees.append(log)
# crawl to the bottom log print('before', trees)
while self.block_at(*padd(log, BLOCK_BELOW)) in blocks.LOG_IDS: trees.sort(key=lambda x: phyp(center, x))
log = padd(log, BLOCK_BELOW) print('after', trees)
return log return trees
def find_tree_openings(self, tree): def find_tree_openings(self, tree):
# returns coords in a cardinal direction where we can stand by tree # returns coords in a cardinal direction where we can stand by tree
@ -553,8 +566,12 @@ class LumberjackStates:
w = MCWorld(self.player_info.chunks) w = MCWorld(self.player_info.chunks)
p = pint(self.player_info.pos) p = pint(self.player_info.pos)
self.tree = w.find_tree(p, 100) trees = w.find_trees(p, 100)
print('Found tree at:', self.tree) print('Found trees:', trees)
while trees[0] in self.bad_trees:
trees.pop(0)
self.tree = trees[0]
openings = w.find_tree_openings(self.tree) openings = w.find_tree_openings(self.tree)
@ -563,8 +580,10 @@ class LumberjackStates:
self.opening = o self.opening = o
if path: break if path: break
else: # for else: # for
print('Unable to get to tree') print('Unable to get to tree', self.tree)
self.bad_trees.append(self.tree)
self.state = self.finished self.state = self.finished
return
s['path'] = path s['path'] = path
self.state = self.going_to_tree self.state = self.going_to_tree
@ -572,11 +591,11 @@ class LumberjackStates:
def going_to_tree(self): def going_to_tree(self):
d = self.player_info.pos - LPoint3f(*self.opening) d = self.player_info.pos - LPoint3f(*self.opening)
if d.length() < 1: if d.length() < 1:
s['look_at'] = LPoint3f(*self.tree) s['look_at'] = self.tree
self.state = self.clear_leaves self.state = self.clear_leaves
def clear_leaves(self): def clear_leaves(self):
if not s['break_finished_packet']: if not s['break_timeout']:
p = pint(self.player_info.pos) p = pint(self.player_info.pos)
diff = psub(self.tree, p) diff = psub(self.tree, p)
@ -592,16 +611,16 @@ class LumberjackStates:
return return
def clear_trunk_base(self): def clear_trunk_base(self):
if not s['break_finished_packet']: if not s['break_timeout']:
base = self.tree base = self.tree
above = padd(self.tree, BLOCK_ABOVE) above = padd(self.tree, BLOCK_ABOVE)
if self.blog(base): if self.blog(base):
s['break'] = (base, 2) s['break'] = (base, 3)
return print('breaking base')
elif self.blog(above): elif self.blog(above):
s['break'] = (above, 2) s['break'] = (above, 3)
return print('breaking above')
else: else:
w = MCWorld(self.player_info.chunks) w = MCWorld(self.player_info.chunks)
p = pint(self.player_info.pos) p = pint(self.player_info.pos)
@ -613,11 +632,11 @@ class LumberjackStates:
def going_to_trunk_base(self): def going_to_trunk_base(self):
d = self.player_info.pos - LPoint3f(*self.opening) d = self.player_info.pos - LPoint3f(*self.opening)
if d.length() < 1: if d.length() < 1:
s['pitch'] = -90 s['look_at'] = padd(self.tree, BLOCK_ABOVE2)
self.state = self.clear_trunk self.state = self.clear_trunk
def clear_trunk(self): def clear_trunk(self):
if not s['break_finished_packet']: if not s['break_timeout']:
check = self.tree check = self.tree
count = 0 count = 0
@ -626,14 +645,22 @@ class LumberjackStates:
count += 1 count += 1
if self.blog(check): if self.blog(check):
s['break'] = (check, 2) print('breaking log', check)
s['break'] = (check, 3)
else: else:
print('Finished clearing tree') print('Finished clearing tree')
self.state = self.finished self.wait_time = 0.5
s['look_at'] = None
self.state = self.wait
def wait(self):
# wait for the last log to fall
if self.wait_time > 0:
self.wait_time -= TICK
else:
self.state = self.finished
def finished(self): def finished(self):
s['pitch'] = 0 # todo, calc with look_at
s['look_at'] = None
return None return None
@ -643,6 +670,8 @@ class LumberjackStates:
self.tree = None self.tree = None
self.opening = None self.opening = None
self.bad_trees = []
self.wait_time = 0
def run(self): def run(self):
self.state() self.state()
@ -659,6 +688,10 @@ class JobStates:
l = self.lumberjack_states l = self.lumberjack_states
if l.state == l.idle: if l.state == l.idle:
l.state = l.find_new_tree l.state = l.find_new_tree
elif l.state == l.finished:
# check time, etc
l.state = l.find_new_tree
l.run() l.run()
def __init__(self, player_info): def __init__(self, player_info):
@ -671,8 +704,11 @@ class JobStates:
TICK = 0.05 TICK = 0.05
ANGLE_DIR = LVector3f(x=0, y=0, z=-1) last_tick = time.time()
ANGLE_REF = LVector3f(x=0, y=1, z=0)
PITCH_ANGLE_DIR = LVector3f(x=0, y=1, z=0)
YAW_ANGLE_DIR = LVector3f(x=0, y=0, z=-1)
YAW_ANGLE_REF = LVector3f(x=0, y=1, z=0)
YAW_LOOK_AHEAD = 4 YAW_LOOK_AHEAD = 4
running = True running = True
@ -684,7 +720,6 @@ last_mod_time = get_mod_time()
s = dict() s = dict()
pitch = 0
@ -700,7 +735,7 @@ def tick(connection, player_info):
p = player_info.pos p = player_info.pos
if len(s['path']): if s['path'] and len(s['path']):
target = LPoint3f(s['path'][0]) target = LPoint3f(s['path'][0])
target.x += 0.5 target.x += 0.5
target.z += 0.5 target.z += 0.5
@ -710,7 +745,7 @@ def tick(connection, player_info):
# jump up block # jump up block
if d.y < -0.9 and not s['y_v']: if d.y < -0.9 and not s['y_v']:
s['y_v'] = 10.0 s['y_v'] = 8.5
s['y_a'] = -36.0 s['y_a'] = -36.0
# jump gap # jump gap
@ -729,7 +764,7 @@ def tick(connection, player_info):
p.y += s['y_v'] * TICK p.y += s['y_v'] * TICK
s['y_v'] += s['y_a'] * TICK s['y_v'] += s['y_a'] * TICK
if player_info.chunks.get_block_at(int(p.x), ceil(p.y-1), int(p.z)) not in blocks.NON_SOLID_IDS: if player_info.chunks.get_block_at(floor(p.x), ceil(p.y-1), floor(p.z)) not in blocks.NON_SOLID_IDS:
p.y = ceil(p.y) p.y = ceil(p.y)
s['y_v'] = 0 s['y_v'] = 0
s['y_a'] = 0 s['y_a'] = 0
@ -739,9 +774,9 @@ def tick(connection, player_info):
if s['look_at']: if s['look_at']:
look_at = LPoint3f(s['look_at']) look_at = LPoint3f(s['look_at'])
elif len(s['path']) > YAW_LOOK_AHEAD: elif s['path'] and len(s['path']) > YAW_LOOK_AHEAD:
look_at = LPoint3f(s['path'][YAW_LOOK_AHEAD]) look_at = LPoint3f(s['path'][YAW_LOOK_AHEAD])
elif len(s['path']): elif s['path'] and len(s['path']):
look_at = LPoint3f(s['path'][-1]) look_at = LPoint3f(s['path'][-1])
else: else:
look_at = None look_at = None
@ -752,11 +787,19 @@ def tick(connection, player_info):
look_at_d = p - look_at look_at_d = p - look_at
if look_at_d.length() > 0.6: if look_at_d.length() > 0.6:
target_yaw = look_at_d.normalized().signedAngleDeg(other=ANGLE_DIR, ref=ANGLE_REF) target_yaw = look_at_d.normalized().signedAngleDeg(other=YAW_ANGLE_DIR, ref=YAW_ANGLE_REF)
target_yaw_d = target_yaw - s['yaw'] target_yaw_d = target_yaw - s['yaw']
target_yaw_d = (target_yaw_d + 180) % 360 - 180 target_yaw_d = (target_yaw_d + 180) % 360 - 180
s['yaw'] += cap(target_yaw_d, 30) s['yaw'] += cap(target_yaw_d, 30)
target_pitch = look_at_d.normalized().angleDeg(PITCH_ANGLE_DIR)
target_pitch = (target_pitch - 90) * -1
target_pitch_d = target_pitch - s['pitch']
s['pitch'] += cap(target_pitch_d, 10)
else:
target_pitch_d = 0 - s['pitch']
s['pitch'] += cap(target_pitch_d, 10)
packet = serverbound.play.PositionAndLookPacket(x=p.x, feet_y=p.y, z=p.z, pitch=s['pitch'], yaw=s['yaw'], on_ground=True) packet = serverbound.play.PositionAndLookPacket(x=p.x, feet_y=p.y, z=p.z, pitch=s['pitch'], yaw=s['yaw'], on_ground=True)
@ -771,10 +814,17 @@ def tick(connection, player_info):
packet.hand = packet.HAND_MAIN packet.hand = packet.HAND_MAIN
connection.write_packet(packet) connection.write_packet(packet)
#print(s['break_time'])
s['break_time'] -= TICK s['break_time'] -= TICK
elif s['break_finished_packet']: elif s['break_finished_packet']:
print('break finished')
connection.write_packet(s['break_finished_packet']) connection.write_packet(s['break_finished_packet'])
s['break_finished_packet'] = None s['break_finished_packet'] = None
elif s['break_timeout'] > 0:
s['break_timeout'] -= TICK
if s['break_timeout'] < 0:
s['break_timeout'] = 0
@ -791,6 +841,7 @@ def init(connection, player_info):
s['break'] = None s['break'] = None
s['break_time'] = 0 s['break_time'] = 0
s['break_timeout'] = 0
s['break_finished_packet'] = None s['break_finished_packet'] = None
s['jobstate'] = JobStates(player_info) s['jobstate'] = JobStates(player_info)
@ -828,6 +879,7 @@ def main(connection, player_info):
solution = list(solution) solution = list(solution)
s['path'] = solution s['path'] = solution
print(len(solution)) print(len(solution))
print(solution)
print(round(time.time() - start, 3), 'seconds') print(round(time.time() - start, 3), 'seconds')
else: else:
packet = serverbound.play.ChatPacket() packet = serverbound.play.ChatPacket()
@ -964,7 +1016,13 @@ def main(connection, player_info):
while running: while running:
tick(connection, player_info) tick(connection, player_info)
time.sleep(TICK)
global last_tick
sleep_time = TICK + last_tick - time.time()
if sleep_time < 0: sleep_time = 0
time.sleep(sleep_time)
last_tick = time.time()
if get_mod_time() != last_mod_time: if get_mod_time() != last_mod_time:
break break