rewritten the Euclidean geometry

This commit is contained in:
Zeno Rogue 2019-11-27 01:01:20 +01:00
parent aed8df0d04
commit 1cba452f07
25 changed files with 484 additions and 1366 deletions

View File

@ -439,7 +439,7 @@ void connectHeptagons(heptspin hi, heptspin hs);
transmatrix adjcell_matrix(heptagon *h, int d);
struct hrmap_archimedean : hrmap {
map<int, struct cdata> eucdata;
map<gp::loc, struct cdata> eucdata;
heptagon *origin;
heptagon *getOrigin() { return origin; }
@ -559,8 +559,11 @@ struct hrmap_archimedean : hrmap {
U = U * inverse(T);
}
if(euclid)
alt = encodeId(pair_to_vec(int(T[0][LDIM]), int(T[1][LDIM])));
if(euclid) {
/* hash the rough coordinates as heptagon* alt */
size_t s = size_t(T[0][LDIM]+.261) * 124101 + size_t(T[1][LDIM]+.261) * 82143;
alt = (heptagon*) s;
}
DEBB(DF_GEOM, ("look for: ", alt, " / ", T * C0));
@ -1361,7 +1364,7 @@ EX int valence() {
#endif
EX map<int, cdata>& get_cdata() { return ((arcm::hrmap_archimedean*) (currentmap))->eucdata; }
EX map<gp::loc, cdata>& get_cdata() { return ((arcm::hrmap_archimedean*) (currentmap))->eucdata; }
}
}

View File

@ -51,7 +51,7 @@ EX int celldistAltRelative(cell *c) {
#if MAXMDIM >= 4
if(euclid && WDIM == 3) return euclid3::dist_relative(c);
#endif
if(euwrap) return celldistAlt(c) - roundTableRadius(c);
if(euclid && quotient) return celldistAlt(c) - roundTableRadius(c);
if(sphere || quotient) {
return celldist(c) - 3;
}
@ -88,15 +88,14 @@ EX int euclidAlt(short x, short y) {
EX int cylinder_alt(cell *c) {
if(specialland == laPrincessQuest)
return celldistance(c, vec_to_cellwalker(pair_to_vec(EPX, EPY)).at);
return celldistance(c, at_euc2_coordinates({EPX, EPY}));
if(specialland == laCamelot)
return celldistance(c, vec_to_cellwalker(pair_to_vec(21, 10)).at);
return celldistance(c, at_euc2_coordinates({21, 10}));
using namespace torusconfig;
int maxmul = 0;
for(int d = 0; d < SG6; d++)
maxmul = max(maxmul, dcross(sdxy(), gp::eudir(d)));
return 5-abs(gdiv(dcross(sdxy(), cell_to_pair(c)), maxmul));
return 5-abs(gdiv(dcross(sdxy(), euc2_coordinates(c)), maxmul));
}
const int NOCOMPASS = 1000000;
@ -876,7 +875,7 @@ EX void setLandSphere(cell *c) {
int y = getHemisphere(c, 2);
elementalXY(c, x, y, (c->type != 6 || GOLDBERG));
}
if(!euwrap)
if(!(euclid && quotient))
if(specialland == laCrossroads || specialland == laCrossroads2 || specialland == laCrossroads3 || specialland == laTerracotta) {
int x = getHemisphere(c, 1);
if(x == 0 && specialland == laTerracotta)
@ -1093,17 +1092,17 @@ EX void setLandEuclid(cell *c) {
setland(c, specialland);
if(specialland == laCrossroads4 || chaosmode) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
c->land = getEuclidLand(y);
}
if(specialland == laCrossroads) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
setland(c, getEuclidLand(y+2*x));
}
if(specialland == laTerracotta) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
if(((y+2*x) & 15) == 1) {
setland(c, laMercuryRiver);
c->wall = waMercury;
@ -1116,9 +1115,9 @@ EX void setLandEuclid(cell *c) {
if(specialland == laPrincessQuest) setland(c, laPalace);
if(specialland == laOcean) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
y += 10;
if(euwrap) y = -celldistAlt(c);
if(euclid && quotient) y = -celldistAlt(c);
if(y == 0)
{ setland(c, laBarrier); if(ishept(c)) c->land = laRlyeh; }
else if(y<0) setland(c, laRlyeh);
@ -1126,7 +1125,7 @@ EX void setLandEuclid(cell *c) {
}
if(specialland == laWestWall) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
x = -5 - x;
if(x == 0)
{setland(c, laBarrier); if(ishept(c)) setland(c, laMotion); }
@ -1135,9 +1134,9 @@ EX void setLandEuclid(cell *c) {
}
if(specialland == laIvoryTower || specialland == laDungeon) {
int x, y;
tie(x,y) = cell_to_pair(c); y = -5 - y;
tie(x,y) = euc2_coordinates(c); y = -5 - y;
if(specialland == laDungeon) y = -10 - y;
if(euwrap) y = -celldistAlt(c);
if(euclid && quotient) y = -celldistAlt(c);
if(y == 0)
{setland(c, laBarrier); if(ishept(c)) setland(c, laAlchemist); }
else if(y<0) setland(c, laAlchemist);
@ -1147,7 +1146,7 @@ EX void setLandEuclid(cell *c) {
}
if(specialland == laElementalWall) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
int x0 = euclid4 ? x : x + (y>>1);
int y0 = y;
@ -1176,7 +1175,7 @@ EX void setLandEuclid(cell *c) {
}
if(specialland == laCrossroads3) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
int y0 = euclid4 ? 2 * y - x : y;
int x0 = euclid4 ? 2 * x + y : x + y/2;
@ -1195,7 +1194,7 @@ EX void setLandEuclid(cell *c) {
}
if(specialland == laWarpCoast) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
int zz = a4 ? x : 2*x+y + 10;
zz = gmod(zz, 30);

View File

@ -175,17 +175,6 @@ EX cell *createMov(cell *c, int d) {
printf("ERROR createmov\n");
}
if(masterless && !c->move(d)) {
int id = decodeId(c->master);
for(int dx=-1; dx<=1; dx++)
for(int dy=-1; dy<=1; dy++)
euclideanAtCreate(id + pair_to_vec(dx, dy));
if(!c->move(d)) {
println(hlog, "id = ", id, " vec_to_pair(id) = ", vec_to_pair(id), ": failed to create move ", d, " in Euclidean\n");
exit(0);
}
}
if(c->move(d)) return c->move(d);
else if(hybri)
hybrid::find_cell_connection(c, d);
@ -282,14 +271,10 @@ EX void initcells() {
#if CAP_ARCM
else if(archimedean) currentmap = arcm::new_map();
#endif
#if MAXMDIM >= 4
else if(euclid && WDIM == 3) currentmap = euclid3::new_map();
#endif
else if(euclid && !penrose) currentmap = euclid3::new_map();
#if CAP_BT
else if(penrose) currentmap = kite::new_map();
#endif
else if(fulltorus) currentmap = new_torus_map();
else if(euclid) currentmap = new_euclidean_map();
#if MAXMDIM >= 4
else if(WDIM == 3 && !binarytiling) currentmap = reg3::new_map();
#endif
@ -412,7 +397,7 @@ EX void verifycell(cell *c) {
for(int i=0; i<t; i++) {
cell *c2 = c->move(i);
if(c2) {
if(!masterless && BITRUNCATED && c == c->master->c7) verifycell(c2);
if(BITRUNCATED && c == c->master->c7) verifycell(c2);
if(c2->move(c->c.spin(i)) && c2->move(c->c.spin(i)) != c) {
printf("cell error %p:%d [%d] %p:%d [%d]\n", c, i, c->type, c2, c->c.spin(i), c2->type);
exit(1);
@ -442,11 +427,6 @@ EX int eudist(int sx, int sy) {
return max(max(z0,z1), z2);
}
EX int eudist(int vec) {
auto p = vec_to_pair(vec);
return eudist(p.first, p.second);
}
EX int compdist(int dx[]) {
int mi = dx[0];
for(int u=0; u<S3; u++) mi = min(mi, dx[u]);
@ -473,13 +453,7 @@ EX int celldist(cell *c) {
hybrid::in_underlying_map([&] { d = celldist(w.first) + abs(w.second); });
return d;
}
if(fulltorus && WDIM == 2)
return get_torus_dist(decodeId(c->master));
if(nil && !quotient) return DISTANCE_UNKNOWN;
if(euwrap && WDIM == 2)
return torusconfig::cyldist(decodeId(c->master), 0);
if(masterless)
return eudist(decodeId(c->master));
if(euclid && (penrose || archimedean)) return celldistance(currentmap->gamestart(), c);
if(sphere || binarytiling || WDIM == 3 || cryst || solnih || penrose) return celldistance(currentmap->gamestart(), c);
#if CAP_IRR
@ -511,13 +485,6 @@ EX int celldistAlt(cell *c) {
hybrid::in_underlying_map([&] { d += celldistAlt(w.first); });
return d;
}
if(masterless) {
if(fulltorus) return celldist(c);
if(euwrap) return cylinder_alt(c);
int x, y;
tie(x,y) = vec_to_pair(decodeId(c->master));
return euclidAlt(x, y);
}
#if CAP_BT
if(binarytiling || solnih) return c->master->distance + (specialland == laCamelot && !tactic::on? 30 : 0);
#endif
@ -836,21 +803,15 @@ cdata *getHeptagonCdata(heptagon *h) {
return h->cdata = new cdata(mydata);
}
cdata *getEuclidCdata(int h) {
cdata *getEuclidCdata(gp::loc h) {
if(euwrap) { // fix cylinder?
static cdata xx;
return &xx;
}
int x, y;
tie(x,y) = h;
auto& data = archimedean ? arcm::get_cdata() : get_cdata();
// hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap);
if(data.count(h)) return &(data[h]);
tie(x,y) = vec_to_pair(h);
if(x == 0 && y == 0) {
cdata xx;
for(int i=0; i<4; i++) xx.val[i] = 0;
@ -867,8 +828,8 @@ cdata *getEuclidCdata(int h) {
int x2 = x - (k<2 ? ord : 0);
int y2 = y + (k>0 ? ord : 0);
cdata *d1 = getEuclidCdata(pair_to_vec(x1,y1));
cdata *d2 = getEuclidCdata(pair_to_vec(x2,y2));
cdata *d1 = getEuclidCdata({x1,y1});
cdata *d2 = getEuclidCdata({x2,y2});
cdata xx;
double disp = pow(2, bid/2.) * 6;
@ -898,9 +859,9 @@ int ld_to_int(ld x) {
return int(x + 1000000.5) - 1000000;
}
EX int pseudocoords(cell *c) {
EX gp::loc pseudocoords(cell *c) {
transmatrix T = arcm::archimedean_gmatrix[c->master].second;
return pair_to_vec(ld_to_int(T[0][LDIM]), ld_to_int((spin(60*degree) * T)[0][LDIM]));
return {ld_to_int(T[0][LDIM]), ld_to_int((spin(60*degree) * T)[0][LDIM])};
}
EX cdata *arcmCdata(cell *c) {
@ -911,7 +872,7 @@ EX cdata *arcmCdata(cell *c) {
}
EX int getCdata(cell *c, int j) {
if(masterless) return getEuclidCdata(decodeId(c->master))->val[j];
if(euclid) return getEuclidCdata(euc2_coordinates(c))->val[j];
else if(archimedean && euclid)
return getEuclidCdata(pseudocoords(c))->val[j];
else if(archimedean && hyperbolic)
@ -928,7 +889,7 @@ EX int getCdata(cell *c, int j) {
}
EX int getBits(cell *c) {
if(masterless) return getEuclidCdata(decodeId(c->master))->bits;
if(euclid) return getEuclidCdata(euc2_coordinates(c))->bits;
else if(archimedean && euclid)
return getEuclidCdata(pseudocoords(c))->bits;
else if(archimedean && (hyperbolic || sl2))
@ -1034,15 +995,6 @@ EX int celldistance(cell *c1, cell *c2) {
return d;
}
if((masterless) && (euclid6 || (euclid4 && PURE))) {
if(!euwrap)
return eudist(decodeId(c1->master) - decodeId(c2->master)); // fix cylinder
else if(euwrap && torusconfig::torus_mode == 0)
return get_torus_dist(torusconfig::vec_to_id(decodeId(c1->master)-decodeId(c2->master)));
else if(euwrap && !fulltorus)
return torusconfig::cyldist(decodeId(c1->master), decodeId(c2->master));
}
#if CAP_FIELD
if(geometry == gFieldQuotient && !GOLDBERG)
return currfp.getdist(fieldpattern::fieldval(c1), fieldpattern::fieldval(c2));
@ -1074,7 +1026,7 @@ EX int celldistance(cell *c1, cell *c2) {
if(cryst) return crystal::precise_distance(c1, c2);
#endif
if(masterless || archimedean || quotient || solnih || (penrose && euclid) || experimental || sl2 || nil) {
if(archimedean || quotient || solnih || (penrose && euclid) || experimental || sl2 || nil) {
if(saved_distances.count(make_pair(c1,c2)))
return saved_distances[make_pair(c1,c2)];
@ -1100,7 +1052,7 @@ EX int celldistance(cell *c1, cell *c2) {
#endif
#if MAXMDIM >= 4
if(euclid && WDIM == 3)
if(euclid && !penrose && !archimedean)
return euclid3::celldistance(c1, c2);
if(hyperbolic && WDIM == 3) return reg3::celldistance(c1, c2);

View File

@ -1684,7 +1684,7 @@ void celldrawer::bookkeeping() {
transmatrix& gm = gmatrix[c];
orig =
gm[LDIM][LDIM] == 0 ? true :
euwrap ? hdist0(tC0(gm)) >= hdist0(tC0(V)) :
euclid ? hdist0(tC0(gm)) >= hdist0(tC0(V)) :
(nil||sol) ? sqhypot_d(3, tC0(gm)) >= sqhypot_d(3, tC0(V)) :
sphereflipped() ? fabs(gm[LDIM][LDIM]-1) <= fabs(V[LDIM][LDIM]-1) :
fabs(gm[LDIM][LDIM]-1) >= fabs(V[LDIM][LDIM]-1) - 1e-8;
@ -1776,20 +1776,9 @@ void celldrawer::draw_cellstat() {
}
if(cmode & sm::TORUSCONFIG) {
using namespace torusconfig;
string label;
bool small;
if(tmflags() & TF_SINGLE) {
int cd = torus_cx * dx + torus_cy * newdy;
cd %= newqty; if(cd<0) cd += newqty;
label = its(cd);
small = cd;
}
else {
small = true;
label = its(torus_cx) + "," + its(torus_cy);
}
queuestr(V, small ? .2 : .6, label, small ? 0xFFFFFFD0 : 0xFFFF0040, 1);
auto p = coord_display(V, c);
if(p.second != "")
queuestr(V, p.first ? .2 : .6, p.second, p.first ? 0xFFFFFFD0 : 0xFFFF0040, 1);
}
#if CAP_EDIT
@ -2507,7 +2496,7 @@ void celldrawer::set_towerfloor(const cellfunction& cf) {
}
int j = -1;
if(masterless) j = 10;
if(euclid) j = 10;
else if(cf(c) > 1) {
int i = towerval(c, cf);
if(i == 4) j = 0;
@ -2532,7 +2521,7 @@ void celldrawer::set_towerfloor(const cellfunction& cf) {
void celldrawer::set_zebrafloor() {
if(masterless) { set_floor(cgi.shTower[10]); return; }
if(euclid) { set_floor(cgi.shTower[10]); return; }
if(weirdhyperbolic) {
set_floor(cgi.shFloor); return;
}
@ -2587,9 +2576,9 @@ void celldrawer::set_reptile_floor(const transmatrix& V, color_t col, bool nodet
else j = 4;
if(euclid6) j = 0;
transmatrix D = applyPatterndir(c, si);
transmatrix D = applyPatterndir(c, si);
if(euclid6 && GOLDBERG) D = ddspin(c, si.dir);
if(wmescher && (stdhyperbolic || euclid6))
set_floor(D, cgi.shReptile[j][0]);
else set_maywarp_floor();
@ -2631,7 +2620,7 @@ void celldrawer::set_reptile_floor(const transmatrix& V, color_t col, bool nodet
}
void celldrawer::set_emeraldfloor() {
if(!masterless && BITRUNCATED && GDIM == 2) {
if(!euclid && BITRUNCATED && GDIM == 2) {
auto si = patterns::getpatterninfo(c, patterns::PAT_EMERALD, patterns::SPF_SYM0123);
int j = -1;

View File

@ -532,7 +532,7 @@ EX geometryinfo1 giSL2 = { gcSL2, 3, 3, 4, {1,1,-1,-1} };
/** list of available geometries */
vector<geometryinfo> ginf = {
{"{7,3}", "none", "{7,3} (standard HyperRogue map)", "HR", 7, 3, 0, giHyperb2, 0, {{7, 5}}, eVariation::bitruncated},
{"{6,3}", "none", "{6,3} (euclidean Hex grid)", "euclid", 6, 3, 0, giEuclid2, 0, {{7, FORBIDDEN}}, eVariation::bitruncated},
{"{6,3}", "none", "{6,3} (euclidean Hex grid)", "euclid", 6, 3, 0, giEuclid2, 0, {{7, 7}}, eVariation::bitruncated},
{"{5,3}", "none", "{5,3} (dodecahedron)", "sphere", 5, 3, qsSMALLB, giSphere2, 0, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated},
{"{5,3}", "elliptic", "elliptic geometry in {5,3}", "elliptic", 5, 3, qsNONORE, giSphere2, 0, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated},
{"{7,3}", "Zebra", "Zebra quotient", "Zebra", 7, 3, qsZEBRA, giHyperb2, 0x00400, {{7, 5}}, eVariation::bitruncated},

View File

@ -280,7 +280,6 @@ static const flagtype qHUGE_BOUNDED = 262144;
// note: dnext assumes that x&7 equals 7
static const int SEE_ALL = 50;
static const int FORBIDDEN = -1;
extern eGeometry geometry;
extern eVariation variation;

View File

@ -15,9 +15,9 @@ EX namespace whirlwind {
EX int fzebra3(cell *c) {
if(archimedean) return 0;
if(euclid) {
if(fulltorus) return 0;
if(bounded) return 0;
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
return 1+((((signed short)(y)+int(50000))/3)%3);
}
if(S7 == 5) return getHemisphere(c, 0) > 0 ? 1 : 2;
@ -571,7 +571,7 @@ struct info {
EX int dist(cell *c) {
if(c->land != laPalace && c->land != laDungeon) return OUT_OF_PALACE;
else if(quotient || sphere || fulltorus) return OUT_OF_PRISON;
else if(quotient || sphere) return OUT_OF_PRISON;
else if(euclid) return celldistAlt(c);
else if(!c->master->alt) return OUT_OF_PRISON;
else return celldistAlt(c);
@ -866,12 +866,12 @@ EX namespace clearing {
if(quotient) return;
if(euclid) {
if(euwrap) return; // fix cylinder
if(quotient) return; // fix cylinder
if(pseudohept(c)) return;
c->monst = moMutant;
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
int xco = x * 2 + y + 1;
c->stuntime = (8-xco/2) & 15;
@ -2978,12 +2978,12 @@ EX namespace prairie {
if(chaosmode) {
c->LHU.fi.rval = 0;
}
else if(euwrap) { // fix cylinder
else if(quotient) { // fix cylinder
c->LHU.fi.rval = 0;
}
else if(euclid) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
c->LHU.fi.rval = (y&15);
}
else if(sphere) {
@ -3759,9 +3759,9 @@ EX namespace dungeon {
*/
if(euclid) {
if(euwrap) return;
if(quotient) return;
int x, y;
tie(x, y) = cell_to_pair(c);
tie(x, y) = euc2_coordinates(c);
string tab6[] = {
".####...",
"L...L...",

View File

@ -638,21 +638,13 @@ EX color_t colorize(cell *c, char whichCanvas) {
co = told(reg3::decode_coord(c->master->fieldval)), dim = 4;
for(int a=0; a<4; a++) if(co[a] > 4) co[a] -= 8;
}
else if(euclid && WDIM == 3) {
#endif
else if(euclid) {
auto tab = euclid3::getcoord(euclid3::get_ispacemap()[c->master]);
for(int a=0; a<3; a++) co[a] = tab[a];
if(PURE) for(int a=0; a<3; a++) co[a] *= 2;
dim = 3;
}
#endif
else if(masterless && !quotient) {
dim = 2;
tie(co[0], co[1]) = vec_to_pair(decodeId(c->master));
if(PURE) {
co[0] *= 2;
co[1] *= 2;
}
}
color_t res = 0;
coord ico = roundcoord(co);

File diff suppressed because it is too large Load Diff

View File

@ -179,7 +179,7 @@ void generate_matrices_scale(ld scale, int noft) {
}
else {
generate_matrices(hex_matrices, ohex, msh(geometry, S6, cgi.hexvdist, cgi.hexhexdist, cgi.hcrossf, (S3-3)*M_PI/S3, scale));
generate_matrices(hept_matrices, ohept, msh(geometry, S7, cgi.rhexf, cgi.hcrossf, cgi.hcrossf, euclid6?0:euclid4?0:M_PI/S7, scale));
generate_matrices(hept_matrices, ohept, msh(geometry, S7, cgi.rhexf, cgi.hcrossf, cgi.hcrossf, M_PI/S7, scale));
}
}
@ -333,7 +333,7 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
for(int k=0; k<SIDEPARS; k++) sizeto(fsh.side[k], id);
int td = ((PURE || euclid) && !(S7&1)) ? S42+S6 : 0;
int td = (PURE && !(S7&1)) ? S42+S6 : 0;
if(&fsh == &shBigHepta) td += S6;
int b = 0;
@ -846,7 +846,7 @@ EX struct dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector<hp
return &queuepolyat(V, shv[arcm::id_of(c->master)], col, prio);
}
#endif
else if((euclid || GOLDBERG) && ishex1(c) && !penrose)
else if(GOLDBERG && ishex1(c))
return &queuepolyat(V * pispin, shv[0], col, prio);
else if(!(S7&1) && PURE && !penrose && !a4) {
auto si = patterns::getpatterninfo(c, patterns::PAT_COLORING, 0);
@ -888,14 +888,15 @@ EX void viewmat() {
for(int i=0; i<cwt.at->type; i++) {
hyperpoint ci = V * get_corner_position(cwt.at, i);
hyperpoint ci1 = V * get_corner_position(cwt.at, (i+1) % cwt.at->type);
hyperpoint cn = V * nearcorner(cwt.at, i);
hyperpoint cf0 = V * farcorner(cwt.at, i, 0);
hyperpoint cf1 = V * farcorner(cwt.at, i, 1);
queuestr(ci, 20, its(i), 0x0000FF, 1);
if(vid.grid)
queuestr(cn, 20, its(i), 0x00FF00, 1);
else
queuestr(gmatrix[cwt.at->move(i)] * C0, 20, its(i), 0x00FFFF, 1);
else
queuestr(V * currentmap->adj(cwt.at, i) * C0, 20, its(i), 0x00FFFF, 1);
queueline(V * C0, ci, 0xFFFFFFFF, 3);
queueline(ci, ci1, 0xFFFF00FF, 3);
queueline(ci, cn, 0xFF00FFFF, 3);

View File

@ -109,180 +109,6 @@ void showQuotientConfig() {
}
#endif
bool torus_bitrunc;
void prepare_torusconfig() {
torusconfig::newdy = torusconfig::dy;
torusconfig::newqty = torusconfig::qty;
torusconfig::newsdx = torusconfig::sdx;
torusconfig::newsdy = torusconfig::sdy;
torusconfig::newmode = torusconfig::torus_mode;
torus_bitrunc = PURE;
}
void showTorusConfig() {
cmode = sm::SIDE | sm::MAYDARK;
if(euclid) cmode |= sm::TORUSCONFIG;
gamescreen(2);
dialog::init(XLAT("advanced configuration"));
auto& mode = torusconfig::tmodes[torusconfig::newmode];
for(int i=0; i<isize(torusconfig::tmodes); i++) {
char let = "0123456789!@#" [i];
dialog::addBoolItem(torusconfig::tmodes[i].name, torusconfig::newmode == i, let);
dialog::add_action([i] () { torusconfig::newmode = torusconfig::eTorusMode(i); });
}
bool single = (mode.flags & torusconfig::TF_SINGLE);
bool square = (mode.flags & torusconfig::TF_SQUARE);
bool simple = (mode.flags & torusconfig::TF_SIMPLE);
bool cyl = (mode.flags & torusconfig::TF_CYL);
bool klein = (mode.flags & torusconfig::TF_KLEIN);
if(single) {
dialog::addSelItem(XLAT("number of cells (n)"), its(torusconfig::newqty), 'n');
if(mode.flags & torusconfig::TF_HEX)
dialog::addSelItem(XLAT("cell bottom-right from 0 (d)"), its(torusconfig::newdy), 'd');
else
dialog::addSelItem(XLAT("cell below 0 (d)"), its(torusconfig::newdy), 'd');
}
else if(cyl) {
dialog::addSelItem(XLAT("period (x)"), its(torusconfig::newsdx), 'x');
dialog::addSelItem(XLAT("period (y)"), its(torusconfig::newsdy), 'y');
}
else {
if(torusconfig::newsdx < 1) torusconfig::newsdx = 1;
if(torusconfig::newsdy < 1) torusconfig::newsdy = 1;
dialog::addSelItem(XLAT("width (x)"), its(torusconfig::newsdx), 'x');
dialog::addSelItem(XLAT("height (y)"), its(torusconfig::newsdy), 'y');
}
if(square) dialog::addBoolItem(XLAT("bitruncated"), torus_bitrunc, 't');
else dialog::addInfo("", 100);
int valid = 2;
int adx = torusconfig::newsdx, ady = torusconfig::newsdy;
if(single) {
if(square) {
dialog::addInfo("this mode has bad patterns", 0x808080), valid = 1;
if(torus_bitrunc && valid == 1 && (torusconfig::newqty%2 || torusconfig::newdy % 2 == 0))
dialog::addInfo("incompatible with bitruncating", 0x808080), valid = 0;
}
else {
if(torusconfig::newqty % 3)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "n", "3"), 0x808080), valid = 1;
if((torusconfig::newdy + 999999) % 3 != 2)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "d+1", "3"), 0x808080), valid = 1;
}
}
else if(cyl) {
if(torusconfig::sdx == 0 && torusconfig::sdy == 0)
dialog::addInfo(XLAT("period cannot be 0"), 0x800000), valid = 0;
else if(square) {
if(torusconfig::newsdy & 1)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "y", "2"), 0x808080), valid = 1;
if(torusconfig::newsdx & 1)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "x", "2"), 0x808080), valid = 1;
if(torus_bitrunc && valid == 1)
dialog::addInfo("incompatible with bitruncating", 0x808080), valid = 0;
if(klein && !torusconfig::mobius_symmetric(square, adx, ady))
dialog::addInfo("Möbius band requires a symmetric period", 0x800000), valid = 0;
}
else {
if(torusconfig::newsdy % 3)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "y", "3"), 0x808080), valid = 1;
if(torusconfig::newsdx % 3)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "x", "3"), 0x808080), valid = 1;
if(klein && !torusconfig::mobius_symmetric(square, adx, ady))
dialog::addInfo("Möbius band requires a symmetric period", 0x800000), valid = 0;
}
}
else {
if(square) {
if(torusconfig::newsdx & 1)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "x", "2"), 0x808080), valid = 1;
if(torusconfig::newsdy & 1)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "y", "2"), 0x808080), valid = 1;
if(torus_bitrunc && valid == 1)
dialog::addInfo("incompatible with bitruncating", 0x808080), valid = 0;
}
else if(simple) {
if(torusconfig::newsdx % 3)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "x", "3"), 0x808080), valid = 1;
if(torusconfig::newsdy % 3)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "y", "3"), 0x808080), valid = 1;
}
else {
if(torusconfig::newsdx & 1)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "x", "3"), 0x808080), valid = 1;
if(torusconfig::newsdy & 1)
dialog::addInfo(XLAT("best if %1 is divisible by %2", "y", "2"), 0x808080), valid = 0;
}
}
if(cyl) {
if(!(square && klein)) {
dialog::addBoolItem(XLAT("set y=-2x for Crossroads"), ady == -2 * adx, 'C');
dialog::add_action([] () { torusconfig::newsdy = -2 * torusconfig::newsdx; });
}
dialog::addBoolItem(XLAT("set y=0 for Crossroads IV and Chaos Mode"), ady == 0, 'D');
dialog::add_action([] () { torusconfig::newsdy = 0; });
}
dialog::addSelItem(XLAT("scale factor"), fts(vid.scale), 'z');
#if CAP_RUG
if(GDIM == 2) dialog::addBoolItem(XLAT("hypersian rug mode"), (rug::rugged), 'u');
#endif
dialog::addItem("activate", 'a');
dialog::addItem("default", 'c');
keyhandler = [=] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(uni == 'n' && single)
dialog::editNumber(torusconfig::newqty, 0, 1000, 3, torusconfig::def_qty, XLAT("number of cells (n)"), "");
else if(uni == 'd' && single)
dialog::editNumber(torusconfig::newdy, -1000, 1000, 3, -torusconfig::def_dy, XLAT("cell below 0 (d)"), "");
else if(uni == 'x' && !single)
dialog::editNumber(torusconfig::newsdx, 0, 1000, square ? 2 : 3, 12, XLAT("width (x)"), "");
else if(uni == 'y' && !single)
dialog::editNumber(torusconfig::newsdy, 0, 1000, square ? 2 : simple ? 3 : 2, 12, XLAT("height (y)"), "");
else if(uni == 't')
torus_bitrunc = !torus_bitrunc;
else if((uni == 'a' || uni == '\n') && valid) dialog::do_if_confirmed([square] {
set_geometry(gNormal);
torusconfig::torus_mode = torusconfig::newmode;
torusconfig::qty = torusconfig::newqty;
torusconfig::dy = torusconfig::newdy;
torusconfig::sdx = torusconfig::newsdx;
torusconfig::sdy = torusconfig::newsdy;
torusconfig::activate();
set_geometry(gTorus);
set_variation((torus_bitrunc || !square) ? eVariation::bitruncated : eVariation::pure);
start_game();
});
else if(uni == 'c') dialog::do_if_confirmed([] {
set_geometry(gEuclid);
torusconfig::torus_mode = torusconfig::tmSingle;
torusconfig::qty = torusconfig::def_qty;
torusconfig::dy = torusconfig::def_dy;
set_geometry(gTorus);
start_game();
});
else if(uni == 'z') editScale();
#if CAP_RUG
else if(uni == 'u' && GDIM == 2) rug::select();
#endif
else if(doexiton(sym, uni))
popScreen();
};
dialog::display();
}
EX string bitruncnames[5] = {" (b)", " (n)", " (g)", " (i)", " (d)"};
void validity_info() {
@ -449,8 +275,6 @@ void set_or_configure_geometry(eGeometry g) {
else if(g == gArchimedean)
pushScreen(arcm::show);
#endif
else if(g == gTorus)
pushScreen(showTorusConfig);
else {
if(among(g, gProduct, gRotSpace)) {
if(WDIM == 3 || euclid) {
@ -623,11 +447,7 @@ EX void select_quotient_screen() {
"no quotient",
g == geometry, key++);
dialog::add_action([g] {
if(g == gTorus) {
prepare_torusconfig();
pushScreen(showTorusConfig);
}
else if(g == gFieldQuotient)
if(g == gFieldQuotient)
pushScreen(showQuotientConfig);
else {
dual::may_split_or_do([g] { set_geometry(g); });
@ -642,7 +462,7 @@ EX void select_quotient_screen() {
}
EX void select_quotient() {
if(euclid && WDIM == 3) {
if(euclid && !penrose && !archimedean) {
euclid3::prepare_torus3();
pushScreen(euclid3::show_torus3);
}
@ -668,10 +488,6 @@ EX void select_quotient() {
println(hlog, "csteps = ", cgi.steps);
};
}
else if(euclid && !archimedean) {
prepare_torusconfig();
pushScreen(showTorusConfig);
}
else {
vector<eGeometry> choices;
for(int i=0; i<isize(ginf); i++) if(same_tiling(eGeometry(i))) choices.push_back(eGeometry(i));
@ -773,6 +589,7 @@ EX void showEuclideanMenu() {
denom /= g;
}
/*
if(fulltorus) {
using namespace torusconfig;
auto& mode = tmodes[torus_mode];
@ -780,8 +597,10 @@ EX void showEuclideanMenu() {
worldsize = qty;
else
worldsize = sdx * sdy;
worldsize = 0;
}
else worldsize = denom ? nom / denom : 0;
else TODO */
worldsize = denom ? nom / denom : 0;
if(euler < 0 && !bounded)
worldsize = -worldsize;
@ -853,8 +672,6 @@ EX void showEuclideanMenu() {
else if(hybri) {
dialog::addSelItem(XLAT("number of levels"), its(cgi.steps / cgi.single_step), 0);
}
else if(ts == 6 && tv == 3)
dialog::addSelItem(XLAT("variations"), XLAT("does not matter"), 'v');
else if(binarytiling) {
dialog::addSelItem(XLAT("width"), fts(vid.binary_width), 'v');
dialog::add_action([] {
@ -1001,7 +818,7 @@ EX void showEuclideanMenu() {
WDIM == 3 && bounded ? its(isize(currentmap->allcells())) :
WDIM == 3 && euclid ? "" :
worldsize < 0 ? (nom%denom ? its(nom)+"/"+its(denom) : its(-worldsize)) + " exp(∞)":
(euwrap && !fulltorus) ? "" :
(euclid && quotient && !bounded) ? "" :
worldsize == 0 ? "∞²" :
its(worldsize),
'3');
@ -1085,31 +902,6 @@ int read_geom_args() {
else if(argis("-mineadj")) {
shift(); mine_adjacency_rule = argi();
}
else if(argis("-tpar")) {
torusconfig::torus_mode = torusconfig::tmSingle;
shift(); sscanf(argcs(), "%d,%d,%d",
&torusconfig::qty,
&torusconfig::dx,
&torusconfig::dy
);
}
else if(argis("-tparx")) {
shift();
int tmode;
sscanf(argcs(), "%d,%d,%d", &tmode,
&torusconfig::sdx,
&torusconfig::sdy
);
if(tmode < 0 || tmode >= isize(torusconfig::tmodes)) {
println(hlog, "bad tmode");
exit(1);
}
torusconfig::torus_mode = torusconfig::eTorusMode(tmode);
if(torusconfig::tmflags() & torusconfig::TF_SINGLE)
torusconfig::qty = torusconfig::sdx,
torusconfig::dy = torusconfig::sdy;
torusconfig::activate();
}
TOGGLE('7', PURE, set_variation(PURE ? eVariation::bitruncated : eVariation::pure))
else if(argis("-geo")) {
PHASEFROM(2);
@ -1143,10 +935,6 @@ int read_geom_args() {
else if(argis("-d:quotient"))
launch_dialog(showQuotientConfig);
#endif
else if(argis("-d:torus")) {
launch_dialog(showTorusConfig);
prepare_torusconfig();
}
else if(argis("-d:geom"))
launch_dialog(showEuclideanMenu);
else return 1;

View File

@ -426,45 +426,6 @@ void geometry_information::prepare_basics() {
if(archimedean && !prod)
ginf[gArchimedean].cclass = gcHyperbolic;
if(euclid) {
// dynamicval<eGeometry> g(geometry, gNormal);
// for(int i=0; i<S84; i++) spinmatrix[i] = spin(i * M_PI / S42);
if(a4 && !BITRUNCATED) {
crossf = .5;
hexf = .5;
hcrossf = crossf * sqrt(2) / 2;
hexhexdist = crossf;
hexvdist = hexf;
hepvdist = hexf;
rhexf = crossf * sqrt(2) / 2;
tessf = crossf;
}
else if(a4 && BITRUNCATED) {
ld s2 = sqrt(2);
ld xx = 1 - s2 / 2;
crossf = .5;
tessf = crossf * s2;
hexf = .5 * xx * s2;
hcrossf = crossf;
hexhexdist = crossf * s2;
hexvdist = crossf * hypot(1-xx, xx);
hepvdist = crossf;
rhexf = hexf;
tessf = crossf;
}
else {
crossf = .5;
tessf = crossf * sqrt(3);
hexf = tessf/3;
hcrossf = crossf;
hexhexdist = crossf;
hexvdist = hexf;
hepvdist = crossf;
rhexf = hexf;
}
goto finish;
}
if(hybri) {
auto t = this;
ld d = prod ? 1 : 2;
@ -489,11 +450,11 @@ void geometry_information::prepare_basics() {
goto finish;
}
tessf = edge_of_triangle_with_angles(S3 >= OINF ? 0 : 2*M_PI/S3, M_PI/S7, M_PI/S7);
tessf = euclid ? 1 : edge_of_triangle_with_angles(S3 >= OINF ? 0 : 2*M_PI/S3, M_PI/S7, M_PI/S7);
if(elliptic && S7 == 4) tessf = M_PI/2;
hcrossf = edge_of_triangle_with_angles(M_PI/2, M_PI/S7, M_PI/S3);
hcrossf = euclid ? (S3 == 3 ? sqrt(3)/3 : sqrt(2)/2) : edge_of_triangle_with_angles(M_PI/2, M_PI/S7, M_PI/S3);
crossf = BITRUNCATED ? hcrossf : tessf;
@ -510,9 +471,9 @@ void geometry_information::prepare_basics() {
rhexf = BITRUNCATED ? hexf : hcrossf;
if(!euclid && BITRUNCATED && !(S7&1))
if(BITRUNCATED && !(S7&1))
hexshift = ALPHA/2 + ALPHA * ((S7-1)/2) + M_PI;
finish:
for(int d=0; d<S7; d++)

View File

@ -44,12 +44,12 @@ EX transmatrix master_relative(cell *c, bool get_inverse IS(false)) {
}
}
#endif
else if(BITRUNCATED && !euclid) {
else if(BITRUNCATED) {
for(int d=0; d<S7; d++) if(c->master->c7->move(d) == c)
return (get_inverse?cgi.invhexmove:cgi.hexmove)[d];
return Id;
}
else if(WDIM == 3 || euclid)
else if(WDIM == 3)
return Id;
else
return pispin * Id;
@ -161,16 +161,8 @@ transmatrix hrmap_standard::relative_matrix(heptagon *h2, heptagon *h1, const hy
EX transmatrix &ggmatrix(cell *c) {
transmatrix& t = gmatrix[c];
if(t[LDIM][LDIM] == 0) {
if(euwrap && centerover && masterless)
t = calc_relative_matrix(c, centerover, C0);
else if(masterless && WDIM == 2) {
if(!centerover) centerover = cwt.at;
t = actual_view_transform * View * eumove(cell_to_vec(c) - cellwalker_to_vec(cellwalker(centerover)));
}
else
t = actual_view_transform * View * calc_relative_matrix(c, centerover, C0);
}
if(t[LDIM][LDIM] == 0)
t = actual_view_transform * View * calc_relative_matrix(c, centerover, C0);
return t;
}
@ -317,8 +309,8 @@ EX bool no_easy_spin() {
ld hrmap_standard::spin_angle(cell *c, int d) {
ld hexshift = 0;
if(ctof(c) && (S7 % 2 == 0) && BITRUNCATED && !euclid) hexshift = cgi.hexshift + 2*M_PI/S7;
else if(cgi.hexshift && ctof(c)) hexshift = cgi.hexshift;
if(c == c->master->c7 && (S7 % 2 == 0) && BITRUNCATED) hexshift = cgi.hexshift + 2*M_PI/S7;
else if(cgi.hexshift && c == c->master->c7) hexshift = cgi.hexshift;
if(IRREGULAR) {
auto id = irr::cellindex[c];
auto& vs = irr::cells[id];
@ -326,8 +318,6 @@ ld hrmap_standard::spin_angle(cell *c, int d) {
auto& p = vs.jpoints[vs.neid[d]];
return -atan2(p[1], p[0]) - hexshift;
}
else if(masterless)
return - d * 2 * M_PI / c->type - hexshift;
else
return M_PI - d * 2 * M_PI / c->type - hexshift;
}

View File

@ -2668,7 +2668,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col
// golems, knights, and hyperbugs don't face the player (mondir-controlled)
// also whatever in the lineview mode, and whatever in the quotient geometry
else if((hasFacing(c) && c->mondir != NODIR) || history::on || quotient || euwrap || dont_face_pc) {
else if((hasFacing(c) && c->mondir != NODIR) || history::on || quotient || dont_face_pc) {
if(c->monst == moKrakenH) Vs = Vb, nospins = nospinb;
if(!nospins && c->mondir < c->type) Vs = Vs * ddspin(c, c->mondir, M_PI);
if(c->monst == moPair) Vs = Vs * xpush(-.12);
@ -3010,6 +3010,7 @@ EX transmatrix applyPatterndir(cell *c, const patterns::patterninfo& si) {
if(NONSTDVAR || binarytiling) return Id;
transmatrix V = ddspin(c, si.dir, M_PI);
if(si.reflect) V = V * Mirror;
if(euclid) return V;
return V * iddspin(c, 0, M_PI);
}
@ -3059,7 +3060,7 @@ EX color_t reptilecolor(cell *c) {
else {
i = zebra40(c);
if(!masterless) {
if(!euclid) {
if(i >= 4 && i < 16) i = 0;
else if(i >= 16 && i < 28) i = 1;
else if(i >= 28 && i < 40) i = 2;
@ -3167,7 +3168,7 @@ EX bool is_nice_dual(cell *c) {
}
EX bool use_swapped_duals() {
return (masterless && !a4) || GOLDBERG;
return (euclid && !a4) || GOLDBERG;
}
#if CAP_SHAPES
@ -4530,7 +4531,7 @@ EX void drawmovestar(double dx, double dy) {
ld R = sqrt(H[0] * H[0] + H[1] * H[1]);
transmatrix Centered = Id;
if(masterless)
if(euclid)
Centered = eupush(H);
else if(R > 1e-9) Centered = rgpushxto0(H);

View File

@ -808,13 +808,18 @@ EX void describeMouseover() {
if(randomPatternsMode)
out += " " + describeRPM(c->land);
if(masterless && cheater) {
out += " ("+its(cell_to_vec(c))+")";
if(!fulltorus || torusconfig::torus_mode != torusconfig::tmSingle) {
int x, y;
tie(x,y) = cell_to_pair(c);
out += " ("+its(short(x))+","+its(short(y))+")";
}
if(euclid && cheater && WDIM == 2 && !archimedean && !penrose) {
auto co = euc2_coordinates(c);
out += " (" + its(co.first);
for(int i=1; i<WDIM; i++) out += "," + its(co.second);
out += ")";
}
if(euclid && cheater && WDIM == 3) {
auto co = euclid3::getcoord(euclid3::get_ispacemap()[c->master]);
out += " (" + its(co[0]);
for(int i=1; i<WDIM; i++) out += "," + its(co[i]);
out += ")";
}
#if CAP_CRYSTAL

11
hyper.h
View File

@ -146,18 +146,12 @@ void addMessage(string s, char spamtype = 0);
#define nonorientable (cgflags & qNONORIENTABLE)
#define elliptic (cgflags & qELLIPTIC)
#define quotient (cgflags & qANYQ)
#define euwrap (quotient && euclid)
#define fulltorus (bounded && euclid)
#define smallbounded (cgflags & qSMALL)
#define bounded (cgflags & qBOUNDED)
// Dry Forest burning, heat transfer, etc. are performed on the whole universe
#define doall (bounded)
// These geometries are generated without the heptagon structure.
// 'master' holds the coordinates
#define masterless among(geometry, gEuclid, gEuclidSquare, gTorus)
#define sphere_narcm (sphere && !archimedean)
#define a4 (S3 == 4)
@ -171,8 +165,8 @@ void addMessage(string s, char spamtype = 0);
#define stdeuc (geometry == gNormal || geometry == gEuclid || geometry == gEuclidSquare)
#define smallsphere (sphere_narcm && S7 < 5)
#define bigsphere (sphere_narcm && S7 == 5)
#define euclid4 (masterless && a4)
#define euclid6 (masterless && !a4)
#define euclid4 (euclid && WDIM == 2 && a4)
#define euclid6 (euclid && WDIM == 2 && !a4)
#define S6 (S3*2)
#define MAX_S3 4
@ -778,7 +772,6 @@ template <class T> void texture_order(const T& f) {
static const color_t NOCOLOR = 0;
typedef pair<cell**, bool> euc_pointer;
static const int max_vec = (1<<14);
extern bool needConfirmationEvenIfSaved();

View File

@ -878,8 +878,6 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
EX transmatrix sphereflip; // on the sphere, flip
EX bool playerfound; // has player been found in the last drawing?
double q3 = sqrt(double(3));
EX bool outofmap(hyperpoint h) {
if(GDIM == 3)
return false;
@ -1138,7 +1136,7 @@ vector<tuple<heptspin, hstate, transmatrix, ld> > drawn_cells;
bool in_multi = false;
bool drawcell_subs(cell *c, transmatrix V) {
EX bool drawcell_subs(cell *c, transmatrix V) {
#if CAP_GP
if(GOLDBERG) {
@ -1163,8 +1161,10 @@ bool drawcell_subs(cell *c, transmatrix V) {
}
#endif
if(do_draw(c, V))
if(do_draw(c, V)) {
draw = true;
drawcell(c, V);
}
if(BITRUNCATED) forCellIdEx(c1, d, c) {
if(c->c.spin(d) == 0) {
@ -1236,62 +1236,6 @@ void hrmap_standard::draw() {
}
}
int mindx=-7, mindy=-7, maxdx=7, maxdy=7;
EX transmatrix eumove(ld x, ld y) {
transmatrix Mat = Id;
Mat[LDIM][LDIM] = 1;
if(a4) {
Mat[0][LDIM] += x * cgi.crossf;
Mat[1][LDIM] += y * cgi.crossf;
}
else {
Mat[0][LDIM] += (x + y * .5) * cgi.crossf;
// Mat[LDIM][0] += (x + y * .5) * cgi.crossf;
Mat[1][LDIM] += y * q3 /2 * cgi.crossf;
// Mat[LDIM][1] += y * q3 /2 * cgi.crossf;
}
ld v = a4 ? 1 : q3;
while(Mat[0][LDIM] <= -16384 * cgi.crossf) Mat[0][LDIM] += 32768 * cgi.crossf;
while(Mat[0][LDIM] >= 16384 * cgi.crossf) Mat[0][LDIM] -= 32768 * cgi.crossf;
while(Mat[1][LDIM] <= -16384 * v * cgi.crossf) Mat[1][LDIM] += 32768 * v * cgi.crossf;
while(Mat[1][LDIM] >= 16384 * v * cgi.crossf) Mat[1][LDIM] -= 32768 * v * cgi.crossf;
return Mat;
}
EX transmatrix eumove(int vec) {
int x, y;
tie(x,y) = vec_to_pair(vec);
return eumove(x, y);
}
EX transmatrix eumovedir(int d) {
if(a4) {
d = d & 3;
switch(d) {
case 0: return eumove(1,0);
case 1: return eumove(0,1);
case 2: return eumove(-1,0);
case 3: return eumove(0,-1);
}
}
else {
d = gmod(d, S6);
switch(d) {
case 0: return eumove(1,0);
case 1: return eumove(0,1);
case 2: return eumove(-1,1);
case 3: return eumove(-1,0);
case 4: return eumove(0,-1);
case 5: return eumove(1,-1);
}
}
return eumove(0,0);
}
EX void spinEdge(ld aspd) {
ld downspin = 0;
if(dual::state == 2 && dual::currently_loaded != dual::main_side) {
@ -1957,7 +1901,7 @@ EX namespace dq {
EX bool do_draw(cell *c) {
// do not display out of range cells, unless on torus
if(c->pathdist == PINFD && geometry != gTorus && vid.use_smart_range == 0)
if(c->pathdist == PINFD && !(euclid && quotient) && vid.use_smart_range == 0)
return false;
// do not display not fully generated cells, unless changing range allowed
if(c->mpdist > 7 && !allowChangeRange()) return false;
@ -2036,7 +1980,7 @@ EX bool do_draw(cell *c, const transmatrix& T) {
if(imag(z) < -models::spiral_cone_rad/2-1e-5 || imag(z) >= models::spiral_cone_rad/2-1e-5) return false;
}
if(cells_drawn > vid.cells_drawn_limit) return false;
bool usr = vid.use_smart_range || quotient || euwrap;
bool usr = vid.use_smart_range || quotient;
if(usr && cells_drawn >= 50 && !in_smart_range(T) && !(WDIM == 2 && GDIM == 3 && hdist0(tC0(T)) < 2.5)) return false;
if(vid.use_smart_range == 2 && !limited_generation(c)) return false;
return true;

View File

@ -271,7 +271,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
}
}
}
else if(PIU(hyperbolic_not37 || fulltorus || S7 < 5 || archimedean || WDIM == 3)) {
else if(PIU(hyperbolic_not37 || (euclid&&bounded) || S7 < 5 || archimedean || WDIM == 3)) {
if(fargen) {
int i = hrand(100);
if(i < 10)
@ -491,7 +491,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
if(d==8) {
if(randomPatternsMode)
c->wall = RANDPAT3(0) ? waCavewall : waCavefloor;
else if(fulltorus) {
else if(euclid && bounded) {
c->wall = waCavefloor;
}
else if(nil) {
@ -509,7 +509,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
#endif
else if(euclid) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
if(((y-2)&7) < 4) c->wall = waCavewall;
else c->wall = waCavefloor;
}
@ -595,12 +595,12 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
else if(archimedean && arcm::current.have_line)
v = arcm::linespattern(c) ? 24 : 16;
#endif
else if(fulltorus || hyperbolic_not37 || quotient || archimedean) {
else if((euclid&&bounded) || hyperbolic_not37 || quotient || archimedean) {
v = hrand(100) < 25 ? 24 : 16;
}
else if(euclid) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
int y0 = gmod(y, 6);
if(y0 == 3 || y0 == 4) v=24; else v=0;
}
@ -656,14 +656,14 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
case laZebra:
if(d==8) {
if(fulltorus) ;
if(euclid && bounded) ;
#if CAP_ARCM
else if(archimedean && arcm::current.have_line)
c->wall = arcm::linespattern(c) ? waTrapdoor : waNone;
#endif
else if(euclid && !archimedean) {
int x,y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
if(y&1) c->wall = waTrapdoor;
else c->wall = waNone;
}
@ -684,7 +684,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
case laWineyard:
if(d==8) {
if(fulltorus) ;
if(euclid && bounded) ;
#if CAP_ARCM
else if(archimedean && arcm::current.have_line)
c->wall = arcm::linespattern(c) ? waVinePlant : waNone;
@ -699,7 +699,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
}
else if(euclid && !archimedean) {
int x,y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
int dy = gmod(y, 3);
if(dy == 1) c->wall = waVinePlant;
}
@ -1221,7 +1221,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
if(quotient && zebra40(c) == 5) {
c->wall = waChasm;
}
if(fulltorus) {
if(euclid && bounded) {
int i = hrand(100);
if(i == 0) c->item = itTreat;
else if(i < 5) c->wall = waChasm;
@ -1285,14 +1285,12 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
bool randstorm = PIU(hyperbolic_not37 || NONSTDVAR || (quotient && geometry != gZebraQuotient));
if(fargen) {
if(fulltorus) {
int pid = decodeId(c->master);
if(pid == torusconfig::qty/3) c->wall = waCharged;
if(pid == torusconfig::qty*2/3) c->wall = waGrounded;
if(euclid && bounded) {
/* todo */
}
else if(euclid) {
int x,y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
if((x+1)%3 == 0 && y%3 == 0) {
if(hrand(100) < 50)
c->wall = hrand(2) ? waCharged : waGrounded;
@ -1301,7 +1299,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
bool sand = false;
for(int i=0; i<c->type; i++) {
createMov(c, i);
tie(x,y) = cell_to_pair(c->move(i));
tie(x,y) = euc2_coordinates(c->move(i));
if((x+1)%3 == 0 && (y)%3 == 0) sand = true;
}
if(sand && hrand(100) < 20)
@ -2655,7 +2653,7 @@ EX void setdist(cell *c, int d, cell *from) {
else if(euclid && WDIM == 3) euclid3::set_land(c);
#endif
else if(hybri) setLandHybrid(c);
else if(sphere || fulltorus) setLandSphere(c);
else if(sphere || (euclid && bounded)) setLandSphere(c);
else if(euclid) setLandEuclid(c);
else if(quotient) { setland(c, specialland); setLandQuotient(c); }
else if(sol) setLandSol(c);

View File

@ -1051,14 +1051,14 @@ EX land_validity_t& land_validity(eLand l) {
if(l == laReptile) {
if(old_daily_id <= 64) {
if(l == laReptile && (a38 || a4 || sphere || !BITRUNCATED || (quotient && !euwrap && geometry != gZebraQuotient)))
if(l == laReptile && (a38 || a4 || sphere || !BITRUNCATED || (quotient && !euclid && geometry != gZebraQuotient)))
return bad_graphics;
}
else {
bool reptile_good = false;
if(hyperbolic_37 && BITRUNCATED) reptile_good = true;
if(euclid6) reptile_good = true;
if(quotient && geometry != gZebraQuotient && !euwrap)
if(quotient && geometry != gZebraQuotient && !euclid)
reptile_good = false;
if(!reptile_good)
return bad_graphics;
@ -1105,7 +1105,7 @@ EX land_validity_t& land_validity(eLand l) {
return great_walls_missing;
// highlight Crossroads on Euclidean
if(euclid && !euwrap && (l == laCrossroads || l == laCrossroads4) && !penrose)
if(euclid && !quotient && (l == laCrossroads || l == laCrossroads4) && !penrose)
return full_game;
if(sol && among(l, laCrossroads, laCrossroads4))
@ -1114,10 +1114,10 @@ EX land_validity_t& land_validity(eLand l) {
if(sol && l == laCamelot)
return not_implemented;
if(euclid && euwrap && !fulltorus && l == laCrossroads && torusconfig::sdy == -2 * torusconfig::sdx)
if(euclid && quotient && !bounded && l == laCrossroads && sdxy().second == -2 * sdxy().first)
return full_game;
if(euclid && euwrap && !fulltorus && l == laCrossroads4 && torusconfig::sdy == 0)
if(euclid && quotient && !bounded && l == laCrossroads4 && sdxy().second == 0)
return full_game;
// highlight Zebra-based lands on Zebra Quotient!
@ -1154,7 +1154,7 @@ EX land_validity_t& land_validity(eLand l) {
return pattern_not_implemented_exclude;
}
if(l == laStorms && fulltorus)
if(l == laStorms && euclid && bounded)
return interesting;
if(l == laMagnetic)

View File

@ -130,14 +130,6 @@ namespace mapstream {
f.write(gp::param.second);
}
#endif
if(geometry == gTorus) {
f.write(torusconfig::qty);
f.write(torusconfig::dx);
f.write(torusconfig::dy);
f.write(torusconfig::sdx);
f.write(torusconfig::sdy);
f.write(torusconfig::torus_mode);
}
#if CAP_FIELD
if(geometry == gFieldQuotient) {
using namespace fieldpattern;
@ -187,17 +179,6 @@ namespace mapstream {
f.read(gp::param.second);
}
#endif
if(geometry == gTorus) {
f.read(torusconfig::qty);
f.read(torusconfig::dx);
f.read(torusconfig::dy);
if(f.vernum >= 10504) {
f.read(torusconfig::sdx);
f.read(torusconfig::sdy);
f.read(torusconfig::torus_mode);
}
torusconfig::activate();
}
#if CAP_CRYSTAL
if(cryst && f.vernum >= 10504) {
int sides;

View File

@ -187,7 +187,7 @@ EX namespace models {
spiral_multiplier = cld(cos_spiral, sin_spiral) * cld(spiral_cone_rad * mul / 2., 0);
}
if(euclid) {
hyperpoint h = tC0(eumove(spiral_x, spiral_y));
hyperpoint h = eumove(as_coord({spiral_x, spiral_y})) * C0;
spiral_multiplier = cld(0, 2 * M_PI) / cld(h[0], h[1]);
}
@ -262,13 +262,13 @@ EX namespace models {
for(int y=0; y<=200; y++)
for(int x=-200; x<=200; x++) {
if(y == 0 && x <= 0) continue;
auto zero = vec_to_cellwalker(euclid_getvec(x, y));
if(zero.at == currentmap->gamestart() && !zero.mirrored)
auto zero = euclid3::canonicalize(as_coord({x, y}));
if(zero == 0)
torus_zeros.emplace_back(x, y);
}
sort(torus_zeros.begin(), torus_zeros.end(), [] (const pair<int,int> p1, const pair<int, int> p2) {
ld d1 = hdist0(tC0(eumove(p1.first, p1.second)));
ld d2 = hdist0(tC0(eumove(p2.first, p2.second)));
ld d1 = hdist0(tC0(eumove(as_coord(p1))));
ld d2 = hdist0(tC0(eumove(as_coord(p2))));
if(d1 < d2 - 1e-6) return true;
if(d1 > d2 + 1e-6) return false;
return p1 < p2;
@ -635,7 +635,7 @@ EX namespace models {
dialog::add_action([](){
dialog::editNumber(spiral_y, -20, 20, 1, 10, XLAT("spiral period: y"), "");
});
if(euwrap) {
if(euclid && quotient) {
dialog::addSelItem(XLAT("match the period"), its(spiral_id), 'n');
dialog::add_action(match_torus_period);
}

View File

@ -36,46 +36,43 @@ int gp_threecolor() {
}
int eupattern(cell *c) {
int v = cell_to_vec(c);
if(a4) {
int x, y;
tie(x,y) = vec_to_pair(v);
int x, y;
tie(x,y) = euc2_coordinates(c);
if(a4)
return ((x&1) + 2*(y&1)) % 3;
}
else {
return gmod(v*2, 3);
}
else
return gmod(y-x, 3);
}
int eupattern4(cell *c) {
int v = cell_to_vec(c);
int x, y;
tie(x,y) = vec_to_pair(v);
tie(x,y) = euc2_coordinates(c);
return (x&1) + ((y&1)) * 2;
}
EX bool ishept(cell *c) {
// EUCLIDEAN
if(euclid) return eupattern(c) == 0;
else return c->type == S7 + (hybri ? 2 : 0);
if(euclid && PURE) return eupattern(c) == 0;
else if(hybri) { cell *c1 = hybrid::get_where(c).first; return c1 == c1->master->c7; }
else return c == c->master->c7;
}
EX bool ishex1(cell *c) {
// EUCLIDEAN
if(euclid) return eupattern(c) == 1;
if(euclid && PURE) return eupattern(c) == 1;
#if CAP_GP
else if(GOLDBERG) return c->master->c7 != c && !pseudohept(c->move(0));
#endif
else return c->type != S6;
else return c->master->c7 != c;
}
bool ishex2(cell *c) {
// EUCLIDEAN
if(euclid) return eupattern(c) == 1;
if(euclid && PURE) return eupattern(c) == 1;
#if CAP_GP
else if(GOLDBERG) return c->master->c7 != c && gp::pseudohept_val(c) == 1;
#endif
else return c->type != S6;
else return c->master->c7 != c;
}
int chessvalue(cell *c) {
@ -111,12 +108,8 @@ unsigned bitmajority(unsigned a, unsigned b, unsigned c) {
}
int eufifty(cell *c) {
if(fulltorus) {
if(c->land == laWildWest) return cell_to_vec(c) % 37;
else return cell_to_vec(c) % 27;
}
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
int ix = x + 99999 + y;
int iy = y + 99999;
if(c->land == laWildWest)
@ -290,7 +283,7 @@ int dir_bitrunc457(cell *c) {
int val46(cell *c);
EX int zebra40(cell *c) {
if(euclid) return eupattern(c);
if(euclid) return pattern_threecolor(c);
else if(IRREGULAR) return c->master->zebraval/10;
else if(a46) {
int v = val46(c);
@ -322,7 +315,6 @@ EX int zebra40(cell *c) {
return 24;
}
else if(sphere) return 0;
else if(euclid) return eupattern(c);
else if(S3 == 4 && S7 == 6) {
return 8 + ((c->master->zebraval / 10 + c->c.spin(0))%2) * 2;
}
@ -348,7 +340,7 @@ EX int zebra40(cell *c) {
}
EX int zebra3(cell *c) {
if(masterless) return 0;
if(euclid) return 0;
else if(ctof(c)) return (c->master->zebraval/10)/4;
else if(euclid || sphere || S7>7 || S6>6) return 0;
else {
@ -391,12 +383,10 @@ EX int fieldval_uniq(cell *c) {
if(ctof(c)) return c->master->fieldval;
else return createMov(c, 0)->master->fieldval + 256 * createMov(c,2)->master->fieldval + (1<<16) * createMov(c,4)->master->fieldval;
}
else if(fulltorus) {
return decodeId(c->master);
}
else if(euclid) {
auto p = cell_to_pair(c);
return gmod(p.first * torusconfig::dx + p.second * torusconfig::dy, torusconfig::qty);
auto p = euc2_coordinates(c);
if(bounded) return p.first + (p.second << 16);
return gmod(p.first - 22 * p.second, 3*127);
}
else if(binarytiling || archimedean || nil || S3 >= OINF || (cgflags & qIDEAL)) return 0;
else if(&currfp == &fp_invalid) return 0;
@ -483,7 +473,7 @@ EX int getHemisphere(heptagon *h, int which) {
}
EX int getHemisphere(cell *c, int which) {
if(euwrap) return 0;
if(euclid && quotient) return 0;
if(hybri) { auto d = hybrid::get_where(c); return PIU(getHemisphere(d.first, which)); }
if(WDIM == 3 && !hybri) {
hyperpoint p = tC0(calc_relative_matrix(c, currentmap->gamestart(), C0));
@ -969,8 +959,19 @@ EX namespace patterns {
break;
}
}
if(euclid6 && (sub & SPF_CHANGEROT))
si.dir = (zebra40(c)*4) % 6;
if(euclid6 && (sub & SPF_CHANGEROT)) {
if(GOLDBERG) {
auto li = gp::get_local_info(c);
if(li.first_dir >= 0)
si.dir = gmod(zebra40(c)*4 - li.total_dir - li.last_dir, 6);
else
si.dir = gmod(zebra40(c)*4, 6);
}
else if(c == c->master->c7)
si.dir = (zebra40(c)*4) % 6;
else
si.dir = (zebra40(c)*4 + 9 - c->c.spin(0)) % 6;
}
if(sub & SPF_ROT) si.id = 1;
if(euclid6 && !(sub & SPF_EXTRASYM)) {
si.symmetries = 6;
@ -1286,6 +1287,12 @@ EX int pattern_threecolor(cell *c) {
patterns::val38(c, si, !BITRUNCATED ? 0 : patterns::SPF_ROT, patterns::PAT_COLORING);
return si.id >> 2;
}
if(euclid6 && gp_threecolor() == 2) {
auto li = gp::get_local_info(c);
int rel = gmod(li.relative.first - li.relative.second, 3);
if(rel && (li.last_dir&1)) rel = 3 - rel;
return rel;
}
#if CAP_GP
if(a4 && GOLDBERG) {
patterns::patterninfo si;
@ -1312,7 +1319,8 @@ EX int pattern_threecolor(cell *c) {
}
if(euclid) {
if(a4 && PURE) return eupattern4(c);
return eupattern(c) % 3;
if(euclid6 && !BITRUNCATED) return eupattern(c) % 3;
return c == c->master->c7 ? 0 : (c->c.spin(0)&1) ? 1 : 2;
}
if(S3 >= OINF) return c->master->distance % 3;
if(S7 == 4 && S3 == 3) {
@ -1498,7 +1506,7 @@ EX namespace patterns {
int sevenval(cell *c) {
if(!euclid) return 0;
auto p = vec_to_pair(cell_to_vec(c));
auto p = euc2_coordinates(c);
return gmod(p.first - p.second * 2, 7);
}
@ -1525,7 +1533,7 @@ EX namespace patterns {
ep.extra_params["chess"] = chessvalue(c);
ep.extra_params["ph"] = pseudohept(c);
ep.extra_params["kph"] = kraken_pseudohept(c);
if(!masterless) {
if(true) {
ep.extra_params["md"] = c->master->distance;
ep.extra_params["me"] = c->master->emeraldval;
ep.extra_params["mf"] = c->master->fieldval;
@ -1539,7 +1547,7 @@ EX namespace patterns {
}
if(euclid) {
int x, y;
tie(x,y) = cell_to_pair(c);
tie(x,y) = euc2_coordinates(c);
ep.extra_params["ex"] = x;
ep.extra_params["ey"] = y;
if(S7 == 6) ep.extra_params["ez"] = -x-y;
@ -2429,12 +2437,14 @@ EX namespace linepatterns {
case patZebraTriangles:
if(euclid) {
if(patterns::sevenval(c)) break;
/* todo
gridline(V, C0, tC0(eumove(-1, +3)), col, 3 + vid.linequality);
gridline(V, C0, tC0(eumove(-3, +2)), col, 3 + vid.linequality);
gridline(V, C0, tC0(eumove(-2, -1)), col, 3 + vid.linequality);
gridline(V, C0, tC0(eumove(+1, -3)), col, 3 + vid.linequality);
gridline(V, C0, tC0(eumove(+3, -2)), col, 3 + vid.linequality);
gridline(V, C0, tC0(eumove(+2, +1)), col, 3 + vid.linequality);
*/
break;
}
if(zebra40(c) / 4 == 10) {

88
rug.cpp
View File

@ -252,8 +252,8 @@ EX rugpoint *addRugpoint(hyperpoint h, double dist) {
m->y1 = (1 - onscreen[1] * vid.scale) / 2;
m->valid = false;
if(euwrap && !bounded) {
hyperpoint h1 = eumove(torusconfig::sdx, torusconfig::sdy) * C0;
if(euclid && quotient && !bounded) {
hyperpoint h1 = eumove(first_period()) * C0;
h1 /= sqhypot_d(2, h1);
if(nonorientable) h1 /= 2;
m->valid = good_shape = true;
@ -428,71 +428,18 @@ void calcparam_rug() {
}
EX void buildTorusRug() {
using namespace torusconfig;
/* todo
calcparam_rug();
models::configure();
struct toruspoint {
int x,y;
toruspoint() { x=y=getqty(); }
toruspoint(int _x, int _y) : x(_x), y(_y) {}
int d2() {
return x*x+(euclid6?x*y:0)+y*y;
}
};
vector<toruspoint> zeropoints;
vector<toruspoint> tps(qty);
auto& mode = tmodes[torus_mode];
bool single = mode.flags & TF_SINGLE;
bool klein = mode.flags & TF_KLEIN;
pair<gp::loc, gp::loc> periods;
pair<toruspoint, toruspoint> solution;
// todo take the periods
if(single) {
for(int ax=-qty; ax<qty; ax++)
for(int ay=-qty; ay<qty; ay++) {
int v = (ax*dx + ay*dy) % qty;
if(v<0) v += qty;
toruspoint tp(ax, ay);
if(tps[v].d2() > tp.d2()) tps[v] = tp;
if(v == 0)
zeropoints.emplace_back(ax, ay);
}
ld bestsol = 1e12;
for(auto p1: zeropoints)
for(auto p2: zeropoints) {
int det = p1.x * p2.y - p2.x * p1.y;
if(det < 0) continue;
if(det != qty && det != -qty) continue;
ld quality = ld(p1.d2()) * p2.d2();
if(quality < bestsol * 3)
if(quality < bestsol)
bestsol = quality, solution.first = p1, solution.second = p2;
}
if(solution.first.d2() > solution.second.d2())
swap(solution.first, solution.second);
}
else {
if(klein)
solution.first = toruspoint(2*sdx, 0);
else
solution.first = toruspoint(sdx, 0);
if(mode.flags & TF_WEIRD)
solution.second = toruspoint(sdy/2, sdy);
else
solution.second = toruspoint(0, sdy);
if(solution.first.d2() > solution.second.d2())
swap(solution.first, solution.second);
}
ld factor = sqrt(ld(solution.second.d2()) / solution.first.d2());
ld factor = sqrt(ld(dsquare(periods.second)) / dsquare(periods.first));
ld xfactor = 0, yfactor = 0;
@ -504,16 +451,10 @@ EX void buildTorusRug() {
// 7,-17
transmatrix z1 = matrix3(
solution.first.x, solution.second.x, 0,
solution.first.y, solution.second.y, 0,
periods.first.first, periods.second.first, 0,
periods.first.second, periods.second.second, 0,
0, 0, 1);
// transmatrix z1 = {{{22,7,0}, {1,-17,0}, {0,0,1}}};
/* transmatrix z1(
point3(solution.first.x, solution.second.x, 0),
point3(solution.first.y, solution.second.y, 0),
point3(0, 0, 1),
point31(0, 0, 0)
); */
transmatrix z2 = inverse(z1);
if(gwhere == gSphere) {
@ -630,6 +571,7 @@ EX void buildTorusRug() {
if(rug_perspective)
push_all_points(2, -model_distance);
*/
return;
}
@ -670,7 +612,7 @@ EX void buildRug() {
need_mouseh = true;
good_shape = false;
if(fulltorus) {
if(euclid && bounded) {
good_shape = true;
buildTorusRug();
return;
@ -687,13 +629,13 @@ EX void buildRug() {
cell *c = p.first;
rugpoint *v = p.second;
if(archimedean || euwrap) {
if(archimedean || (euclid && quotient)) {
rugpoint *p[MAX_EDGE+1];
for(int j=0; j<c->type; j++) p[j] = findOrAddRugpoint(ggmatrix(c) * get_corner_position(c, j), v->dist);
for(int j=0; j<c->type; j++) addTriangle(v, p[j], p[(j+1) % c->type]);
if(euwrap && nonorientable) {
transmatrix T = ggmatrix(c) * eumove(torusconfig::sdx, torusconfig::sdy);
if((euclid && quotient) && nonorientable) {
transmatrix T = ggmatrix(c) * eumove(first_period());
rugpoint *Tv = addRugpoint(T * C0, 0);
for(int j=0; j<c->type; j++) p[j] = findOrAddRugpoint(T * get_corner_position(c, j), v->dist);
for(int j=0; j<c->type; j++) addTriangle(Tv, p[j], p[(j+1) % c->type]);
@ -902,7 +844,7 @@ int divides = 0;
bool stop = false;
EX bool subdivide_further() {
if(fulltorus) return false;
if(euclid && bounded) return false;
if(GDIM == 3) return false;
return isize(points) * 4 < vertex_limit;
}
@ -1081,7 +1023,7 @@ EX void addNewPoints() {
if(anticusp_factor && detect_cusps())
return;
if(euwrap || qvalid == isize(points)) {
if((euclid && quotient) || qvalid == isize(points)) {
subdivide();
return;
}

View File

@ -242,7 +242,7 @@ EX void initgame() {
if(gamegen_failure) return;
if(euclid && specialland == laPrincessQuest) {
cell *c = *euclideanAtCreate(pair_to_vec(EPX, EPY)).first;
cell *c = at_euc2_coordinates({EPX, EPY});
princess::generating = true;
c->land = laPalace;
setdist(c, 7 - getDistLimit() - genrange_bonus, NULL);
@ -1230,7 +1230,7 @@ EX void set_geometry(eGeometry target) {
EX void set_variation(eVariation target) {
if(variation != target) {
stop_game();
if(euclid6 || binarytiling || sol || penrose || WDIM == 3) if(!prod) geometry = gNormal;
if(binarytiling || sol || penrose || WDIM == 3) if(!prod) geometry = gNormal;
auto& cd = ginf[gCrystal];
if(target == eVariation::bitruncated && cryst && cd.sides == 8 && cd.vertex == 4) {
cd.vertex = 3;

View File

@ -1139,18 +1139,8 @@ modecode_t modecode() {
typedef long long ll;
// 32 bits [29..61) for geometry specifics
if(euwrap) {
mct += ll(torusconfig::torus_mode) << 29;
auto& mode = torusconfig::tmodes[torusconfig::torus_mode];
bool single = (mode.flags & torusconfig::TF_SINGLE);
if(single) {
mct += ll(torusconfig::qty) << 37;
mct += ll(torusconfig::dy) << 45;
}
else {
mct += ll(torusconfig::sdx) << 37;
mct += ll(torusconfig::sdy) << 45;
}
if(euclid && quotient) {
/* todo */
}
#if CAP_FIELD