feat(*): Add dumb mode and more safety for dinosaurs

This commit is contained in:
Josh Creek
2025-12-27 13:30:19 +00:00
parent 24353a6255
commit 7b1a9263f1
+197 -41
View File
@@ -55,6 +55,8 @@ import helpers
# Fully traversing a very large farm can take a long time and you might not actually need that many bones. Feel
# free to use set_world_size() to change the size of the farm to something more convenient.
dumb_mode = True
last_move = None
next_x = -1
next_y = -1
@@ -66,80 +68,187 @@ OPPOSITE = {
West: East
}
tail = []
tail_length = 0
def any_other_move_available():
for d in [North, East, South, West]:
if last_move is not None and d == OPPOSITE[last_move]:
if last_move != None and d == OPPOSITE[last_move]:
continue
if can_move(d):
return True
return False
def safe_move(direction):
global last_move
# Only forbid reversal if another move exists
if last_move is not None and direction == OPPOSITE[last_move]:
if any_other_move_available():
return False
moved = move(direction)
if moved:
last_move = direction
return moved
def reset():
global last_move
global next_x
global next_y
global tail
global tail_length
last_move = None
next_x = -1
next_y = -1
tail = []
tail_length = 0
def safe_move(direction):
global last_move
global tail
global tail_length
# Prevent immediate reversal only if some other move exists
if last_move != None and direction == OPPOSITE[last_move]:
if any_other_move_available():
return False
if not can_move(direction):
return False
moved = move(direction)
if moved:
last_move = direction
tail.insert(0, (get_pos_x(), get_pos_y()))
if len(tail) > tail_length:
tail.pop()
return True
return False
def flood_can_reach_tail(head, simulated_tail):
# Breadth First Search - can head reach tail end if tail (except last) is blocked?
world = get_world_size()
if len(simulated_tail) == 0:
return True
blocked = set(simulated_tail[:-1])
target = simulated_tail[-1]
queue = [head]
visited = {head}
while queue:
x, y = queue.pop(0)
if (x, y) == target:
return True
for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
nx = x + dx
ny = y + dy
if 0 <= nx < world and 0 <= ny < world:
pos = (nx, ny)
if (pos not in blocked) and (pos not in visited):
visited.add(pos)
queue.append(pos)
return False
def move_one_step_towards(tx, ty):
# A tiny greedy stepper to head toward a target (helps get unstuck)
cx = get_pos_x()
cy = get_pos_y()
dx = tx - cx
dy = ty - cy
preferred = []
if abs(dx) >= abs(dy):
if dx > 0:
preferred.append(East)
elif dx < 0:
preferred.append(West)
if dy > 0:
preferred.append(North)
elif dy < 0:
preferred.append(South)
else:
if dy > 0:
preferred.append(North)
elif dy < 0:
preferred.append(South)
if dx > 0:
preferred.append(East)
elif dx < 0:
preferred.append(West)
for d in preferred + [North, East, South, West]:
if safe_move(d):
return True
return False
def clear_grid():
columns_per_drone = get_world_size() / max_drones()
for x in range(columns_per_drone):
for y in range(get_world_size()):
columns_per_drone = get_world_size() // max_drones()
for _ in range(columns_per_drone):
for _ in range(get_world_size()):
till()
safe_move(North)
safe_move(East)
def move_to_coords_avoiding_tail(x, y):
global last_move
if get_pos_x() == x and get_pos_y() == y:
return
while True:
current_x = get_pos_x()
current_y = get_pos_y()
cx = get_pos_x()
cy = get_pos_y()
dx = x - current_x
dy = y - current_y
dx = x - cx
dy = y - cy
moved = False
preferred = []
if abs(dx) >= abs(dy):
if dx > 0:
moved = safe_move(East)
preferred.append(East)
elif dx < 0:
moved = safe_move(West)
preferred.append(West)
if dy > 0:
preferred.append(North)
elif dy < 0:
preferred.append(South)
else:
if dy > 0:
moved = safe_move(North)
preferred.append(North)
elif dy < 0:
moved = safe_move(South)
preferred.append(South)
# Fallbacks
if not moved:
for d in [North, East, South, West]:
if safe_move(d):
moved = True
break
if dx > 0:
preferred.append(East)
elif dx < 0:
preferred.append(West)
# Try the preferred direction, then any direction
for d in preferred + [North, East, South, West]:
if safe_move(d):
moved = True
break
# We're completely stuck so just claim the rewards
if not moved:
# If we still have a tail, see if we can reach the tail end.
if tail_length > 1 and len(tail) > 0:
head = (get_pos_x(), get_pos_y())
can_escape = flood_can_reach_tail(head, tail)
if can_escape:
# We're not truly stuck, our greedy choices boxed us in.
# Unstick by walking toward the tail end a few steps.
tx, ty = tail[-1]
for _ in range(10):
if move_one_step_towards(tx, ty):
break
continue
# Truly stuck sp let's harvest and restart
change_hat(Hats.Straw_Hat)
reset()
change_hat(Hats.Dinosaur_Hat)
@@ -148,15 +257,53 @@ def move_to_coords_avoiding_tail(x, y):
if get_pos_x() == x and get_pos_y() == y:
return
def do_dumb():
global tail_length
# 32x32 grid
world_size = get_world_size()
moving_up = True
move(North)
for x in range(world_size):
for y in range(world_size - 2):
if get_entity_type() == Entities.Apple:
tail_length = tail_length + 1
if moving_up:
move(North)
if get_entity_type() == Entities.Apple:
tail_length = tail_length + 1
else:
move(South)
if get_entity_type() == Entities.Apple:
tail_length = tail_length + 1
move(East)
if get_entity_type() == Entities.Apple:
tail_length = tail_length + 1
moving_up = not moving_up
# now move back to 0,0
move(South)
if get_entity_type() == Entities.Apple:
tail_length = tail_length + 1
for x in range(world_size):
move(West)
if get_entity_type() == Entities.Apple:
tail_length = tail_length + 1
if tail_length > 900:
harvest()
def process():
global next_x
global next_y
global tail_length
global dumb_mode
reset()
world_size = get_world_size()
columns_per_drone = world_size / max_drones()
columns_per_drone = world_size // max_drones()
i = 0
while i < world_size:
@@ -167,8 +314,17 @@ def process():
clear_grid()
change_hat(Hats.Dinosaur_Hat)
tail_length = 1
if dumb_mode:
while True:
do_dumb()
else:
while True:
next_x, next_y = measure()
while True:
next_x, next_y = measure()
safe_move(North)
move_to_coords_avoiding_tail(next_x, next_y)
# Apple is eaten on the next move, tail grows by 1
tail_length = tail_length + 1
safe_move(North)
move_to_coords_avoiding_tail(next_x, next_y)