Skip to content

Instantly share code, notes, and snippets.

@andrew-raphael-lukasik
Last active May 18, 2026 20:16
Show Gist options
  • Select an option

  • Save andrew-raphael-lukasik/ad3b7eb048bb9135734feb76a96f9f9f to your computer and use it in GitHub Desktop.

Select an option

Save andrew-raphael-lukasik/ad3b7eb048bb9135734feb76a96f9f9f to your computer and use it in GitHub Desktop.
"The Farmer Was Replaced" maze solver
def create_maze():
clear()
for i in range(get_world_size()):
plant(Entities.Bush)
while get_water()<0.9:
use_item(Items.Water)
move(North)
for i in range(get_world_size()):
while can_harvest()==False:
pass
while get_entity_type()==Entities.Bush:
if num_items(Items.Fertilizer)==0:
trade(Items.Fertilizer)
#if num_items(Items.Fertilizer)==0:
#main()
use_item(Items.Fertilizer)
treasure_hunt()
def treasure_hunt():
dir = West
x = get_pos_x()
y = get_pos_y()
while True:
move(dir)
x2 = get_pos_x()
y2 = get_pos_y()
if x==x2 and y==y2:
if dir==West:
dir = North
elif dir==North:
dir = East
elif dir==East:
dir = South
elif dir==South:
dir = West
else:
x = get_pos_x()
y = get_pos_y()
if dir==West:
dir = South
elif dir==North:
dir = West
elif dir==East:
dir = North
elif dir==South:
dir = East
if get_entity_type()==Entities.Treasure:
harvest()
create_maze()
@khwong-c
Copy link
Copy Markdown

khwong-c commented Jan 18, 2026

I found the above scripts may held the drone and oscillated between two squares.
Instead, I am using DFS to solve the puzzle. It's generally faster than the above implementation, and guaranteed to solve the maze.

Size and location (origin) can be specified. Therefore it is handy for multi-drone farming for higher throughput.
16 * 8x8 mazes / 25 * 6x6 mazes are effective.

def treasure(origin, sz=0):
    def create_maze(origin, sz=0):
        movement.to(origin)  # Move the Drone to the center first
        # Following is taken directly from in game advice
        if sz == 0:
            sz = get_world_size()
        if get_ground_type() != Grounds.Grassland:
            till()
        plant(Entities.Bush)
        substance = sz * 2 ** (num_unlocked(Unlocks.Mazes) - 1)
        use_item(Items.Weird_Substance, substance)

    def dfs(last_dir):   
        # Defining the reverse direction. Used to determine where the drone comes from.
        reverse = {
            North: South, South: North, East: West, West: East, 
            None: None, # None is added to handle the first move
        }
        if get_entity_type() == Entities.Treasure:
            harvest()
            return True # Notify the callers to stop

        # Consider each direction as a branch.
        for dir in (North, East, South, West):
            # Skipping the Reverse of the Last Action, which is the previous space.
            # Also Skipping directions with wall.
            if dir == reverse[last_dir] or not can_move(dir):
                continue
            move(dir)           # Step into the next direction.
            found = dfs(dir)    # See if we can find the treasure from the next direction + the following moves.
            if found:
                return True     # Notify the callers to stop
            move(reverse[dir])  # Not found... Step back and try another direction.
        return False            # All Directions are not found. The caller shall not stop.

    create_maze(origin, sz)
    dfs(None)

# Example: Create a 8x8 maze, centered at (4,4) and solve it.
tresaure((4,4), 8)

If you don't have the implementation of movement.to(origin), which moves the drone to a specific place:

def to(pos):
	x,y = pos
	dx,dy = get_pos_x()-x, get_pos_y()-y
	if dx != 0:
		dir = East
		if dx > 0:
			dir = West
		for _ in range(abs(dx)):
			move(dir)
	if dy != 0:
		dir = North
		if dy > 0:
			dir = South
		for _ in range(abs(dy)):
			move(dir)

@linuskjk
Copy link
Copy Markdown

linuskjk commented Apr 27, 2026

this is what I use, it is quite efficient on big maps and easily adaptable for all desires:

helper functions in my 'funcs' file:

def delay(time: int):
	start = get_time()
	while not get_time() - start >= time:
		#do_a_flip()
		change_hat(Hats.Carrot_Hat)
		change_hat(Hats.Purple_Hat)


def plantx(what: str):
	
	if can_harvest():
			harvest()
			
			
	if what == "carrot":
		if get_ground_type() == Grounds.Grassland:
			till()
		plant(Entities.Carrot)
		if num_items(Items.Water) > 0:
			use_item(Items.Water)
			
			
	if what == "wheat":
		if get_ground_type() == Grounds.Soil:
			till()
		plant(Entities.Grass)
		if num_items(Items.Water) > 0:
			use_item(Items.Water)
			
	if what == "bush":
		if get_ground_type() == Grounds.Soil:
			till()
		plant(Entities.Bush)
		if num_items(Items.Water) > 0:
			use_item(Items.Water)
			
	
	if what == "tree":
		if get_ground_type() == Grounds.Soil:
			till()
		plant(Entities.Tree)
		if num_items(Items.Water) > 0:
			use_item(Items.Water)
			
	if what == "sunflower":
		if get_ground_type() == Grounds.Grassland:
			till()
		plant(Entities.Sunflower)
		if num_items(Items.Water) > 0:
			use_item(Items.Water)
			
			
	if what == "pumpkin":
		if get_ground_type() == Grounds.Grassland:
			till()
		plant(Entities.Pumpkin)

	if can_harvest():
			harvest()
			
			
			
def movex(direction: str, amount: int):
	if direction == "n":
		for _ in range(0, amount):
			move(North)
			
		
	if direction == "s":
		for _ in range(0, amount):
			move(South)
			
			
	if direction == "w":
		for _ in range(0, amount):
			move(West)
			
			
	if direction == "e":
		for _ in range(0, amount):
			move(East)
			
			


def goSpawn():
	while get_pos_x() > 0:
		move(West)
	while get_pos_y() > 0:
		move(South)
		



def cleanup(Groundtype: Grounds, plant=""):
	goSpawn()
	for i in range(get_world_size()):
		for _ in range(get_world_size()):
			if can_harvest():
				harvest()
			plantx(plant)
			#if not get_ground_type() == Groundtype:
			#	till()
			move(North)
		#goSpawn()
		#movex("e", i +1)
		move(East)
	goSpawn()
	return 1

main:

import funcs

def create_maze():
	plant(Entities.Bush)
	while get_entity_type()==Entities.Bush:
			substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
			if num_items(Items.Weird_Substance) > substance:
				use_item(Items.Weird_Substance, substance)
				return 1
			if can_harvest():
				harvest()
				plant(Entities.Bush)
			if num_items(Items.Fertilizer)==0:
				#trade(Items.Fertilizer)
				return 0
			
			use_item(Items.Fertilizer)


def turn_left(dir):
	if dir == North:
		return West
	if dir == West:
		return South
	if dir == South:
		return East
	if dir == East:
		return North

def turn_right(dir):
	if dir == North:
		return East
	if dir == East:
		return South
	if dir == South:
		return West
	if dir == West:
		return North

def try_move(dir):
	if can_move(dir):
		move(dir)
		return True
	return False


def wall_follow_left():
	dir = North
	while get_ground_type() == Entities.Hedge:
		left = turn_left(dir)
		if can_move(left):
			dir = left
			move(dir)
		elif can_move(dir):
			move(dir)
		else:
			dir = turn_right(dir)
		
		if get_entity_type() == Entities.Treasure:
			harvest()
			#clear()
			goSpawn()
			break
			return 1



def wall_follow_right():
	dir = North
	while get_ground_type() == Entities.Hedge:
		right = turn_right(dir)
		if can_move(right):
			dir = right
			move(dir)
		elif can_move(dir):
			move(dir)
		else:
			dir = turn_left(dir)
		
		if get_entity_type() == Entities.Treasure:
			harvest()
			#clear()
			goSpawn()
			break
			return 1


def move_towards_treasure():
	tiles = {}
	path = []
	bifurcations = []   

	while get_ground_type() == Entities.Hedge:
		m = measure()
		if m == None:
			while measure() == None:
				return 1

		x = get_pos_x()
		y = get_pos_y()
		pos = (x, y)

		if get_entity_type() == Entities.Treasure:
			harvest()
			return 1
			clear()

		walls = {
			North: not can_move(North),
			East:  not can_move(East),
			South: not can_move(South),
			West:  not can_move(West)
		}

		if pos not in tiles:
			n_walls = 0

			if walls[North]:
				n_walls = n_walls + 1
			if walls[East]:
				n_walls = n_walls + 1
			if walls[South]:
				n_walls = n_walls + 1
			if walls[West]:
				n_walls = n_walls + 1

			is_bifurcation = n_walls < 3

			tiles[pos] = {
				"walls": walls,
				"visited": True,
				"bifurcation": is_bifurcation
			}

			if is_bifurcation:
				bifurcations.append(pos)

		tiles[pos]["visited"] = True

		if len(path) == 0 or path[-1] != pos:
			path.append(pos)

		free_dirs = []
		for d in [North, East, South, West]:
			if not walls[d]:
				dx = 0
				dy = 0
				if d == North:
					dy = 1
				elif d == South:
					dy = -1
				elif d == East:
					dx = 1
				elif d == West:
					dx = -1

				next_pos = (x + dx, y + dy)

				if next_pos not in tiles or not tiles[next_pos]["visited"]:
					free_dirs.append(d)

		if len(free_dirs) > 0:
			r = random()
			dir = free_dirs[0]

			if len(free_dirs) == 2:
				if r > 0.5:
					dir = free_dirs[1]
			elif len(free_dirs) == 3:
				if r < 0.33:
					dir = free_dirs[0]
				elif r < 0.66:
					dir = free_dirs[1]
				else:
					dir = free_dirs[2]
			elif len(free_dirs) == 4:
				if r < 0.25:
					dir = free_dirs[0]
				elif r < 0.5:
					dir = free_dirs[1]
				elif r < 0.75:
					dir = free_dirs[2]
				else:
					dir = free_dirs[3]

			move(dir)
			continue

		if len(path) > 1:
			path.pop()
			prev = path[-1]
			px = prev[0]
			py = prev[1]

			if px > x:
				move(East)
			elif px < x:
				move(West)
			elif py > y:
				move(North)
			elif py < y:
				move(South)

			x = get_pos_x()
			y = get_pos_y()
			pos = (x, y)

			if pos in tiles and tiles[pos]["bifurcation"]:
				walls = tiles[pos]["walls"]
				free_dirs = []

				for d in [North, East, South, West]:
					if not walls[d]:
						dx = 0
						dy = 0
						if d == North:
							dy = 1
						elif d == South:
							dy = -1
						elif d == East:
							dx = 1
						elif d == West:
							dx = -1
		
						next_pos = (x + dx, y + dy)
						
						if next_pos == m:
							move(d)
							harvest()
							return 1
		
						if next_pos not in tiles or not tiles[next_pos]["visited"]:
							free_dirs.append(d)

				if len(free_dirs) > 0:
					r = random()
					dir = free_dirs[0]

					if len(free_dirs) == 2:
						if r > 0.5:
							dir = free_dirs[1]
					elif len(free_dirs) == 3:
						if r < 0.33:
							dir = free_dirs[0]
						elif r < 0.66:
							dir = free_dirs[1]
						else:
							dir = free_dirs[2]
					elif len(free_dirs) == 4:
						if r < 0.25:
							dir = free_dirs[0]
						elif r < 0.5:
							dir = free_dirs[1]
						elif r < 0.75:
							dir = free_dirs[2]
						else:
							dir = free_dirs[3]

					move(dir)


def calc_wait_time(num):
	return ((max_drones() + 2) - num* 0.5) - 6

def strategy_0(order: int):
	#funcs.delay(calc_wait_time(order))
	while not get_entity_type() == Entities.Hedge:
		pass
	wall_follow(True)

def strategy_1(order: int):
	#funcs.delay(calc_wait_time(order))
	while not get_entity_type() == Entities.Hedge:
		pass
	wall_follow(False)

def strategy_2(order: int = 0):
	if order != 0:
		delay(calc_wait_time(order))
	move_towards_treasure()

def strategy_3(order: int):
	funcs.delay(calc_wait_time(order))
	directional_search([North, East, West, South])

def strategy_4(order: int):
	funcs.delay(calc_wait_time(order))
	directional_search([South, West, North, East])

def strategy_5(order: int):
	funcs.delay(calc_wait_time(order))
	while get_entity_type() != Entities.Treasure:
		dirs = [North, East, South, West]
		valid = []
		for d in dirs:
			if can_move(d):
				valid.append(d)
		
		n = len(valid)
		r = random()
		
		if n == 1:
			move(valid[0])
		elif n == 2:
			if r < 0.5:
				move(valid[0])
			else:
				move(valid[1])
		elif n == 3:
			if r < 0.33:
				move(valid[0])
			elif r < 0.66:
				move(valid[1])
			else:
				move(valid[2])
		elif n == 4:
			if r < 0.25:
				move(valid[0])
			elif r < 0.5:
				move(valid[1])
			elif r < 0.75:
				move(valid[2])
			else:
				move(valid[3])
	harvest()
	#clear()
	funcs.goSpawn()


def strategy_6(order: int):
	delay(calc_wait_time(order))
	steps = 1
	while get_entity_type() != Entities.Treasure:
		for d in [North, East, South, West]:
			for _ in range(steps):
				if get_entity_type() == Entities.Treasure:
					break
				try_move(d)
			if d == East or d == West:
				steps += 1
	harvest()
	#clear()
	funcs.goSpawn()
	break

def strategy_7(order: int):
	delay(calc_wait_time(order))
	while get_entity_type() != Entities.Treasure:
		target = measure()
		if target == None:
			return
		tx, ty = target[0], target[1]
		cx, cy = get_pos_x(), get_pos_y()
		
		if tx > cx and try_move(East):
			continue
		if tx < cx and try_move(West):
			continue
		if ty > cy and try_move(North):
			continue
		if ty < cy and try_move(South):
			continue
		strategy_5() 
	harvest()
	clear()


def wall_follow(left=True):
	dir = North
	while get_entity_type() != Entities.Treasure:
		if left:
			next_dir = turn_left(dir)
		else:
			next_dir = turn_right(dir)
		if can_move(next_dir):
			dir = next_dir
			move(dir)
		elif can_move(dir):
			move(dir)
		else:
			if left:
				dir = turn_right(dir)
			else:
				dir = turn_left(dir)
	harvest()
	#clear()
	funcs.goSpawn()
	

def directional_search(priority):
	while get_entity_type() != Entities.Treasure:
		moved = False
		for d in priority:
			if can_move(d):
				move(d)
				moved = True
				break
		if not moved: # Sackgasse
			move(priority[2])
	harvest()
	#clear()
	funcs.goSpawn()
	
def start():
	
	starting_tm = get_time()
	starting_money = num_items(Items.Gold)
	
	clear()
	
	strategies = [
		strategy_0, strategy_1, strategy_2, strategy_3,
		strategy_4, strategy_5, strategy_6, strategy_7
	]
	
	strategies2 = []
	
	for _ in range(max_drones()//2):
		strategies2.append(strategy_0)
		strategies2.append(strategy_1)
	


	while num_items(Items.Power) < ((get_world_size()**2)//4)*max_drones():
		while num_items(Items.Carrot) < get_world_size()**2*2:
			funcs.cleanup(Grounds.Grassland, "carrot")
			
		if funcs.cleanup(Grounds.Soil, "sunflower"):
			continue
			funcs.cleanup(Grounds.Grassland, "")
			
			
		while num_items(Items.Hay) < get_world_size()**2*16:
			funcs.cleanup(Grounds.Grassland, "wheat")
		while num_items(Items.Wood) < get_world_size()**2*16:
			funcs.cleanup(Grounds.Grassland, "bush")
	
	drone_amount_line = max_drones()**0.5
	space = get_world_size() / drone_amount_line
	print(max_drones())
	
	print(space)
	funcs.goSpawn()
		
	move(North)
	move(East)
	indx = -1
	height = 0 
	current_line = 0
			   #                                                     ↓↓↓↓↓↓
	for i in range(1, max_drones() + 2): # x-------x-------x-------x--------
		print(i)
		if indx < len(strategies): #                                 ↑↑↑↑↑↑  
			indx += 1
		else:
			indx = 0
		print("current", current_line)
		print("line", drone_amount_line)
		if current_line <= drone_amount_line:
			if i < max_drones() + 2:
				spawn_drone(strategies2[indx], i)
				#print(str(strategies2[indx]))
			current_line += 1
			if current_line < drone_amount_line:#prevent last move like ↑
				funcs.movex("e", space)
			else:
				indx -=1
				funcs.movex("w", (space * (drone_amount_line-1)) + 1)
				if height <  drone_amount_line:
					height += 1
				funcs.movex("n", space)
				current_line = 0
	
	funcs.movex("e", 4)
	create_maze()
	strategy_2()
	
	
	# Results:
	funcs.goSpawn()
	money_per_run = num_items(Items.Gold) - starting_money
	time_took = get_time() - starting_tm
	money_per_sec = money_per_run/time_took
	print("you made ", money_per_run, " Gold in ", time_took, "seconds. That is ", money_per_sec, "Gold per second")
	
	
while True:
	start()
	
	

also if you want to plant things faster you can use this

helper:

def isAtEdge(side = None):
	pos_x = get_pos_x()
	pos_y = get_pos_y()
	size = get_world_size() - 1
	
	if side == "n":
		return pos_y == size
	if side == "e":
		return pos_x == size
	if side == "s":
		return pos_y == 0
	if side == "w":
		return pos_x == 0
	return pos_x == 0 or pos_x == size or pos_y == 0 or pos_y == size

main:

def OptimusHelper(plant, time, use_fert):
	start = get_time()
	while get_time() - start < time:
		if use_fert:
			use_item(Items.Fertilizer)
		if can_harvest():
			harvest()
		plantx(plant)

def OptimusPlanter(what, seconds, use_fert: bool):
	set_execution_speed(100)
	max_drones = get_world_size() * get_world_size()
	num = 1
	start_tm = get_time()
	while num < max_drones and get_time() - start_tm < seconds:
		spawn_drone(OptimusHelper, what, seconds, use_fert)
		
		if not isAtEdge("n"):
			move(North)
		elif not isAtEdge("e"):
			move(East)
			while not isAtEdge("s"):
				move(South)
		
		num += 1
	goSpawn()

@capfroggy
Copy link
Copy Markdown

capfroggy commented Apr 28, 2026

Yo he estado usando este script, espero les sirva a todos:

# Maze
clear()

ALL_DIRECTIONS = [North, South, East, West]


def opposite_direction(direction):
    if direction == North:
        return South
    elif direction == East:
        return West
    elif direction == South:
        return North
    elif direction == West:
        return East


def explore_option_iterative(start_direction):
    global ALL_DIRECTIONS
    if not move(start_direction):
        return False

    path_stack = [(start_direction, 0)]

    while path_stack and num_items(Items.Gold) < 9863168000000:
        if get_entity_type() == Entities.Treasure:
            harvest()
            start_maze()
            return True

        last_move_direction, next_dir_index = path_stack[-1]

        while next_dir_index < len(ALL_DIRECTIONS):
            explore_direction = ALL_DIRECTIONS[next_dir_index]

            path_stack[-1] = (last_move_direction, next_dir_index + 1)

            if opposite_direction(explore_direction) != last_move_direction:
                if move(explore_direction):
                    path_stack.append((explore_direction, 0))
                    break

            next_dir_index += 1

        if next_dir_index == len(ALL_DIRECTIONS):
            path_stack.pop()
            move(opposite_direction(last_move_direction))

    move(opposite_direction(start_direction))
    return False


def start_maze():
    plant(Entities.Bush)
    substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
    use_item(Items.Weird_Substance, substance)


def search():
    global drone_id
    global ALL_DIRECTIONS

    for _ in range(drone_id):
        do_a_flip()

    if drone_id % 2:
        ALL_DIRECTIONS = ALL_DIRECTIONS[::-1]
    if drone_id % 3:
        ALL_DIRECTIONS[0], ALL_DIRECTIONS[1] = (ALL_DIRECTIONS[1], ALL_DIRECTIONS[0])
    if drone_id % 5:
        ALL_DIRECTIONS[1], ALL_DIRECTIONS[3] = (ALL_DIRECTIONS[3], ALL_DIRECTIONS[1])

    while True:
        for direction in ALL_DIRECTIONS:
            if explore_option_iterative(direction):
                break


drone_id = 0
start_maze()

for i in range(max_drones()):
    drone_id = i
    spawn_drone(search)

drone_id = 0

search()

def generate_maze():
    plant(Entities.Bush)
    substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
    use_item(Items.Weird_Substance, substance)


def maze():
    while True:
        if num_drones() == 25:
            if get_entity_type() == Entities.Treasure:
                harvest()
            generate_maze()


clear()
set_world_size(5)
list = []

while num_drones() < 26:
    pos_x = get_pos_x()
    pos_y = get_pos_y()
    current = (pos_x, pos_y)
    if current not in list:
        list.append(current)
        spawn_drone(maze)
        move(North)
    else:
        move(East)

@Potatobrain04
Copy link
Copy Markdown

Yo he hecho este script que guarda las intersecciones en una lista y si por un lado no encuentra el cofre, vuelve a la intersección y va por otro lado:

def Maze():
	while 1:
		last_move = North
		list = [(0,0)]
		move_list = [North, East, South, West]
		clear()
		plant(Entities.Bush)
		substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
		use_item(Items.Weird_Substance, substance)
		aurrera = [North, East, South, West]
		eskumara = [North, East, South, West]
		aurrera = [North, East, South, West]
		aurrera = [North, East, South, West]

		while get_entity_type() != Entities.Treasure:
			back_move = None
			if last_move == North:
				aurrera = move_list[0]
				eskumara = move_list[1]
				atzera = move_list[2]
				ezkerrera = move_list[3]
			elif last_move == East:
				aurrera = move_list[1]
				eskumara = move_list[2]
				atzera = move_list[3]
				ezkerrera = move_list[0]
			elif last_move == South:
				aurrera = move_list[2]
				eskumara = move_list[3]
				atzera = move_list[0]
				ezkerrera = move_list[1]
			else:
				aurrera = move_list[3]
				eskumara = move_list[0]
				atzera = move_list[1]
				ezkerrera = move_list[2]
		
			if can_move(eskumara) and not (can_move(ezkerrera) or can_move(aurrera)):
				move(eskumara)
				last_move = eskumara
			elif can_move(eskumara):
				list.insert(0, (get_pos_x(), get_pos_y()))
				move(eskumara)
				last_move = eskumara
			elif can_move(aurrera) and not can_move(ezkerrera):
				move(aurrera)
				last_move = aurrera
			elif can_move(aurrera):
				list.insert(0, (get_pos_x(), get_pos_y()))
				move(aurrera)
				last_move = aurrera
			elif can_move(ezkerrera):
				move(ezkerrera)
				last_move = ezkerrera
			else: # atras
				while (get_pos_x(), get_pos_y()) != list[0]:
					if can_move(atzera) and back_move != aurrera:
						while can_move(atzera) and (get_pos_x(), get_pos_y()) != list[0]:
							move(atzera)
						last_move = atzera
						back_move = None
					elif can_move(eskumara) and last_move != ezkerrera:
						while can_move(eskumara) and (get_pos_x(), get_pos_y()) != list[0]:
							move(eskumara)
						last_move = eskumara
						back_move = None
					elif can_move(ezkerrera) and last_move != eskumara:
						while can_move(ezkerrera) and (get_pos_x(), get_pos_y()) != list[0]:
							move(ezkerrera)
						last_move = ezkerrera
						back_move = None
					else:
						while can_move(aurrera) and (get_pos_x(), get_pos_y()) != list[0]:
							move(aurrera)
						last_move = aurrera
						back_move = aurrera
						
				list.pop(0)
		harvest()
Maze()

aurrera = adelante
eskuma = derecha
ezkerra = izquierda
atzera = atras

@BilgiPasa
Copy link
Copy Markdown

In addition to the wall-following strategy, I created code that marks the forks, so it explores a fork until the end. If it doesn't find the treasure, it returns to the fork and explores the next one.

This is useful for larger mazes with a larger number of drones.

def create_maze():
	clear()
	plant(Entities.Bush)
	while get_entity_type()==Entities.Bush:
			substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
			if num_items(Items.Weird_Substance) > substance:
				use_item(Items.Weird_Substance, substance)
				return 1
			if can_harvest():
				harvest()
				plant(Entities.Bush)
			if num_items(Items.Fertilizer)==0:
				# I do not have trade unlocked
				#trade(Items.Fertilizer)
				return 0
			
			use_item(Items.Fertilizer)

# === Helper Functions ===

def turn_left(dir):
	if dir == North:
		return West
	if dir == West:
		return South
	if dir == South:
		return East
	if dir == East:
		return North

def turn_right(dir):
	if dir == North:
		return East
	if dir == East:
		return South
	if dir == South:
		return West
	if dir == West:
		return North

def try_move(dir):
	if can_move(dir):
		move(dir)
		return True
	return False

# === Strategy 1: Follow the left wall ===

def wall_follow_left():
	dir = North
	while True:
		left = turn_left(dir)
		if can_move(left):
			dir = left
			move(dir)
		elif can_move(dir):
			move(dir)
		else:
			dir = turn_right(dir)
		
		if get_entity_type() == Entities.Treasure:
			harvest()
			return 1


# === Strategy 2: Follow the right wall ===

def wall_follow_right():
	dir = North
	while True:
		right = turn_right(dir)
		if can_move(right):
			dir = right
			move(dir)
		elif can_move(dir):
			move(dir)
		else:
			dir = turn_left(dir)
		
		if get_entity_type() == Entities.Treasure:
			harvest()
			return 1

# === Strategy 3 (improved): Move towards the treasure with exploration memory ===

def move_towards_treasure():
	tiles = {}          # Dictionary: (x, y) -> info about walls and bifurcation
	path = []           # List containing the path taken
	bifurcations = []   # List containing bifurcations not yet fully explored

	while True:
		# If another drone already got the treasure, wait until the maze resets
		m = measure()
		if m == None:
			while measure() == None:
				return 1

		x = get_pos_x()
		y = get_pos_y()
		pos = (x, y)

		# Check if standing on the treasure
		if get_entity_type() == Entities.Treasure:
			harvest()
			return 1

		# Detect walls around the current tile
		walls = {
			North: not can_move(North),
			East:  not can_move(East),
			South: not can_move(South),
			West:  not can_move(West)
		}

		# If the tile hasn't been recorded yet
		if pos not in tiles:
			n_walls = 0

			if walls[North]:
				n_walls = n_walls + 1
			if walls[East]:
				n_walls = n_walls + 1
			if walls[South]:
				n_walls = n_walls + 1
			if walls[West]:
				n_walls = n_walls + 1

			is_bifurcation = n_walls < 3  # Less than 3 walls = bifurcation

			tiles[pos] = {
				"walls": walls,
				"visited": True,
				"bifurcation": is_bifurcation
			}

			if is_bifurcation:
				bifurcations.append(pos)

		# Mark the tile as visited
		tiles[pos]["visited"] = True

		if len(path) == 0 or path[-1] != pos:
			path.append(pos)

		# Find free directions not yet visited
		free_dirs = []
		for d in [North, East, South, West]:
			if not walls[d]:
				dx = 0
				dy = 0
				if d == North:
					dy = 1
				elif d == South:
					dy = -1
				elif d == East:
					dx = 1
				elif d == West:
					dx = -1

				next_pos = (x + dx, y + dy)

				if next_pos not in tiles or not tiles[next_pos]["visited"]:
					free_dirs.append(d)

		# Randomly choose one of the available directions
		if len(free_dirs) > 0:
			r = random()
			dir = free_dirs[0]

			if len(free_dirs) == 2:
				if r > 0.5:
					dir = free_dirs[1]
			elif len(free_dirs) == 3:
				if r < 0.33:
					dir = free_dirs[0]
				elif r < 0.66:
					dir = free_dirs[1]
				else:
					dir = free_dirs[2]
			elif len(free_dirs) == 4:
				if r < 0.25:
					dir = free_dirs[0]
				elif r < 0.5:
					dir = free_dirs[1]
				elif r < 0.75:
					dir = free_dirs[2]
				else:
					dir = free_dirs[3]

			move(dir)
			continue

		# No free paths — backtrack to the previous bifurcation
		if len(path) > 1:
			path.pop()
			prev = path[-1]
			px = prev[0]
			py = prev[1]

			# Physically move backwards
			if px > x:
				move(East)
			elif px < x:
				move(West)
			elif py > y:
				move(North)
			elif py < y:
				move(South)

			x = get_pos_x()
			y = get_pos_y()
			pos = (x, y)

			# If back at a bifurcation, try another unexplored direction
			if pos in tiles and tiles[pos]["bifurcation"]:
				walls = tiles[pos]["walls"]
				free_dirs = []

				for d in [North, East, South, West]:
					if not walls[d]:
						dx = 0
						dy = 0
						if d == North:
							dy = 1
						elif d == South:
							dy = -1
						elif d == East:
							dx = 1
						elif d == West:
							dx = -1
						next_pos = (x + dx, y + dy)

						if next_pos not in tiles or not tiles[next_pos]["visited"]:
							free_dirs.append(d)

				if len(free_dirs) > 0:
					r = random()
					dir = free_dirs[0]

					if len(free_dirs) == 2:
						if r > 0.5:
							dir = free_dirs[1]
					elif len(free_dirs) == 3:
						if r < 0.33:
							dir = free_dirs[0]
						elif r < 0.66:
							dir = free_dirs[1]
						else:
							dir = free_dirs[2]
					elif len(free_dirs) == 4:
						if r < 0.25:
							dir = free_dirs[0]
						elif r < 0.5:
							dir = free_dirs[1]
						elif r < 0.75:
							dir = free_dirs[2]
						else:
							dir = free_dirs[3]

					move(dir)

			
def treasure_hunt():
	
	# Uses wall-following strategies
	spawn_drone(wall_follow_left)
	spawn_drone(wall_follow_right)
	
	# Uses the bifurcation exploration strategy
	while num_drones() != max_drones():
		spawn_drone(move_towards_treasure)

	move_towards_treasure()

to use

from MazeUtil2 import create_maze, treasure_hunt

times = 30

#for i in range(times):
	
	#create_maze()
	#treasure_hunt()

while True:
	if create_maze():
		if treasure_hunt():
			continue

Thank you very much for the multiple drone maze code. It it working very well!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment