Add multithreaded maze exploration with drone spawning and enhanced treasure detection logic
This commit is contained in:
168
maze.py
168
maze.py
@@ -1,6 +1,26 @@
|
|||||||
import utils
|
import utils
|
||||||
from __builtins__ import *
|
from __builtins__ import *
|
||||||
|
|
||||||
|
spawn_dirs = []
|
||||||
|
spawn_index = [0]
|
||||||
|
spawned_branches = []
|
||||||
|
treasure_found = [0]
|
||||||
|
gold_start = [0]
|
||||||
|
|
||||||
|
def pop_spawn_dir():
|
||||||
|
if spawn_index[0] >= len(spawn_dirs):
|
||||||
|
return None
|
||||||
|
direction = spawn_dirs[spawn_index[0]]
|
||||||
|
spawn_index[0] = spawn_index[0] + 1
|
||||||
|
return direction
|
||||||
|
|
||||||
|
def is_spawned_at(vx, vy, direction):
|
||||||
|
for i in range(len(spawned_branches)):
|
||||||
|
entry = spawned_branches[i]
|
||||||
|
if entry[0] == vx and entry[1] == vy and entry[2] == direction:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
# Plant a full maze.
|
# Plant a full maze.
|
||||||
#
|
#
|
||||||
# Parameters:
|
# Parameters:
|
||||||
@@ -17,12 +37,13 @@ def solve(dimensions=None):
|
|||||||
if dimensions == None:
|
if dimensions == None:
|
||||||
dimensions = get_world_size()
|
dimensions = get_world_size()
|
||||||
|
|
||||||
|
treasure_found[0] = 0
|
||||||
|
gold_start[0] = num_items(Items.Gold)
|
||||||
|
spawn_index[0] = len(spawn_dirs)
|
||||||
|
|
||||||
grid_size = get_world_size()
|
grid_size = get_world_size()
|
||||||
|
|
||||||
directions = [North, East, South, West]
|
directions = [North, East, South, West]
|
||||||
left_of = {North: West, West: South, South: East, East: North}
|
|
||||||
right_of = {North: East, East: South, South: West, West: North}
|
|
||||||
back_of = {North: South, South: North, East: West, West: East}
|
|
||||||
|
|
||||||
def next_pos(x, y, direction):
|
def next_pos(x, y, direction):
|
||||||
if direction == North:
|
if direction == North:
|
||||||
@@ -56,6 +77,10 @@ def solve(dimensions=None):
|
|||||||
stack = [[x, y, 0]]
|
stack = [[x, y, 0]]
|
||||||
|
|
||||||
while len(stack) > 0:
|
while len(stack) > 0:
|
||||||
|
if treasure_found[0] or num_items(Items.Gold) > gold_start[0]:
|
||||||
|
treasure_found[0] = 1
|
||||||
|
return
|
||||||
|
|
||||||
current = stack[-1]
|
current = stack[-1]
|
||||||
x = current[0]
|
x = current[0]
|
||||||
y = current[1]
|
y = current[1]
|
||||||
@@ -63,8 +88,30 @@ def solve(dimensions=None):
|
|||||||
|
|
||||||
if get_entity_type() == Entities.Treasure and can_harvest():
|
if get_entity_type() == Entities.Treasure and can_harvest():
|
||||||
harvest()
|
harvest()
|
||||||
|
treasure_found[0] = 1
|
||||||
return
|
return
|
||||||
|
|
||||||
|
candidates = []
|
||||||
|
for i in range(len(directions)):
|
||||||
|
direction = directions[i]
|
||||||
|
if can_move(direction):
|
||||||
|
next_xy = next_pos(x, y, direction)
|
||||||
|
nx = next_xy[0]
|
||||||
|
ny = next_xy[1]
|
||||||
|
if not is_visited(nx, ny):
|
||||||
|
candidates.append(direction)
|
||||||
|
|
||||||
|
if len(candidates) > 1 and num_drones() < max_drones():
|
||||||
|
for i in range(1, len(candidates)):
|
||||||
|
candidate = candidates[i]
|
||||||
|
if not is_spawned_at(x, y, candidate):
|
||||||
|
spawned_branches.append([x, y, candidate])
|
||||||
|
spawn_dirs.append(candidate)
|
||||||
|
spawn_drone(maze_worker)
|
||||||
|
next_xy = next_pos(x, y, candidate)
|
||||||
|
visited.append([next_xy[0], next_xy[1]])
|
||||||
|
break
|
||||||
|
|
||||||
moved = False
|
moved = False
|
||||||
while next_dir_index < len(directions):
|
while next_dir_index < len(directions):
|
||||||
direction = directions[next_dir_index]
|
direction = directions[next_dir_index]
|
||||||
@@ -93,3 +140,118 @@ def solve(dimensions=None):
|
|||||||
back_dir = direction_between(x, y, prev_x, prev_y)
|
back_dir = direction_between(x, y, prev_x, prev_y)
|
||||||
move(back_dir)
|
move(back_dir)
|
||||||
stack.pop()
|
stack.pop()
|
||||||
|
|
||||||
|
def maze_worker():
|
||||||
|
start_x = get_pos_x()
|
||||||
|
start_y = get_pos_y()
|
||||||
|
|
||||||
|
grid_size = get_world_size()
|
||||||
|
directions = [North, East, South, West]
|
||||||
|
|
||||||
|
def next_pos(x, y, direction):
|
||||||
|
if direction == North:
|
||||||
|
return x, (y + 1) % grid_size
|
||||||
|
if direction == South:
|
||||||
|
return x, (y - 1) % grid_size
|
||||||
|
if direction == East:
|
||||||
|
return (x + 1) % grid_size, y
|
||||||
|
return (x - 1) % grid_size, y
|
||||||
|
|
||||||
|
def direction_between(x, y, nx, ny):
|
||||||
|
if (x + 1) % grid_size == nx and y == ny:
|
||||||
|
return East
|
||||||
|
if (x - 1) % grid_size == nx and y == ny:
|
||||||
|
return West
|
||||||
|
if x == nx and (y + 1) % grid_size == ny:
|
||||||
|
return North
|
||||||
|
return South
|
||||||
|
|
||||||
|
visited = []
|
||||||
|
visited.append([start_x, start_y])
|
||||||
|
|
||||||
|
def is_visited(vx, vy):
|
||||||
|
for i in range(len(visited)):
|
||||||
|
if visited[i][0] == vx and visited[i][1] == vy:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
first_dir = pop_spawn_dir()
|
||||||
|
if not first_dir:
|
||||||
|
return
|
||||||
|
if not can_move(first_dir):
|
||||||
|
return
|
||||||
|
|
||||||
|
next_xy = next_pos(start_x, start_y, first_dir)
|
||||||
|
move(first_dir)
|
||||||
|
visited.append([next_xy[0], next_xy[1]])
|
||||||
|
stack = [[next_xy[0], next_xy[1], 0]]
|
||||||
|
|
||||||
|
while len(stack) > 0:
|
||||||
|
if treasure_found[0] or num_items(Items.Gold) > gold_start[0]:
|
||||||
|
treasure_found[0] = 1
|
||||||
|
return
|
||||||
|
|
||||||
|
current = stack[-1]
|
||||||
|
x = current[0]
|
||||||
|
y = current[1]
|
||||||
|
next_dir_index = current[2]
|
||||||
|
|
||||||
|
if get_entity_type() == Entities.Treasure and can_harvest():
|
||||||
|
harvest()
|
||||||
|
treasure_found[0] = 1
|
||||||
|
return
|
||||||
|
|
||||||
|
candidates = []
|
||||||
|
for i in range(len(directions)):
|
||||||
|
direction = directions[i]
|
||||||
|
if can_move(direction):
|
||||||
|
next_xy = next_pos(x, y, direction)
|
||||||
|
nx = next_xy[0]
|
||||||
|
ny = next_xy[1]
|
||||||
|
if not is_visited(nx, ny):
|
||||||
|
candidates.append(direction)
|
||||||
|
|
||||||
|
if len(candidates) > 1 and num_drones() < max_drones():
|
||||||
|
for i in range(1, len(candidates)):
|
||||||
|
candidate = candidates[i]
|
||||||
|
if not is_spawned_at(x, y, candidate):
|
||||||
|
spawned_branches.append([x, y, candidate])
|
||||||
|
spawn_dirs.append(candidate)
|
||||||
|
spawn_drone(maze_worker)
|
||||||
|
next_xy = next_pos(x, y, candidate)
|
||||||
|
visited.append([next_xy[0], next_xy[1]])
|
||||||
|
break
|
||||||
|
|
||||||
|
moved = False
|
||||||
|
while next_dir_index < len(directions):
|
||||||
|
direction = directions[next_dir_index]
|
||||||
|
stack[-1][2] = next_dir_index + 1
|
||||||
|
if can_move(direction):
|
||||||
|
next_xy = next_pos(x, y, direction)
|
||||||
|
nx = next_xy[0]
|
||||||
|
ny = next_xy[1]
|
||||||
|
if not is_visited(nx, ny):
|
||||||
|
move(direction)
|
||||||
|
visited.append([nx, ny])
|
||||||
|
stack.append([nx, ny, 0])
|
||||||
|
moved = True
|
||||||
|
break
|
||||||
|
next_dir_index = stack[-1][2]
|
||||||
|
|
||||||
|
if moved:
|
||||||
|
continue
|
||||||
|
|
||||||
|
prev_x = start_x
|
||||||
|
prev_y = start_y
|
||||||
|
if len(stack) > 1:
|
||||||
|
prev = stack[-2]
|
||||||
|
prev_x = prev[0]
|
||||||
|
prev_y = prev[1]
|
||||||
|
|
||||||
|
back_dir = direction_between(x, y, prev_x, prev_y)
|
||||||
|
move(back_dir)
|
||||||
|
stack.pop()
|
||||||
|
|
||||||
|
if len(stack) == 0:
|
||||||
|
if get_pos_x() == start_x and get_pos_y() == start_y:
|
||||||
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user