Improve finding sand by using slices

This commit is contained in:
2020-12-02 05:16:46 +00:00
parent eabb0a04d1
commit b7295b4beb
4 changed files with 195 additions and 39 deletions
+70 -5
View File
@@ -163,11 +163,9 @@ class MCWorld:
return False
return True
def find_sand(self, center, distance, origin):
def find_sand(self, center, distance, player):
sand = []
for i in range(10):
check = utils.padd(center, utils.alternate(i, 1))
sand.extend(self.find_blocks(check, distance, [blocks.SAND], 20))
sand.extend(self.find_blocks(center, distance, [blocks.SAND], 25))
safe_sand = []
for s in sand:
@@ -187,9 +185,61 @@ class MCWorld:
safe_sand.append(s)
safe_sand.sort(key=lambda x: utils.phyp_bias(center, x, origin))
safe_sand.sort(key=lambda x: utils.phyp(player, x))
return safe_sand
def check_sand_slice(self, center):
# checks if a 5x5x1 slice has diggable sand in it
for i in range(9):
s = utils.padd(center, utils.spiral(i))
if self.block_at(*s) != blocks.SAND:
continue
# make sure it has solid below
if self.block_at(*utils.padd(s, path.BLOCK_BELOW)) in blocks.NON_SOLID_IDS:
continue
# make sure it has solid two below - prevent hanging sand
if self.block_at(*utils.padd(s, path.BLOCK_BELOW2)) in blocks.NON_SOLID_IDS:
continue
# and walkable air above
if self.block_at(*utils.padd(s, path.BLOCK_ABOVE)) not in blocks.NON_SOLID_IDS:
continue
if not self.sand_adjacent_safe(s):
continue
return True
return False
def find_sand_slice(self, center, distance, skip_to=(0, 0)):
# returns the centre coord of the next 5x5x1 slice that still has
# diggable sand in it. lower slices are only valid if there's an
# adjacent slice farther at the same level. this should ensure an
# upside down pyramid gets excavated so the edges are still climbable
skip_vertical, skip_spiral = skip_to
for v in count(skip_vertical):
peak = utils.padd(center, (0, 20-v, 0))
layer = 0
start_step = skip_spiral if v == skip_vertical else 0
for step in count(start_step):
offset = utils.spiral(step)
layer = max(layer, *offset)
offset = utils.pmul(offset, 3)
check = utils.padd(peak, offset)
check = utils.padd(check, (0, layer, 0))
if utils.phyp(center, check) >= distance:
break
if self.check_sand_slice(check):
return (v-1, step+1), check
if v > 40:
return None, None
def find_bed_openings(self, area):
# returns coords in a cardinal direction where we can stand by bed
result = []
@@ -454,8 +504,23 @@ class Game:
if command == 'cache':
self.g.job.state = self.g.job.cache_items
self.g.job.cache_items_states.minimum = 0
self.g.job.cache_items_states.silent = True
reply = 'ok'
if command == 'spiral' and data:
for i in range(int(data)):
print(utils.spiral(i))
if command == 'sand_slice':
try:
_, result = self.g.world.find_sand_slice(utils.pint(self.g.pos), 50)
reply = str(result)
except:
import traceback
print(traceback.format_exc())
reply = 'error'
if reply:
print(reply)
if private and not reply.startswith('/'):