Compare commits

...

6 Commits

4 changed files with 410 additions and 122 deletions

208
cactus.py
View File

@@ -6,17 +6,17 @@ import utils
# Returns:
# Tuple
def compute_cost(width, height):
cost = get_cost(Unlocks.Cactus)
seeds = width * height
cost = get_cost(Unlocks.Cactus)
seeds = width * height
for item in cost:
if item == Items.Cactus:
cost[item] = seeds * cost[item]
for item in cost:
if item == Items.Cactus:
cost[item] = seeds * cost[item]
return cost
return cost
def place(width, height):
utils.plant_grid(width, height, [Entities.Cactus], 0.0, True)
utils.plant_grid(width, height, [Entities.Cactus], 0.0, True)
# Harvests all cacti in the specified area.
#
@@ -31,116 +31,116 @@ def place(width, height):
# width (int): The number of columns in the grid.
# height (int): The number of rows in the grid.
def sort_and_harvest(width, height):
x = get_pos_x()
y = get_pos_y()
# first sort all by row, and in this loop we keep tally of the sum of all cacti in each row
for row in range(height):
_sort_row_bubble(width)
if row < height - 1:
move(North)
y += 1
utils.move_to(x, y)
x = get_pos_x()
y = get_pos_y()
# first sort all by row, and in this loop we keep tally of the sum of all cacti in each row
for row in range(height):
_sort_row_bubble(width)
if row < height - 1:
move(North)
y += 1
utils.move_to(x, y)
y -= (height - 1)
utils.move_to(x, y)
y -= (height - 1)
utils.move_to(x, y)
# now sort each row by column to account for north/south, but we don't need to keep track of the sum of each column
for col in range(width):
_sort_column_bubble(height)
if col < width - 1:
move(East)
x += 1
utils.move_to(x, y)
# now sort each row by column to account for north/south, but we don't need to keep track of the sum of each column
for col in range(width):
_sort_column_bubble(height)
if col < width - 1:
move(East)
x += 1
utils.move_to(x, y)
move(West)
move(West)
# we should be fully sorted! so just harvest...
harvest()
# we should be fully sorted! so just harvest...
harvest()
# Sort a row of cacti based on size. Implement bubble sort.
#
# Parameters:
# width (int): The number of columns in the grid.
# Sort a row of cacti based on size. Implement bubble sort.
#
# Parameters:
# width (int): The number of columns in the grid.
def _sort_row_bubble(width):
start_index = 0
end_index = width - 1
swapped = True
start_index = 0
end_index = width - 1
swapped = True
while start_index < end_index and swapped:
swapped = False
# Forward pass (East): Bubble the largest item to the right (end_index)
# We travel from start_index to end_index
for _ in range(end_index - start_index):
if measure(East) < measure():
swap(East)
swapped = True
move(East)
# The rightmost element is now sorted
end_index -= 1
while start_index < end_index and swapped:
swapped = False
# Forward pass (East): Bubble the largest item to the right (end_index)
# We travel from start_index to end_index
for _ in range(end_index - start_index):
if measure(East) < measure():
swap(East)
swapped = True
move(East)
# The rightmost element is now sorted
end_index -= 1
if not swapped:
break
swapped = False
# Backward pass (West): Bubble the smallest item to the left (start_index)
# We travel from end_index back to start_index
# FIXED: Added +1 to range to ensure we reach start_index
for _ in range(end_index - start_index + 1):
if measure(West) > measure():
swap(West)
swapped = True
move(West)
# The leftmost element is now sorted
start_index += 1
# Move to the start of the new window
# We are currently at (start_index - 1), so move East once to get to start_index
if start_index < end_index:
move(East)
if not swapped:
break
swapped = False
# Backward pass (West): Bubble the smallest item to the left (start_index)
# We travel from end_index back to start_index
# FIXED: Added +1 to range to ensure we reach start_index
for _ in range(end_index - start_index + 1):
if measure(West) > measure():
swap(West)
swapped = True
move(West)
# The leftmost element is now sorted
start_index += 1
# Move to the start of the new window
# We are currently at (start_index - 1), so move East once to get to start_index
if start_index < end_index:
move(East)
# Sort a column of cacti based on size. Implement bubble sort.
#
# Parameters:
# height (int): The number of rows in the grid.
# Sort a column of cacti based on size. Implement bubble sort.
#
# Parameters:
# height (int): The number of rows in the grid.
def _sort_column_bubble(height):
start_index = 0
end_index = height - 1
swapped = True
start_index = 0
end_index = height - 1
swapped = True
while start_index < end_index and swapped:
swapped = False
# Forward pass (North): Bubble the largest item to the top (end_index)
for _ in range(end_index - start_index):
if measure(North) < measure():
swap(North)
swapped = True
move(North)
end_index -= 1
while start_index < end_index and swapped:
swapped = False
# Forward pass (North): Bubble the largest item to the top (end_index)
for _ in range(end_index - start_index):
if measure(North) < measure():
swap(North)
swapped = True
move(North)
end_index -= 1
if not swapped:
break
swapped = False
# Backward pass (South): Bubble the smallest item to the bottom (start_index)
# FIXED: Added +1 to range to ensure we reach start_index
for _ in range(end_index - start_index + 1):
if measure(South) > measure():
swap(South)
swapped = True
move(South)
start_index += 1
if start_index < end_index:
move(North)
if not swapped:
break
swapped = False
# Backward pass (South): Bubble the smallest item to the bottom (start_index)
# FIXED: Added +1 to range to ensure we reach start_index
for _ in range(end_index - start_index + 1):
if measure(South) > measure():
swap(South)
swapped = True
move(South)
start_index += 1
if start_index < end_index:
move(North)

40
main.py
View File

@@ -1,5 +1,6 @@
import cactus
import utils
import maze
import pumpkins
import sunflowers
from __builtins__ import *
@@ -12,8 +13,8 @@ def plant_carrots(width, height):
def plant_grass(width, height):
utils.plant_grid(width, height, [Entities.Grass], 0.75, False)
def plant_alternating(width, height, plantWith):
utils.plant_grid(width, height, plantWith, 0.75, False)
def plant_alternating(width, height, plantWith, fn = None):
utils.plant_grid(width, height, plantWith, 0.75, False, fn)
# Entire grid utils:
# These are utilities to plant & harvest the entire grid with specific plants.
@@ -38,6 +39,16 @@ def entire_grid_trees_and_grass():
utils.move_to(0, 0)
plant_alternating(world_size, world_size, [ Entities.Tree, Entities.Grass ])
def entire_grid_trees_and_grass_fertilizer():
world_size = get_world_size()
utils.move_to(0, 0)
def on_plant(x, y):
use_item(Items.Fertilizer)
plant_alternating(world_size, world_size, [ Entities.Tree, Entities.Grass ], on_plant)
def entire_grid_cactus():
world_size = get_world_size()
utils.move_to(0, 0)
@@ -76,12 +87,21 @@ if __name__ == "__main__":
while num_items(Items.Pumpkin) < 500000:
entire_grid_pumpkins()
for i in range(10):
entire_grid_trees_and_grass()
utils.move_to(0, 0)
entire_grid_carrots()
entire_grid_carrots()
entire_grid_pumpkins()
maze.place(utils.world_size)
maze.solve(utils.world_size)
# entire_grid_trees_and_grass_fertilizer()
# utils.harvest_grid(get_world_size(), get_world_size())
# for i in range(10):
# entire_grid_trees_and_grass()
# entire_grid_carrots()
# entire_grid_carrots()
# entire_grid_pumpkins()
while True:
worldSize = get_world_size()
@@ -91,11 +111,11 @@ if __name__ == "__main__":
# only run this if our total power is below 5k.
# why? because the rest doesn't use over 5k power.
while num_items(Items.Power) < 5000:
while num_items(Items.Power) < 50000:
utils.move_to(0, 0)
grid = sunflowers.place(sectionSize, sectionSize)
grid = sunflowers.place(worldSize, worldSize)
utils.move_to(0, 0)
sunflowers.harvest_grid(sectionSize, sectionSize, grid)
sunflowers.harvest_grid(grid)
utils.move_to(0, 0)
cactus.place(sectionSize, sectionSize)

257
maze.py Normal file
View File

@@ -0,0 +1,257 @@
import utils
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.
#
# Parameters:
# dimensions (tuple): The dimensions of the maze. If not set, default to the maximum size.
def place(dimensions=None):
if dimensions == None:
dimensions = get_world_size()
plant(Entities.Bush)
substance = dimensions * 2**(num_unlocked(Unlocks.Mazes) - 1)
use_item(Items.Weird_Substance, substance)
def solve(dimensions=None):
if dimensions == None:
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()
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 = []
x = get_pos_x()
y = get_pos_y()
visited.append([x, 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
stack = [[x, y, 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
if len(stack) == 1:
return
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()
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

View File

@@ -3,15 +3,26 @@ from __builtins__ import *
world_size = get_world_size()
def move_to(x, y):
while x > get_pos_x():
move(East)
while x < get_pos_x():
move(West)
cx = get_pos_x()
cy = get_pos_y()
while y > get_pos_y():
move(North)
while y < get_pos_y():
move(South)
east_steps = (x - cx) % world_size
west_steps = (cx - x) % world_size
if east_steps <= west_steps:
for _ in range(east_steps):
move(East)
else:
for _ in range(west_steps):
move(West)
north_steps = (y - cy) % world_size
south_steps = (cy - y) % world_size
if north_steps <= south_steps:
for _ in range(north_steps):
move(North)
else:
for _ in range(south_steps):
move(South)