From 78d88b59099616fb9b4de3dec55e186ce78acc85 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Fri, 8 Mar 2019 22:38:44 +0100 Subject: [PATCH] improved in the OO fashion: draw, relative_matrix, create_step, and several minor functions are now virtual in hrmap --- archimedean.cpp | 265 ++++++++++++++++---------------- bigstuff.cpp | 36 ++--- binary-tiling.cpp | 377 +++++++++++++++++++++++++--------------------- cell.cpp | 12 +- complex.cpp | 6 +- crystal.cpp | 80 +++++----- euclid.cpp | 145 +++++++++++++----- floorshapes.cpp | 1 - geometry2.cpp | 68 +-------- graph.cpp | 19 +-- heptagon.cpp | 32 +--- hyper.h | 57 ++++--- hypgraph.cpp | 62 +------- irregular.cpp | 4 +- landgen.cpp | 2 +- quotient.cpp | 6 +- reg3.cpp | 102 +++++++------ savemem.cpp | 3 +- sphere.cpp | 29 +++- 19 files changed, 655 insertions(+), 651 deletions(-) diff --git a/archimedean.cpp b/archimedean.cpp index 7bd38400..2de839f4 100644 --- a/archimedean.cpp +++ b/archimedean.cpp @@ -357,11 +357,18 @@ hrmap *current_altmap; heptagon *build_child(heptspin p, pair adj); +bool skip_digons(heptspin hs, int step); +void connect_digons_too(heptspin h1, heptspin h2); +void fixup_matrix(transmatrix& T, const transmatrix& X, ld step); +void connectHeptagons(heptspin hi, heptspin hs); +transmatrix adjcell_matrix(heptagon *h, int d); + struct hrmap_archimedean : hrmap { heptagon *origin; heptagon *getOrigin() { return origin; } hrmap_archimedean() { + dynamicval curmap(currentmap, this); int id = DUAL ? current.N * 2 : 0;; int N0 = isize(current.adjacent[id]); origin = tailored_alloc (N0); @@ -405,9 +412,9 @@ struct hrmap_archimedean : hrmap { origin->c.connect(s, hnew, s, false); } else if(current.real_faces == 0) { - create_adjacent(origin, 0); + may_create_step(origin, 0); heptagon *o0 = origin->move(0); - create_adjacent(origin, 1); + may_create_step(origin, 1); heptagon *o1 = origin->move(1); for(int s=1; s<2*current.N; s+=2) o0->c.connect(s, o1, 2*current.N-s, false); @@ -420,8 +427,8 @@ struct hrmap_archimedean : hrmap { o1->c.connect(1, o0, 2*current.N-1, false); } else if(origin->degree() == 2) { - create_adjacent(origin, 0); - create_adjacent(origin, 1); + may_create_step(origin, 0); + may_create_step(origin, 1); origin->move(0)->c.connect(1, origin->move(1), 2*current.N-1, false); origin->move(1)->c.connect(1, origin->move(0), 2*current.N-1, false); } @@ -443,12 +450,136 @@ struct hrmap_archimedean : hrmap { } } void verify() { } + + heptagon *create_step(heptagon *h, int d) { + + SDEBUG( printf("%p.%d ~ ?\n", h, d); ) + + heptspin hi(h, d); + + while(skip_digons(hi, 1)) hi++; + + auto& t1 = current.get_triangle(hi); + + // * spin(-tri[id][pi+i].first) * xpush(t.second) * pispin * spin(tri[id'][p'+d'].first) + + auto& p1 = archimedean_gmatrix[h]; + + heptagon *alt = p1.first; + + transmatrix T = p1.second * spin(-t1.first) * xpush(t1.second); + transmatrix U = Id; + + if(hyperbolic) { + dynamicval g(geometry, gNormal); + dynamicval cm(currentmap, current_altmap); + U = T; + virtualRebaseSimple(alt, T); + U = U * inverse(T); + } + + if(euclid) + alt = encodeId(pair_to_vec(int(T[0][2]), int(T[1][2]))); + + SDEBUG( println(hlog, "look for: ", alt, " / ", T * C0); ) + + for(auto& p2: altmap[alt]) if(intval(p2.second * C0, T * C0) < 1e-4) { + SDEBUG( println(hlog, "cell found: ", p2.first); ) + for(int d2=0; d2degree(); d2++) { + heptspin hs(p2.first, d2); + auto& t2 = current.get_triangle(p2.first, d2); + transmatrix T1 = T * spin(M_PI + t2.first); + SDEBUG( print(hlog, "compare: ", T1 * xpush0(1)); ) + SDEBUG( println(hlog, ":: ", p2.second * xpush0(1)); ) + if(intval(T1 * xpush0(1), p2.second * xpush0(1)) < 1e-4) { + + // T1 = p2.second + // T * spin(pi+t2.first) == p2.second + // p1.second * spinm(-t1.first) * xpush(t1.second) * spin(pi+t2.first) == p2.second + + // bring p1 and p2 closer, to prevent floating point errors + if(hyperbolic) { + fixup_matrix(p1.second, U * p2.second * spin(-M_PI - t2.first) * xpush(-t1.second) * spin(t1.first), 0.25); + fixup_matrix(p2.second, T1, 0.25); + } + + while(skip_digons(hs, -1)) hs--; + connectHeptagons(hi, hs); + connect_digons_too(hi, hs); + return h->move(d); + } + } + SDEBUG( println(hlog, "but rotation not found")); + } + + auto& t2 = current.get_triangle(current.get_adj(hi)); + transmatrix T1 = T * spin(M_PI + t2.first); + fixmatrix(T1); + + heptagon *hnew = build_child(hi, current.get_adj(hi)); + altmap[alt].emplace_back(hnew, T1); + archimedean_gmatrix[hnew] = make_pair(alt, T1); + connect_digons_too(hi, heptspin(hnew, 0)); + + return hnew; + } + + void draw() { + dq::visited.clear(); + dq::enqueue(viewctr.at, cview()); + + while(!dq::drawqueue.empty()) { + auto& p = dq::drawqueue.front(); + heptagon *h = get<0>(p); + transmatrix V = get<1>(p); + dynamicval b(band_shift, get<2>(p)); + dq::drawqueue.pop(); + + int id = id_of(h); + int S = isize(current.triangles[id]); + + if(id < 2*current.N ? !DUAL : !PURE) { + if(!do_draw(h->c7, V)) continue; + drawcell(h->c7, V, 0, false); + } + + for(int i=0; icmove(i); + if(PURE && id >= 2*current.N && h->move(i) && id_of(h->move(i)) >= 2*current.N) continue; + transmatrix V1 = V * adjcell_matrix(h, i); + bandfixer bf(V1); + dq::enqueue(h->move(i), V1); + } + } + } + + transmatrix relative_matrix(heptagon *h2, heptagon *h1) { + if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) + return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; + transmatrix gm = Id, where = Id; + while(h1 != h2) { + for(int i=0; imove(i) == h2) { + return gm * adjcell_matrix(h1, i) * where; + } + } + if(h1->distance > h2->distance) { + gm = gm * adjcell_matrix(h1, 0); + h1 = h1->move(0); + } + else { + where = inverse(adjcell_matrix(h2, 0)) * where; + h2 = h2->move(0); + } + } + return gm * where; + } + }; hrmap *new_map() { return new hrmap_archimedean; } -transmatrix adjcell_matrix(heptagon *h, int d); - heptagon *build_child(heptspin p, pair adj) { indenter ind; auto h = buildHeptagon1(tailored_alloc (isize(current.adjacent[adj.first])), p.at, p.spin, hstate(1), 0); @@ -540,76 +671,6 @@ void fixup_matrix(transmatrix& T, const transmatrix& X, ld step) { fixmatrix(T); } -void create_adjacent(heptagon *h, int d) { - - SDEBUG( printf("%p.%d ~ ?\n", h, d); ) - - heptspin hi(h, d); - - while(skip_digons(hi, 1)) hi++; - - auto& t1 = current.get_triangle(hi); - - // * spin(-tri[id][pi+i].first) * xpush(t.second) * pispin * spin(tri[id'][p'+d'].first) - - auto& p1 = archimedean_gmatrix[h]; - - heptagon *alt = p1.first; - - transmatrix T = p1.second * spin(-t1.first) * xpush(t1.second); - transmatrix U = Id; - - if(hyperbolic) { - dynamicval g(geometry, gNormal); - U = T; - virtualRebaseSimple(alt, T); - U = U * inverse(T); - } - - if(euclid) - alt = encodeId(pair_to_vec(int(T[0][2]), int(T[1][2]))); - - SDEBUG( println(hlog, "look for: ", alt, " / ", T * C0); ) - - for(auto& p2: altmap[alt]) if(intval(p2.second * C0, T * C0) < 1e-4) { - SDEBUG( println(hlog, "cell found: ", p2.first); ) - for(int d2=0; d2degree(); d2++) { - heptspin hs(p2.first, d2); - auto& t2 = current.get_triangle(p2.first, d2); - transmatrix T1 = T * spin(M_PI + t2.first); - SDEBUG( print(hlog, "compare: ", T1 * xpush0(1)); ) - SDEBUG( println(hlog, ":: ", p2.second * xpush0(1)); ) - if(intval(T1 * xpush0(1), p2.second * xpush0(1)) < 1e-4) { - - // T1 = p2.second - // T * spin(pi+t2.first) == p2.second - // p1.second * spinm(-t1.first) * xpush(t1.second) * spin(pi+t2.first) == p2.second - - // bring p1 and p2 closer, to prevent floating point errors - if(hyperbolic) { - fixup_matrix(p1.second, U * p2.second * spin(-M_PI - t2.first) * xpush(-t1.second) * spin(t1.first), 0.25); - fixup_matrix(p2.second, T1, 0.25); - } - - while(skip_digons(hs, -1)) hs--; - connectHeptagons(hi, hs); - connect_digons_too(hi, hs); - return; - } - } - SDEBUG( println(hlog, "but rotation not found")); - } - - auto& t2 = current.get_triangle(current.get_adj(hi)); - transmatrix T1 = T * spin(M_PI + t2.first); - fixmatrix(T1); - - heptagon *hnew = build_child(hi, current.get_adj(hi)); - altmap[alt].emplace_back(hnew, T1); - archimedean_gmatrix[hnew] = make_pair(alt, T1); - connect_digons_too(hi, heptspin(hnew, 0)); - } - pair& archimedean_tiling::get_triangle(heptagon *h, int cid) { return triangles[id_of(h)][(parent_index_of(h) + cid + MODFIXER) % neighbors_of(h)]; } @@ -637,58 +698,6 @@ transmatrix adjcell_matrix(heptagon *h, int d) { return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first); } -void draw() { - dq::visited.clear(); - dq::enqueue(viewctr.at, cview()); - - while(!dq::drawqueue.empty()) { - auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - dq::drawqueue.pop(); - - int id = id_of(h); - int S = isize(current.triangles[id]); - - if(id < 2*current.N ? !DUAL : !PURE) { - if(!do_draw(h->c7, V)) continue; - drawcell(h->c7, V, 0, false); - } - - for(int i=0; icmove(i); - if(PURE && id >= 2*current.N && h->move(i) && id_of(h->move(i)) >= 2*current.N) continue; - transmatrix V1 = V * adjcell_matrix(h, i); - bandfixer bf(V1); - dq::enqueue(h->move(i), V1); - } - } - } - -transmatrix relative_matrix(heptagon *h2, heptagon *h1) { - if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) - return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; - transmatrix gm = Id, where = Id; - while(h1 != h2) { - for(int i=0; imove(i) == h2) { - return gm * adjcell_matrix(h1, i) * where; - } - } - if(h1->distance > h2->distance) { - gm = gm * adjcell_matrix(h1, 0); - h1 = h1->move(0); - } - else { - where = inverse(adjcell_matrix(h2, 0)) * where; - h2 = h2->move(0); - } - } - return gm * where; - } - int fix(heptagon *h, int spin) { int type = isize(current.adjacent[id_of(h)]); spin %= type; diff --git a/bigstuff.cpp b/bigstuff.cpp index 6c64663e..e32907d9 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -102,7 +102,7 @@ cell *findcompass(cell *c) { while(inscreenrange(c)) { if(!eubinary && !sphere && !quotient) - generateAlts(c->master); + currentmap->generateAlts(c->master); forCellEx(c2, c) if(compassDist(c2) < d) { c = c2; d = compassDist(c2); @@ -120,7 +120,7 @@ bool grailWasFound(cell *c) { return c->master->alt->alt->emeraldval & GRAIL_FOUND; } -void generateAlts(heptagon *h, int levs, bool link_cdata) { +void hrmap::generateAlts(heptagon *h, int levs, bool link_cdata) { if(!h->alt) return; preventbarriers(h->c7); if(h->c7) forCellEx(c2, h->c7) preventbarriers(c2); @@ -165,7 +165,7 @@ void generateAlts(heptagon *h, int levs, bool link_cdata) { } ho->alt = hm; if(link_cdata) hm->cdata = (cdata*) ho; - if(levs) generateAlts(ho, levs-1, link_cdata); + if(levs) currentmap->generateAlts(ho, levs-1, link_cdata); } } @@ -232,7 +232,7 @@ heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special) { alt->cdata = (cdata*) h; for(int d=rad; d>=0; d--) { - generateAlts(cx[d]->master); + currentmap->generateAlts(cx[d]->master); preventbarriers(cx[d]); } @@ -265,7 +265,7 @@ void beCIsland(cell *c) { } void generateTreasureIsland(cell *c) { - if(!eubinary) generateAlts(c->master); + if(!eubinary) currentmap->generateAlts(c->master); if(isOnCIsland(c)) return; bool src = hrand(100) < 10; @@ -277,7 +277,7 @@ void generateTreasureIsland(cell *c) { int qc = 0, qlo, qhi; for(int i=0; itype; i++) { cell *c2 = createMov(c, i); - if(!eubinary) generateAlts(c2->master); + if(!eubinary) currentmap->generateAlts(c2->master); if((eubinary || (c->master->alt && c2->master->alt)) && celldistAlt(c2) < celldistAlt(c)) { ctab[qc++] = c2; qlo = i; qhi = i; @@ -1174,7 +1174,7 @@ void buildBigStuff(cell *c, cell *from) { (princess::challenge || kills[moVizier] || peace::on) && !tactic::on && !yendor::on && !racing::on) { createAlternateMap(c, PRADIUS0, hsOrigin, waPalace); celllister cl(c, 5, 1000000, NULL); - for(cell *c: cl.lst) if(c->master->alt) generateAlts(c->master); + for(cell *c: cl.lst) if(c->master->alt) currentmap->generateAlts(c->master); } } @@ -1225,12 +1225,12 @@ bool no_barriers_in_radius(cell *c, int rad) { void buildCamelot(cell *c) { int d = celldistAltRelative(c); if(tactic::on || (d <= 14 && roundTableRadius(c) > 20)) { - if(!eubinary) generateAlts(c->master); + if(!eubinary) currentmap->generateAlts(c->master); preventbarriers(c); if(d == 10) { if(weirdhyperbolic ? hrand(100) < 50 : pseudohept(c)) buildCamelotWall(c); else { - if(!eubinary) for(int i=0; imaster->move(i)); + if(!eubinary) for(int i=0; igenerateAlts(c->master->move(i)); int q = 0; if(weirdhyperbolic) { for(int t=0; ttype; t++) createMov(c, t); @@ -1277,7 +1277,7 @@ void buildCamelot(cell *c) { // roughly as many knights as table cells if(hrand(1000000) < 1000000 / expansion.get_growth()) c->monst = moKnight; - if(!eubinary) for(int i=0; imaster->move(i)); + if(!eubinary) for(int i=0; igenerateAlts(c->master->move(i)); for(int i=0; itype; i++) if(c->move(i) && celldistAltRelative(c->move(i)) < d) c->mondir = (i+3) % 6; @@ -1304,16 +1304,16 @@ void moreBigStuff(cell *c) { if(c->land == laPalace && !eubinary && c->master->alt) { int d = celldistAlt(c); - if(d <= PRADIUS1) generateAlts(c->master); + if(d <= PRADIUS1) currentmap->generateAlts(c->master); } if(c->land == laCanvas && !eubinary && c->master->alt && !quotient) - generateAlts(c->master); + currentmap->generateAlts(c->master); if(c->land == laStorms) if(!eubinary && !quotient && !sphere) { if(c->master->alt && c->master->alt->distance <= 2) { - generateAlts(c->master); + currentmap->generateAlts(c->master); preventbarriers(c); int d = celldistAlt(c); if(d <= -2) { @@ -1336,7 +1336,7 @@ void moreBigStuff(cell *c) { else if((c->land == laRlyeh && !euclid) || c->land == laTemple) if(!(binarytiling && specialland != laTemple)) { if(eubinary || (c->master->alt && (tactic::on || c->master->alt->distance <= 2))) { - if(!eubinary && !chaosmode) generateAlts(c->master); + if(!eubinary && !chaosmode) currentmap->generateAlts(c->master); preventbarriers(c); int d = celldistAlt(c); if(d <= 0) { @@ -1352,7 +1352,7 @@ void moreBigStuff(cell *c) { else if(pseudohept(c)) c->wall = waColumn; else { - if(!eubinary) for(int i=0; imaster->move(i)); + if(!eubinary) for(int i=0; igenerateAlts(c->master->move(i)); int q = 0; for(int t=0; ttype; t++) { createMov(c, t); @@ -1366,7 +1366,7 @@ void moreBigStuff(cell *c) { if((c->land == laOvergrown && !euclid) || c->land == laClearing) if(!(binarytiling && specialland != laClearing)) { if(eubinary || (c->master->alt && (tactic::on || c->master->alt->distance <= 2))) { - if(!eubinary) generateAlts(c->master); + if(!eubinary) currentmap->generateAlts(c->master); preventbarriers(c); int d = celldistAlt(c); if(d <= 0) { @@ -1379,7 +1379,7 @@ void moreBigStuff(cell *c) { if((c->land == laJungle && !euclid) || c->land == laMountain) if(!(binarytiling && specialland != laMountain)) { if(eubinary || (c->master->alt && (tactic::on || c->master->alt->distance <= 2))) { - if(!eubinary) generateAlts(c->master); + if(!eubinary) currentmap->generateAlts(c->master); preventbarriers(c); int d = celldistAlt(c); if(d <= 0 || (firstland == laMountain && tactic::on)) { @@ -1395,7 +1395,7 @@ void moreBigStuff(cell *c) { if(yendor::on && yendor::clev().l == laWhirlpool) fullwhirlpool = true; if(eubinary || (c->master->alt && (fullwhirlpool || c->master->alt->distance <= 2))) { - if(!eubinary) generateAlts(c->master); + if(!eubinary) currentmap->generateAlts(c->master); preventbarriers(c); int dd = celldistAlt(c); if(dd <= 0 || fullwhirlpool) { diff --git a/binary-tiling.cpp b/binary-tiling.cpp index e85a270a..568c50c6 100644 --- a/binary-tiling.cpp +++ b/binary-tiling.cpp @@ -45,6 +45,9 @@ namespace binary { void breakhere() { exit(1); } + + const transmatrix& tmatrix(heptagon *h, int dir); + const transmatrix& itmatrix(heptagon *h, int dir); heptagon *path(heptagon *h, int d, int d1, std::initializer_list p) { static int rec = 0; @@ -53,7 +56,7 @@ namespace binary { heptagon *h1 = h; for(int d0: p) { // printf(" [%d]", d0); - h1 = hr::createStep(h1, d0); + h1 = currentmap->may_create_step(h1, d0); // printf(" %p", h1); } @@ -104,113 +107,205 @@ namespace binary { } #endif - heptagon *createStep(heptagon *parent, int d) { - auto h = parent; - switch(d) { - case bd_right: { - if(mapside(h) > 0 && type_of(h) == 7) - return path(h, d, bd_left, {bd_left, bd_down, bd_right, bd_up}); - else if(mapside(h) >= 0) - return build(parent, bd_right, bd_left, type_of(parent) ^ 1, 1, 0); - else if(type_of(h) == 6) - return path(h, d, bd_left, {bd_down, bd_right, bd_up, bd_left}); - else - return path(h, d, bd_left, {bd_down_right, bd_up}); - } - case bd_left: { - if(mapside(h) < 0 && type_of(h) == 7) - return path(h, d, bd_right, {bd_right, bd_down, bd_left, bd_up}); - else if(mapside(h) <= 0) - return build(parent, bd_left, bd_right, type_of(parent) ^ 1, -1, 0); - else if(type_of(h) == 6) - return path(h, d, bd_right, {bd_down, bd_left, bd_up, bd_right}); - else - return path(h, d, bd_right, {bd_down_left, bd_up}); - } - case bd_up_right: { - return path(h, d, bd_down_left, {bd_up, bd_right}); - } - case bd_up_left: { - return path(h, d, bd_down_right, {bd_up, bd_left}); - } - case bd_up: - return build(parent, bd_up, bd_down, 6, mapside(parent), 1); - default: - /* bd_down */ - if(type_of(h) == 6) { - if(mapside(h) == 0) - return build(parent, bd_down, bd_up, 6, 0, -1); - else if(mapside(h) == 1) - return path(h, d, bd_up, {bd_left, bd_left, bd_down, bd_right}); - else if(mapside(h) == -1) - return path(h, d, bd_up, {bd_right, bd_right, bd_down, bd_left}); - } - /* bd_down_left */ - else if(d == bd_down_left) { - return path(h, d, bd_up_right, {bd_left, bd_down}); - } - else if(d == bd_down_right) { - return path(h, d, bd_up_left, {bd_right, bd_down}); - } - } - printf("error: case not handled in binary tiling\n"); - breakhere(); - return NULL; - } - - #if MAXMDIM==4 - heptagon *createStep3(heptagon *parent, int d) { - auto h = parent; - if(geometry == gBinary3) - switch(d) { - case 0: case 1: - case 2: case 3: - return build3(parent, d, 8, 1); - case 8: - return build3(parent, 8, hrand(4), -1); - case 4: - parent->cmove(8); - if(parent->c.spin(8) & 1) - return path(h, 4, 5, {8, parent->c.spin(8) ^ 1}); - else - return path(h, 4, 5, {8, 4, parent->c.spin(8) ^ 1}); - case 5: - parent->cmove(8); - if(!(parent->c.spin(8) & 1)) - return path(h, 5, 4, {8, parent->c.spin(8) ^ 1}); - else - return path(h, 5, 4, {8, 5, parent->c.spin(8) ^ 1}); - case 6: - parent->cmove(8); - if(parent->c.spin(8) & 2) - return path(h, 6, 7, {8, parent->c.spin(8) ^ 2}); - else - return path(h, 6, 7, {8, 6, parent->c.spin(8) ^ 2}); - case 7: - parent->cmove(8); - if(!(parent->c.spin(8) & 2)) - return path(h, 7, 6, {8, parent->c.spin(8) ^ 2}); - else - return path(h, 7, 6, {8, 7, parent->c.spin(8) ^ 2}); - } - if(geometry == gHoroTris) switch(d) { - case 0: case 1: case 2: case 3: - return build3(parent, d, 7, 1); - case 7: - return build3(parent, 7, hrand(3), -1); - case 4: case 5: case 6: - parent->cmove(7); - int s = parent->c.spin(7); - if(s == 0) return path(h, d, d, {7, d-3}); - else if(s == d-3) return path(h, d, d, {7, 0}); - else return path(h, d, d, {7, d, 9-d-s}); - } - printf("error: case not handled in binary tiling\n"); - breakhere(); - return NULL; - } - #endif + struct hrmap_binary : hrmap_hyperbolic { + hrmap_binary(heptagon *o) : hrmap_hyperbolic(o) {} + + hrmap_binary() : hrmap_hyperbolic() {} + + heptagon *create_step(heptagon *parent, int d) { + auto h = parent; + switch(geometry) { + case gBinaryTiling: { + switch(d) { + case bd_right: { + if(mapside(h) > 0 && type_of(h) == 7) + return path(h, d, bd_left, {bd_left, bd_down, bd_right, bd_up}); + else if(mapside(h) >= 0) + return build(parent, bd_right, bd_left, type_of(parent) ^ 1, 1, 0); + else if(type_of(h) == 6) + return path(h, d, bd_left, {bd_down, bd_right, bd_up, bd_left}); + else + return path(h, d, bd_left, {bd_down_right, bd_up}); + } + case bd_left: { + if(mapside(h) < 0 && type_of(h) == 7) + return path(h, d, bd_right, {bd_right, bd_down, bd_left, bd_up}); + else if(mapside(h) <= 0) + return build(parent, bd_left, bd_right, type_of(parent) ^ 1, -1, 0); + else if(type_of(h) == 6) + return path(h, d, bd_right, {bd_down, bd_left, bd_up, bd_right}); + else + return path(h, d, bd_right, {bd_down_left, bd_up}); + } + case bd_up_right: { + return path(h, d, bd_down_left, {bd_up, bd_right}); + } + case bd_up_left: { + return path(h, d, bd_down_right, {bd_up, bd_left}); + } + case bd_up: + return build(parent, bd_up, bd_down, 6, mapside(parent), 1); + default: + /* bd_down */ + if(type_of(h) == 6) { + if(mapside(h) == 0) + return build(parent, bd_down, bd_up, 6, 0, -1); + else if(mapside(h) == 1) + return path(h, d, bd_up, {bd_left, bd_left, bd_down, bd_right}); + else if(mapside(h) == -1) + return path(h, d, bd_up, {bd_right, bd_right, bd_down, bd_left}); + } + /* bd_down_left */ + else if(d == bd_down_left) { + return path(h, d, bd_up_right, {bd_left, bd_down}); + } + else if(d == bd_down_right) { + return path(h, d, bd_up_left, {bd_right, bd_down}); + } + } + printf("error: case not handled in binary tiling\n"); + breakhere(); + return NULL; + } + case gBinary3: { + switch(d) { + case 0: case 1: + case 2: case 3: + return build3(parent, d, 8, 1); + case 8: + return build3(parent, 8, hrand(4), -1); + case 4: + parent->cmove(8); + if(parent->c.spin(8) & 1) + return path(h, 4, 5, {8, parent->c.spin(8) ^ 1}); + else + return path(h, 4, 5, {8, 4, parent->c.spin(8) ^ 1}); + case 5: + parent->cmove(8); + if(!(parent->c.spin(8) & 1)) + return path(h, 5, 4, {8, parent->c.spin(8) ^ 1}); + else + return path(h, 5, 4, {8, 5, parent->c.spin(8) ^ 1}); + case 6: + parent->cmove(8); + if(parent->c.spin(8) & 2) + return path(h, 6, 7, {8, parent->c.spin(8) ^ 2}); + else + return path(h, 6, 7, {8, 6, parent->c.spin(8) ^ 2}); + case 7: + parent->cmove(8); + if(!(parent->c.spin(8) & 2)) + return path(h, 7, 6, {8, parent->c.spin(8) ^ 2}); + else + return path(h, 7, 6, {8, 7, parent->c.spin(8) ^ 2}); + } + } + case gHoroTris: { + switch(d) { + case 0: case 1: case 2: case 3: + return build3(parent, d, 7, 1); + case 7: + return build3(parent, 7, hrand(3), -1); + case 4: case 5: case 6: + parent->cmove(7); + int s = parent->c.spin(7); + if(s == 0) return path(h, d, d, {7, d-3}); + else if(s == d-3) return path(h, d, d, {7, 0}); + else return path(h, d, d, {7, d, 9-d-s}); + } + } + + default: ; + } + printf("error: case not handled in binary tiling\n"); + breakhere(); + return NULL; + } + + void draw() { + dq::visited.clear(); + dq::enqueue(viewctr.at, cview()); + { + dynamicval d(poly_outline, 0xFFFFFFFF); + for(int i=0; i(p); + transmatrix V = get<1>(p); + dynamicval b(band_shift, get<2>(p)); + bandfixer bf(V); + dq::drawqueue.pop(); + + + cell *c = h->c7; + if(!do_draw(c, V)) continue; + drawcell(c, V, 0, false); + + if(DIM == 2) { + dq::enqueue(h->move(bd_up), V * xpush(-log(2))); + dq::enqueue(h->move(bd_right), V * parabolic(1)); + dq::enqueue(h->move(bd_left), V * parabolic(-1)); + if(c->type == 6) + dq::enqueue(h->move(bd_down), V * xpush(log(2))); + if(c->type == 7) { + dq::enqueue(h->move(bd_down_left), V * parabolic(-1) * xpush(log(2))); + dq::enqueue(h->move(bd_down_right), V * parabolic(1) * xpush(log(2))); + } + } + else { + for(int i=0; imove(i), V * tmatrix(h, i)); + } + } + } + + transmatrix relative_matrix(heptagon *h2, heptagon *h1) { + if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) + return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; + transmatrix gm = Id, where = Id; + while(h1 != h2) { + if(h1->distance <= h2->distance) { + if(DIM == 3) + where = itmatrix(h2, S7-1) * where, h2 = may_create_step(h2, S7-1); + else { + if(type_of(h2) == 6) + h2 = may_create_step(h2, bd_down), where = xpush(-log(2)) * where; + else if(mapside(h2) == 1) + h2 = may_create_step(h2, bd_left), where = parabolic(+1) * where; + else if(mapside(h2) == -1) + h2 = may_create_step(h2, bd_right), where = parabolic(-1) * where; + } + } + else { + if(DIM == 3) + gm = gm * tmatrix(h1, S7-1), h1 = may_create_step(h1, S7-1); + else { + if(type_of(h1) == 6) + h1 = may_create_step(h1, bd_down), gm = gm * xpush(log(2)); + else if(mapside(h1) == 1) + h1 = may_create_step(h1, bd_left), gm = gm * parabolic(-1); + else if(mapside(h1) == -1) + h1 = may_create_step(h1, bd_right), gm = gm * parabolic(+1); + } + } + } + return gm * where; + } + }; + + hrmap *new_map() { return new hrmap_binary; } + + struct hrmap_alternate_binary : hrmap_binary { + heptagon *origin; + hrmap_alternate_binary(heptagon *o) { origin = o; } + ~hrmap_alternate_binary() { clearfrom(origin); } + }; + + hrmap *new_alt_map(heptagon *o) { return new hrmap_binary(o); } + transmatrix direct_tmatrix[8]; transmatrix inverse_tmatrix[8]; @@ -312,74 +407,6 @@ namespace binary { return point3(log(2) + log(-h[0]), h[1] / co, h[2] / co); } - void draw() { - dq::visited.clear(); - dq::enqueue(viewctr.at, cview()); - - while(!dq::drawqueue.empty()) { - auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); - dq::drawqueue.pop(); - - - cell *c = h->c7; - if(!do_draw(c, V)) continue; - drawcell(c, V, 0, false); - - if(DIM == 2) { - dq::enqueue(h->move(bd_up), V * xpush(-log(2))); - dq::enqueue(h->move(bd_right), V * parabolic(1)); - dq::enqueue(h->move(bd_left), V * parabolic(-1)); - if(c->type == 6) - dq::enqueue(h->move(bd_down), V * xpush(log(2))); - if(c->type == 7) { - dq::enqueue(h->move(bd_down_left), V * parabolic(-1) * xpush(log(2))); - dq::enqueue(h->move(bd_down_right), V * parabolic(1) * xpush(log(2))); - } - } - else { - for(int i=0; imove(i), V * tmatrix(h, i)); - } - } - } - - transmatrix relative_matrix(heptagon *h2, heptagon *h1) { - if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) - return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; - transmatrix gm = Id, where = Id; - while(h1 != h2) { - if(h1->distance <= h2->distance) { - if(DIM == 3) - where = itmatrix(h2, S7-1) * where, h2 = hr::createStep(h2, S7-1); - else { - if(type_of(h2) == 6) - h2 = hr::createStep(h2, bd_down), where = xpush(-log(2)) * where; - else if(mapside(h2) == 1) - h2 = hr::createStep(h2, bd_left), where = parabolic(+1) * where; - else if(mapside(h2) == -1) - h2 = hr::createStep(h2, bd_right), where = parabolic(-1) * where; - } - } - else { - if(DIM == 3) - gm = gm * tmatrix(h1, S7-1), h1 = hr::createStep(h1, S7-1); - else { - if(type_of(h1) == 6) - h1 = hr::createStep(h1, bd_down), gm = gm * xpush(log(2)); - else if(mapside(h1) == 1) - h1 = hr::createStep(h1, bd_left), gm = gm * parabolic(-1); - else if(mapside(h1) == -1) - h1 = hr::createStep(h1, bd_right), gm = gm * parabolic(+1); - } - } - } - return gm * where; - } - #if CAP_COMMANDLINE auto bt_config = addHook(hooks_args, 0, [] () { using namespace arg; diff --git a/cell.cpp b/cell.cpp index dc96eb22..18d70c94 100644 --- a/cell.cpp +++ b/cell.cpp @@ -39,16 +39,11 @@ struct cdata { hrmap *currentmap; vector allmaps; -// --- auxiliary hyperbolic map for horocycles --- -struct hrmap_alternate : hrmap { - heptagon *origin; - hrmap_alternate(heptagon *o) { origin = o; } - ~hrmap_alternate() { clearfrom(origin); } - }; - -hrmap *newAltMap(heptagon *o) { return new hrmap_alternate(o); } +hrmap *newAltMap(heptagon *o) { return new hrmap_hyperbolic(o); } // --- hyperbolic geometry --- +hrmap_hyperbolic::hrmap_hyperbolic(heptagon *o) { origin = o; } + hrmap_hyperbolic::hrmap_hyperbolic() { // printf("Creating hyperbolic map: %p\n", this); origin = tailored_alloc (S7); @@ -235,6 +230,7 @@ void initcells() { else if(DIM == 3 && !binarytiling) currentmap = reg3::new_map(); else if(sphere) currentmap = new hrmap_spherical; else if(quotient) currentmap = new quotientspace::hrmap_quotient; + else if(binarytiling) currentmap = binary::new_map(); else currentmap = new hrmap_hyperbolic; allmaps.push_back(currentmap); diff --git a/complex.cpp b/complex.cpp index 0f93bbc3..f4ad3b85 100644 --- a/complex.cpp +++ b/complex.cpp @@ -765,9 +765,9 @@ namespace clearing { int plantdir(cell *c) { if(!quotient) { - generateAlts(c->master); + currentmap->generateAlts(c->master); for(int i=0; imaster->move(i)); + currentmap->generateAlts(c->master->move(i)); } int d = celldistAlt(c); @@ -848,7 +848,7 @@ namespace clearing { } // cell *oc = c; - if(!euclid) generateAlts(c->master); + if(!euclid) currentmap->generateAlts(c->master); if(pseudohept(c)) return; heptagon *a = euclid ? NULL : c->master->alt->alt; clearingdata& bd(bpdata[a]); diff --git a/crystal.cpp b/crystal.cpp index a2031340..b6cf62b9 100644 --- a/crystal.cpp +++ b/crystal.cpp @@ -352,7 +352,9 @@ int fiftyrule(coord c) { */ } -struct hrmap_crystal : hrmap { +bool is_bi(crystal_structure& cs, coord co); + +struct hrmap_crystal : hrmap_standard { heptagon *getOrigin() { return get_heptagon_at(c0, S7); } map hcoords; @@ -435,6 +437,44 @@ struct hrmap_crystal : hrmap { void verify() { } void prepare_east(); + + heptagon *create_step(heptagon *h, int d) { + if(!hcoords.count(h)) { + printf("not found\n"); + return NULL; + } + auto co = hcoords[h]; + + if(is_bi(cs, co)) { + heptspin hs(h, d); + (hs + 1 + wstep + 1).cpeek(); + return h->move(d); + } + + auto lw = makewalker(co, d); + + if(ginf[gCrystal].vertex == 4) { + auto c1 = add(co, lw, FULLSTEP); + auto lw1 = lw+wstep; + + h->c.connect(d, heptspin(get_heptagon_at(c1, S7), lw1.spin)); + } + else { + auto coc = add(add(co, lw, HALFSTEP), lw+1, HALFSTEP); + auto hc = get_heptagon_at(coc, 8); + for(int a=0; a<8; a+=2) { + hc->c.connect(a, heptspin(h, lw.spin)); + if(h->modmove(lw.spin-1)) { + hc->c.connect(a+1, heptspin(h, lw.spin) - 1 + wstep - 1); + } + co = add(co, lw, FULLSTEP); + lw = lw + wstep + (-1); + h = get_heptagon_at(co, S7); + } + } + return h->move(d); + } + }; hrmap_crystal *crystal_map() { @@ -450,44 +490,6 @@ bool is_bi(crystal_structure& cs, coord co) { return false; } -void create_step(heptagon *h, int d) { - auto m = crystal_map(); - if(geometry != gCrystal) return; - if(!m->hcoords.count(h)) { - printf("not found\n"); - return; - } - auto co = m->hcoords[h]; - - if(is_bi(m->cs, co)) { - heptspin hs(h, d); - (hs + 1 + wstep + 1).cpeek(); - return; - } - - auto lw = m->makewalker(co, d); - - if(ginf[gCrystal].vertex == 4) { - auto c1 = add(co, lw, FULLSTEP); - auto lw1 = lw+wstep; - - h->c.connect(d, heptspin(m->get_heptagon_at(c1, S7), lw1.spin)); - } - else { - auto coc = add(add(co, lw, HALFSTEP), lw+1, HALFSTEP); - auto hc = m->get_heptagon_at(coc, 8); - for(int a=0; a<8; a+=2) { - hc->c.connect(a, heptspin(h, lw.spin)); - if(h->modmove(lw.spin-1)) { - hc->c.connect(a+1, heptspin(h, lw.spin) - 1 + wstep - 1); - } - co = add(co, lw, FULLSTEP); - lw = lw + wstep + (-1); - h = m->get_heptagon_at(co, S7); - } - } - } - array, MAX_EDGE> distlimit_table = {{ {{SEE_ALL,SEE_ALL}}, {{SEE_ALL,SEE_ALL}}, {{SEE_ALL,SEE_ALL}}, {{SEE_ALL,SEE_ALL}}, {{15, 10}}, {{6, 4}}, {{5, 3}}, {{4, 3}}, {{4, 3}}, {{3, 2}}, {{3, 2}}, {{3, 2}}, {{3, 2}}, {{3, 2}} diff --git a/euclid.cpp b/euclid.cpp index 32184832..0dc03942 100644 --- a/euclid.cpp +++ b/euclid.cpp @@ -10,6 +10,8 @@ namespace hr { // NOTE: patterns assume that pair_to_vec(0,1) % 3 == 2! // Thus, pair_to_vec(0,1) must not be e.g. a power of four +int cell_to_vec(cell *c); + int pair_to_vec(int x, int y) { return x + (y << 15); } @@ -299,7 +301,11 @@ template void build_euclidean_moves(cell *c, int vec, const T& builder) } } -struct hrmap_torus : hrmap { +struct hrmap_euclid_any : hrmap { + void draw() override; + }; + +struct hrmap_torus : hrmap_euclid_any { vector all; vector dists; @@ -340,6 +346,27 @@ struct hrmap_torus : hrmap { ~hrmap_torus() { for(cell *c: all) tailored_delete(c); } + + transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) { + transmatrix t = Id; + // if(whateveri) printf("[%p,%d] ", c2, celldistance(c2, c1)); + int d = celldistance(c2, c1); + while(d) { + forCellIdEx(cc, i, c1) { + int d1 = celldistance(cc, c2); + if(d1 < d) { + t = t * cellrelmatrix(c1, i); + c1 = cc; + d = d1; + goto again; + } + } + printf("ERROR not reached\n"); + break; + again: ; + } + return t; + } }; hrmap_torus *torusmap() { @@ -352,7 +379,7 @@ hrmap_torus *torusmap() { return cur->all[id]; } */ -struct hrmap_euclidean : hrmap { +struct hrmap_euclidean : hrmap_euclid_any { cell *gamestart() { return *(euclideanAtCreate(0).first); @@ -400,6 +427,10 @@ struct hrmap_euclidean : hrmap { } eucdata.clear(); } + + transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) { + return eumove(cell_to_vec(c2) - cell_to_vec(c1)); + } }; cellwalker vec_to_cellwalker(int vec) { @@ -558,9 +589,36 @@ namespace euclid3 { return h; } - heptagon *createStep(heptagon *parent, int d) { + heptagon *create_step(heptagon *parent, int d) { return build(parent, d, ispacemap[parent] + shifttable[d]); + } + + void draw() { + dq::visited.clear(); + dq::enqueue(viewctr.at, cview()); + + while(!dq::drawqueue.empty()) { + auto& p = dq::drawqueue.front(); + heptagon *h = get<0>(p); + transmatrix V = get<1>(p); + dynamicval b(band_shift, get<2>(p)); + bandfixer bf(V); + dq::drawqueue.pop(); + + cell *c = h->c7; + if(!do_draw(c, V)) continue; + drawcell(c, V, 0, false); + + for(int i=0; imove(i), V * tmatrix[i]); + } } + + transmatrix relative_matrix(heptagon *h2, heptagon *h1) { + auto v = getcoord(ispacemap[h2] - ispacemap[h1]); + return eupush3(v[0], v[1], v[2]); + } + }; hrmap_euclid3* cubemap() { @@ -571,10 +629,6 @@ namespace euclid3 { return new hrmap_euclid3; } - heptagon *createStep(heptagon *parent, int d) { - return cubemap()->createStep(parent, d); - } - bool pseudohept(cell *c) { coord co = cubemap()->ispacemap[c->master]; auto v = getcoord(co); @@ -595,34 +649,6 @@ namespace euclid3 { else return v[2]/2; } - void draw() { - dq::visited.clear(); - dq::enqueue(viewctr.at, cview()); - auto cm = cubemap(); - - while(!dq::drawqueue.empty()) { - auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); - dq::drawqueue.pop(); - - cell *c = h->c7; - if(!do_draw(c, V)) continue; - drawcell(c, V, 0, false); - - for(int i=0; imove(i), V * cm->tmatrix[i]); - } - } - - transmatrix relative_matrix(heptagon *h2, heptagon *h1) { - auto cm = cubemap(); - auto v = getcoord(cm->ispacemap[h2] - cm->ispacemap[h1]); - return eupush3(v[0], v[1], v[2]); - } - bool get_emerald(cell *c) { auto v = getcoord(cubemap()->ispacemap[c->master]); int s0 = 0, s1 = 0; @@ -665,4 +691,53 @@ namespace euclid3 { } #endif + +ld matrixnorm(const transmatrix& Mat) { + return Mat[0][2] * Mat[0][2] + Mat[1][2] * Mat[1][2]; + } + +void hrmap_euclid_any::draw() { + DEBB(DF_GRAPH, (debugfile,"drawEuclidean\n")); + sphereflip = Id; + if(!centerover.at) centerover = cwt; + // printf("centerover = %p player = %p [%d,%d]-[%d,%d]\n", lcenterover, cwt.c, + // mindx, mindy, maxdx, maxdy); + int pvec = cellwalker_to_vec(centerover); + + typedef pair euspot; + + const euspot zero = {0,0}; + + set visited = {zero}; + vector dfs = {zero}; + + ld centerd = matrixnorm(View); + auto View0 = View; + + for(int i=0; itype) * Mirror : Mat, cw.spin, cw.mirrored); + for(int x=-1; x<=+1; x++) + for(int y=-1; y<=+1; y++) { + euspot p(dx+x, dy+y); + if(!visited.count(p)) visited.insert(p), dfs.push_back(p); + } + } + } + } + } diff --git a/floorshapes.cpp b/floorshapes.cpp index 7efb8978..a2cb956e 100644 --- a/floorshapes.cpp +++ b/floorshapes.cpp @@ -535,7 +535,6 @@ void generate_floorshapes() { namespace gp { int pshid[3][8][32][32][8]; int nextid; - extern gp::local_info draw_li; void clear_plainshapes() { for(int m=0; m<3; m++) diff --git a/geometry2.cpp b/geometry2.cpp index 7e799e4e..319f262b 100644 --- a/geometry2.cpp +++ b/geometry2.cpp @@ -56,75 +56,17 @@ transmatrix calc_relative_matrix(cell *c2, cell *c1, int direction_hint) { return calc_relative_matrix(c2, c1, ddspin(c1, direction_hint) * xpush0(1e-2)); } +transmatrix calc_relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) { + return currentmap->relative_matrix(c2, c1, point_hint); + } + // target, source, direction from source to target #if CAP_GP namespace gp { extern gp::local_info draw_li; } #endif -transmatrix calc_relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) { - - if(sphere_narcm && DIM == 2) { - if(!gmatrix0.count(c2) || !gmatrix0.count(c1)) { - printf("building gmatrix0 (size=%d)\n", isize(gmatrix0)); - #if CAP_GP - auto bak = gp::draw_li; - #endif - swap(gmatrix, gmatrix0); - just_gmatrix = true; - drawStandard(); - just_gmatrix = false; - swap(gmatrix, gmatrix0); - #if CAP_GP - gp::draw_li = bak; - #endif - } - if(gmatrix0.count(c2) && gmatrix0.count(c1)) { - transmatrix T = inverse(gmatrix0[c1]) * gmatrix0[c2]; - if(elliptic && T[2][2] < 0) - T = centralsym * T; - return T; - } - else { - printf("error: gmatrix0 not known\n"); - return Id; - } - } - - #if CAP_BT - if(binarytiling) return binary::relative_matrix(c2->master, c1->master); - #endif - #if MAXMDIM == 4 - if(euclid && DIM == 3) return euclid3::relative_matrix(c2->master, c1->master); - if(DIM == 3) return reg3::relative_matrix(c2->master, c1->master); - #endif - #if CAP_ARCM - if(archimedean) return arcm::relative_matrix(c2->master, c1->master); - #endif - - if(euwrap) { - transmatrix t = Id; - // if(whateveri) printf("[%p,%d] ", c2, celldistance(c2, c1)); - int d = celldistance(c2, c1); - while(d) { - forCellIdEx(cc, i, c1) { - int d1 = celldistance(cc, c2); - if(d1 < d) { - t = t * cellrelmatrix(c1, i); - c1 = cc; - d = d1; - goto again; - } - } - printf("ERROR not reached\n"); - break; - again: ; - } - return t; - } - - if(euclid) - return eumove(cell_to_vec(c2) - cell_to_vec(c1)); +transmatrix hrmap_standard::relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) { heptagon *h1 = c1->master; transmatrix gm = master_relative(c1, true); diff --git a/graph.cpp b/graph.cpp index 6edc337a..d9d881b9 100644 --- a/graph.cpp +++ b/graph.cpp @@ -5912,24 +5912,7 @@ void drawthemap() { arrowtraps.clear(); profile_start(1); - if(masterless) - drawEuclidean(); - #if CAP_BT - else if(binarytiling) - binary::draw(); - #endif - #if CAP_ARCM - else if(archimedean) - arcm::draw(); - #endif - #if MAXMDIM == 4 - else if(euclid && DIM == 3) - euclid3::draw(); - else if(DIM == 3) - reg3::draw(); - #endif - else - drawStandard(); + currentmap->draw(); drawWormSegments(); drawBlizzards(); drawArrowTraps(); diff --git a/heptagon.cpp b/heptagon.cpp index 2a6da5eb..470968d3 100644 --- a/heptagon.cpp +++ b/heptagon.cpp @@ -217,32 +217,12 @@ hookset *hooks_createStep; heptagon *createStep(heptagon *h, int d) { d = h->c.fix(d); - if(!h->move(d)) - callhooks(hooks_createStep, h, d); - #if CAP_CRYSTAL - if(!h->move(d) && geometry == gCrystal) - crystal::create_step(h, d); - #endif - #if CAP_BT - if(!h->move(d) && binarytiling && DIM == 2) - return binary::createStep(h, d); - #endif - #if CAP_BT && MAXMDIM == 4 - if(!h->move(d) && binarytiling && DIM == 3) - return binary::createStep3(h, d); - #endif - #if MAXMDIM == 4 - if(!h->move(d) && euclid && DIM == 3) - return euclid3::createStep(h, d); - if(!h->move(d) && DIM == 3) - return reg3::createStep(h, d); - #endif - #if CAP_ARCM - if(!h->move(d) && archimedean) { - arcm::create_adjacent(h, d); - return h->move(d); - } - #endif + if(h->move(d)) return h->move(d); + callhooks(hooks_createStep, h, d); + return currentmap->create_step(h, d); + } + +heptagon *hrmap_standard::create_step(heptagon *h, int d) { if(!h->move(0) && h->s != hsOrigin && !binarytiling && (geometry != gCrystal)) { // cheating: int pard=0; diff --git a/hyper.h b/hyper.h index e4cf10f9..865d9e16 100644 --- a/hyper.h +++ b/hyper.h @@ -3032,8 +3032,6 @@ namespace princess { int eudist(int sx, int sy); -heptagon *createStep(heptagon *h, int d); - cell *createMovR(cell *c, int d); bool ishept(cell *c); @@ -3050,20 +3048,48 @@ struct hrmap { virtual ~hrmap() { }; virtual vector& allcells() { return dcal; } virtual void verify() { } + virtual void link_alt(const cellwalker& hs) { } + virtual void generateAlts(heptagon *h, int levs = IRREGULAR ? 1 : S3-3, bool link_cdata = true); + heptagon *may_create_step(heptagon *h, int direction) { + if(h->move(direction)) return h->move(direction); + return create_step(h, direction); + } + virtual heptagon *create_step(heptagon *h, int direction) { + printf("create_step called unexpectedly\n"); exit(1); + return NULL; + } + virtual transmatrix relative_matrix(heptagon *h2, heptagon *h1) { + printf("relative_matrix called unexpectedly\n"); + return Id; + } + virtual transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) { + return relative_matrix(c2->master, c1->master); + } + virtual void draw() { + printf("undrawable\n"); + } }; -struct hrmap_hyperbolic : hrmap { +// hrmaps which are based on regular non-Euclidean 2D tilings, possibly quotient +struct hrmap_standard : hrmap { + void draw() override; + transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) override; + heptagon *create_step(heptagon *h, int direction) override; + }; + +struct hrmap_hyperbolic : hrmap_standard { heptagon *origin; eVariation mvar; hrmap_hyperbolic(); - heptagon *getOrigin() { return origin; } + hrmap_hyperbolic(heptagon *origin); + heptagon *getOrigin() override { return origin; } ~hrmap_hyperbolic() { DEBMEM ( verifycells(origin); ) // printf("Deleting hyperbolic map: %p\n", this); dynamicval ph(variation, mvar); clearfrom(origin); } - void verify() { verifycells(origin); } + void verify() override { verifycells(origin); } }; namespace irr { @@ -3671,6 +3697,8 @@ namespace gp { int first_dir; int total_dir; }; + + extern local_info draw_li; local_info get_local_info(cell *c); const char *disp(loc at); @@ -4063,7 +4091,6 @@ void queuestr(const hyperpoint& h, int size, const string& chr, color_t col, int void queuechr(const transmatrix& V, double size, char chr, color_t col, int frame = 0); extern bool just_gmatrix; -void drawStandard(); bool haveLeaderboard(int id); int get_currentscore(int id); @@ -4231,8 +4258,6 @@ extern void switchHardcore(); extern bool shaderside_projection; -void generateAlts(heptagon *h, int levs = IRREGULAR ? 1 : S3-3, bool link_cdata = true); - namespace ors { extern int mode; extern string choices[]; @@ -4256,20 +4281,16 @@ hyperpoint get_horopoint(ld y, ld x); hyperpoint get_horopoint3(ld y, ld x, ld z); namespace binary { - heptagon *createStep(heptagon *parent, int d); - #if MAXMDIM == 4 - heptagon *createStep3(heptagon *parent, int d); - #endif transmatrix parabolic(ld u); transmatrix parabolic3(ld u, ld v); extern ld btrange, btrange_cosh; - transmatrix relative_matrix(heptagon *h2, heptagon *h1); + hrmap *new_map(); + hrmap *new_alt_map(heptagon *o); } #endif #if MAXMDIM == 4 namespace euclid3 { - heptagon *createStep(heptagon *parent, int d); hrmap* new_map(); void draw(); } @@ -4277,11 +4298,7 @@ namespace euclid3 { namespace reg3 { void generate(); hrmap* new_map(); - heptagon *createStep(heptagon *parent, int d); extern vector cellshape; - void draw(); - transmatrix relative_matrix(heptagon *h2, heptagon *h1); - int dist_alt(cell *c); int celldistance(cell *c1, cell *c2); bool pseudohept(cell *c); } @@ -4357,10 +4374,7 @@ namespace arcm { extern map> archimedean_gmatrix; void initialize(heptagon *root); - transmatrix relative_matrix(heptagon *h1, heptagon *h2); short& id_of(heptagon *); - void draw(); - void create_adjacent(heptagon*, int); int fix(heptagon *h, int spin); #endif } @@ -4385,7 +4399,6 @@ namespace crystal { int precise_distance(cell *c1, cell *c2); ld space_distance(cell *c1, cell *c2); hrmap *new_map(); - void create_step(heptagon *h, int d); void build_rugdata(); void apply_rotation(const transmatrix t); void switch_z_coordinate(); diff --git a/hypgraph.cpp b/hypgraph.cpp index db4f4bde..1ef349ed 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -839,7 +839,7 @@ void drawrec(cell *c, const transmatrix& V) { vector > drawn_cells; -void drawStandard() { +void hrmap_standard::draw() { drawn_cells.clear(); drawn_cells.emplace_back(viewctr, hsOrigin, cview(), band_shift); for(int i=0; i euspot; - - const euspot zero = {0,0}; - - set visited = {zero}; - vector dfs = {zero}; - - ld centerd = matrixnorm(View); - auto View0 = View; - - for(int i=0; itype) * Mirror : Mat, cw.spin, cw.mirrored); - for(int x=-1; x<=+1; x++) - for(int y=-1; y<=+1; y++) { - euspot p(dx+x, dy+y); - if(!visited.count(p)) visited.insert(p), dfs.push_back(p); - } - } - } - } - void spinEdge(ld aspd) { if(playerfound && vid.fixed_facing) { @@ -1127,17 +1079,7 @@ void optimizeview() { for(int i=0; ic7->type; i++) { int i1 = i * DUALMUL; heptagon *h2 = createStep(viewctr.at, i1); - transmatrix T; - #if CAP_BT - if(binarytiling) T = binary::relative_matrix(h2, viewctr.at); - #endif - #if MAXMDIM == 4 - else if(euclid && DIM == 3) T = euclid3::relative_matrix(h2, viewctr.at); - else if(DIM == 3) T = reg3::relative_matrix(h2, viewctr.at); - #endif - #if CAP_ARCM - if(archimedean) T = arcm::relative_matrix(h2, viewctr.at); - #endif + transmatrix T = currentmap->relative_matrix(h2, viewctr.at); hyperpoint H = View * tC0(T); ld quality = hdist0(H); if(quality < best) best = quality, turn = i1, TB = T; diff --git a/irregular.cpp b/irregular.cpp index e5ab3525..43e49727 100644 --- a/irregular.cpp +++ b/irregular.cpp @@ -718,7 +718,7 @@ void compute_horocycle(heptagon *alt) { set region; for(int i=0; igenerateAlts(h); for(int j=0; jmove(j)->alt->alt != master->alt->alt) continue; region.insert(h->move(j)); @@ -789,7 +789,7 @@ int celldist(cell *c, bool alts) { } } if(doalts == 0) { - generateAlts(master); + currentmap->generateAlts(master); for(int i=0; imove(i)->alt == master->alt->move[0] && periodmap[master->move(i)].celldists[true].empty()) compute_horocycle(master); } diff --git a/landgen.cpp b/landgen.cpp index 6bcaf76e..4430a799 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -1514,7 +1514,7 @@ void giantLandSwitch(cell *c, int d, cell *from) { if(fargen) { if(!eubinary) { if(c->master->alt && c->master->alt->distance <= 2) { - if(!eubinary) generateAlts(c->master); + if(!eubinary) currentmap->generateAlts(c->master); preventbarriers(c); int d = celldistAlt(c); if(d <= 0) diff --git a/quotient.cpp b/quotient.cpp index 464378df..0a8ad5ea 100644 --- a/quotient.cpp +++ b/quotient.cpp @@ -38,7 +38,7 @@ namespace quotientspace { int rv(int x) { return (rvadd+x*rvdir) % S7; } -struct hrmap_quotient : hrmap { +struct hrmap_quotient : hrmap_standard { hrmap_hyperbolic base; @@ -64,6 +64,8 @@ struct hrmap_quotient : hrmap { hrmap_quotient() { + dynamicval cmap(currentmap, this); + static int symmask = (1<<30); connections.clear(); @@ -350,7 +352,7 @@ struct hrmap_quotient : hrmap { for(int i=0; i= isize(by_dist)) { printf("too fast\n"); exit(1); } for(int a=0; amove(a)->alt == NULL) by_dist.push_back(by_dist[i]->move(a)); - generateAlts(by_dist[i], 0, false); + currentmap->generateAlts(by_dist[i], 0, false); } for(int i=0; idistance = 0; alt->alt = alt; alt->cdata = NULL; - binary_map = newAltMap(alt); + binary_map = binary::new_alt_map(alt); T = xpush(.01241) * spin(1.4117) * xpush(0.1241) * cspin(0, 2, 1.1249) * xpush(0.07) * Id; } + else binary_map = NULL; reg_gmatrix[origin] = make_pair(alt, T); altmap[alt].emplace_back(origin, T); @@ -218,7 +219,7 @@ namespace reg3 { #define DEB 0 - heptagon *createStep(heptagon *parent, int d) { + heptagon *create_step(heptagon *parent, int d) { auto& p1 = reg_gmatrix[parent]; if(DEB) println(hlog, "creating step ", parent, ":", d, ", at ", p1.first, tC0(p1.second)); heptagon *alt = p1.first; @@ -226,6 +227,7 @@ namespace reg3 { transmatrix T1 = T; if(hyperbolic) { dynamicval g(geometry, gBinary3); + dynamicval cm(currentmap, binary_map); binary::virtualRebaseSimple(alt, T); } @@ -277,6 +279,53 @@ namespace reg3 { return created; } + ~hrmap_reg3() { + if(binary_map) delete binary_map; + clearfrom(origin); + } + + void generateAlts(heptagon* h) { + } + + void draw() { + sphereflip = Id; + + // for(int i=0; i(p); + transmatrix V = get<1>(p); + dynamicval b(band_shift, get<2>(p)); + bandfixer bf(V); + dq::drawqueue.pop(); + + + cell *c = h->c7; + if(!do_draw(c, V)) continue; + drawcell(c, V, 0, false); + + for(int i=0; imove(i)) + dq::enqueue(h->move(i), V * relative_matrix(h->move(i), h)); + } + } + + transmatrix relative_matrix(heptagon *h2, heptagon *h1) { + auto p1 = reg_gmatrix[h1]; + auto p2 = reg_gmatrix[h2]; + transmatrix T = Id; + if(hyperbolic) { + dynamicval g(geometry, gBinary3); + dynamicval cm(currentmap, binary_map); + T = binary_map->relative_matrix(p2.first, p1.first); + } + return inverse(p1.second) * T * p2.second; + } + }; hrmap* new_map() { @@ -287,54 +336,12 @@ hrmap_reg3* regmap() { return ((hrmap_reg3*) currentmap); } -heptagon *createStep(heptagon *parent, int d) { - return regmap()->createStep(parent, d); - } - -transmatrix relative_matrix(heptagon *h2, heptagon *h1) { - auto m = regmap(); - auto p1 = m->reg_gmatrix[h1]; - auto p2 = m->reg_gmatrix[h2]; - transmatrix T = Id; - if(hyperbolic) { - dynamicval g(geometry, gBinary3); - T = binary::relative_matrix(p2.first, p1.first); - } - return inverse(p1.second) * T * p2.second; - } - -void draw() { - sphereflip = Id; - - // for(int i=0; i(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); - dq::drawqueue.pop(); - - - cell *c = h->c7; - if(!do_draw(c, V)) continue; - drawcell(c, V, 0, false); - - for(int i=0; imove(i), V * relative_matrix(h->move(i), h)); - } - } - int celldistance(cell *c1, cell *c2) { if(c1 == c2) return 0; auto r = regmap(); - hyperpoint h = tC0(relative_matrix(c1->master, c2->master)); + hyperpoint h = tC0(r->relative_matrix(c1->master, c2->master)); int b = bucketer(h); if(close_distances.count(b)) return close_distances[b]; @@ -343,8 +350,9 @@ int celldistance(cell *c1, cell *c2) { } bool pseudohept(cell *c) { + auto m = regmap(); if(sphere) { - hyperpoint h = tC0(relative_matrix(c->master, regmap()->origin)); + hyperpoint h = tC0(m->relative_matrix(c->master, regmap()->origin)); if(S7 == 12) { hyperpoint h1 = cspin(0, 1, atan2(16, 69) + M_PI/4) * h; for(int i=0; i<4; i++) if(abs(abs(h1[i]) - .5) > .01) return false; @@ -353,7 +361,7 @@ bool pseudohept(cell *c) { if(S7 == 8) return h[3] >= .99 || h[3] <= -.99 || abs(h[3]) < .01; if(loop == 3 && face == 3 && S7 == 4) - return c == currentmap->gamestart(); + return c == m->gamestart(); if(loop == 4 && face == 3) return abs(h[3]) > .9; if(loop == 3 && face == 4) diff --git a/savemem.cpp b/savemem.cpp index 3aa1256b..be559e03 100644 --- a/savemem.cpp +++ b/savemem.cpp @@ -60,8 +60,7 @@ void recursive_delete(heptagon *h, int i) { if(h2->alt && h2->alt->alt == h2->alt) { DEBSM(printf("destroying alternate map %p\n", h2->alt);) for(hrmap *& hm: allmaps) { - auto hm2 = dynamic_cast (hm); - if(hm2 && hm2->origin == h2->alt) { + if(hm->getOrigin() == h2->alt) { delete hm; hm = allmaps.back(); allmaps.pop_back(); diff --git a/sphere.cpp b/sphere.cpp index 7e25e33d..b4d30287 100644 --- a/sphere.cpp +++ b/sphere.cpp @@ -17,7 +17,7 @@ int spherecells() { vector siblings; -struct hrmap_spherical : hrmap { +struct hrmap_spherical : hrmap_standard { heptagon *dodecahedron[12]; eVariation mvar; @@ -156,6 +156,33 @@ struct hrmap_spherical : hrmap { } for(int i=0; i