def snake_fill_gen(m: 'Model', a: Pos, b: Pos): prevPos = a nextPos = a # The main idea is to skip path points where model has no voxels below it. # And then go to the next "job" using long lenear move. We always above our # buildings so we will never collide with anything. for diff in snake_path_gen(a, b): nextPos = nextPos + diff fillBelow = False for d in [Diff(0, -1, 0), Diff(0, -1, 1), Diff(0, -1, -1)]: if inside_region((nextPos + d), a, b) and m[nextPos + d]: fillBelow = True if fillBelow: dx = nextPos.x - prevPos.x dy = nextPos.y - prevPos.y dz = nextPos.z - prevPos.z # y first for x in split_linear_move(Diff(0, dy, 0)): yield x for x in split_linear_move(Diff(0, 0, dz)): yield x for x in split_linear_move(Diff(dx, 0, 0)): yield x for d in [Diff(0, -1, 0), Diff(0, -1, 1), Diff(0, -1, -1)]: if inside_region((nextPos + d), a, b) and m[nextPos + d]: yield Cmd.Fill(d) m[nextPos + d] = False prevPos = nextPos yield prevPos
def test_illegal_smoves(): em = Cpp.Emulator(set_cpp_state()) # bot 2 moves out of bounds assert em.check_add_command(ctp(pc.Wait())) == '' msg = em.check_command(ctp(pc.SMove(Diff(0, 0, 3)))) assert msg != '' # bot 2 moves through the filled area msg = em.check_command(ctp(pc.SMove(Diff(3, 0, 0)))) assert msg != '' # ... c = ctp(pc.Wait()) em.add_command(c) em.add_command(c) em.run_step() # bot 1 moves through bot 2 msg = em.check_command(ctp(pc.SMove(Diff(0, 0, 3)))) assert msg != '' # bot 2 moves through volatile area assert em.check_add_command(ctp(pc.Fill(Diff(0, 1, 1)))) == '' msg = em.check_command(ctp(pc.SMove(Diff(0, 1, 0)))) assert msg != '' # bots 2 & 3 move freely assert em.check_add_command(ctp(pc.SMove(Diff(1, 0, 0)))) == '' assert em.check_add_command(ctp(pc.SMove(Diff(0, 4, 0)))) == '' assert em.steptrace_is_complete() em.run_step()
def solve_gen(self, model: 'Model'): self.commands = iter([]) self.state = State(model.R) voxels_to_fill = breadth_first_search(floor_contact(model), filled_neighbors(model)) for voxel in voxels_to_fill: current_position = self.state.bots[0].pos self.add_commands(navigate_near_voxel(current_position, voxel)) current_position = self.state.bots[0].pos self.add_commands([Cmd.Fill(voxel - current_position)]) self.add_commands(self.finish()) return self.commands
def test_illegal_lmoves(): em = Cpp.Emulator(set_cpp_state()) # bot 2 moves out of bounds assert em.check_add_command(ctp(pc.Wait())) == '' msg = em.check_add_command(ctp(pc.LMove(Diff(0, -1, 0), Diff(0, 0, 3)))) assert msg != '' msg = em.check_add_command(ctp(pc.LMove(Diff(0, 1, 0), Diff(0, 0, 3)))) assert msg != '' msg = em.check_add_command(ctp(pc.LMove(Diff(0, 0, 2), Diff(0, 0, 2)))) assert msg != '' # bot 2 moves through the filled area msg = em.check_add_command(ctp(pc.LMove(Diff(2, 0, 0), Diff(0, 0, 1)))) assert msg != '' msg = em.check_add_command(ctp(pc.LMove(Diff(0, 3, 0), Diff(3, 0, 0)))) assert msg != '' # ... em.add_command(ctp(pc.Wait())) # bot 3 moves through bots 1 & 2 msg = em.check_add_command(ctp(pc.LMove(Diff(-1, 0, 0), Diff(0, 0, 4)))) assert msg != '' # ... em.add_command(ctp(pc.Wait())) em.run_step() # bot 2 moves through volatile area assert em.check_add_command(ctp(pc.Fill(Diff(0, 1, 0)))) == '' msg = em.check_add_command(ctp(pc.LMove(Diff(0, 1, 0), Diff(0, 0, -1)))) assert msg != '' # bot 2 moves freely assert em.check_add_command(ctp(pc.LMove(Diff(0, 2, 0), Diff(0, 0, -1)))) == '' # bot 2 dangles around freely assert em.check_add_command(ctp(pc.LMove(Diff(2, 0, 0), Diff(-3, 0, 0)))) == ''
def cmd_from_cpp(ccmd): if isinstance(ccmd, Cpp.Halt): return commands.Halt() if isinstance(ccmd, Cpp.Wait): return commands.Wait() if isinstance(ccmd, Cpp.Flip): return commands.Flip() if isinstance(ccmd, Cpp.SMove): return commands.SMove(ccmd.lld) if isinstance(ccmd, Cpp.LMove): return commands.LMove(ccmd.sld1, ccmd.sld2) if isinstance(ccmd, Cpp.Fission): return commands.Fission(ccmd.nd, ccmd.m) if isinstance(ccmd, Cpp.Fill): return commands.Fill(ccmd.nd) if isinstance(ccmd, Cpp.Void): return commands.Void(ccmd.nd) if isinstance(ccmd, Cpp.GFill): return commands.GFill(ccmd.nd, ccmd.fd) if isinstance(ccmd, Cpp.GVoid): return commands.GVoid(ccmd.nd, ccmd.fd) assert False, ccmd
def main_simple_cmd_check(): x = commands.Fill(Diff(-1, 1, 0)) y = cmd_to_cpp(x) z = cmd_from_cpp(y) print("PyCommand -> CppCommand -> PyCommand gives initial: ", x == z, "\n")
def main_run_interactive(): import production.utils as utils # assuming we have left state and expecting right state # x-> # z ... ... ... | 2.. ... ... # | 2o. ... ... | .o. .o. ... # v ... ... ... | 3.. ... ... # y ----------> m = Model(3) m[Pos(1, 0, 1)] = 1 s = State(3) s.matrix = m s.harmonics = LOW s.energy = 30 s.bots = [Bot(bid=2, pos=Pos(0, 0, 1), seeds=[3, 4, 5])] cmds = [ commands.Fill(Diff(1, 1, 0)), commands.Fission(Diff(0, 0, 1), 2), commands.SMove(Diff(0, 0, -1)), commands.Wait() ] # pass state to emulator (step count set to 0) em = Cpp.Emulator(state_to_cpp(s)) # LOGGING -- temporary out of service # if no logfile name given, emulator doesn't log # problemname & solutionname are optional from production import utils em.setlogfile(str(utils.project_root() / 'outputs' / 'cpp_emulator.log')) em.setproblemname("some handmade problem") em.setsolutionname("John Doe's ingenious alg") # OPTION 1: Run set of commands cpp_cmds = list(map(cmd_to_cpp, cmds)) em.run_commands(cpp_cmds) cs = em.get_state() print("Energy: ", cs.energy) print("Central cell: ", cs[Cpp.Pos(1, 1, 1)]) print("Active bots: ", sum(b.active for b in cs.bots)) # OPTION 2: Command by command # x-> # z 2.. ... ... # | .o. .o. ... # v 3.. ... ... # y ----------> ccmd = cmd_to_cpp(commands.LMove(Diff(1, 0, 0), Diff(0, 0, 1))) msg = em.check_command(ccmd) print(msg == '', 'Error: ', msg) # void string if command is valid ccmd = cmd_to_cpp(commands.Fill(Diff(0, 0, 1))) msg = em.check_command(ccmd) print(msg == '', 'Error: ', msg) em.add_command(ccmd) ccmd = cmd_to_cpp(commands.SMove(Diff(0, 0, -1))) msg = em.check_command(ccmd) print(msg == '', 'Error: ', msg) # to check command and add iff it's valid ccmd = cmd_to_cpp(commands.Wait()) msg = em.check_add_command(ccmd) print(msg == '', 'Error: ', msg) # if there are enough commands for next step, new commands cannot # be checked until change of state, and every check will fail ccmd = cmd_to_cpp(commands.Wait()) msg = em.check_add_command(ccmd) print(msg == '', 'Error: ', msg) # you can still add command without checks print('Trace is full: ', em.steptrace_is_complete()) print('Energy: ', em.energy()) em.add_command(ccmd) em.run_step() print('Trace is full: ', em.steptrace_is_complete()) print('Energy: ', em.energy())