#include "grid.h" #include "gradient.h" #include "machine.h" #include "slice.h" #include #include #include void make(depth at, grid const* goal, grid const* bit, grid* state, slice* s) { s->at = at; s->bit = bit; s->goal = goal; s->state = state; make(*bit, 1, &s->edges); make(s->edges, *goal, at, &s->block); mark(0, 0, xsize(*state) + xsize(*bit) - 1, ysize(*bit) / 2, 1, &s->block); mark(0, 0, xsize(*bit) / 2, ysize(*state) + ysize(*bit) - 1, 1, &s->block); make(s->edges, *state, at, &s->cut); } static void debug_outline(slice const& s, int x, int y, depth color, grid* d) { for (int i = 0; i < EDGES; ++i) { for (size_t j = 0; j < s.edges[i].size(); ++j) { int ex = x + xsize(*s.bit)/2 - s.edges[i][j].x; int ey = y + ysize(*s.bit)/2 - s.edges[i][j].y; if (ex >= 0 && ey >= 0) { resize(std::max(xsize(*d), ex + 1), std::max(ysize(*d), ey + 1), d); (*d)[ex][ey] = color; } } } } int drill(int x, int y, slice* s, machine* m, grid* debug) { if (m->at == s->at && m->x == x && m->y == y) return 0; if (debug) { if (m->at == s->at) debug_outline(*s, m->x, m->y, color(0xFF, 0, 0), debug); debug_outline(*s, x, y, color(0, 0xFF, 0), debug); } if (m->at != 0) m->move(m->x, m->y, 0); m->move(x, y, 0); int count = 0, top = s->at; x -= xsize(*s->bit) - 1; y -= ysize(*s->bit) - 1; for (int i = 0; i < xsize(*s->bit); ++i) { for (int j = 0; j < ysize(*s->bit); ++j) { int d = get(*s->state, x + i, y + j); if ((*s->bit)[i][j] == 0 && d < s->at) { (*s->state)[x + i][y + j] = s->at; update(s->edges, x + i, y + j, -1, &s->cut); top = std::min(top, d); ++count; } } } m->move(m->x, m->y, top); m->cut(m->x, m->y, s->at); return count; } int mill(int x, int y, slice* s, machine* m, grid* debug) { int count = 0; assert(m->at == s->at); for (path p(s->cut, m->x, m->y, x, y); !p.done(); p.next()) { if (p.amount() > 0) { m->cut(p.x, p.y, m->at); if (debug && p.x >= 1 && p.y >= 1) { resize(std::max(xsize(*debug), p.x + 2), std::max(ysize(*debug), p.y + 2), debug); (*debug)[p.x - 1][p.y] = color(0x80, 0x80, 0x80); (*debug)[p.x][p.y - 1] = color(0x80, 0x80, 0x80); (*debug)[p.x + 1][p.y] = color(0x80, 0x80, 0x80); (*debug)[p.x][p.y + 1] = color(0x80, 0x80, 0x80); } count += p.amount(); for (size_t i = 0; i < s->edges[p.forward].size(); ++i) { int ex = p.x - s->edges[p.forward][i].x; int ey = p.y - s->edges[p.forward][i].y; if (get(*s->state, ex, ey) < s->at) { (*s->state)[ex][ey] = s->at; update(s->edges, ex, ey, -1, &s->cut); } } assert(0 == p.amount()); } else { m->move(p.x, p.y, m->at); if (debug && p.x >= 0 && p.y >= 0) { resize(std::max(xsize(*debug), p.x + 1), std::max(ysize(*debug), p.y + 1), debug); (*debug)[p.x][p.y] = color(0x80, 0x80, 0x80); } } } m->x = x; m->y = y; return count; } void debug_map(slice const& s, grid* out) { int xo = xsize(*s.bit) / 2, yo = ysize(*s.bit) / 2; resize(std::max(xsize(*s.goal), xsize(*s.state)) + xo, std::max(ysize(*s.goal), ysize(*s.state)) + yo, out); for (int x = 0; x < xsize(*out); ++x) { int bn = 0, cn = 0; for (path bp(s.block, x, -1, x, ysize(*out) - 1), cp(s.cut, x, -1, x, ysize(*out) - 1); !bp.done() && !cp.done(); bp.next(), cp.next()) { bn += bp.net(); cn += cp.net(); if ((*out)[bp.x][bp.y] != BOTTOM) continue; bool bs = get(*s.goal, bp.x - xo, bp.y - yo) < s.at; bool cs = get(*s.state, bp.x - xo, bp.y - yo) < s.at; if (bs) { if (cs) (*out)[bp.x][bp.y] = color(0x00, 0x00, 0x00); else (*out)[bp.x][bp.y] = color(0xFF, 0x00, 0x00); } else if (bn) { if (cs) (*out)[bp.x][bp.y] = color(0xFF, 0xFF, 0x80); else if (cn) (*out)[bp.x][bp.y] = color(0xFF, 0x80, 0xFF); else (*out)[bp.x][bp.y] = color(0xFF, 0x80, 0x80); } else { if (cs) (*out)[bp.x][bp.y] = color(0x80, 0xFF, 0x80); else if (cn) (*out)[bp.x][bp.y] = color(0x80, 0x80, 0xFF); else (*out)[bp.x][bp.y] = color(0xFF, 0xFF, 0xFF); } } } }