def spawn_down(model, x, y, z): prog = single() if model[Pos(x,y-1,z)]: prog += single(Void(Diff(0,-1,0))) prog += +single(Fission(Diff(0,-1,0), 0)) return prog
def print_hyperrectangle(model, x, z, width, height, depth): prog = single() for i in range(height): last = i == height - 1 prog += print_strip_below(model, i, x, z, x + width, depth, last) if not last: prog += single(SMove(Diff(0,1,0))) return prog
def print_strip_below(model, i, lbound, z0, rbound, depth, last_layer): prog = single() for z in range(z0, z0 + depth): if model[Pos(lbound,i,z)]: prog += single(Fill(Diff(0,-1,0))) for x in range(lbound + 1, rbound): prog += single(SMove(Diff(1,0,0))) if model[Pos(x,i,z)]: prog += single(Fill(Diff(0,-1,0))) prog += move_x(-1 * (rbound - lbound - 1)) prog += single(SMove(Diff(0,0,1))) # TODO: optimise this part, make an L move prog += move_z(-1 * (depth + last_layer * z0)) return prog
def move_and_unfork(strips): if not strips: return single() # Wait for everyone on the right to finish prog = single() // move_and_unfork(strips[1:]) # Move our child bot to the left prog += single() // move_x(-1 * (strips[0] - 1)) # Unfork the bot immediately to the right prog += -single(FusionP(Diff(1,0,0))) // single(FusionS(Diff(-1,0,0))) return prog
def collapse_cube(width, height, depth): # Move 2 up to 1 (4 to 3, 6 to 5, 8 to 7) prog_contract_up = (single() // move_y(height - 1)) + -( single(FusionP(Diff(0, -1, 0))) // single(FusionS(Diff(0, 1, 0)))) # Move 3 back to 1 (7 to 5) prog_contract_back = (single() // move_z(-depth)) + -( single(FusionP(Diff(0, 0, 1))) // single(FusionS(Diff(0, 0, -1)))) # Move 5 left to 1 prog_contract_left = (single() // move_x(-width + 2)) + -( single(FusionP(Diff(1, 0, 0))) // single(FusionS(Diff(-1, 0, 0)))) return (prog_contract_up**4) + (prog_contract_back**2) + prog_contract_left
def move_z(delta): if delta == 0: return single() c = 1 - 2 * (delta < 0) delta = abs(delta) full_steps = delta // JUMP_LONG last = delta - JUMP_LONG * full_steps return singles([SMove(Diff(0,0,c * JUMP_LONG))] * full_steps + [SMove(Diff(0,0,c * last))] * (last > 0))
def void_cube(width, height, depth): return single(GVoid(Diff(0,-1, 1), Diff(width-1,-height+1,depth-1))) // \ single(GVoid(Diff(0, 0, 1), Diff(width-1,height-1,depth-1))) // \ single(GVoid(Diff(0,-1,-1), Diff(width-1,-height+1,-depth+1))) // \ single(GVoid(Diff(0, 0,-1), Diff(width-1,height-1,-depth+1))) // \ single(GVoid(Diff(0,-1, 1), Diff(-width+1,-height+1,depth-1))) // \ single(GVoid(Diff(0, 0, 1), Diff(-width+1,height-1,depth-1))) // \ single(GVoid(Diff(0,-1,-1), Diff(-width+1,-height+1,-depth+1))) // \ single(GVoid(Diff(0, 0,-1), Diff(-width+1,height-1,-depth+1)))
def drill_down(model, x, y, z, depth) -> GroupProgram: prog = single() while depth > 0: if model[Pos(x, y - 1, z)]: prog += single(Void(Diff(0, -1, 0))) step = 1 for i in range(2, depth + 1): if model[Pos(x, y - i, z)]: break else: step += 1 prog += move_y(-step) y -= step depth -= step return prog
def distribute_roots(x, y, z, full_w, last_w, seeds): if full_w == 0: return single() if full_w == 1 and last_w == 0: return single() return +single(Fission(Diff(-1,0,0),6)) + \ (+single(Fission(Diff(1,0,0),max(seeds-7-1,0))) // single()) + \ (-(single(FusionP(Diff(-1,0,0))) // single(FusionS(Diff(1,0,0)))) // (move_x(G_DIST) + distribute_roots(x+G_DIST, y, z, full_w - 1, last_w, seeds-7-1)))
def erase_layers(model, x, y, z, full_w, last_w, full_h, last_h, depth): if full_h == 0: if last_h != 0: return erase_layer(model, x, y, z, full_w, last_w, last_h, depth) else: return single()**(full_w + (1 if last_w else 0)) return erase_layer(model, x, y, z, full_w, last_w, G_DIST + 1, depth) + \ (move_y(-G_DIST - 1) ** (full_w + (1 if last_w else 0))) + \ erase_layers(model, x, y - G_DIST - 1, z, full_w, last_w, full_h - 1, last_h, depth)
def fork_and_move_new(seeds, space_right): if not seeds: return single() # Each bot gets its own strip bots = 1 + len(seeds) strip_width = floor(space_right / bots) strips.append(strip_width) nonlocal strips_sum strips_sum += strip_width # fork right giving them all our seeds prog = +single(Fission(Diff(1,0,0), len(seeds) - 1)) # the new bot moves into its position and does the same newprog = move_x(strip_width - 1) + fork_and_move_new(seeds[1:], space_right - strip_width) # wait for it do this prog += single() // newprog return prog
def erase_rows(model, x, y, z, full_w, last_w, height, full_d, last_d): cubes = full_w + (1 if last_w else 0) if full_d == 0: if last_d != 0: return erase_row(model, x, y, z, full_w, last_w, height, last_d) else: return single()**(full_w + (1 if last_w else 0)) else: prog = erase_row(model, x, y, z, full_w, last_w, height, G_DIST + 1) prog += move_z(G_DIST + 1)**cubes prog += erase_rows(model, x, y, z + G_DIST + 1, full_w, last_w, height, full_d - 1, last_d) prog += move_z(-G_DIST - 1)**cubes return prog
def erase_row(model, x, y, z, full_w, last_w, height, depth): # SAME UGLY HACK cubes = full_w + (1 if last_w else 0) prog_init = single()**cubes prog_fini = single()**cubes if depth == 1: depth += 1 prog_init += move_z(-1)**cubes prog_fini += move_z(+1)**cubes z -= 1 if height == 1: height += 1 prog_init += move_y(+1)**cubes prog_fini += move_y(-1)**cubes y += 1 prog_depl = empty() for i in range(full_w): prog_depl //= deploy_cube(model, x + i * (G_DIST + 1), y, z, G_DIST + 1, height, depth) if last_w != 0: prog_depl //= deploy_cube(model, x + full_w * (G_DIST + 1), y, z, last_w, height, depth) prog_void = empty() for i in range(full_w): prog_void //= void_cube(G_DIST + 1, height, depth) if last_w != 0: prog_void //= void_cube(last_w, height, depth) prog_clps = empty() for i in range(full_w): prog_clps //= collapse_cube(G_DIST + 1, height, depth) if last_w != 0: prog_clps //= collapse_cube(last_w, height, depth) return prog_init + prog_depl + prog_void + prog_clps + prog_fini
def clear_all_squads(model, x, y, z, width, height, depth) -> GroupProgram: deltax = 0 prog = single() while width > 0: last = width <= SQUAD_W this_w = min(SQUAD_W, width) prog += execute_squad(model, x + deltax, y, z, this_w, height, depth, 39) if not last: prog += move_x(this_w) deltax += this_w width -= this_w prog += move_x(-deltax) return prog
def clear_all(model, x, y, z, width, height, depth) -> GroupProgram: (full_w, last_w) = divmod(width, G_DIST + 1) deltax = 0 prog = single() for i in range(full_w): last = not last_w and i == full_w - 1 prog += clear_forward(model, x + deltax, y, z, G_DIST + 1, height, depth) if not last: prog += move_x(G_DIST + 1) deltax += (G_DIST + 1) if last_w: prog += clear_forward(model, x + deltax, y, z, last_w, height, depth) prog += move_x(-deltax) return prog
def clear_forward(model, x, y, z, width, height, depth) -> GroupProgram: assert width <= G_DIST + 1 (full_d, last_d) = divmod(depth, G_DIST + 1) deltaz = 0 prog = single() for i in range(full_d): last = not last_d and i == full_d - 1 prog += clear_tower(model, x, y, z + deltaz, width, height, G_DIST + 1) if not last: prog += move_z(G_DIST + 1) deltaz += (G_DIST + 1) if last_d: prog += clear_tower(model, x, y, z + deltaz, width, height, last_d) prog += move_z(-deltaz) return prog
def up_pass(model, high=False): prog = single() (pos1, pos2) = bounding_box(model) width = pos2.x - pos1.x + 1 height = pos2.y + 1 depth = pos2.z - pos1.z + 1 prog += move_x(pos1.x) x = pos1.x prog += move_y(1) prog += move_z(pos1.z) z = pos1.z max_bots = min(20, width) # Fission into a line (steps_distr, strips) = fission_fill_right(list(range(2, max_bots + 1)), width) prog += steps_distr if high: prog += single(Flip()) // (single() ** (max_bots - 1)) # Print each strip layer by layer in parallel print_prog = empty() for strip in strips: print_prog //= print_hyperrectangle(model, x, z, strip, height, depth) x += strip prog += print_prog if high: prog += single(Flip()) // (single() ** (max_bots - 1)) prog += fusion_unfill_right(strips) prog += move_x(-pos1.x) prog += move_y(-height) prog += single(Halt()) return prog
def collapse_roots(full_w, last_w): if full_w == 0: return single() if full_w == 1 and last_w == 0: return single() return (single() // (collapse_roots(full_w - 1, last_w) + move_x(-G_DIST))) + \ -(single(FusionP(Diff(1,0,0))) // single(FusionS(Diff(-1,0,0))))
def deploy_cube(model, x, y, z, width, height, depth): prog7 = move_z(depth) + spawn_down(model, x + (width-1), y, z + (depth+1)) + \ (single() // drill_down(model, x + (width-1), y-1, z + (depth+1), height-1)) prog57 = move_x(width-2) + spawn_down(model, x + (width-1), y, z) + \ (+single(Fission(Diff(0,0,1), 1)) // single()) + \ (single() // move_y(-height+1) // prog7) prog3 = move_z(depth) + spawn_down(model, x, y, z + (depth+1)) + \ (single() // drill_down(model, x, y - 1, z + (depth+1), height-1)) prog1 = +single(Fission(Diff(0,-1,0), 0)) + \ (+single(Fission(Diff(0,0,1), 1)) // single()) + \ (+single(Fission(Diff(1,0,0), 3)) // single() // single()) + \ (single() // move_y(-height+1) // prog3 // prog57) return prog1
def clear_cube_below(model, x, y, z, width, height, depth) -> GroupProgram: logging.debug("Cube at x=%d y=%d z=%d, %d x %d x %d", x,y,z,width,height,depth) assert width <= G_DIST + 1 and height <= G_DIST + 1 and depth <= G_DIST + 1 # assert depth > 1 # assert height > 1 # assert width > 1 # THIS IS A STUPID HACK FOR ABOVE (see also prog_fini) prog_init = single() prog_fini = single() if depth == 1: depth += 1 prog_init += move_z(-1) prog_fini += move_z(+1) z -= 1 if width == 1: width += 1 prog_init += move_x(-1) prog_fini += move_x(+1) x -= 1 if height == 1: height += 1 prog_init += move_y(+1) y += 1 prog7 = move_z(depth) + spawn_down(model, x + (width-1), y, z + (depth+1)) + \ (single() // drill_down(model, x + (width-1), y-1, z + (depth+1), height-1)) prog57 = move_x(width-2) + spawn_down(model, x + (width-1), y, z) + \ (+single(Fission(Diff(0,0,1), 1)) // single()) + \ (single() // move_y(-height+1) // prog7) prog3 = move_z(depth) + spawn_down(model, x, y, z + (depth+1)) + \ (single() // drill_down(model, x, y - 1, z + (depth+1), height-1)) prog1 = +single(Fission(Diff(0,-1,0), 0)) + \ (+single(Fission(Diff(0,0,1), 1)) // single()) + \ (+single(Fission(Diff(1,0,0), 3)) // single() // single()) + \ (single() // move_y(-height+1) // prog3 // prog57) prog_expand = prog1 prog_clear = single(GVoid(Diff(0,-1, 1), Diff(width-1,-height+1,depth-1))) // \ single(GVoid(Diff(0, 0, 1), Diff(width-1,height-1,depth-1))) // \ single(GVoid(Diff(0,-1,-1), Diff(width-1,-height+1,-depth+1))) // \ single(GVoid(Diff(0, 0,-1), Diff(width-1,height-1,-depth+1))) // \ single(GVoid(Diff(0,-1, 1), Diff(-width+1,-height+1,depth-1))) // \ single(GVoid(Diff(0, 0, 1), Diff(-width+1,height-1,depth-1))) // \ single(GVoid(Diff(0,-1,-1), Diff(-width+1,-height+1,-depth+1))) // \ single(GVoid(Diff(0, 0,-1), Diff(-width+1,height-1,-depth+1))) # Move 1 down to 2 (3 to 4, 5 to 6, 7 to 8) prog_contract_down = (move_y(-height+1) // single()) + -(single(FusionP(Diff(0,-1,0))) // single(FusionS(Diff(0,1,0)))) # Move 3 back to 1 (7 to 5) prog_contract_back = (single() // move_z(-depth)) + -(single(FusionP(Diff(0,0,1))) // single(FusionS(Diff(0,0,-1)))) # Move 5 left to 1 prog_contract_left = (single() // move_x(-width+2)) + -(single(FusionP(Diff(1,0,0))) // single(FusionS(Diff(-1,0,0)))) prog_contract = (prog_contract_down ** 4) + (prog_contract_back ** 2) + prog_contract_left + move_y(-1) return prog_init + prog_expand + prog_clear + prog_contract + prog_fini