Exemplo n.º 1
0
def bounding_box_region(
        model,
        fx: Optional[int] = None,
        fy: Optional[int] = None,
        fz: Optional[int] = None) -> Tuple[Optional[Pos], Optional[Pos]]:
    def rangify(R, fv=None):
        if fv is None:
            fv = range(R)
        else:
            fv = [fv]
        return fv

    fx = rangify(model.R, fx)
    fy = rangify(model.R, fy)
    fz = rangify(model.R, fz)

    pos0 = pos1 = None
    for x in fx:
        for y in fy:
            for z in fz:
                if model[Pos(x, y, z)]:
                    if pos0 is None:
                        pos0 = pos1 = Pos(x, y, z)
                        filled_cell_visited = True
                    else:
                        pos0 = Pos(min(pos0.x, x), min(pos0.y, y),
                                   min(pos0.z, z))
                        pos1 = Pos(max(pos1.x, x), max(pos1.y, y),
                                   max(pos1.z, z))

    return (pos0, pos1)
    def filling_func(x, y, z, zup, bbox):
        bbox_min, bbox_max = bbox

        lookahead = (0 if z == bbox_max.z else int(reassembly))\
                        if zup else (0 if z == bbox_min.z else -int(reassembly))
        lookbehind = (0 if z == bbox_min.z else -int(reassembly))\
                        if zup else (0 if z == bbox_max.z else int(reassembly))

        if reassembly and model_src[Pos(x, y - offset, z + lookahead)]:
            if lookahead != 0:
                commands.append(Void(Diff(0, -offset, lookahead)))
        if x != bbox_min.x:
            action = choose_action(model_src, model_tgt,
                                   Pos(x - 1, y - offset, z))
            if action is not None:
                commands.append(action(Diff(-1, -offset, 0)))
        if not reassembly or lookbehind != 0:
            action = choose_action(model_src, model_tgt,
                                   Pos(x, y - offset, z + lookbehind),
                                   lookbehind != 0)
            if action is not None:
                commands.append(action(Diff(0, -offset, lookbehind)))
        if x != bbox_max.x:
            action = choose_action(model_src, model_tgt,
                                   Pos(x + 1, y - offset, z))
            if action is not None:
                commands.append(action(Diff(1, -offset, 0)))
Exemplo n.º 3
0
 def filled_voxels(self) -> Set[Pos]:
     filled = set()
     for x in range(self.R):
         for y in range(self.R):
             for z in range(self.R):
                 if self[Pos(x, y, z)]:
                     filled.add(Pos(x, y, z))
     return filled
Exemplo n.º 4
0
 def bounding_box(self) -> Optional[Region]:
     end = Pos(self.R - 1, self.R - 1, self.R - 1)
     box = None
     for pos in Region(Pos(0, 0, 0), end):
         if self[pos]:
             if not box:
                 box = Region(pos, pos)
             else:
                 box.expand(pos)
     return box
Exemplo n.º 5
0
def merge_bounding_boxes(b0, b1) -> Tuple[Pos, Pos]:
    bmin0, bmax0 = b0
    bmin1, bmax1 = b1
    if bmin0 is None:
        return b1
    if bmin1 is None:
        return b0
    new_min = Pos(min(bmin0.x, bmin1.x), min(bmin0.y, bmin1.y),
                  min(bmin0.z, bmin1.z))
    new_max = Pos(max(bmax0.x, bmax1.x), max(bmax0.y, bmax1.y),
                  max(bmax0.z, bmax1.z))
    return new_min, new_max
Exemplo n.º 6
0
 def __init__(self, source: Model, target: Model):
     assert source.R == target.R
     self.R = source.R
     self._data = [
         Cell.FULL if source._data[i] else Cell.EMPTY
         for i in range(self.R**3)
     ]
     self.target = target
     self.bots = [Bot(1, Pos(0, 0, 0), list(range(2, 41)))]
     self._set(Pos(0, 0, 0), Cell.BOT)
     self.trace = []
     self.antigrav = False
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 solve_gen(m: 'Model'):
    yield Cmd.Flip()

    pos = None
    for x in snake_fill_gen(m, Pos(0, 0, 0), Pos(m.R - 1, m.R - 1, m.R - 1)):
        if type(x) == Pos:
            pos = x
        else:
            yield x

    for x in return_home_gen(pos, Pos(0, 0, 0)):
        yield x

    yield Cmd.Flip()
    yield Cmd.Halt()
def single_bot_trace(model, model_height, plots):
    trace = []
    trace.append(Flip())
    empty = True
    current_pos = Pos(0, 0, 0)
    for plot in plots:
        plot_pos, plot_height = plot
        trace.extend(move_in_empty_space(plot_pos - current_pos))
        current_pos = plot_pos
        plot_trace, current_pos = fill_plot(model, model_height, plot)
        trace.extend(plot_trace)
    trace.append(Flip())
    trace.extend(move_in_empty_space(Pos(0, 0, 0) - current_pos))
    trace.append(Halt())
    return trace
Exemplo n.º 10
0
def print_strip_below(model, i, lbound, rbound, last_layer):
    moves = []
    for z in range(1, model.R - 1):
        if model[Pos(lbound, i, z)]:
            moves.append(Fill(Diff(0, -1, 0)))
        logging.debug('xyz = %d %d %d', lbound, i, z)
        for x in range(lbound + 1, rbound):
            logging.debug('xyz = %d %d %d', x, i, z)
            moves.append(SMove(Diff(1, 0, 0)))
            if model[Pos(x, i, z)]:
                moves.append(Fill(Diff(0, -1, 0)))
        moves.extend(move_x(-1 * (rbound - lbound - 1)))
        moves.append(SMove(Diff(
            0, 0, 1)))  # TODO: optimise this part, make an L move
    moves.extend(move_z(-1 * (model.R - 2 + last_layer)))
    return moves
Exemplo n.º 11
0
def default_disassembly(model_src, model_tgt=None) -> List[Command]:

    finish, start = bounding_box(model_src)
    start = Pos(finish.x, start.y, finish.z)

    return apply_default_strategy(model_src, Model(model_src.R), (3, -1, 1),
                                  start, False)
Exemplo n.º 12
0
def iterate_region(m, a: Pos, b: Pos):
    def rg(t1, t2):
        return range(min(t1, t2), max(t1, t2) + 1)

    for x in rg(a.x, b.x):
        for z in rg(a.z, b.z):
            for y in rg(a.y, b.y):
                yield (m[Pos(x, y, z)], (x, y, z))
Exemplo n.º 13
0
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
Exemplo n.º 14
0
def get_plot_height(model, plot_pos):
    x_z = [(plot_pos.x + dx, plot_pos.z + dz) \
      for (dx, dz) in dx_dz_3x3(plot_pos.x, plot_pos.z, model.R)]
    for y in range(model.R - 2, -1, -1):
        for x, z in x_z:
            if model[Pos(x, y, z)]:
                return y + 1
    return 0
Exemplo n.º 15
0
def default_reassembly(model_src, model_tgt) -> List[Command]:

    finish, start = merge_bounding_boxes(bounding_box(model_src),
                                         bounding_box(model_tgt))
    start = Pos(finish.x, start.y, finish.z)

    return apply_default_strategy(model_src, model_tgt, (3, -1, 1), start,
                                  True)
Exemplo n.º 16
0
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
Exemplo n.º 17
0
    def make_layer_pass(x, y, z, zup, layer_bounding_box, behaviour_func):
        bbox_min, bbox_max = layer_bounding_box

        while (x >= bbox_min.x and not xup) or (x <= bbox_max.x and xup):
            while (z >= bbox_min.z and not zup) or (z <= bbox_max.z and zup):

                behaviour_func(x, y, z, zup, layer_bounding_box)

                if (not zup and z == bbox_min.z) or (z == bbox_max.z and zup):
                    break
                dz = z_speed if zup else -z_speed
                commands.append(SMove(Diff(0, 0, dz)))
                z += dz
            if (not xup and x == bbox_min.x) or (xup and x == bbox_max.x):
                break

            dx = x_speed if xup else -x_speed

            if not is_inside_region(Pos(x + dx, y - offset, z), bbox_min,
                                    bbox_max):
                bbox = bbox_max
                if not xup:
                    bbox = bbox_min

                dx = bbox.x - x

            if reassembly:

                off = 1 if zup else -1
                commands.append(SMove(Diff(0, 0, off)))
                if model_tgt[Pos(x, y, z)]:
                    commands.append(Fill(Diff(0, 0, -off)))
                commands.append(SMove(Diff(dx, 0, 0)))
                x += dx

                if model_src[Pos(x, y, z)]:
                    commands.append(Void(Diff(0, 0, -off)))
                commands.append(SMove(Diff(0, 0, -off)))
            else:
                commands.append(SMove(Diff(dx, 0, 0)))
                x += dx

            zup = not zup

        return x, y, z, zup
Exemplo n.º 18
0
def create_plots(model):
    pos0, pos1 = bounding_box_footprint(model)
    plots = []
    for x in range(pos0.x + 1, min(pos1.x + 2, model.R), 3):
        for z in range(pos0.z + 1, min(pos1.z + 2, model.R), 3):
            plot_pos = Pos(x, 0, z)
            plot_height = get_plot_height(model, plot_pos)
            if plot_height > 0:
                plots.append((plot_pos, plot_height))
    return plots
def snake_fill_gen(m: 'Model', a: Pos, b: Pos):
    prevPos = Pos(a.x, b.y, a.z)
    nextPos = Pos(a.x, b.y, a.z)

    # 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 append([Diff(0, 0, 0)], snake_path_gen(a, b)):
    for diff in snake_path_gen(a, b):
        # if diff.mlen() > 0:
        #     yield SMove(diff)

        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.Void(d)
                    m[nextPos + d] = False

            prevPos = nextPos

    yield prevPos
Exemplo n.º 20
0
def partition_space(a, b, x_cnt, z_cnt):
    x_step = (b.x - a.x + 1) / x_cnt
    z_step = (b.z - a.z + 1) / z_cnt

    res = []
    for z in range(z_cnt):
        row = []
        z1 = round(a.z + z_step * z)
        if z != z_cnt - 1:
            z2 = round(a.z + z_step * (z + 1)) - 1
        else:
            z2 = b.z
        for x in range(x_cnt):
            x1 = round(a.x + x_step * x)
            if x != x_cnt - 1:
                x2 = round(a.x + x_step * (x + 1)) - 1
            else:
                x2 = b.x
            row.append((Pos(x1, 0, z1), Pos(x2, b.y + 1, z2)))

        res.append(row)

    return res
Exemplo n.º 21
0
    def grounded_voxels(self) -> Set[Pos]:
        visited = set()

        def visit(pos):
            if pos in visited:
                return
            if self[pos] == 0:
                return
            visited.add(pos)
            for p in pos.enum_adjacent(self.R):
                visit(p)

        for x in range(self.R):
            for z in range(self.R):
                visit(Pos(x, 0, z))

        return visited
Exemplo n.º 22
0
def main():
    from production import data_files

    name = 'LA004_tgt.mdl'
    data = data_files.lightning_problem(name)
    m = Model.parse(data)

    print(f'Central vertical slice of {name}:')
    x = m.R // 2
    for y in reversed(range(m.R)):
        s = []
        for z in range(m.R):
            if m[Pos(x, y, z)]:
                s.append('*')
            else:
                s.append('.')
        print(' '.join(s))
    print('R =', m.R)
Exemplo n.º 23
0
def set_cpp_state():
    m = Model(5)
    m[Pos(2, 0, 2)] = True
    m[Pos(2, 1, 2)] = True
    m[Pos(2, 2, 2)] = True
    m[Pos(2, 3, 2)] = True

    s = State(5)
    s.matrix = m
    s.harmonics = LOW
    s.energy = 0
    s.bots = [
        Bot(bid=1, pos=Pos(0, 0, 1), seeds=[]),
        Bot(bid=2, pos=Pos(0, 0, 2), seeds=list(range(4, 40))),
        Bot(bid=40, pos=Pos(1, 0, 0), seeds=[])
    ]

    return state_to_cpp(s)
Exemplo n.º 24
0
def floor(model):
    for x in range(model.R):
        for z in range(model.R):
            yield Pos(x, 0, z)
Exemplo n.º 25
0
 def enum_voxels(self):
     for x in range(self.R):
         for y in range(self.R):
             for z in range(self.R):
                 yield Pos(x, y, z)
Exemplo n.º 26
0
 def __setitem__(self, pos: Pos, value: bool):
     R = self.R
     assert pos.is_inside_matrix(R)
     self._data[pos.x * R * R + pos.y * R + pos.z] = value
Exemplo n.º 27
0
 def __getitem__(self, pos: Pos) -> bool:
     R = self.R
     assert pos.is_inside_matrix(R), pos
     return self._data[pos.x * R * R + pos.y * R + pos.z]
Exemplo n.º 28
0
def projection_front(m):
    return [[any([m[Pos(x, y, z)] for z in range(m.R)]) for y in range(m.R)]
            for x in range(m.R)]
Exemplo n.º 29
0
def bounding_box_footprint(model):
    pos0, pos1 = bounding_box_region(model)
    pos0 = Pos(pos0.x, 0, pos0.z)
    pos1 = Pos(pos1.x, 0, pos1.z)
    return (pos0, pos1)
Exemplo n.º 30
0
    def tick(self):
        newbots = []
        commands = []

        for bot in self.bots:
            command = bot.command
            commands.append(command)
            if isinstance(command, Halt):
                assert len(self.bots) == 1
                assert self.bots[0].pos == Pos(0, 0, 0)
                self._set(Pos(0, 0, 0), Cell.EMPTY)
            elif isinstance(command, Wait):
                newbots.append(bot)
            elif isinstance(command, Flip):
                self.antigrav = not self.antigrav
                newbots.append(bot)

            elif isinstance(command, SMove):
                assert command.lld.is_long_linear()
                self._set(bot.pos, Cell.EMPTY)
                bot.pos += command.lld
                self._set(bot.pos, Cell.BOT)
                newbots.append(bot)
            elif isinstance(command, LMove):
                assert command.sld1.is_short_linear()
                assert command.sld2.is_short_linear()
                self._set(bot.pos, Cell.EMPTY)
                bot += command.sld1
                assert bot.pos.is_inside_matrix(self.R)
                bot += command.sld1
                self._set(bot.pos, Cell.BOT)
                newbots.append(bot)

            elif isinstance(command, Fission):
                newbot = Bot(bot.seeds[0], bot.pos + command.nd,
                             bot.seeds[1:command.m + 1])
                self._set(newbot.pos, Cell.BOT)
                bot.seeds = bot.seeds[command.m + 1:]
                newbots.append(bot)
                newbots.append(newbot)

            elif isinstance(command, Fill):
                assert command.nd.is_near()
                self._set(bot.pos + command.nd, Cell.FULL)
                newbots.append(bot)
            elif isinstance(command, Void):
                assert command.nd.is_near()
                self._set(bot.pos + command.nd, Cell.EMPTY)
                newbots.append(bot)

            elif isinstance(command, FusionP):
                assert self[(bot.pos + command.nd)] == Cell.BOT
                self._set(bot.pos + command.nd, Cell.EMPTY)
                otherbot = self.bot_at(bot.pos + command.nd)
                assert otherbot
                bot.seeds = sorted(bot.seeds + otherbot.seeds + [otherbot.bid])
                newbots.append(bot)
            elif isinstance(command, FusionS):
                assert self[(bot.pos + command.nd)] == Cell.BOT

            elif isinstance(command, GFill):
                assert command.nd.is_near()
                assert command.fd.is_far()
                for pos in Region(bot.pos + command.nd,
                                  bot.pos + command.nd + command.fd):
                    self._set(pos, Cell.FULL)
                newbots.append(bot)
            elif isinstance(command, GVoid):
                assert command.nd.is_near()
                assert command.fd.is_far()
                for pos in Region(bot.pos + command.nd,
                                  bot.pos + command.nd + command.fd):
                    self._set(pos, Cell.EMPTY)
                newbots.append(bot)

        self.bots = newbots
        self.bots.sort(key=lambda bot: bot.bid)
        self.trace.append(commands)

        for bot in self.bots:
            bot.command = Wait()