mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-24 17:10:36 +00:00
syntetic tilings (WIP)
This commit is contained in:
parent
0b20c0a0cb
commit
749ad03138
@ -976,7 +976,7 @@ int wallchance(cell *c, bool deepOcean) {
|
|||||||
|
|
||||||
bool horo_ok() {
|
bool horo_ok() {
|
||||||
// do the horocycles work in the current geometry?
|
// do the horocycles work in the current geometry?
|
||||||
return hyperbolic && !binarytiling;
|
return hyperbolic && !binarytiling && !syntetic;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gp_wall_test() {
|
bool gp_wall_test() {
|
||||||
|
41
cell.cpp
41
cell.cpp
@ -73,7 +73,9 @@ hrmap_hyperbolic::hrmap_hyperbolic() {
|
|||||||
h.alt = NULL;
|
h.alt = NULL;
|
||||||
h.distance = 0;
|
h.distance = 0;
|
||||||
isnonbitrunc = nonbitrunc;
|
isnonbitrunc = nonbitrunc;
|
||||||
if(binarytiling) {
|
if(syntetic)
|
||||||
|
synt::initialize(&h);
|
||||||
|
else if(binarytiling) {
|
||||||
#if DEBUG_BINARY_TILING
|
#if DEBUG_BINARY_TILING
|
||||||
binary::xcode.clear();
|
binary::xcode.clear();
|
||||||
binary::rxcode.clear();
|
binary::rxcode.clear();
|
||||||
@ -845,7 +847,7 @@ cell *createMov(cell *c, int d) {
|
|||||||
printf("ERROR createmov\n");
|
printf("ERROR createmov\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(euclid && !c->mov[d]) {
|
if(masterless && !c->mov[d]) {
|
||||||
int id = decodeId(c->master);
|
int id = decodeId(c->master);
|
||||||
for(int dx=-1; dx<=1; dx++)
|
for(int dx=-1; dx<=1; dx++)
|
||||||
for(int dy=-1; dy<=1; dy++)
|
for(int dy=-1; dy<=1; dy++)
|
||||||
@ -864,7 +866,14 @@ cell *createMov(cell *c, int d) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(nonbitrunc) {
|
else if(nonbitrunc && syntetic) {
|
||||||
|
if(synt::id_of(c->master) <= synt::N * 2) {
|
||||||
|
heptspin hs = heptspin(c->master, d) + wstep + 2 + wstep + 1;
|
||||||
|
merge(c,d,hs.h->c7,hs.spin,false);
|
||||||
|
}
|
||||||
|
else merge(c, d, c, d, false);
|
||||||
|
}
|
||||||
|
else if(nonbitrunc || syntetic) {
|
||||||
heptagon *h2 = createStep(c->master, d);
|
heptagon *h2 = createStep(c->master, d);
|
||||||
merge(c,d,h2->c7,c->master->spin(d),false);
|
merge(c,d,h2->c7,c->master->spin(d),false);
|
||||||
}
|
}
|
||||||
@ -933,7 +942,8 @@ cell*& euclideanAtCreate(int vec) {
|
|||||||
void initcells() {
|
void initcells() {
|
||||||
DEBB(DF_INIT, (debugfile,"initcells\n"));
|
DEBB(DF_INIT, (debugfile,"initcells\n"));
|
||||||
|
|
||||||
if(torus) currentmap = new hrmap_torus;
|
if(syntetic) currentmap = new hrmap_hyperbolic;
|
||||||
|
else if(torus) currentmap = new hrmap_torus;
|
||||||
else if(euclid) currentmap = new hrmap_euclidean;
|
else if(euclid) currentmap = new hrmap_euclidean;
|
||||||
else if(sphere) currentmap = new hrmap_spherical;
|
else if(sphere) currentmap = new hrmap_spherical;
|
||||||
else if(quotient) currentmap = new quotientspace::hrmap_quotient;
|
else if(quotient) currentmap = new quotientspace::hrmap_quotient;
|
||||||
@ -1040,7 +1050,7 @@ void verifycell(cell *c) {
|
|||||||
for(int i=0; i<t; i++) {
|
for(int i=0; i<t; i++) {
|
||||||
cell *c2 = c->mov[i];
|
cell *c2 = c->mov[i];
|
||||||
if(c2) {
|
if(c2) {
|
||||||
if(!euclid && !nonbitrunc && c == c->master->c7) verifycell(c2);
|
if(!stdeuclid && !nonbitrunc && c == c->master->c7) verifycell(c2);
|
||||||
if(c2->mov[c->spn(i)] && c2->mov[c->spn(i)] != c) {
|
if(c2->mov[c->spn(i)] && c2->mov[c->spn(i)] != c) {
|
||||||
printf("cell error %p:%d [%d] %p:%d [%d]\n", c, i, c->type, c2, c->spn(i), c2->type);
|
printf("cell error %p:%d [%d] %p:%d [%d]\n", c, i, c->type, c2, c->spn(i), c2->type);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -1050,7 +1060,7 @@ void verifycell(cell *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void verifycells(heptagon *at) {
|
void verifycells(heptagon *at) {
|
||||||
if(gp::on || irr::on) return;
|
if(gp::on || irr::on || syntetic) return;
|
||||||
for(int i=0; i<S7; i++) if(at->move[i] && at->move[i]->move[at->spin(i)] && at->move[i]->move[at->spin(i)] != at) {
|
for(int i=0; i<S7; i++) if(at->move[i] && at->move[i]->move[at->spin(i)] && at->move[i]->move[at->spin(i)] != at) {
|
||||||
printf("hexmix error %p [%d s=%d] %p %p\n", at, i, at->spin(i), at->move[i], at->move[i]->move[at->spin(i)]);
|
printf("hexmix error %p [%d s=%d] %p %p\n", at, i, at->spin(i), at->move[i], at->move[i]->move[at->spin(i)]);
|
||||||
}
|
}
|
||||||
@ -1091,14 +1101,13 @@ int compdist(int dx[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int celldist(cell *c) {
|
int celldist(cell *c) {
|
||||||
if(euclid) {
|
if(torus)
|
||||||
if(torus)
|
return torusmap()->dists[decodeId(c->master)];
|
||||||
return torusmap()->dists[decodeId(c->master)];
|
if(masterless)
|
||||||
return eudist(decodeId(c->master));
|
return eudist(decodeId(c->master));
|
||||||
}
|
|
||||||
if(sphere) return celldistance(c, currentmap->gamestart());
|
if(sphere) return celldistance(c, currentmap->gamestart());
|
||||||
if(irr::on) return irr::celldist(c, false);
|
if(irr::on) return irr::celldist(c, false);
|
||||||
if(ctof(c)) return c->master->distance;
|
if(binarytiling || syntetic || ctof(c)) return c->master->distance;
|
||||||
if(gp::on) return gp::compute_dist(c, celldist);
|
if(gp::on) return gp::compute_dist(c, celldist);
|
||||||
int dx[MAX_S3];
|
int dx[MAX_S3];
|
||||||
for(int u=0; u<S3; u++)
|
for(int u=0; u<S3; u++)
|
||||||
@ -1115,7 +1124,7 @@ int celldist(cell *c) {
|
|||||||
int euclidAlt(short x, short y);
|
int euclidAlt(short x, short y);
|
||||||
|
|
||||||
int celldistAlt(cell *c) {
|
int celldistAlt(cell *c) {
|
||||||
if(euclid) {
|
if(stdeuclid) {
|
||||||
if(torus) return celldist(c);
|
if(torus) return celldist(c);
|
||||||
int x, y;
|
int x, y;
|
||||||
tie(x,y) = vec_to_pair(decodeId(c->master));
|
tie(x,y) = vec_to_pair(decodeId(c->master));
|
||||||
@ -1429,7 +1438,7 @@ cdata *getEuclidCdata(int h) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int getCdata(cell *c, int j) {
|
int getCdata(cell *c, int j) {
|
||||||
if(euclid) return getEuclidCdata(decodeId(c->master))->val[j];
|
if(stdeuclid) return getEuclidCdata(decodeId(c->master))->val[j];
|
||||||
else if(geometry) return 0;
|
else if(geometry) return 0;
|
||||||
else if(ctof(c)) return getHeptagonCdata(c->master)->val[j]*3;
|
else if(ctof(c)) return getHeptagonCdata(c->master)->val[j]*3;
|
||||||
else {
|
else {
|
||||||
@ -1442,7 +1451,7 @@ int getCdata(cell *c, int j) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int getBits(cell *c) {
|
int getBits(cell *c) {
|
||||||
if(euclid) return getEuclidCdata(decodeId(c->master))->bits;
|
if(stdeuclid) return getEuclidCdata(decodeId(c->master))->bits;
|
||||||
else if(geometry) return 0;
|
else if(geometry) return 0;
|
||||||
else if(c->type != 6) return getHeptagonCdata(c->master)->bits;
|
else if(c->type != 6) return getHeptagonCdata(c->master)->bits;
|
||||||
else {
|
else {
|
||||||
@ -1486,7 +1495,7 @@ map<pair<cell*, cell*>, int> saved_distances;
|
|||||||
int celldistance(cell *c1, cell *c2) {
|
int celldistance(cell *c1, cell *c2) {
|
||||||
int d = 0;
|
int d = 0;
|
||||||
|
|
||||||
if(euclid6 || (euclid4 && nonbitrunc)) {
|
if((stdeuclid) && (euclid6 || (euclid4 && nonbitrunc))) {
|
||||||
if(!torus)
|
if(!torus)
|
||||||
return eudist(decodeId(c1->master) - decodeId(c2->master));
|
return eudist(decodeId(c1->master) - decodeId(c2->master));
|
||||||
else if(torus && torusconfig::torus_mode == 0)
|
else if(torus && torusconfig::torus_mode == 0)
|
||||||
@ -1511,7 +1520,7 @@ int celldistance(cell *c1, cell *c2) {
|
|||||||
return 64;
|
return 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gp::on || euclid || irr::on) {
|
if(gp::on || stdeuclid || irr::on) {
|
||||||
|
|
||||||
if(saved_distances.count(make_pair(c1,c2)))
|
if(saved_distances.count(make_pair(c1,c2)))
|
||||||
return saved_distances[make_pair(c1,c2)];
|
return saved_distances[make_pair(c1,c2)];
|
||||||
|
@ -1680,7 +1680,8 @@ geometryinfo ginf[gGUARD] = {
|
|||||||
{"Bolza Surface", "Bolza", 8, 3, qSMALL | qDOCKS, gcHyperbolic, 0x18200, {{6, 4}}},
|
{"Bolza Surface", "Bolza", 8, 3, qSMALL | qDOCKS, gcHyperbolic, 0x18200, {{6, 4}}},
|
||||||
{"Bolza Surface x2", "Bolza2", 8, 3, qSMALL | qDOCKS, gcHyperbolic, 0x18400, {{6, 4}}},
|
{"Bolza Surface x2", "Bolza2", 8, 3, qSMALL | qDOCKS, gcHyperbolic, 0x18400, {{6, 4}}},
|
||||||
{"minimal quotient", "minimal", 7, 3, qSMALL | qNONOR, gcHyperbolic, 0x18600, {{7, 5}}},
|
{"minimal quotient", "minimal", 7, 3, qSMALL | qNONOR, gcHyperbolic, 0x18600, {{7, 5}}},
|
||||||
{"binary tiling", "binary", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}}
|
{"binary tiling", "binary", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}},
|
||||||
|
{"syntetic tiling", "syntetic", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle
|
|||||||
|
|
||||||
enum eGeometry {
|
enum eGeometry {
|
||||||
gNormal, gEuclid, gSphere, gElliptic, gZebraQuotient, gFieldQuotient, gTorus, gOctagon, g45, g46, g47, gSmallSphere, gTinySphere, gEuclidSquare, gSmallElliptic,
|
gNormal, gEuclid, gSphere, gElliptic, gZebraQuotient, gFieldQuotient, gTorus, gOctagon, g45, g46, g47, gSmallSphere, gTinySphere, gEuclidSquare, gSmallElliptic,
|
||||||
gKleinQuartic, gBolza, gBolza2, gMinimal, gBinaryTiling,
|
gKleinQuartic, gBolza, gBolza2, gMinimal, gBinaryTiling, gSyntetic,
|
||||||
gGUARD};
|
gGUARD};
|
||||||
|
|
||||||
enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere };
|
enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere };
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "fieldpattern.cpp"
|
#include "fieldpattern.cpp"
|
||||||
#include "heptagon.cpp"
|
#include "heptagon.cpp"
|
||||||
#include "binary-tiling.cpp"
|
#include "binary-tiling.cpp"
|
||||||
|
#include "syntetic.cpp"
|
||||||
#include "language.cpp"
|
#include "language.cpp"
|
||||||
#include "cell.cpp"
|
#include "cell.cpp"
|
||||||
#include "goldberg.cpp"
|
#include "goldberg.cpp"
|
||||||
|
@ -579,6 +579,7 @@ int read_geom_args() {
|
|||||||
}
|
}
|
||||||
TOGGLE('7', nonbitrunc, stop_game_and_switch_mode(rg::bitrunc))
|
TOGGLE('7', nonbitrunc, stop_game_and_switch_mode(rg::bitrunc))
|
||||||
else if(argis("-geo")) {
|
else if(argis("-geo")) {
|
||||||
|
PHASEFROM(2);
|
||||||
shift(); targetgeometry = (eGeometry) argi();
|
shift(); targetgeometry = (eGeometry) argi();
|
||||||
if(targetgeometry != geometry)
|
if(targetgeometry != geometry)
|
||||||
stop_game_and_switch_mode(rg::geometry);
|
stop_game_and_switch_mode(rg::geometry);
|
||||||
|
@ -53,6 +53,8 @@ void precalc() {
|
|||||||
int vertexdegree = S6/2;
|
int vertexdegree = S6/2;
|
||||||
ld fmin, fmax;
|
ld fmin, fmax;
|
||||||
|
|
||||||
|
if(syntetic) return;
|
||||||
|
|
||||||
if(euclid) {
|
if(euclid) {
|
||||||
// dynamicval<eGeometry> g(geometry, gNormal);
|
// dynamicval<eGeometry> g(geometry, gNormal);
|
||||||
// precalc(); }
|
// precalc(); }
|
||||||
|
40
graph.cpp
40
graph.cpp
@ -248,7 +248,7 @@ int displaydir(cell *c, int d) {
|
|||||||
int dirs[8] = {0, 11, 21, 31, 42, 53, 63, 73};
|
int dirs[8] = {0, 11, 21, 31, 42, 53, 63, 73};
|
||||||
return -21-dirs[d];
|
return -21-dirs[d];
|
||||||
}
|
}
|
||||||
else if(euclid)
|
else if(stdeuclid)
|
||||||
return - d * S84 / c->type;
|
return - d * S84 / c->type;
|
||||||
else
|
else
|
||||||
return S42 - d * S84 / c->type;
|
return S42 - d * S84 / c->type;
|
||||||
@ -286,7 +286,7 @@ void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) {
|
|||||||
if(onplayer && (items[itOrbSword] || items[itOrbSword2])) {
|
if(onplayer && (items[itOrbSword] || items[itOrbSword2])) {
|
||||||
using namespace sword;
|
using namespace sword;
|
||||||
|
|
||||||
double esh = euclid ? M_PI - M_PI*3/S84 + 2.5 * M_PI/S42: 0;
|
double esh = stdeuclid ? M_PI - M_PI*3/S84 + 2.5 * M_PI/S42: 0;
|
||||||
|
|
||||||
if(shmup::on) {
|
if(shmup::on) {
|
||||||
#if CAP_POLY
|
#if CAP_POLY
|
||||||
@ -305,7 +305,7 @@ void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) {
|
|||||||
transmatrix Vnow = gmatrix[c] * rgpushxto0(inverse(gmatrix[c]) * tC0(V)) * (irr::on ? ddspin(c,0,S42) : spin(-hexshiftat(c)));
|
transmatrix Vnow = gmatrix[c] * rgpushxto0(inverse(gmatrix[c]) * tC0(V)) * (irr::on ? ddspin(c,0,S42) : spin(-hexshiftat(c)));
|
||||||
|
|
||||||
#if CAP_QUEUE
|
#if CAP_QUEUE
|
||||||
if(!euclid) for(int a=0; a<S42; a++) {
|
if(!stdeuclid) for(int a=0; a<S42; a++) {
|
||||||
int dda = S42 + (-1-2*a);
|
int dda = S42 + (-1-2*a);
|
||||||
if(a == ang && items[itOrbSword]) continue;
|
if(a == ang && items[itOrbSword]) continue;
|
||||||
if(nonbitrunc && !gp::on && !irr::on && a%3 != ang%3) continue;
|
if(nonbitrunc && !gp::on && !irr::on && a%3 != ang%3) continue;
|
||||||
@ -997,7 +997,7 @@ bool drawMonsterType(eMonster m, cell *where, const transmatrix& V, int col, dou
|
|||||||
queuepoly(VBODY, shPSword, darkena(0xFFFF00, 0, 0xFF));
|
queuepoly(VBODY, shPSword, darkena(0xFFFF00, 0, 0xFF));
|
||||||
queuepoly(VBODY, shKnightArmor, darkena(0xD0D0D0, 1, 0xFF));
|
queuepoly(VBODY, shKnightArmor, darkena(0xD0D0D0, 1, 0xFF));
|
||||||
int col;
|
int col;
|
||||||
if(!euclid && where && where->master->alt)
|
if(!eubinary && where && where->master->alt)
|
||||||
col = cloakcolor(roundTableRadius(where));
|
col = cloakcolor(roundTableRadius(where));
|
||||||
else
|
else
|
||||||
col = cloakcolor(newRoundTableRadius());
|
col = cloakcolor(newRoundTableRadius());
|
||||||
@ -2054,7 +2054,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
|
|||||||
if(d>=4) cw += 2;
|
if(d>=4) cw += 2;
|
||||||
transmatrix Vs = Vparam;
|
transmatrix Vs = Vparam;
|
||||||
bool mirr = cw.mirrored;
|
bool mirr = cw.mirrored;
|
||||||
Vs = Vs * ddspin(c, cw.spin-cwt.spin, euclid ? 0 : S42);
|
Vs = Vs * ddspin(c, cw.spin-cwt.spin, stdeuclid ? 0 : S42);
|
||||||
nospins = applyAnimation(cwt.c, Vs, footphase, LAYER_SMALL);
|
nospins = applyAnimation(cwt.c, Vs, footphase, LAYER_SMALL);
|
||||||
if(!nospins) Vs = Vs * ddspin(c, cwt.spin);
|
if(!nospins) Vs = Vs * ddspin(c, cwt.spin);
|
||||||
if(mirr) Vs = Vs * Mirror;
|
if(mirr) Vs = Vs * Mirror;
|
||||||
@ -2118,7 +2118,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
|
|||||||
Vb = Vb * xpush(tentacle_length - cellgfxdist(c, c->mondir));
|
Vb = Vb * xpush(tentacle_length - cellgfxdist(c, c->mondir));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(ctof(c) && !euclid) Vb = Vb * xpush(hexhexdist - hcrossf);
|
// if(ctof(c) && !stdeuclid) Vb = Vb * xpush(hexhexdist - hcrossf);
|
||||||
// return nonbitrunc ? tessf * gp::scale : (c->type == 6 && (i&1)) ? hexhexdist : crossf;
|
// return nonbitrunc ? tessf * gp::scale : (c->type == 6 && (i&1)) ? hexhexdist : crossf;
|
||||||
return drawMonsterTypeDH(m, c, Vb, col, darkhistory, footphase);
|
return drawMonsterTypeDH(m, c, Vb, col, darkhistory, footphase);
|
||||||
}
|
}
|
||||||
@ -2406,7 +2406,7 @@ void set_towerfloor(cell *c, cellfunction *cf = coastvalEdge) {
|
|||||||
}
|
}
|
||||||
int j = -1;
|
int j = -1;
|
||||||
|
|
||||||
if(euclid) j = 10;
|
if(stdeuclid) j = 10;
|
||||||
else if((*cf)(c) > 1) {
|
else if((*cf)(c) > 1) {
|
||||||
int i = towerval(c, cf);
|
int i = towerval(c, cf);
|
||||||
if(i == 4) j = 0;
|
if(i == 4) j = 0;
|
||||||
@ -2431,7 +2431,7 @@ void set_towerfloor(cell *c, cellfunction *cf = coastvalEdge) {
|
|||||||
|
|
||||||
void set_zebrafloor(cell *c) {
|
void set_zebrafloor(cell *c) {
|
||||||
|
|
||||||
if(euclid) { set_floor(shTower[10]); return; }
|
if(stdeuclid) { set_floor(shTower[10]); return; }
|
||||||
if(weirdhyperbolic) {
|
if(weirdhyperbolic) {
|
||||||
set_floor(shFloor); return;
|
set_floor(shFloor); return;
|
||||||
}
|
}
|
||||||
@ -2520,7 +2520,7 @@ void draw_reptile(cell *c, const transmatrix &V, int col) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void set_emeraldfloor(cell *c) {
|
void set_emeraldfloor(cell *c) {
|
||||||
if(!euclid && !nonbitrunc) {
|
if(!stdeuclid && !nonbitrunc) {
|
||||||
auto si = patterns::getpatterninfo(c, 'f', patterns::SPF_SYM0123);
|
auto si = patterns::getpatterninfo(c, 'f', patterns::SPF_SYM0123);
|
||||||
|
|
||||||
int j = -1;
|
int j = -1;
|
||||||
@ -2600,7 +2600,7 @@ bool drawstaratvec(double dx, double dy) {
|
|||||||
int reptilecolor(cell *c) {
|
int reptilecolor(cell *c) {
|
||||||
int i = zebra40(c);
|
int i = zebra40(c);
|
||||||
|
|
||||||
if(!euclid) {
|
if(!stdeuclid) {
|
||||||
if(i >= 4 && i < 16) i = 0;
|
if(i >= 4 && i < 16) i = 0;
|
||||||
else if(i >= 16 && i < 28) i = 1;
|
else if(i >= 16 && i < 28) i = 1;
|
||||||
else if(i >= 28 && i < 40) i = 2;
|
else if(i >= 28 && i < 40) i = 2;
|
||||||
@ -2642,7 +2642,7 @@ void setcolors(cell *c, int& wcol, int &fcol) {
|
|||||||
if(c->mov[i]->wall != waSea && c->mov[i]->wall != waBoat)
|
if(c->mov[i]->wall != waSea && c->mov[i]->wall != waBoat)
|
||||||
nearshore = true;
|
nearshore = true;
|
||||||
if(nearshore) mafcol += 30; */
|
if(nearshore) mafcol += 30; */
|
||||||
fcol = fcol + mafcol * (4+sin(ticks / 500. + ((euclid||c->master->alt) ? celldistAlt(c) : 0)*1.5))/5;
|
fcol = fcol + mafcol * (4+sin(ticks / 500. + ((eubinary||c->master->alt) ? celldistAlt(c) : 0)*1.5))/5;
|
||||||
}
|
}
|
||||||
else if(c->land == laDocks) {
|
else if(c->land == laDocks) {
|
||||||
fcol = 0x0000A0;
|
fcol = 0x0000A0;
|
||||||
@ -2748,7 +2748,7 @@ void setcolors(cell *c, int& wcol, int &fcol) {
|
|||||||
fcol = gradient(0x008000, 0x800000, 0, c->landparam, 10);
|
fcol = gradient(0x008000, 0x800000, 0, c->landparam, 10);
|
||||||
break;
|
break;
|
||||||
case laMountain:
|
case laMountain:
|
||||||
if(euclid || sphere || c->master->alt)
|
if(eubinary || sphere || c->master->alt)
|
||||||
fcol = celldistAlt(c) & 1 ? 0x604020 : 0x302010;
|
fcol = celldistAlt(c) & 1 ? 0x604020 : 0x302010;
|
||||||
else fcol = 0;
|
else fcol = 0;
|
||||||
if(c->wall == waPlatform) wcol = 0xF0F0A0;
|
if(c->wall == waPlatform) wcol = 0xF0F0A0;
|
||||||
@ -2877,7 +2877,7 @@ void setcolors(cell *c, int& wcol, int &fcol) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case laCamelot: {
|
case laCamelot: {
|
||||||
int d = showoff ? 0 : ((euclid||c->master->alt) ? celldistAltRelative(c) : 0);
|
int d = showoff ? 0 : ((eubinary||c->master->alt) ? celldistAltRelative(c) : 0);
|
||||||
#if CAP_TOUR
|
#if CAP_TOUR
|
||||||
if(!tour::on) camelotcheat = false;
|
if(!tour::on) camelotcheat = false;
|
||||||
if(camelotcheat)
|
if(camelotcheat)
|
||||||
@ -3107,7 +3107,7 @@ bool is_nice_dual(cell *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool use_swapped_duals() {
|
bool use_swapped_duals() {
|
||||||
return (euclid && !a4) || gp::on;
|
return (stdeuclid && !a4) || gp::on;
|
||||||
}
|
}
|
||||||
|
|
||||||
void floorShadow(cell *c, const transmatrix& V, int col) {
|
void floorShadow(cell *c, const transmatrix& V, int col) {
|
||||||
@ -5218,7 +5218,7 @@ void drawthemap() {
|
|||||||
compute_graphical_distance();
|
compute_graphical_distance();
|
||||||
|
|
||||||
centdist = 1e20;
|
centdist = 1e20;
|
||||||
if(!euclid) centerover.c = NULL;
|
if(!stdeuclid) centerover.c = NULL;
|
||||||
|
|
||||||
for(int i=0; i<multi::players; i++) {
|
for(int i=0; i<multi::players; i++) {
|
||||||
multi::ccdist[i] = 1e20; multi::ccat[i] = NULL;
|
multi::ccdist[i] = 1e20; multi::ccat[i] = NULL;
|
||||||
@ -5238,10 +5238,12 @@ void drawthemap() {
|
|||||||
arrowtraps.clear();
|
arrowtraps.clear();
|
||||||
|
|
||||||
profile_start(1);
|
profile_start(1);
|
||||||
if(euclid)
|
if(stdeuclid)
|
||||||
drawEuclidean();
|
drawEuclidean();
|
||||||
else if(binarytiling)
|
else if(binarytiling)
|
||||||
binary::draw();
|
binary::draw();
|
||||||
|
else if(syntetic)
|
||||||
|
synt::draw();
|
||||||
else
|
else
|
||||||
drawrec(viewctr, hsOrigin, cview());
|
drawrec(viewctr, hsOrigin, cview());
|
||||||
drawWormSegments();
|
drawWormSegments();
|
||||||
@ -5330,7 +5332,7 @@ void drawmovestar(double dx, double dy) {
|
|||||||
ld R = sqrt(H[0] * H[0] + H[1] * H[1]);
|
ld R = sqrt(H[0] * H[0] + H[1] * H[1]);
|
||||||
transmatrix Centered = Id;
|
transmatrix Centered = Id;
|
||||||
|
|
||||||
if(euclid)
|
if(stdeuclid)
|
||||||
Centered = eupush(H[0], H[1]);
|
Centered = eupush(H[0], H[1]);
|
||||||
else if(R > 1e-9) Centered = rgpushxto0(H);
|
else if(R > 1e-9) Centered = rgpushxto0(H);
|
||||||
|
|
||||||
@ -5766,7 +5768,7 @@ void restartGraph() {
|
|||||||
View = Id;
|
View = Id;
|
||||||
if(!autocheat) linepatterns::clearAll();
|
if(!autocheat) linepatterns::clearAll();
|
||||||
if(currentmap) {
|
if(currentmap) {
|
||||||
if(euclid) {
|
if(stdeuclid) {
|
||||||
centerover = vec_to_cellwalker(0);
|
centerover = vec_to_cellwalker(0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -5899,7 +5901,7 @@ void drawBug(const cellwalker& cw, int col) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cell *viewcenter() {
|
cell *viewcenter() {
|
||||||
if(euclid) return centerover.c;
|
if(stdeuclid) return centerover.c;
|
||||||
else return viewctr.h->c7;
|
else return viewctr.h->c7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
heptagon.cpp
19
heptagon.cpp
@ -74,7 +74,7 @@ heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0, int fix
|
|||||||
h->spintable = 0;
|
h->spintable = 0;
|
||||||
h->move[pard] = parent; tsetspin(h->spintable, pard, d);
|
h->move[pard] = parent; tsetspin(h->spintable, pard, d);
|
||||||
parent->move[d] = h; tsetspin(parent->spintable, d, pard);
|
parent->move[d] = h; tsetspin(parent->spintable, d, pard);
|
||||||
if(binarytiling) return h;
|
if(binarytiling || syntetic) return h;
|
||||||
if(parent->c7) {
|
if(parent->c7) {
|
||||||
if(irr::on)
|
if(irr::on)
|
||||||
irr::link_next(parent, d);
|
irr::link_next(parent, d);
|
||||||
@ -203,9 +203,9 @@ void connectHeptagons(heptagon *h1, int d1, heptagon *h2, int d2) {
|
|||||||
int recsteps;
|
int recsteps;
|
||||||
|
|
||||||
void addSpin(heptagon *h, int d, heptagon *from, int rot, int spin) {
|
void addSpin(heptagon *h, int d, heptagon *from, int rot, int spin) {
|
||||||
rot = fixrot(rot);
|
rot = fixrot(h, rot);
|
||||||
createStep(from, rot);
|
createStep(from, rot);
|
||||||
int fr = fixrot(from->spin(rot) + spin);
|
int fr = fixrot(from, from->spin(rot) + spin);
|
||||||
connectHeptagons(h, d, from->move[rot], fr);
|
connectHeptagons(h, d, from->move[rot], fr);
|
||||||
/* h->move[d] = from->move[rot];
|
/* h->move[d] = from->move[rot];
|
||||||
h->setspin(d, fr);
|
h->setspin(d, fr);
|
||||||
@ -219,8 +219,13 @@ extern int hrand(int);
|
|||||||
// a structure used to walk on the heptagonal tesselation
|
// a structure used to walk on the heptagonal tesselation
|
||||||
// (remembers not only the heptagon, but also direction)
|
// (remembers not only the heptagon, but also direction)
|
||||||
|
|
||||||
|
int fixrot(heptagon *h, int a) {
|
||||||
|
if(syntetic) return synt::fix(h, a);
|
||||||
|
return (a+MODFIXER) % S7;
|
||||||
|
}
|
||||||
|
|
||||||
heptspin& operator += (heptspin& hs, int spin) {
|
heptspin& operator += (heptspin& hs, int spin) {
|
||||||
hs.spin = fixrot(hs.spin + (MIRR(hs)?-spin:spin));
|
hs.spin = fixrot(hs.h, hs.spin + (MIRR(hs)?-spin:spin));
|
||||||
return hs;
|
return hs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,9 +243,13 @@ heptspin operator - (heptspin h, int spin) { return h += -spin; }
|
|||||||
heptspin& operator += (heptspin& h, wstep_t) { h = h + wstep; return h; }
|
heptspin& operator += (heptspin& h, wstep_t) { h = h + wstep; return h; }
|
||||||
|
|
||||||
heptagon *createStep(heptagon *h, int d) {
|
heptagon *createStep(heptagon *h, int d) {
|
||||||
d = fixrot(d);
|
d = fixrot(h, d);
|
||||||
if(!h->move[d] && binarytiling)
|
if(!h->move[d] && binarytiling)
|
||||||
return binary::createStep(h, d);
|
return binary::createStep(h, d);
|
||||||
|
if(!h->move[d] && syntetic) {
|
||||||
|
synt::create_adjacent(h, d);
|
||||||
|
return h->move[d];
|
||||||
|
}
|
||||||
if(!h->move[0] && h->s != hsOrigin && !binarytiling) {
|
if(!h->move[0] && h->s != hsOrigin && !binarytiling) {
|
||||||
// cheating:
|
// cheating:
|
||||||
int pard=0;
|
int pard=0;
|
||||||
|
20
hyper.h
20
hyper.h
@ -88,6 +88,7 @@ void addMessage(string s, char spamtype = 0);
|
|||||||
#define stdhyperbolic (S7 == 7 && S3 == 3 && !gp::on && !irr::on && !binarytiling)
|
#define stdhyperbolic (S7 == 7 && S3 == 3 && !gp::on && !irr::on && !binarytiling)
|
||||||
|
|
||||||
#define binarytiling (geometry == gBinaryTiling)
|
#define binarytiling (geometry == gBinaryTiling)
|
||||||
|
#define syntetic (geometry == gSyntetic)
|
||||||
#define eubinary (euclid || binarytiling)
|
#define eubinary (euclid || binarytiling)
|
||||||
|
|
||||||
#define cgclass (ginf[geometry].cclass)
|
#define cgclass (ginf[geometry].cclass)
|
||||||
@ -102,6 +103,10 @@ void addMessage(string s, char spamtype = 0);
|
|||||||
#define smallbounded (sphere || (quotient & qSMALL) || torus)
|
#define smallbounded (sphere || (quotient & qSMALL) || torus)
|
||||||
#define bounded (sphere || quotient || torus)
|
#define bounded (sphere || quotient || torus)
|
||||||
|
|
||||||
|
#define masterless among(geometry, gEuclid, gEuclidSquare)
|
||||||
|
#define stdeuclid (torus || masterless)
|
||||||
|
#define stdsphere (sphere && !syntetic)
|
||||||
|
|
||||||
#define a4 (S3 == 4)
|
#define a4 (S3 == 4)
|
||||||
#define a45 (S3 == 4 && S7 == 5)
|
#define a45 (S3 == 4 && S7 == 5)
|
||||||
#define a46 (S3 == 4 && S7 == 6)
|
#define a46 (S3 == 4 && S7 == 6)
|
||||||
@ -319,7 +324,8 @@ inline void tsetspin(uint32_t& t, int d, int spin) { t &= ~(15 << (d<<2)); t |=
|
|||||||
inline int tspin(uint32_t& t, int d) { return (t >> (d<<2)) & 7; }
|
inline int tspin(uint32_t& t, int d) { return (t >> (d<<2)) & 7; }
|
||||||
inline bool tmirror(uint32_t& t, int d) { return (t >> ((d<<2)+3)) & 1; }
|
inline bool tmirror(uint32_t& t, int d) { return (t >> ((d<<2)+3)) & 1; }
|
||||||
|
|
||||||
inline int fixrot(int a) { return (a+MODFIXER)% S7; }
|
int fixrot(struct heptagon *h, int a);
|
||||||
|
|
||||||
inline int fix42(int a) { return (a+MODFIXER)% S42; }
|
inline int fix42(int a) { return (a+MODFIXER)% S42; }
|
||||||
|
|
||||||
struct cell;
|
struct cell;
|
||||||
@ -357,8 +363,8 @@ struct heptagon {
|
|||||||
// associated generator of alternate structure, for Camelot and horocycles
|
// associated generator of alternate structure, for Camelot and horocycles
|
||||||
heptagon *alt;
|
heptagon *alt;
|
||||||
// functions
|
// functions
|
||||||
heptagon*& modmove(int i) { return move[fixrot(i)]; }
|
heptagon*& modmove(int i) { return move[fixrot(this, i)]; }
|
||||||
unsigned char gspin(int i) { return spin(fixrot(i)); }
|
unsigned char gspin(int i) { return spin(fixrot(this, i)); }
|
||||||
heptagon () { heptacount++; }
|
heptagon () { heptacount++; }
|
||||||
~heptagon () { heptacount--; }
|
~heptagon () { heptacount--; }
|
||||||
};
|
};
|
||||||
@ -3765,4 +3771,12 @@ namespace binary {
|
|||||||
heptagon *createStep(heptagon *parent, int d);
|
heptagon *createStep(heptagon *parent, int d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace synt {
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
12
hypgraph.cpp
12
hypgraph.cpp
@ -499,18 +499,20 @@ bool confusingGeometry() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ld master_to_c7_angle() {
|
ld master_to_c7_angle() {
|
||||||
return nonbitrunc ? M_PI + gp::alpha : 0;
|
return (nonbitrunc && !binarytiling && !syntetic) ? M_PI + gp::alpha : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
transmatrix actualV(const heptspin& hs, const transmatrix& V) {
|
transmatrix actualV(const heptspin& hs, const transmatrix& V) {
|
||||||
if(irr::on)
|
if(irr::on)
|
||||||
return V * spin(M_PI + 2 * M_PI / S7 * (hs.spin + irr::periodmap[hs.h].base.spin));
|
return V * spin(M_PI + 2 * M_PI / S7 * (hs.spin + irr::periodmap[hs.h].base.spin));
|
||||||
|
if(syntetic) return V * spin(-synt::triangles[synt::id_of(hs.h)][hs.spin].first);
|
||||||
if(binarytiling) return V;
|
if(binarytiling) return V;
|
||||||
return (hs.spin || nonbitrunc) ? V * spin(hs.spin*2*M_PI/S7 + master_to_c7_angle()) : V;
|
return (hs.spin || nonbitrunc) ? V * spin(hs.spin*2*M_PI/S7 + master_to_c7_angle()) : V;
|
||||||
}
|
}
|
||||||
|
|
||||||
transmatrix applyspin(const heptspin& hs, const transmatrix& V) {
|
transmatrix applyspin(const heptspin& hs, const transmatrix& V) {
|
||||||
if(binarytiling) return V;
|
if(binarytiling) return V;
|
||||||
|
if(syntetic) return V * spin(synt::triangles[synt::id_of(hs.h)][hs.spin].first);
|
||||||
return hs.spin ? V * spin(hs.spin*2*M_PI/S7) : V;
|
return hs.spin ? V * spin(hs.spin*2*M_PI/S7) : V;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,7 +610,7 @@ void drawrec(const heptspin& hs, hstate s, const transmatrix& V) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!nonbitrunc) for(int d=0; d<S7; d++) {
|
if(!nonbitrunc) for(int d=0; d<S7; d++) {
|
||||||
int ds = fixrot(hs.spin + d);
|
int ds = fixrot(hs.h, hs.spin + d);
|
||||||
// createMov(c, ds);
|
// createMov(c, ds);
|
||||||
if(c->mov[ds] && c->spn(ds) == 0 && dodrawcell(c->mov[ds])) {
|
if(c->mov[ds] && c->spn(ds) == 0 && dodrawcell(c->mov[ds])) {
|
||||||
transmatrix V2 = V1 * hexmove[d];
|
transmatrix V2 = V1 * hexmove[d];
|
||||||
@ -802,11 +804,11 @@ void optimizeview() {
|
|||||||
|
|
||||||
transmatrix TB = Id;
|
transmatrix TB = Id;
|
||||||
|
|
||||||
if(binarytiling) {
|
if(binarytiling || syntetic) {
|
||||||
turn = -1, best = View[2][2];
|
turn = -1, best = View[2][2];
|
||||||
for(int i=0; i<viewctr.h->c7->type; i++) {
|
for(int i=0; i<viewctr.h->c7->type; i++) {
|
||||||
heptagon *h2 = createStep(viewctr.h, i);
|
heptagon *h2 = createStep(viewctr.h, i);
|
||||||
transmatrix T = binary::relative_matrix(h2, viewctr.h);
|
transmatrix T = (binarytiling) ? binary::relative_matrix(h2, viewctr.h) : synt::relative_matrix(h2, viewctr.h);
|
||||||
hyperpoint H = View * tC0(T);
|
hyperpoint H = View * tC0(T);
|
||||||
if(H[2] < best) best = H[2], turn = i, TB = T;
|
if(H[2] < best) best = H[2], turn = i, TB = T;
|
||||||
}
|
}
|
||||||
@ -863,7 +865,7 @@ void resetview() {
|
|||||||
DEBB(DF_GRAPH, (debugfile,"reset view\n"));
|
DEBB(DF_GRAPH, (debugfile,"reset view\n"));
|
||||||
View = Id;
|
View = Id;
|
||||||
// EUCLIDEAN
|
// EUCLIDEAN
|
||||||
if(!euclid)
|
if(!stdeuclid)
|
||||||
viewctr.h = cwt.c->master,
|
viewctr.h = cwt.c->master,
|
||||||
viewctr.spin = cwt.spin;
|
viewctr.spin = cwt.spin;
|
||||||
else centerover = cwt;
|
else centerover = cwt;
|
||||||
|
@ -264,7 +264,7 @@ bool haveOrbPower() {
|
|||||||
cell *c = dcal[i];
|
cell *c = dcal[i];
|
||||||
if(itemclass(c->item) == IC_ORB) return true;
|
if(itemclass(c->item) == IC_ORB) return true;
|
||||||
}
|
}
|
||||||
else if(sphere) for(int i=0; i<spherecells(); i++) {
|
else if(stdsphere) for(int i=0; i<spherecells(); i++) {
|
||||||
cell *c = getDodecahedron(i)->c7;
|
cell *c = getDodecahedron(i)->c7;
|
||||||
if(itemclass(c->item) == IC_ORB) return true;
|
if(itemclass(c->item) == IC_ORB) return true;
|
||||||
forCellEx(c2, c) if(itemclass(c2->item) == IC_ORB) return true;
|
forCellEx(c2, c) if(itemclass(c2->item) == IC_ORB) return true;
|
||||||
@ -446,7 +446,7 @@ void wandering() {
|
|||||||
}
|
}
|
||||||
if(!peace::on && c->land == laKraken && ((sphere && !hrand(15)) || wchance(items[itKraken], 240)) && !kraken_pseudohept(c)) {
|
if(!peace::on && c->land == laKraken && ((sphere && !hrand(15)) || wchance(items[itKraken], 240)) && !kraken_pseudohept(c)) {
|
||||||
bool b = sphere || canReachPlayer(c, moKrakenH);
|
bool b = sphere || canReachPlayer(c, moKrakenH);
|
||||||
if(sphere && (haveKraken() || !items[itOrbFish])) {
|
if(stdsphere && (haveKraken() || !items[itOrbFish])) {
|
||||||
c->monst = moViking; c->wall = waBoat; c->item = itOrbFish;
|
c->monst = moViking; c->wall = waBoat; c->item = itOrbFish;
|
||||||
playSeenSound(c);
|
playSeenSound(c);
|
||||||
continue;
|
continue;
|
||||||
|
14
pattern2.cpp
14
pattern2.cpp
@ -343,7 +343,7 @@ int fieldval_uniq(cell *c) {
|
|||||||
auto p = cell_to_pair(c);
|
auto p = cell_to_pair(c);
|
||||||
return gmod(p.first * torusconfig::dx + p.second * torusconfig::dy, torusconfig::qty);
|
return gmod(p.first * torusconfig::dx + p.second * torusconfig::dy, torusconfig::qty);
|
||||||
}
|
}
|
||||||
else if(binarytiling) return 0;
|
else if(binarytiling || syntetic) return 0;
|
||||||
if(ctof(c) || gp::on || irr::on) return c->master->fieldval/S7;
|
if(ctof(c) || gp::on || irr::on) return c->master->fieldval/S7;
|
||||||
else {
|
else {
|
||||||
int z = 0;
|
int z = 0;
|
||||||
@ -873,6 +873,11 @@ namespace patterns {
|
|||||||
si.dir = 0; si.reflect = false; si.id = ctof(c);
|
si.dir = 0; si.reflect = false; si.id = ctof(c);
|
||||||
si.symmetries = c->type;
|
si.symmetries = c->type;
|
||||||
|
|
||||||
|
if(syntetic) {
|
||||||
|
si.id = synt::id_of(c->master);
|
||||||
|
return si;
|
||||||
|
}
|
||||||
|
|
||||||
if(binarytiling) {
|
if(binarytiling) {
|
||||||
if(pat == PAT_SINGLETYPE) si.id = 0;
|
if(pat == PAT_SINGLETYPE) si.id = 0;
|
||||||
si.dir = 2;
|
si.dir = 2;
|
||||||
@ -1168,6 +1173,7 @@ int pattern_threecolor(cell *c) {
|
|||||||
bool pseudohept(cell *c) {
|
bool pseudohept(cell *c) {
|
||||||
if(irr::on) return irr::pseudohept(c);
|
if(irr::on) return irr::pseudohept(c);
|
||||||
if(binarytiling) return c->type & c->master->distance & 1;
|
if(binarytiling) return c->type & c->master->distance & 1;
|
||||||
|
if(syntetic) return synt::id_of(c->master) < 2 * isize(synt::faces);
|
||||||
if(gp::on && gp_threecolor() == 2)
|
if(gp::on && gp_threecolor() == 2)
|
||||||
return gp::pseudohept_val(c) == 0;
|
return gp::pseudohept_val(c) == 0;
|
||||||
if(gp::on && gp_threecolor() == 1 && (S7&1) && (S3 == 3))
|
if(gp::on && gp_threecolor() == 1 && (S7&1) && (S3 == 3))
|
||||||
@ -2075,6 +2081,12 @@ namespace linepatterns {
|
|||||||
col,
|
col,
|
||||||
1 + vid.linequality);
|
1 + vid.linequality);
|
||||||
}
|
}
|
||||||
|
else if(syntetic) {
|
||||||
|
if(!pseudohept(c)) for(int i=0; i<c->type; i++) if(c->mov[i] && c < c->mov[i] && !pseudohept(c->mov[i]) && gmatrix.count(c->mov[i]))
|
||||||
|
queuelinef(tC0(V), gmatrix[c->mov[i]]*C0,
|
||||||
|
col,
|
||||||
|
1 + vid.linequality);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
int a = emeraldval(c);
|
int a = emeraldval(c);
|
||||||
if(pseudohept(c) && a/4 == 8) for(int i=0; i<7; i++) {
|
if(pseudohept(c) && a/4 == 8) for(int i=0; i<7; i++) {
|
||||||
|
@ -3375,6 +3375,7 @@ transmatrix calc_relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(binarytiling) return binary::relative_matrix(c2->master, c1->master);
|
if(binarytiling) return binary::relative_matrix(c2->master, c1->master);
|
||||||
|
if(syntetic) return synt::relative_matrix(c2->master, c1->master);
|
||||||
|
|
||||||
if(torus) {
|
if(torus) {
|
||||||
transmatrix t = Id;
|
transmatrix t = Id;
|
||||||
|
666
syntetic.cpp
Normal file
666
syntetic.cpp
Normal file
@ -0,0 +1,666 @@
|
|||||||
|
namespace hr {
|
||||||
|
|
||||||
|
namespace synt {
|
||||||
|
|
||||||
|
int indent;
|
||||||
|
|
||||||
|
struct indenter {
|
||||||
|
indenter() { indent += 2; }
|
||||||
|
~indenter() { indent -= 2; }
|
||||||
|
};
|
||||||
|
|
||||||
|
void doindent() { fflush(stdout); for(int i=0; i<indent; i++) printf(" "); }
|
||||||
|
|
||||||
|
bool do_sdebug = false;
|
||||||
|
|
||||||
|
#define SDEBUG(x) if(do_sdebug) { doindent(); x; fflush(stdout); }
|
||||||
|
|
||||||
|
// Marek-snub
|
||||||
|
vector<int> faces = {3, 6, 6, 6};
|
||||||
|
vector<int> adj = {1, 0, 2, 3};
|
||||||
|
vector<bool> invert = {false, false, true, false};
|
||||||
|
|
||||||
|
/*
|
||||||
|
vector<int> faces = {3, 6, 6, 6};
|
||||||
|
vector<int> adj = {1, 0, 2, 3};
|
||||||
|
vector<bool> invert = {false, false, false, false};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
vector<int> faces = {7, 6, 6};
|
||||||
|
vector<int> adj = {1, 0, 2};
|
||||||
|
vector<bool> invert = {false, false, false};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
vector<int> faces = {8, 8, 8};
|
||||||
|
vector<int> adj = {0, 1, 2};
|
||||||
|
vector<bool> invert = {false, false, false};
|
||||||
|
*/
|
||||||
|
|
||||||
|
int repetition = 1;
|
||||||
|
int N;
|
||||||
|
|
||||||
|
vector<vector<pair<int, int>>> adjacent;
|
||||||
|
|
||||||
|
vector<vector<pair<ld, ld>>> triangles;
|
||||||
|
|
||||||
|
// id of vertex in the syntetic tiling
|
||||||
|
// odd numbers = reflected tiles
|
||||||
|
// 0, 2, ..., 2(N-1) = as in the symbol
|
||||||
|
// 2N = bitruncated tile
|
||||||
|
|
||||||
|
short& id_of(heptagon *h) {
|
||||||
|
return h->zebraval;
|
||||||
|
}
|
||||||
|
|
||||||
|
// which index in id_of's neighbor list does h->move[0] have
|
||||||
|
|
||||||
|
short& parent_index_of(heptagon *h) {
|
||||||
|
return h->emeraldval;
|
||||||
|
}
|
||||||
|
|
||||||
|
// total number of neighbors
|
||||||
|
|
||||||
|
int neighbors_of(heptagon *h) {
|
||||||
|
return isize(triangles[id_of(h)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// right_sibling_of(h) has the same distance ('right sibling'), then we have some at smaller or equal distance,
|
||||||
|
// parents_of(h) has the same distance again ('left sibling'), and then we have vertices at bigger distance,
|
||||||
|
// who are our 'children' except the rightmost one which is typically a child of the right sibling
|
||||||
|
|
||||||
|
short& right_sibling_of(heptagon *h) {
|
||||||
|
return h->fiftyval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parents_of(heptagon *h) {
|
||||||
|
return h->s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int children_of(heptagon *h) {
|
||||||
|
return right_sibling_of(h) - 1 - parents_of(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
ld edgelength;
|
||||||
|
vector<ld> inradius, circumradius, alphas;
|
||||||
|
|
||||||
|
void prepare() {
|
||||||
|
|
||||||
|
/* build the 'adjacent' table */
|
||||||
|
|
||||||
|
N = isize(faces);
|
||||||
|
adjacent.clear();
|
||||||
|
adjacent.resize(2*N+2);
|
||||||
|
for(int i=0; i<N; i++) {
|
||||||
|
for(int oi=0; oi<1; oi++) {
|
||||||
|
int at = (i+oi)%N;
|
||||||
|
int inv = oi;
|
||||||
|
printf("vertex ");
|
||||||
|
for(int z=0; z<faces[i]; z++) {
|
||||||
|
printf("[%d %d] " , at, inv);
|
||||||
|
adjacent[2*i+oi].emplace_back(2*N+int(inv), inv ? (2*at+2*N-2) % (2*N) : 2*at);
|
||||||
|
if(invert[at]) inv ^= 1;
|
||||||
|
at = adj[at];
|
||||||
|
if(inv) at = (at+1) % N;
|
||||||
|
else at = (at+N-1) % N;
|
||||||
|
}
|
||||||
|
printf("-> [%d %d]\n", at, inv);
|
||||||
|
if(faces[at] != faces[i]) printf("error!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int i=0; i<N; i++) {
|
||||||
|
adjacent[2*N].emplace_back(2*i, 0);
|
||||||
|
int ai = (i+1) % N;
|
||||||
|
adjacent[2*N].emplace_back(2*N+int(invert[ai]), (2*adj[ai]+2*N-1) % (2*N));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<2*N+2; i++) {
|
||||||
|
printf("prelim adjacent %2d:", i);
|
||||||
|
for(int j=0; j<isize(adjacent[i]); j++) {
|
||||||
|
auto p = adjacent[i][j];
|
||||||
|
printf(" (%d,%d)", p.first, p.second);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int d=0; d<=2*N; d+=2) {
|
||||||
|
int s = isize(adjacent[d]);
|
||||||
|
for(int i=0; i<s; i++) {
|
||||||
|
auto& orig = adjacent[d][s-1-i];
|
||||||
|
adjacent[d+1].emplace_back(orig.first ^ 1, orig.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int d=0; d<2*N+2; d++) {
|
||||||
|
int s = isize(adjacent[d]);
|
||||||
|
for(int i=0; i<s; i++) {
|
||||||
|
auto& orig = adjacent[d][i];
|
||||||
|
if(orig.first & 1) orig.second = isize(adjacent[orig.first]) - 1 - orig.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<2*N+2; i++) {
|
||||||
|
printf("adjacent %2d:", i);
|
||||||
|
for(int j=0; j<isize(adjacent[i]); j++) {
|
||||||
|
auto p = adjacent[i][j];
|
||||||
|
printf(" (%d,%d)", p.first, p.second);
|
||||||
|
auto q = adjacent[p.first][p.second];
|
||||||
|
printf(" <%d,%d>", q.first, q.second);
|
||||||
|
if(isize(adjacent[q.first]) != isize(adjacent[i])) printf(" {error}");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* verify all the triangles */
|
||||||
|
for(int i=0; i<2*N+2; i++) {
|
||||||
|
for(int j=0; j<isize(adjacent[i]); j++) {
|
||||||
|
int ai = i, aj = j;
|
||||||
|
printf("triangle ");
|
||||||
|
for(int s=0; s<3; s++) {
|
||||||
|
printf("[%d %d] ", ai, aj); fflush(stdout);
|
||||||
|
tie(ai, aj) = adjacent[ai][aj];
|
||||||
|
aj++; if(aj >= isize(adjacent[ai])) aj = 0;
|
||||||
|
}
|
||||||
|
printf("-> [%d %d]\n", ai, aj);
|
||||||
|
if(isize(adjacent[ai]) != isize(adjacent[i])) printf("error!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ld sum = 0;
|
||||||
|
for(int f: faces) sum += (f-2.) / f;
|
||||||
|
if(sum < 1.999999) ginf[gSyntetic].cclass = gcSphere;
|
||||||
|
else if(sum > 2.000001) ginf[gSyntetic].cclass = gcHyperbolic;
|
||||||
|
else ginf[gSyntetic].cclass = gcEuclid;
|
||||||
|
|
||||||
|
printf("sum = %lf\n", double(sum));
|
||||||
|
|
||||||
|
dynamicval<eGeometry> dv(geometry, gSyntetic);
|
||||||
|
|
||||||
|
/* compute the geometry */
|
||||||
|
inradius.resize(N);
|
||||||
|
circumradius.resize(N);
|
||||||
|
alphas.resize(N);
|
||||||
|
ld elmin = 0, elmax = hyperbolic ? 10 : sphere ? M_PI : 1;
|
||||||
|
for(int p=0; p<100; p++) {
|
||||||
|
edgelength = (elmin + elmax) / 2;
|
||||||
|
|
||||||
|
ld alpha_total = 0;
|
||||||
|
|
||||||
|
for(int i=0; i<N; i++) {
|
||||||
|
ld crmin = 0, crmax = sphere ? M_PI : 10;
|
||||||
|
for(int q=0; q<100; q++) {
|
||||||
|
circumradius[i] = (crmin + crmax) / 2;
|
||||||
|
hyperpoint p1 = xpush(circumradius[i]) * C0;
|
||||||
|
hyperpoint p2 = spin(2 * M_PI / faces[i]) * p1;
|
||||||
|
inradius[i] = hdist0(mid(p1, p2));
|
||||||
|
if(hdist(p1, p2) > edgelength) crmax = circumradius[i];
|
||||||
|
else crmin = circumradius[i];
|
||||||
|
}
|
||||||
|
hyperpoint h = xpush(edgelength/2) * spin(M_PI/2) * xpush(inradius[i]) * C0;
|
||||||
|
alphas[i] = atan2(-h[1], h[0]);
|
||||||
|
alpha_total += alphas[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("el = %lf alpha = %lf\n", double(edgelength), double(alpha_total));
|
||||||
|
|
||||||
|
if(sphere ^ (alpha_total > M_PI)) elmin = edgelength;
|
||||||
|
else elmax = edgelength;
|
||||||
|
if(euclid) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("computed edgelength = %lf\n", double(edgelength));
|
||||||
|
|
||||||
|
triangles.clear();
|
||||||
|
triangles.resize(2*N+2);
|
||||||
|
for(int i=0; i<N; i++) for(int j=0; j<2; j++)
|
||||||
|
for(int k=0; k<faces[i]; k++)
|
||||||
|
triangles[2*i+j].emplace_back(2*M_PI/faces[i], circumradius[i]);
|
||||||
|
|
||||||
|
for(int k=0; k<N; k++) {
|
||||||
|
triangles[2*N].emplace_back(alphas[k], circumradius[k]);
|
||||||
|
triangles[2*N].emplace_back(alphas[(k+1)%N], edgelength);
|
||||||
|
triangles[2*N+1].emplace_back(alphas[N-1-k], edgelength);
|
||||||
|
triangles[2*N+1].emplace_back(alphas[N-1-k], circumradius[N-1-k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& ts: triangles) {
|
||||||
|
ld total = 0;
|
||||||
|
for(auto& t: ts) tie(t.first, total) = make_pair(total, total + t.first);
|
||||||
|
// printf("total = %lf\n", double(total));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& ts: triangles) {
|
||||||
|
printf("T");
|
||||||
|
for(auto& t: ts) printf(" %lf@%lf", double(t.first), double(t.second));
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(heptagon *h) {
|
||||||
|
|
||||||
|
prepare();
|
||||||
|
|
||||||
|
/* initialize the root */
|
||||||
|
|
||||||
|
parent_index_of(h) = 0;
|
||||||
|
id_of(h) = 0;
|
||||||
|
h->c7 = newCell(isize(adjacent[0]), h);
|
||||||
|
|
||||||
|
if(sphere) celllister cl(h->c7, 1000, 1000000, NULL);
|
||||||
|
|
||||||
|
/* test */
|
||||||
|
SDEBUG(
|
||||||
|
printf("started testing\n");
|
||||||
|
heptagon *htest = h;
|
||||||
|
for(int i=0; i<10000; i++)
|
||||||
|
htest = createStep(htest, hrand(neighbors_of(htest)));
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
void verify_distance_delta(heptagon *h, int d, int delta) {
|
||||||
|
if(!h->move[d]) return;
|
||||||
|
if(h->move[d]->distance != h->distance + delta) {
|
||||||
|
SDEBUG( printf("ERROR: delta %p.%d (%d/%d)\n", h, d, h->move[d]->distance, h->distance + delta); )
|
||||||
|
// exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug(heptagon *h) {
|
||||||
|
auto& p = adjacent[id_of(h)];
|
||||||
|
if(h->s == hsOrigin) {
|
||||||
|
for(int i=0; i<isize(p); i++) verify_distance_delta(h, i, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int first = h->s + 1;
|
||||||
|
verify_distance_delta(h, 0, -1);
|
||||||
|
verify_distance_delta(h, first-2, -1);
|
||||||
|
verify_distance_delta(h, first-1, 0);
|
||||||
|
verify_distance_delta(h, isize(p)-1, 0);
|
||||||
|
for(int d=first; d<isize(p)-1; d++) verify_distance_delta(h, d, 1);
|
||||||
|
for(int d=0; d<isize(p); d++) if(h->move[d]) {
|
||||||
|
auto& p = adjacent[id_of(h)];
|
||||||
|
auto uv = p[(parent_index_of(h) + d) % isize(p)];
|
||||||
|
if(neighbors_of(h->move[d]) != isize(adjacent[uv.first])) {
|
||||||
|
SDEBUG( printf("neighbors mismatch at %p/%d->%p: is %d expected %d\n", h, d, h->move[d], neighbors_of(h->move[d]), isize(adjacent[uv.first])); )
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
heptagon *build_child(heptagon *parent, int d, int id, int pindex) {
|
||||||
|
indenter ind;
|
||||||
|
auto h = buildHeptagon(parent, d, hstate(1), 0);
|
||||||
|
id_of(h) = id;
|
||||||
|
parent_index_of(h) = pindex;
|
||||||
|
int nei = neighbors_of(h);
|
||||||
|
right_sibling_of(h) = nei - 1;
|
||||||
|
h->distance = parent->distance + 1;
|
||||||
|
h->c7 = newCell(nei, h);
|
||||||
|
SDEBUG( printf("%p.%d/%d ~ %p.0/%d (state=1/NEW,id=%d,pindex=%d,distance=%d)\n", parent, d, neighbors_of(parent), h, neighbors_of(h), id, pindex, h->distance); )
|
||||||
|
debug(h); debug(parent);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connectHeptagons(heptagon *h, int i, heptspin hs) {
|
||||||
|
indenter ind;
|
||||||
|
SDEBUG( printf("%p.%d/%d ~ %p.%d/%d (state=%d,id=%d,pindex=%d,distance=%d)\n", h, i, neighbors_of(h), hs.h, hs.spin, neighbors_of(hs.h),
|
||||||
|
hs.h->s, id_of(hs.h), parent_index_of(hs.h), hs.h->distance); )
|
||||||
|
if(h->move[i] == hs.h && h->spin(i) == hs.spin) {
|
||||||
|
SDEBUG( printf("WARNING: already connected\n"); )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(h->move[i]) {
|
||||||
|
SDEBUG( printf("ERROR: already connected left to: %p not %p\n", h->move[i], hs.h); )
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(hs.h->move[hs.spin]) {
|
||||||
|
SDEBUG( printf("ERROR: already connected right to: %p not %p\n", hs.h->move[hs.spin], h); )
|
||||||
|
exit(1);
|
||||||
|
// exit(1);
|
||||||
|
}
|
||||||
|
hr::connectHeptagons(h, i, hs.h, hs.spin);
|
||||||
|
debug(h);
|
||||||
|
debug(hs.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
int prune(heptagon*& h) {
|
||||||
|
int result = 1;
|
||||||
|
int n = neighbors_of(h);
|
||||||
|
auto h0 = h;
|
||||||
|
SDEBUG( printf("pruning: %p\n", h0); )
|
||||||
|
for(int i=0; i<n; i++)
|
||||||
|
if(h0->move[i]) {
|
||||||
|
if(h0->spin(i) == 0)
|
||||||
|
result += prune(h0->move[i]);
|
||||||
|
else {
|
||||||
|
h0->move[i]->move[h0->spin(i)] = NULL;
|
||||||
|
h0->move[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete h0->c7;
|
||||||
|
delete h0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void contract(heptagon *h) {
|
||||||
|
switch(children_of(h)) {
|
||||||
|
case 0: {
|
||||||
|
SDEBUG( printf("handling contraction (0) at %p\n", h); )
|
||||||
|
heptspin right = heptspin(h, right_sibling_of(h)) + wstep + 1;
|
||||||
|
heptspin left = heptspin(h, parents_of(h)) + wstep - 1;
|
||||||
|
connectHeptagons(right.h, right.spin, left);
|
||||||
|
right.h->s++;
|
||||||
|
right_sibling_of(left.h)--;
|
||||||
|
contract(right.h);
|
||||||
|
contract(left.h);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case -1: {
|
||||||
|
SDEBUG( printf("handling contraction (-1) at %p\n", h); )
|
||||||
|
indenter ind2;
|
||||||
|
heptspin hs0(h, neighbors_of(h)-1);
|
||||||
|
heptspin hs = hs0;
|
||||||
|
hs = hs + 1 + wstep + 1;
|
||||||
|
while(hs.spin == neighbors_of(hs.h) - 1) {
|
||||||
|
SDEBUG( printf("hsr at %p.%d/%d (%d parents)\n", hs.h, hs.spin, neighbors_of(hs.h), parents_of(hs.h)); )
|
||||||
|
hs = hs + wstep + 1;
|
||||||
|
}
|
||||||
|
SDEBUG( printf("hsr at %p.%d/%d (%d parents)\n", hs.h, hs.spin, neighbors_of(hs.h), parents_of(hs.h)); )
|
||||||
|
heptspin correct = hs + wstep;
|
||||||
|
SDEBUG( printf("correct is: %p.%d/%d (%d parents)\n", correct.h, correct.spin, neighbors_of(correct.h), parents_of(correct.h)); )
|
||||||
|
heptspin hsl = hs0;
|
||||||
|
correct = correct+1; correct.h->s++;
|
||||||
|
connectHeptagons(hsl.h, hsl.spin, correct);
|
||||||
|
hsl = hsl - 1 + wstep - 1;
|
||||||
|
while(true) {
|
||||||
|
SDEBUG( printf("hsl at %p.%d/%d (%d parents)\n", hsl.h, hsl.spin, neighbors_of(hsl.h), parents_of(hsl.h)); )
|
||||||
|
if(hsl.spin == parents_of(hsl.h)) {
|
||||||
|
SDEBUG(printf("go left\n"))
|
||||||
|
hsl = hsl + wstep - 1;
|
||||||
|
}
|
||||||
|
else if(hsl.h->move[hsl.spin] && hsl.h->move[hsl.spin] != correct.h) {
|
||||||
|
SDEBUG(printf("prune\n");)
|
||||||
|
if(neighbors_of(hsl.h->move[hsl.spin]) != neighbors_of(correct.h)) {
|
||||||
|
SDEBUG(printf("neighbors mismatch while pruning %d -> %d\n",
|
||||||
|
neighbors_of(hsl.h->move[hsl.spin]),
|
||||||
|
neighbors_of(correct.h)
|
||||||
|
);)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
prune(hsl.h->move[hsl.spin]);
|
||||||
|
}
|
||||||
|
else if(hsl.h->move[hsl.spin] == NULL) {
|
||||||
|
correct = correct+1; correct.h->s++;
|
||||||
|
SDEBUG( printf("connect\n") )
|
||||||
|
connectHeptagons(hsl.h, hsl.spin, correct);
|
||||||
|
}
|
||||||
|
else if(hsl.spin == parents_of(hsl.h)+1) {
|
||||||
|
SDEBUG( printf("single child so go left\n") )
|
||||||
|
hsl = hsl - 1 + wstep - 1;
|
||||||
|
}
|
||||||
|
else { SDEBUG( printf("ready\n"); ) break; }
|
||||||
|
}
|
||||||
|
contract(correct.h);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case -2: {
|
||||||
|
SDEBUG( printf("ERROR: contraction (-2) not handled\n"); )
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!sphere) for(int i=0; i<neighbors_of(h); i++) if(!h->move[i]) {
|
||||||
|
auto uv = adjacent[id_of(h)][(parent_index_of(h) + i) % neighbors_of(h)];
|
||||||
|
if(isize(adjacent[uv.first]) < 6) {
|
||||||
|
SDEBUG( printf("prebuilding weak neighbor\n") )
|
||||||
|
createStep(h, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void build_siblings(heptagon *h, int x) {
|
||||||
|
for(int i=right_sibling_of(h); i<neighbors_of(h); i++) createStep(h, i);
|
||||||
|
for(int i=0; i<=parents_of(h); i++) createStep(h, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_adjacent(heptagon *h, int d) {
|
||||||
|
indenter ind;
|
||||||
|
int nei = neighbors_of(h);
|
||||||
|
|
||||||
|
if(h->s == 0) {
|
||||||
|
auto& p = adjacent[id_of(h)];
|
||||||
|
for(int i=0; i<nei; i++)
|
||||||
|
build_child(h, i, p[i].first, p[i].second);
|
||||||
|
for(int i=0; i<nei; i++) {
|
||||||
|
heptagon *h1 = h->move[i];
|
||||||
|
heptagon *h2 = h->move[(i+nei-1)%nei];
|
||||||
|
connectHeptagons(h1, 1, heptspin(h2, isize(adjacent[id_of(h2)])-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
int first = h->s + 1;
|
||||||
|
SDEBUG( printf("h=%p dist=%d d=%d/%d s=%d id=%d pindex=%d\n",
|
||||||
|
h, h->distance, d, nei, h->s, id_of(h), parent_index_of(h)); )
|
||||||
|
indenter ind2;
|
||||||
|
|
||||||
|
// these vertices are not children (or possibly contractions)
|
||||||
|
if(d < first || d > right_sibling_of(h))
|
||||||
|
connectHeptagons(h, d, heptspin(h, d-1) + wstep - 1 + wstep - 1);
|
||||||
|
else if(d == right_sibling_of(h)) {
|
||||||
|
connectHeptagons(h, d, heptspin(h, 0) + wstep + 1 + wstep + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
build_siblings(h, 10);
|
||||||
|
build_siblings(h, -10);
|
||||||
|
if(h->move[d]) return;
|
||||||
|
heptspin hs(h, d);
|
||||||
|
// make sure no contractions on the left
|
||||||
|
heptspin hsl(h, d);
|
||||||
|
int steps = 0;
|
||||||
|
while(hsl.spin == parents_of(hsl.h) + 1 && steps < 100) {
|
||||||
|
hsl = hsl - 1 + wstep - 1;
|
||||||
|
steps++;
|
||||||
|
}
|
||||||
|
if(steps == 100) {
|
||||||
|
SDEBUG( printf("generating top\n"); )
|
||||||
|
auto uv = adjacent[id_of(hs.h)][(parent_index_of(hs.h) + hs.spin) % neighbors_of(hs.h)];
|
||||||
|
heptagon *newchild = build_child(hs.h, hs.spin, uv.first, uv.second);
|
||||||
|
hs = hs - 1 + wstep - 1;
|
||||||
|
while(hs.h != h) {
|
||||||
|
newchild->s++;
|
||||||
|
connectHeptagons(hs.h, hs.spin, heptspin(newchild, newchild->s-1));
|
||||||
|
hs = hs - 1 + wstep - 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// while trying to generate the last child, go right
|
||||||
|
while(true) {
|
||||||
|
if(h->move[d]) {
|
||||||
|
SDEBUG( printf("solved itself\n"); )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SDEBUG( printf("going right at %p.%d/%d parents = %d\n", hs.h, hs.spin, neighbors_of(hs.h), parents_of(hs.h)); )
|
||||||
|
// rightmost child
|
||||||
|
if(hs.spin == right_sibling_of(hs.h) - 1)
|
||||||
|
hs = hs + 1 + wstep + 1;
|
||||||
|
else if(children_of(hs.h) <= 0) {
|
||||||
|
SDEBUG( printf("unexpected situation\n"); )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
auto uv = adjacent[id_of(hs.h)][(parent_index_of(hs.h) + hs.spin) % neighbors_of(hs.h)];
|
||||||
|
heptagon *newchild = build_child(hs.h, hs.spin, uv.first, uv.second);
|
||||||
|
bool add_parent = false;
|
||||||
|
while(true) {
|
||||||
|
SDEBUG( printf("going left at %p.%d/%d parents = %d\n", hs.h, hs.spin, neighbors_of(hs.h), parents_of(hs.h)); )
|
||||||
|
// add parent
|
||||||
|
if(hs.spin > parents_of(hs.h) && add_parent) {
|
||||||
|
SDEBUG( printf("add parent\n"); )
|
||||||
|
newchild->s++;
|
||||||
|
connectHeptagons(hs.h, hs.spin, heptspin(newchild, newchild->s-1));
|
||||||
|
add_parent = false;
|
||||||
|
}
|
||||||
|
// childless
|
||||||
|
if(children_of(hs.h) <= 0) {
|
||||||
|
SDEBUG( printf("unexpected situation v2\n"); )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// lefmost child
|
||||||
|
else if(hs.spin == parents_of(hs.h)+1) {
|
||||||
|
SDEBUG( printf("(leftmost child)\n"); )
|
||||||
|
hs = hs - 1 + wstep - 1;
|
||||||
|
add_parent = true;
|
||||||
|
}
|
||||||
|
// no more parents
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
contract(newchild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
set<heptagon*> visited;
|
||||||
|
queue<pair<heptagon*, transmatrix>> drawqueue;
|
||||||
|
|
||||||
|
void enqueue(heptagon *h, const transmatrix& T) {
|
||||||
|
if(visited.count(h)) { return; }
|
||||||
|
visited.insert(h);
|
||||||
|
drawqueue.emplace(h, T);
|
||||||
|
}
|
||||||
|
|
||||||
|
transmatrix adjcell_matrix(heptagon *h, int d) {
|
||||||
|
int S = neighbors_of(h);
|
||||||
|
int pindex = parent_index_of(h);
|
||||||
|
int id = id_of(h);
|
||||||
|
auto& t1 = triangles[id][(pindex + d)%S];
|
||||||
|
|
||||||
|
heptagon *h2 = h->move[d];
|
||||||
|
|
||||||
|
int d2 = h->spin(d);
|
||||||
|
int id2 = id_of(h2);
|
||||||
|
int pindex2 = parent_index_of(h2);
|
||||||
|
auto& t2 = triangles[id2][(pindex2 + d2) % neighbors_of(h2)];
|
||||||
|
|
||||||
|
// * spin(-tri[id][pi+i].first) * xpush(t.second) * pispin * spin(tri[id'][p'+d'].first)
|
||||||
|
|
||||||
|
return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw() {
|
||||||
|
visited.clear();
|
||||||
|
enqueue(viewctr.h, cview());
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
while(!drawqueue.empty()) {
|
||||||
|
auto p = drawqueue.front();
|
||||||
|
drawqueue.pop();
|
||||||
|
heptagon *h = p.first;
|
||||||
|
transmatrix V = p.second;
|
||||||
|
int id = id_of(h);
|
||||||
|
int S = isize(triangles[id]);
|
||||||
|
|
||||||
|
if(!nonbitrunc || id < 2*N) {
|
||||||
|
if(!dodrawcell(h->c7)) continue;
|
||||||
|
drawcell(h->c7, V, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<S; i++) {
|
||||||
|
if(nonbitrunc && id >= 2*N && h->move[i] && id_of(h->move[i]) >= 2*N) continue;
|
||||||
|
enqueue(h->move[i], V * adjcell_matrix(h, i));
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else 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(adjacent[id_of(h)]);
|
||||||
|
spin %= type;
|
||||||
|
if(spin < 0) spin += type;
|
||||||
|
return spin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_symbol(string s) {
|
||||||
|
int at = 0;
|
||||||
|
|
||||||
|
auto peek = [&] () { if(at == isize(s)) return char(0); else return s[at]; };
|
||||||
|
auto isnumber = [&] () { char p = peek(); return p >= '0' && p <= '9'; };
|
||||||
|
auto read_number = [&] () { int result = 0; while(isnumber()) result = 10 * result + peek() - '0', at++; return result; };
|
||||||
|
|
||||||
|
faces.clear();
|
||||||
|
while(true) {
|
||||||
|
if(peek() == ')' || peek() == '^' || (peek() == '(' && isize(faces)) || peek() == 0) break;
|
||||||
|
else if(isnumber()) faces.push_back(read_number());
|
||||||
|
else at++;
|
||||||
|
}
|
||||||
|
repetition = 1;
|
||||||
|
N = isize(faces);
|
||||||
|
invert.clear(); invert.resize(N, 0);
|
||||||
|
adj.clear(); adj.resize(N, 0); for(int i=0; i<N; i++) adj[i] = i;
|
||||||
|
while(peek() != 0) {
|
||||||
|
if(peek() == '^') at++, repetition = read_number();
|
||||||
|
else if(peek() == '(') {
|
||||||
|
at++; int a = read_number(); while(!isnumber() && !among(peek(), '(', '[', ')',']', 0)) at++;
|
||||||
|
if(isnumber()) { int b = read_number(); adj[a] = b; adj[b] = a; }
|
||||||
|
}
|
||||||
|
else if(peek() == '[') {
|
||||||
|
at++; int a = read_number(); while(!isnumber() && !among(peek(), '(', '[', ')',']', 0)) at++;
|
||||||
|
if(isnumber()) { int b = read_number(); adj[a] = b; adj[b] = a; invert[a] = invert[b] = true; }
|
||||||
|
else { invert[a] = true; }
|
||||||
|
}
|
||||||
|
else at++;
|
||||||
|
}
|
||||||
|
prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CAP_COMMANDLINE
|
||||||
|
int readArgs() {
|
||||||
|
using namespace arg;
|
||||||
|
|
||||||
|
if(0) ;
|
||||||
|
else if(argis("-symbol")) {
|
||||||
|
targetgeometry = gSyntetic;
|
||||||
|
if(targetgeometry != geometry)
|
||||||
|
stop_game_and_switch_mode(rg::geometry);
|
||||||
|
showstartmenu = false;
|
||||||
|
shift(); parse_symbol(args());
|
||||||
|
}
|
||||||
|
else if(argis("-sd")) do_sdebug = true;
|
||||||
|
else return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if CAP_COMMANDLINE
|
||||||
|
auto hook =
|
||||||
|
addHook(hooks_args, 100, readArgs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user