mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-24 09:00:34 +00:00
improved in the OO fashion: draw, relative_matrix, create_step, and several minor functions are now virtual in hrmap
This commit is contained in:
parent
d8428f2ec3
commit
78d88b5909
265
archimedean.cpp
265
archimedean.cpp
@ -357,11 +357,18 @@ hrmap *current_altmap;
|
||||
|
||||
heptagon *build_child(heptspin p, pair<int, int> 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<hrmap*> curmap(currentmap, this);
|
||||
int id = DUAL ? current.N * 2 : 0;;
|
||||
int N0 = isize(current.adjacent[id]);
|
||||
origin = tailored_alloc<heptagon> (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<eGeometry> g(geometry, gNormal);
|
||||
dynamicval<hrmap*> 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; d2<p2.first->degree(); 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<ld> 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; i<S; i++) {
|
||||
if(DUAL && (i&1)) continue;
|
||||
h->cmove(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; i<neighbors_of(h1); i++) {
|
||||
if(h1->move(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<int, int> adj) {
|
||||
indenter ind;
|
||||
auto h = buildHeptagon1(tailored_alloc<heptagon> (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<eGeometry> 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; d2<p2.first->degree(); 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<ld, ld>& 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<ld> 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; i<S; i++) {
|
||||
if(DUAL && (i&1)) continue;
|
||||
h->cmove(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; i<neighbors_of(h1); i++) {
|
||||
if(h1->move(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;
|
||||
|
36
bigstuff.cpp
36
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; i<c->type; 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; i<S7; i++) generateAlts(c->master->move(i));
|
||||
if(!eubinary) for(int i=0; i<S7; i++) currentmap->generateAlts(c->master->move(i));
|
||||
int q = 0;
|
||||
if(weirdhyperbolic) {
|
||||
for(int t=0; t<c->type; 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; i<S7; i++) generateAlts(c->master->move(i));
|
||||
if(!eubinary) for(int i=0; i<S7; i++) currentmap->generateAlts(c->master->move(i));
|
||||
for(int i=0; i<c->type; 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; i<S7; i++) generateAlts(c->master->move(i));
|
||||
if(!eubinary) for(int i=0; i<S7; i++) currentmap->generateAlts(c->master->move(i));
|
||||
int q = 0;
|
||||
for(int t=0; t<c->type; 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) {
|
||||
|
@ -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<int> 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<color_t> d(poly_outline, 0xFFFFFFFF);
|
||||
for(int i=0; i<S7; i++) queuepolyat(cview(), shWall3D[i], 0, PPR::SUPERLINE);
|
||||
}
|
||||
|
||||
while(!dq::drawqueue.empty()) {
|
||||
auto& p = dq::drawqueue.front();
|
||||
heptagon *h = get<0>(p);
|
||||
transmatrix V = get<1>(p);
|
||||
dynamicval<ld> 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; i<S7; i++)
|
||||
dq::enqueue(h->move(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<ld> 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; i<S7; i++)
|
||||
dq::enqueue(h->move(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;
|
||||
|
12
cell.cpp
12
cell.cpp
@ -39,16 +39,11 @@ struct cdata {
|
||||
hrmap *currentmap;
|
||||
vector<hrmap*> 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<heptagon> (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);
|
||||
|
@ -765,9 +765,9 @@ namespace clearing {
|
||||
|
||||
int plantdir(cell *c) {
|
||||
if(!quotient) {
|
||||
generateAlts(c->master);
|
||||
currentmap->generateAlts(c->master);
|
||||
for(int i=0; i<S7; i++)
|
||||
generateAlts(c->master->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]);
|
||||
|
80
crystal.cpp
80
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<heptagon*, coord> 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<array<int,2>, 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}}
|
||||
|
145
euclid.cpp
145
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<class T> 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<cell*> all;
|
||||
vector<int> 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<ld> 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; i<S7; i++)
|
||||
dq::enqueue(h->move(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<ld> 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; i<S7; i++)
|
||||
dq::enqueue(h->move(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<int, int> euspot;
|
||||
|
||||
const euspot zero = {0,0};
|
||||
|
||||
set<euspot> visited = {zero};
|
||||
vector<euspot> dfs = {zero};
|
||||
|
||||
ld centerd = matrixnorm(View);
|
||||
auto View0 = View;
|
||||
|
||||
for(int i=0; i<isize(dfs); i++) {
|
||||
int dx, dy;
|
||||
tie(dx, dy) = dfs[i];
|
||||
|
||||
cellwalker cw = vec_to_cellwalker(pvec + euclid_getvec(dx, dy));
|
||||
if(!cw.at) continue;
|
||||
transmatrix Mat = View0 * eumove(dx, dy);
|
||||
torusconfig::torus_cx = dx;
|
||||
torusconfig::torus_cy = dy;
|
||||
|
||||
if(true) {
|
||||
ld locald = matrixnorm(Mat);
|
||||
if(locald < centerd) centerd = locald, centerover = cw, View = Mat;
|
||||
}
|
||||
|
||||
if(do_draw(cw.at, Mat)) {
|
||||
drawcell(cw.at, cw.mirrored ? Mat * spin(-2*M_PI*cw.spin / cw.at->type) * 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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++)
|
||||
|
@ -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);
|
||||
|
19
graph.cpp
19
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();
|
||||
|
32
heptagon.cpp
32
heptagon.cpp
@ -217,32 +217,12 @@ hookset<void(heptagon*, int)> *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;
|
||||
|
57
hyper.h
57
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<cell*>& 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<eVariation> 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<hyperpoint> 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<heptagon*, pair<heptagon*, transmatrix>> 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();
|
||||
|
62
hypgraph.cpp
62
hypgraph.cpp
@ -839,7 +839,7 @@ void drawrec(cell *c, const transmatrix& V) {
|
||||
|
||||
vector<tuple<heptspin, hstate, transmatrix, ld> > 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<isize(drawn_cells); i++) {
|
||||
@ -969,54 +969,6 @@ transmatrix eumovedir(int d) {
|
||||
return eumove(0,0);
|
||||
}
|
||||
|
||||
ld matrixnorm(const transmatrix& Mat) {
|
||||
return Mat[0][2] * Mat[0][2] + Mat[1][2] * Mat[1][2];
|
||||
}
|
||||
|
||||
void drawEuclidean() {
|
||||
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<int, int> euspot;
|
||||
|
||||
const euspot zero = {0,0};
|
||||
|
||||
set<euspot> visited = {zero};
|
||||
vector<euspot> dfs = {zero};
|
||||
|
||||
ld centerd = matrixnorm(View);
|
||||
auto View0 = View;
|
||||
|
||||
for(int i=0; i<isize(dfs); i++) {
|
||||
int dx, dy;
|
||||
tie(dx, dy) = dfs[i];
|
||||
|
||||
cellwalker cw = vec_to_cellwalker(pvec + euclid_getvec(dx, dy));
|
||||
if(!cw.at) continue;
|
||||
transmatrix Mat = View0 * eumove(dx, dy);
|
||||
torusconfig::torus_cx = dx;
|
||||
torusconfig::torus_cy = dy;
|
||||
|
||||
if(true) {
|
||||
ld locald = matrixnorm(Mat);
|
||||
if(locald < centerd) centerd = locald, centerover = cw, View = Mat;
|
||||
}
|
||||
|
||||
if(do_draw(cw.at, Mat)) {
|
||||
drawcell(cw.at, cw.mirrored ? Mat * spin(-2*M_PI*cw.spin / cw.at->type) * 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; i<viewctr.at->c7->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;
|
||||
|
@ -718,7 +718,7 @@ void compute_horocycle(heptagon *alt) {
|
||||
set<heptagon*> region;
|
||||
for(int i=0; i<LOOKUP-1; i++) {
|
||||
for(auto h: hs[i]) {
|
||||
generateAlts(h);
|
||||
currentmap->generateAlts(h);
|
||||
for(int j=0; j<S7; j++) {
|
||||
if(h->move(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; i<S7; i++) if(master->move(i)->alt == master->alt->move[0] && periodmap[master->move(i)].celldists[true].empty())
|
||||
compute_horocycle(master);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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<hrmap*> cmap(currentmap, this);
|
||||
|
||||
static int symmask = (1<<30);
|
||||
|
||||
connections.clear();
|
||||
@ -350,7 +352,7 @@ struct hrmap_quotient : hrmap {
|
||||
for(int i=0; i<TOT; i++) {
|
||||
if(i >= isize(by_dist)) { printf("too fast\n"); exit(1); }
|
||||
for(int a=0; a<S7; a++) if(by_dist[i]->move(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; i<TOT; i++) {
|
||||
|
102
reg3.cpp
102
reg3.cpp
@ -196,9 +196,10 @@ namespace reg3 {
|
||||
alt->distance = 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<eGeometry> g(geometry, gBinary3);
|
||||
dynamicval<hrmap*> 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<S6; i++) queuepoly(ggmatrix(cwt.at), shWall3D[i], 0xFF0000FF);
|
||||
|
||||
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<ld> 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; i<S7; i++)
|
||||
if(h->move(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<eGeometry> g(geometry, gBinary3);
|
||||
dynamicval<hrmap*> 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<eGeometry> 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<S6; i++) queuepoly(ggmatrix(cwt.at), shWall3D[i], 0xFF0000FF);
|
||||
|
||||
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<ld> 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; i<S7; i++)
|
||||
dq::enqueue(h->move(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)
|
||||
|
@ -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<hrmap_alternate*> (hm);
|
||||
if(hm2 && hm2->origin == h2->alt) {
|
||||
if(hm->getOrigin() == h2->alt) {
|
||||
delete hm;
|
||||
hm = allmaps.back();
|
||||
allmaps.pop_back();
|
||||
|
29
sphere.cpp
29
sphere.cpp
@ -17,7 +17,7 @@ int spherecells() {
|
||||
|
||||
vector<int> 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<spherecells(); i++) verifycells(dodecahedron[i]);
|
||||
}
|
||||
|
||||
transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) {
|
||||
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;
|
||||
draw();
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
heptagon *getDodecahedron(int i) {
|
||||
|
Loading…
Reference in New Issue
Block a user