improved in the OO fashion: draw, relative_matrix, create_step, and several minor functions are now virtual in hrmap

This commit is contained in:
Zeno Rogue 2019-03-08 22:38:44 +01:00
parent d8428f2ec3
commit 78d88b5909
19 changed files with 655 additions and 651 deletions

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -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]);

View File

@ -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}}

View File

@ -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);
}
}
}
}
}

View File

@ -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++)

View File

@ -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);

View File

@ -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();

View File

@ -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
View File

@ -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();

View File

@ -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;

View File

@ -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);
}

View File

@ -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)

View File

@ -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
View File

@ -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)

View File

@ -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();

View File

@ -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) {