Toy maze solver (stateless) for https://store.steampowered.com/app/2060160/The_Farmer_Was_Replaced/
-
-
Save andrew-raphael-lukasik/ad3b7eb048bb9135734feb76a96f9f9f to your computer and use it in GitHub Desktop.
| 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() |
Can someone explain why this algorithm works?
@mahdi-mezghani this is straight-forward wall-hugging. Every valid maze can be solved by following a wall and this is exactly what treasure_hunt() does here. It's nothing complicated. Simplicity is an underappreciated code quality.
This approach won't produce an optimal path every time but it doesn't matter that much in this game. At least while mazes are relatively small. For big mazes this method becomes ill-fitted, but it's a problem most players won't even have.
Ope. I'll see what I can do to prevent this.
Stack overflow is caused by recursive function calls.
Any specific reason why you're planting a full row of bushes and watering them before spawning a maze? You should just need to move to (0,0) and plant a single bush (then use substances) in create_maze(). From my testing, water or fertilizers do nothing to mazes, too...
Any specific reason why you're planting a full row of bushes and watering them before spawning a maze? You should just need to move to (0,0) and plant a single bush (then use substances) in create_maze()
This is simply how it worked at the time of me writing this code. Have no idea how it changed since then
I added a summon drone to run in the opposite direction- to speed up maze completion. I also added *2 for the upgraded maze. The weird substance cost and earnings increase for higher level mazes.
With the drone, I also had to add a get entity for grass. If the summoned drone completed the maze it was stuck in a loop, so I had to return 1.
I'm new to Github and coding- sorry if the code and posting isn't quite right.
(https://gist.github.com/1337dondongo/6cb2506bb1847d1b4490260673aa49c4)
Thank you for the maze code! It really helped me!
I added a summon drone to run in the opposite direction- to speed up maze completion. I also added *2 for the upgraded maze. The weird substance cost and earnings increase for higher level mazes.
With the drone, I also had to add a get entity for grass. If the summoned drone completed the maze it was stuck in a loop, so I had to return 1.
I'm new to Github and coding- sorry if the code and posting isn't quite right.
(https://gist.github.com/1337dondongo/6cb2506bb1847d1b4490260673aa49c4)
Maybe you know how to add up to 4 drones?
Maybe you know how to add up to 4 drones?
Andrew wrote great code, but the game forces you to start mazes at 1 location. You can spawn more drones, but unless you code new ways to explore the maze it won't make it faster. His code followed the left hand side so I simply added a drone to follow the right hand side- at the same time. Maybe there's another way to explore the maze I can't think of?
You can spawn more drones, but unless you code new ways to explore the maze it won't make it faster. His code followed the left hand side so I simply added a drone to follow the right hand side- at the same time. Maybe there's another way to explore the maze I can't think of?
If it is really possible to spawn more drones now, then you can "multi-thread" the search process by moving every drone to a different starting position. Start with map corners or spread them evenly across the maze. This will lower the search time slightly with every new drone added.
sidenote:
As number of drones approaches get_world_size() this search technique could potentially start to lose to more "naive" search patterns. For example:
- Every drone picking a row and just scanning it start to finish simultaneously
(imagine a police search party where people search an area by moving in a line formation). - Every drone picking an equally spaced starting position and searching in some kind growing-spiral pattern
(like a coastal guard searching an area) - Every drone calculating its unique rectangular area to scan at the start then each scanning his own quadrant
What I personally do is use this two-drone approach in opposite directions, and make them only return when they reach the end. This is suboptimal but quite easy to implement. Once a different drone picks the treasure, the remaining drones will remain walking in 2x2 circles wherever they were, meaning that my distribution of drones around the field trends upwards, and they are reasonably evenly distributed. That’s probably the fastest you can get without using proper search algorithms.
If it is really possible to spawn more drones now, then you can "multi-thread" the search process by moving every drone to a different starting position. Start with map corners or spread them evenly across the maze. This will lower the search time slightly with every new drone added.
Good idea. I put the 1 spawn drone in def treasure_hunt():, so the clone is spawned after the maze is created. Not sure, but they normally spawn on the original drones location.
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():
continueI updated my code in the link. I drop the drones before starting the maze, and removed the clear function. This is in response to KanzakiRanko1 who had a great idea on letting spawned drones persist between mazes.
I made a few changes to Filipe-Brr's code and it seems to be going much faster. I moved clear() from the beginning of def create_maze to right above the while loop in the trigger code (the one marked as "to use"). At first this made the maze only run a few times then stall, but this was fixed by changing the last paragraph of def treasure_hunt() as follows:
while num_drones() != max_drones():
spawn_drone(move_towards_treasure)
if get_entity_type() != Entities.Hedge:
return 1It now works indefinitely, and after when it would have normally stalled all the drones stay in their previous positions when the map reloads, making for much faster maze clear times.
One of the things I would add to the code would be with the Strategy 3 stuff.
That is updating the for d checks for this:
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: #You're right next to the chest, so move there!
move(d)
harvest()
return 1
if next_pos not in tiles or not tiles[next_pos]["visited"]:
free_dirs.append(d)I also do try to 'priortize' moves that would lead closer to the chest's X/Y coordinates, but that doesn't always work faster.
Shortest working simple code for me is that.
def createLab(): # taken directly from in game advice
plant(Entities.Bush)
substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
use_item(Items.Weird_Substance, substance)
def findLeftTreasure(): # This code will work like our drone have left hand on the wall while trying to find treasure
rightOf={North:East, East:South, South:West, West:North}
leftOf={North:West, West:South, South:East, East:North}
dir=North
while True:
if can_move(dir):
move(dir)
dir=leftOf[dir]
else:
dir=rightOf[dir]
if get_entity_type()==Entities.Treasure:
harvest()
return 1
def TreasureUp(Target):
while num_items(Items.Gold)<Target: # Code will continue till target ammount of gold is met
createLab()
findLeftTreasure()
return 1
Target=100000
TreasureUp(Target)Shortest working simple code for me is that.
def createLab(): # taken directly from in game advice plant(Entities.Bush) substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1) use_item(Items.Weird_Substance, substance) def findLeftTreasure(): # This code will work like our drone have left hand on the wall while trying to find treasure rightOf={North:East, East:South, South:West, West:North} leftOf={North:West, West:South, South:East, East:North} dir=North while True: if can_move(dir): move(dir) dir=leftOf[dir] else: dir=rightOf[dir] if get_entity_type()==Entities.Treasure: harvest() return 1 def TreasureUp(Target): while num_items(Items.Gold)<Target: # Code will continue till target ammount of gold is met createLab() findLeftTreasure() return 1 Target=100000 TreasureUp(Target)
I modified this to use both a left and right hand path, and then after 100 steps each done will spawn a drone of it's opposing direction. Helps it to feel more efficient.
def createLab(): # taken directly from in game advice
if get_ground_type() != Grounds.Grassland:
till()
plant(Entities.Bush)
substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
use_item(Items.Weird_Substance, substance)
def findLeftTreasure(): # This code will work like our drone have left hand on the wall while trying to find treasure
rightOf={North:East, East:South, South:West, West:North}
leftOf={North:West, West:South, South:East, East:North}
dir=North
cnt = 0
while True:
cnt = cnt+1
if cnt == 100:
spawn_drone(findRightTreasure)
if can_move(dir):
move(dir)
dir=leftOf[dir]
else:
dir=rightOf[dir]
if get_entity_type()==Entities.Treasure:
harvest()
return 1
if can_move(East) and can_move(West) and can_move(North) and can_move(South):
return 1
def findRightTreasure(): # This code will work like our drone have left hand on the wall while trying to find treasure
rightOf={North:West, West:South, South:East, East:North}
leftOf={North:East, East:South, South:West, West:North}
dir=South
cnt = 0
while True:
cnt = cnt+1
if cnt == 100:
spawn_drone(findLeftTreasure)
if can_move(dir):
move(dir)
dir=leftOf[dir]
else:
dir=rightOf[dir]
if get_entity_type()==Entities.Treasure:
harvest()
return 1
if can_move(East) and can_move(West) and can_move(North) and can_move(South):
return 1
def TreasureUp(Target):
while num_items(Items.Gold)<Target: # Code will continue till target ammount of gold is met
createLab()
spawn_drone(findRightTreasure)
findLeftTreasure()
Target=100000
TreasureUp(Target)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)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 1main:
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 == sizemain:
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()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)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
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!

in the newer version you need to change just a little bit in the code for it to run. but its only in the main script because of the new import function
its a simple fix: