diff --git a/cell.cpp b/cell.cpp index 5363aa53..8d80add8 100644 --- a/cell.cpp +++ b/cell.cpp @@ -371,15 +371,24 @@ namespace torusconfig { int tester = addHook(hooks_tests, 0, torus_test); void activate() { - if(tmflags() & TF_HEX) - ginf[gTorus].vertex = 3, ginf[gTorus].sides = 6; - else - ginf[gTorus].vertex = 4, ginf[gTorus].sides = 4; + auto& gi(ginf[gTorus]); - flagtype& flags = ginf[gTorus].flags; + if(tmflags() & TF_HEX) + gi.vertex = 3, gi.sides = 6, gi.tiling_name = "{6,3}"; + else + gi.vertex = 4, gi.sides = 4, gi.tiling_name = "{4,4}"; + + flagtype& flags = gi.flags; set_flag(flags, qNONORIENTABLE, tmflags() & TF_KLEIN); set_flag(flags, qBOUNDED, !(tmflags() & TF_CYL)); + + int i = 0; + if(tmflags() & TF_KLEIN) i++; + if(tmflags() & TF_CYL) i+=2; + + const char *quonames[4] = {"torus", "Klein bottle", "cylinder", "Möbius band"}; + gi.quotient_name = quonames[i]; } int dscalar(gp::loc e1, gp::loc e2) { diff --git a/classes.cpp b/classes.cpp index e29a80d4..674ded70 100644 --- a/classes.cpp +++ b/classes.cpp @@ -1668,33 +1668,33 @@ static const flagtype qsDOCKS = qANYQ | qSMALL | qBOUNDED | qDOCKS; static const flagtype qsSMALLB = qSMALL | qBOUNDED; vector ginf = { - {"standard", "HR", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}, eVariation::bitruncated}, - {"Euclidean", "euclid", 6, 3, 0, gcEuclid, 0, {{7, FORBIDDEN}}, eVariation::bitruncated}, - {"spherical", "sphere", 5, 3, qsSMALLB, gcSphere, 0, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"elliptic", "elliptic", 5, 3, qsNONOR, gcSphere, 0, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"Zebra quotient", "Zebra", 7, 3, qsZEBRA, gcHyperbolic, 0x00400, {{7, 5}}, eVariation::bitruncated}, - {"field quotient", "field", 7, 3, qsFIELD, gcHyperbolic, 0x00200, {{7, 5}}, eVariation::bitruncated}, - {"torus/Klein bottle", "torus", 6, 3, qsBQ, gcEuclid, 0x00600, {{7, 7}}, eVariation::bitruncated}, - {"octagons", "oct", 8, 3, 0, gcHyperbolic, 0x08000, {{6, 4}}, eVariation::bitruncated}, - {"four pentagons", "4x5", 5, 4, 0, gcHyperbolic, 0x08200, {{6, 4}}, eVariation::bitruncated}, - {"four hexagons", "4x6", 6, 4, 0, gcHyperbolic, 0x08400, {{5, 3}}, eVariation::bitruncated}, - {"four heptagons", "4x7", 7, 4, 0, gcHyperbolic, 0x08600, {{4, 3}}, eVariation::bitruncated}, - {"cube", "3x4", 4, 3, qsSMALLB, gcSphere, 0x10000, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"tetrahedron", "3x3", 3, 3, qsSMALLB, gcSphere, 0x10200, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"square grid", "4x4", 4, 4, 0, gcEuclid, 0x10400, {{7, 7}}, eVariation::bitruncated}, - {"cube/elliptic", "e3x4", 4, 3, qsNONOR, gcSphere, 0x10600, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"Klein Quartic", "Klein", 7, 3, qsSMALL, gcHyperbolic, 0x18000, {{7, 5}}, eVariation::bitruncated}, - {"Bolza Surface", "Bolza", 8, 3, qsDOCKS, gcHyperbolic, 0x18200, {{6, 4}}, eVariation::bitruncated}, - {"Bolza Surface x2", "Bolza2", 8, 3, qsDOCKS, gcHyperbolic, 0x18400, {{6, 4}}, eVariation::bitruncated}, - {"minimal quotient", "minimal", 7, 3, qsSMALLN, gcHyperbolic, 0x18600, {{7, 5}}, eVariation::bitruncated}, - {"binary tiling", "binary", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}, eVariation::pure}, - {"Archimedean", "A", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}, eVariation::pure}, - {"Macbeath Surface", "Macbeath", 7, 3, qsSMALL, gcHyperbolic, 0x20000, {{7, 5}}, eVariation::bitruncated}, - {"Bring's Surface", "Bring", 5, 4, qsSMALL, gcHyperbolic, 0x20200, {{6, 4}}, eVariation::bitruncated}, - {"Schmutz's M(3)", "M3", 12, 3, qsSMALL, gcHyperbolic, 0x20400, {{4, 2}}, eVariation::bitruncated}, - {"Schmutz's M(4)", "M4", 12, 3, qsSMALL, gcHyperbolic, 0x20600, {{4, 2}}, eVariation::bitruncated}, - {"dimensional crystal", "Crystal", 6, 4, qANYQ, gcHyperbolic, 0x28000, {{5, 3}}, eVariation::pure}, - {"octahedron", "4x3", 3, 4, qsSMALLB, gcSphere, 0x28200, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{7,3}", "none", "{7,3} (standard HyperRogue map)", "HR", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}, eVariation::bitruncated}, + {"{6,3}", "none", "{6,3} (euclidean Hex grid)", "euclid", 6, 3, 0, gcEuclid, 0, {{7, FORBIDDEN}}, eVariation::bitruncated}, + {"{5,3}", "none", "{5,3} (dodecahedron)", "sphere", 5, 3, qsSMALLB, gcSphere, 0, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{5,3}", "elliptic", "elliptic geometry in {5,3}", "elliptic", 5, 3, qsNONOR, gcSphere, 0, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{7,3}", "Zebra", "Zebra quotient", "Zebra", 7, 3, qsZEBRA, gcHyperbolic, 0x00400, {{7, 5}}, eVariation::bitruncated}, + {"{7,3}", "field", "field quotient", "field", 7, 3, qsFIELD, gcHyperbolic, 0x00200, {{7, 5}}, eVariation::bitruncated}, + {"{6,3}", "torus", "torus/Klein bottle/...", "torus", 6, 3, qsBQ, gcEuclid, 0x00600, {{7, 7}}, eVariation::bitruncated}, + {"{8,3}", "none", "{8,3} (like standard but with octagons)", "oct", 8, 3, 0, gcHyperbolic, 0x08000, {{6, 4}}, eVariation::bitruncated}, + {"{5,4}", "none", "{5,4} (four pentagons)", "4x5", 5, 4, 0, gcHyperbolic, 0x08200, {{6, 4}}, eVariation::bitruncated}, + {"{6,4}", "none", "{6,4} (four hexagons)", "4x6", 6, 4, 0, gcHyperbolic, 0x08400, {{5, 3}}, eVariation::bitruncated}, + {"{7,4}", "none", "{7,4} (four heptagons)", "4x7", 7, 4, 0, gcHyperbolic, 0x08600, {{4, 3}}, eVariation::bitruncated}, + {"{4,3}", "none", "{4,3} (cube)", "3x4", 4, 3, qsSMALLB, gcSphere, 0x10000, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{3,3}", "none", "{3,3} (tetrahedron)", "3x3", 3, 3, qsSMALLB, gcSphere, 0x10200, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{4,4}", "none", "{4,4} (Euclidean square grid)", "4x4", 4, 4, 0, gcEuclid, 0x10400, {{7, 7}}, eVariation::bitruncated}, + {"{4,3}", "elliptic", "elliptic geometry in {4,3}", "e3x4", 4, 3, qsNONOR, gcSphere, 0x10600, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{7,3}", "Klein", "Klein Quartic", "Klein", 7, 3, qsSMALL, gcHyperbolic, 0x18000, {{7, 5}}, eVariation::bitruncated}, + {"{8,3}", "Bolza", "Bolza Surface", "Bolza", 8, 3, qsDOCKS, gcHyperbolic, 0x18200, {{6, 4}}, eVariation::bitruncated}, + {"{8,3}", "Bolza2", "Bolza Surface x2", "Bolza2", 8, 3, qsDOCKS, gcHyperbolic, 0x18400, {{6, 4}}, eVariation::bitruncated}, + {"{7,3}", "minimal", "minimal quotient", "minimal", 7, 3, qsSMALLN, gcHyperbolic, 0x18600, {{7, 5}}, eVariation::bitruncated}, + {"binary","none", "variant of the binary tiling", "binary", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}, eVariation::pure}, + {"Arch", "none", "Archimedean", "A", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}, eVariation::pure}, + {"{7,3}", "Macbeath", "Macbeath Surface", "Macbeath", 7, 3, qsSMALL, gcHyperbolic, 0x20000, {{7, 5}}, eVariation::bitruncated}, + {"{5,4}", "Bring", "Bring's Surface", "Bring", 5, 4, qsSMALL, gcHyperbolic, 0x20200, {{6, 4}}, eVariation::bitruncated}, + {"{12,3}","M3", "Schmutz's M(3)", "M3", 12, 3, qsSMALL, gcHyperbolic, 0x20400, {{4, 2}}, eVariation::bitruncated}, + {"{12,3}","M4", "Schmutz's M(4)", "M4", 12, 3, qsSMALL, gcHyperbolic, 0x20600, {{4, 2}}, eVariation::bitruncated}, + {"{6,4}", "Crystal", "dimensional crystal", "Crystal", 6, 4, qANYQ, gcHyperbolic, 0x28000, {{5, 3}}, eVariation::pure}, + {"{3,4}", "none", "{3,4} (octahedron)", "4x3", 3, 4, qsSMALLB, gcSphere, 0x28200, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, }; // remember to match the following mask when specifying codes for extra geometries: 0x78600 diff --git a/classes.h b/classes.h index d64341fb..c43c04f1 100644 --- a/classes.h +++ b/classes.h @@ -217,7 +217,9 @@ enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere }; enum class eVariation { bitruncated, pure, goldberg, irregular, dual }; struct geometryinfo { - const char* name; + const char* tiling_name; + const char* quotient_name; + const char* menu_displayed_name; const char* shortname; int sides; int vertex; diff --git a/crystal.cpp b/crystal.cpp index be8431f3..893a4878 100644 --- a/crystal.cpp +++ b/crystal.cpp @@ -1000,6 +1000,9 @@ void set_crystal(int sides) { set_variation(eVariation::pure); ginf[gCrystal].sides = sides; ginf[gCrystal].vertex = 4; + static char buf[20]; + sprintf(buf, "{%d,4}", sides); + ginf[gCrystal].tiling_name = buf; need_reset_geometry = true; if(sides < MAX_EDGE) ginf[gCrystal].distlimit = distlimit_table[sides]; diff --git a/expansion.cpp b/expansion.cpp index c8c69ea0..85a8250a 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -738,7 +738,7 @@ int expansion_hook = addHook(hooks_handleKey, 0, expansion_handleKey); #if !CAP_MINI void compute_coefficients() { - printf("%s %s\n", gp::operation_name().c_str(), ginf[geometry].name); + printf("%s %s\n", gp::operation_name().c_str(), ginf[geometry].tiling_name); start_game(); printf(" sizes:"); diff --git a/fieldpattern.cpp b/fieldpattern.cpp index 9c0b8484..6efc095a 100644 --- a/fieldpattern.cpp +++ b/fieldpattern.cpp @@ -778,6 +778,7 @@ void enableFieldChange() { ginf[geometry].sides = ginf[gxcur.base].sides; ginf[geometry].vertex = ginf[gxcur.base].vertex; ginf[geometry].distlimit = ginf[gxcur.base].distlimit; + ginf[geometry].tiling_name = ginf[gxcur.base].tiling_name; fieldpattern::current_quotient_field.init(gxcur.primes[gxcur.current_prime_id].p); } diff --git a/geom-exp.cpp b/geom-exp.cpp index 6e30dd2d..51848fe4 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -32,8 +32,6 @@ string euchelp = "* Halloween is specially designed for spherical geometry.\n" "* To see the difference, try Hunting Grounds in Euclidean -- it is impossible.\n"; -int ewhichscreen = 2; - void showQuotientConfig() { using namespace fieldpattern; gamescreen(2); @@ -41,7 +39,7 @@ void showQuotientConfig() { fgeomextra& gxcur = fgeomextras[current_extra]; for(int i=0; i= 25) landvisited[i] = true; landvisited[laCrossroads] = true; @@ -299,348 +301,385 @@ void showEuclideanMenu() { landvisited[laSnakeNest] |= landvisited[laRedRock]; landvisited[laCamelot] |= hiitemsMax(treasureType(laCamelot)) >= 1; landvisited[laCA] = true; + + dialog::init(XLAT("experiment with geometry")); + + // dialog::addSelItem(XLAT("geometry"), XLAT(bitruncnames[int(variation)]), '5'); + // dialog::addBreak(50); + + generateLandList([] (eLand l) { return land_validity(l).flags & lv::appears_in_geom_exp; }); + stable_sort(landlist.begin(), landlist.end(), [] (eLand l1, eLand l2) { return land_validity(l1).quality_level > land_validity(l2).quality_level; }); + + for(int i=0; i= isize(landlist)) { dialog::addBreak(100); break; } + eLand l = landlist[euperpage * eupage + i]; + char ch; + if(i < 26) ch = 'a' + i; + else ch = 'A' + (i-26); + string s = XLAT1(linf[l].name); + + if(landvisited[l]) { + dialog::addBoolItem(s, l == specialland, ch); + } + else { + dialog::addSelItem(s, XLAT("(locked)"), ch); + } + + dialog::lastItem().color = linf[l].color; + dialog::lastItem().value += validclasses[land_validity(l).quality_level]; + dialog::add_action([l] { + if(landvisited[l]) dialog::do_if_confirmed([l] { + stop_game_and_switch_mode(tactic::on ? rg::tactic : rg::nothing); + firstland = specialland = l; + start_game(); + popScreen(); + }); + }); + } + dialog::addBreak(50); + if(chaosUnlocked && !quotient && !euclid && !sphere) { + dialog::addItem(XLAT("Chaos mode"), '1'); + dialog::add_action([] { + if(chaosUnlocked) dialog::do_if_confirmed([] { + stop_game_and_switch_mode(rg::chaos); + start_game(); + }); + }); + } + dialog::addItem(XLAT("next page"), '-'); + + dialog::addBreak(25); + validity_info(); + dialog::addBreak(25); + + dialog::addBack(); + dialog::display(); + + keyhandler = [] (int sym, int uni) { + dialog::handleNavigation(sym, uni); + + if(uni == '-' || uni == PSEUDOKEY_WHEELUP || uni == PSEUDOKEY_WHEELDOWN) { + eupage++; + if(eupage * euperpage >= isize(landlist)) eupage = 0; + } + else if(doexiton(sym, uni)) popScreen(); + }; + } + +vector tilinglist = { + gTinySphere, gSmallSphere, gSphere, gEuclid, gNormal, gOctagon, + gOctahedron, gEuclidSquare, g45, g46, g47, + gArchimedean, gBinaryTiling + }; + +vector quotientlist = { + gElliptic, + gZebraQuotient, gFieldQuotient, gTorus, + gSmallElliptic, + gKleinQuartic, gBolza, gBolza2, gMinimal, + gMacbeath, gBring, gSchmutzM2, gSchmutzM3, gCrystal + }; + +void ge_select_tiling(const vector& lst) { + cmode = sm::SIDE | sm::MAYDARK; + gamescreen(0); + + dialog::init(XLAT("experiment with geometry")); + + char letter = 'a'; + for(eGeometry i: lst) { + bool on = geometry == i; + dynamicval cg(geometry, eGeometry(i)); + dialog::addBoolItem(XLAT(ginf[i].menu_displayed_name), on, letter++); + dialog::lastItem().value += validclasses[land_validity(specialland).quality_level]; + dialog::add_action([i] { + eGeometry targetgeometry = eGeometry(i); + if(targetgeometry == gCrystal) + pushScreen(crystal::show); + else if(targetgeometry == gArchimedean) + pushScreen(arcm::show); + else dialog::do_if_confirmed([targetgeometry] () { + set_geometry(targetgeometry); + start_game(); + if(euwrap) { + prepare_torusconfig(); + pushScreen(showTorusConfig); + } + if(geometry == gFieldQuotient) { + pushScreen(showQuotientConfig); + } + }); + }); + } + + dialog::addBack(); + dialog::display(); + } + +string current_proj_name() { + if(pmodel != mdDisk) + return conformal::get_model_name(pmodel); + else if(hyperbolic && vid.alpha == 1) + return "Poincaré"; + else if(hyperbolic && vid.alpha == 0) + return "Klein"; + else if(hyperbolic && vid.alpha == -1) + return "inverted Poincaré"; + else if(sphere && vid.alpha == 1) + return "stereographic"; + else if(sphere && vid.alpha == 0) + return "gnomonic"; + else + return "generalized perspective"; + } + +void showEuclideanMenu() { // for(int i=2; i cg(geometry, eGeometry(i)); - if(!!(quotient || elliptic || euwrap) != showquotients) continue; - dialog::addBoolItem(XLAT(ginf[i].name), on, letter++); - dialog::lastItem().value += validclasses[land_validity(specialland).quality_level]; - dialog::add_action([i] { - eGeometry targetgeometry = eGeometry(i); - if(targetgeometry == gCrystal) - pushScreen(crystal::show); - else if(targetgeometry == gArchimedean) - pushScreen(arcm::show); - else dialog::do_if_confirmed([targetgeometry] () { - set_geometry(targetgeometry); - start_game(); - }); - }); - } - - dialog::addBreak(50); - dialog::addBoolItem(XLAT("show quotient spaces"), showquotients, 'z'); - dialog::addBreak(50); + dialog::init(XLAT("experiment with geometry")); - 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::addSelItem(XLAT("basic tiling"), XLAT(ginf[geometry].tiling_name), 't'); + dialog::add_action([] { pushScreen([] { ge_select_tiling(tilinglist); }); }); + + int ts = ginf[geometry].sides; + int tv = ginf[geometry].vertex; + int nom = (BITRUNCATED ? tv+ts : tv) * 4; + int denom = (2*ts + 2*tv - ts * tv); + + if(GOLDBERG && S3) + nom = 2 * (2*tv + ts * (gp::area-1)); + + if(GOLDBERG && S3 == 4) + nom = 2 * (2*tv + 2 * ts * (gp::area-1)); + + int worldsize; + + int euler = 0; + if(euclid) euler = 0; + else if(sphere && nonorientable) euler = 1; + else if(sphere) euler = 2; + else if(!bounded) euler = -2; + else switch(geometry) { + case gFieldQuotient: + worldsize = isize(currentmap->allcells()); + euler = 2 * worldsize * denom / nom; + break; + + case gMinimal: + euler = -1; + break; + + case gZebraQuotient: + case gBolza: + euler = -2; + break; + + case gKleinQuartic: + case gSchmutzM2: + case gBolza2: + euler = -4; + break; + + case gSchmutzM3: + case gBring: + euler = -6; + break; + + case gMacbeath: + euler = -12; + break; + + default: + println(hlog, "warning: Euler characteristics unknown"); + break; + } + + nom *= euler; + denom *= 2; + + int g = gcd(nom, denom); + if(g) { + nom /= g; + denom /= g; + } + + if(fulltorus) { + using namespace torusconfig; + auto& mode = tmodes[torus_mode]; + if(mode.flags & TF_SINGLE) + worldsize = qty; else - dialog::addSelItem(XLAT("variations"), gp::operation_name(), 'v'); + worldsize = sdx * sdy; + } + else worldsize = denom ? nom / denom : 0; - dialog::addBreak(25); - validity_info(); - dialog::addBreak(25); - - int worldsize; - - int euler = 0; - if(euclid) euler = 0; - else if(sphere && nonorientable) euler = 1; - else if(sphere) euler = 2; - else if(!bounded) euler = -2; - else switch(geometry) { - case gFieldQuotient: - worldsize = isize(currentmap->allcells()); - euler = 2 * worldsize * denom / nom; - break; - - case gMinimal: - euler = -1; - break; - - case gZebraQuotient: - case gBolza: - euler = -2; - break; - - case gKleinQuartic: - case gSchmutzM2: - case gBolza2: - euler = -4; - break; - - case gSchmutzM3: - case gBring: - euler = -6; - break; - - case gMacbeath: - euler = -12; - break; - - default: - println(hlog, "warning: Euler characteristics unknown"); - break; - } - - nom *= euler; - denom *= 2; - - int g = gcd(nom, denom); - if(g) { - nom /= g; - denom /= g; - } - - if(fulltorus) { - using namespace torusconfig; - auto& mode = tmodes[torus_mode]; - if(mode.flags & TF_SINGLE) - worldsize = qty; - else - worldsize = sdx * sdy; - } - else worldsize = denom ? nom / denom : 0; - - if(euler < 0 && !bounded) - worldsize = -worldsize; + if(euler < 0 && !bounded) + worldsize = -worldsize; - string spf = its(ts); - if(archimedean) { - spf = ""; - for(int i: arcm::current.faces) { - if(spf != "") spf += ","; - spf += its(i); - } - if(BITRUNCATED) spf = "[" + spf + "]," + its(arcm::current.N * 2) + "," + its(arcm::current.N * 2); - if(DUAL) spf = its(arcm::current.N) + "^[" + spf + "]"; + string spf = its(ts); + if(archimedean) { + spf = ""; + for(int i: arcm::current.faces) { + if(spf != "") spf += ","; + spf += its(i); } - else if(binarytiling) - spf = "6,[6,7],7"; - else if(BITRUNCATED && !euclid6) - spf = spf + "," + its(S6) + "," + its(S6); - else if(IRREGULAR && irr::bitruncations_performed) - spf = "[4..8],6,6"; - else if(IRREGULAR) - spf = "[4..8]^3"; - else if(GOLDBERG && S3 == 4 && gp::param == gp::loc(1, 1)) - spf = spf + ",4," + spf + ",4"; - else if(GOLDBERG && S3 == 4 && gp::param == gp::loc(2, 0)) - spf = spf + ",4,4,4"; - else if(GOLDBERG && S3 == 4) - spf = "[" + spf + ",4],4,4,4"; - else if(GOLDBERG && S3 == 3) - spf = "[" + spf + ",6],6,6"; - else { - string spf0 = spf; - for(int z=1; zallcells())) : - geometry == gCrystal ? "∞^" + its(ts/2) : - worldsize < 0 ? (nom%denom ? its(nom)+"/"+its(denom) : its(-worldsize)) + " exp(∞)": - (euwrap && !fulltorus) ? "∞" : - worldsize == 0 ? "∞²" : - its(worldsize), - '3'); + dialog::add_action([] { pushScreen([] { ge_select_tiling(quotientlist); }); }); - if(bounded) { - dialog::addSelItem(XLAT("Euler characteristics"), its(euler), 0); - if(nonorientable) - dialog::addSelItem(XLAT("demigenus"), its(2-euler), 0); - else - dialog::addSelItem(XLAT("genus"), its((2-euler)/2), 0); - } - else dialog::addBreak(200); - - switch(ginf[geometry].cclass) { - case 0: - dialog::addSelItem(XLAT("Curvature"), XLAT("hyperbolic"), 0); - break; - - case 1: - dialog::addSelItem(XLAT("Curvature"), XLAT("flat"), 0); - break; - - case 2: - dialog::addSelItem(XLAT("Curvature"), XLAT("spherical"), 0); - break; - } - - if(sphere) - dialog::addBoolItem(XLAT("stereographic/orthogonal"), vid.alpha>10, '1'); - else - dialog::addBoolItem(XLAT("Poincaré/Klein"), vid.alpha>.5, '1'); - if(euwrap || geometry == gFieldQuotient) - dialog::addItem(XLAT("advanced parameters"), '4'); - dialog::addHelp(); - dialog::addBack(); - dialog::display(); + if(hyperbolic && IRREGULAR) { + nom = isize(irr::cells); + // both Klein Quartic and Bolza2 are double the Zebra quotiennt + denom = -2; + if(!quotient) worldsize = nom / denom; + } - keyhandler = [] (int sym, int uni) { - dialog::handleNavigation(sym, uni); - if(uni == 'z') - showquotients = !showquotients; - else if(uni == 'v') { - if(euclid6) ; - else if(archimedean) arcm::next_variation(); - else if(binarytiling) { - dialog::editNumber(vid.binary_width, 0, 2, 0.1, 1, XLAT("binary tiling width"), ""); - dialog::reaction = [] () { - need_reset_geometry = true; - #if CAP_TEXTURE - texture::config.remap(); - #endif - }; - } - else if(euclid4) dialog::do_if_confirmed([] { - set_variation(PURE ? eVariation::bitruncated : eVariation::pure); - start_game(); - }); - else // if(S3 == 3) - gp::configure(); - } - else if(uni == '2' || sym == SDLK_F1) gotoHelp(euchelp); - else if(uni == '3' && !viewdists) { enable_viewdists(); pushScreen(viewdist_configure_dialog); } - else if(uni == '3' && viewdists) { viewdists = false; } - else if(uni == '1' && !euclid) { - if(sphere) { - if(vid.alpha < 10) { vid.alpha = 999; vid.scale = 998; } - else {vid.alpha = 1; vid.scale = .4; } - } - else { - if(vid.alpha > .5) { vid.alpha = 0; vid.scale = 1; } - else {vid.alpha = 1; vid.scale = 1; } - } - } - else if(uni == '5') - ewhichscreen ^= 3; - else if(uni == '4') { - if(euwrap) - prepare_torusconfig(), - pushScreen(showTorusConfig); - else if(geometry == gFieldQuotient) - pushScreen(showQuotientConfig); - } - else if(doexiton(sym, uni)) - popScreen(); - }; + 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([] { + dialog::editNumber(vid.binary_width, 0, 2, 0.1, 1, XLAT("binary tiling width"), ""); + dialog::reaction = [] () { + need_reset_geometry = true; + #if CAP_TEXTURE + texture::config.remap(); + #endif + }; + }); } else { - dialog::init(XLAT("experiment with geometry")); - - dialog::addSelItem(XLAT("geometry"), XLAT(ginf[geometry].name) + XLAT(bitruncnames[int(variation)]), '5'); - dialog::addBreak(50); - - generateLandList([] (eLand l) { return land_validity(l).flags & lv::appears_in_geom_exp; }); - stable_sort(landlist.begin(), landlist.end(), [] (eLand l1, eLand l2) { return land_validity(l1).quality_level > land_validity(l2).quality_level; }); - - for(int i=0; i= isize(landlist)) { dialog::addBreak(100); break; } - eLand l = landlist[euperpage * eupage + i]; - char ch; - if(i < 26) ch = 'a' + i; - else ch = 'A' + (i-26); - string s = XLAT1(linf[l].name); - - if(landvisited[l]) { - dialog::addBoolItem(s, l == specialland, ch); - } - else { - dialog::addSelItem(s, XLAT("(locked)"), ch); - } - - dialog::lastItem().color = linf[l].color; - dialog::lastItem().value += validclasses[land_validity(l).quality_level]; - } - dialog::addBreak(50); - if(chaosUnlocked && !quotient && !euclid && !sphere) - dialog::addItem(XLAT("Chaos mode"), '1'); - dialog::addItem(XLAT("next page"), '-'); - - dialog::addBreak(25); - validity_info(); - dialog::addBreak(25); - - dialog::addHelp(); - dialog::addBack(); - dialog::display(); - - keyhandler = [] (int sym, int uni) { - dialog::handleNavigation(sym, uni); - int lid; - if(uni >= 'a' && uni <= 'z') lid = uni - 'a'; - else if(uni >= 'A' && uni <= 'Z') lid = 26 + uni - 'A'; - else lid = -1; - - if(lid >= 0) lid += euperpage * eupage; - - if(uni == '5') - ewhichscreen ^= 3; - else if(uni == '-' || uni == PSEUDOKEY_WHEELUP || uni == PSEUDOKEY_WHEELDOWN) { - eupage++; - if(eupage * euperpage >= isize(landlist)) eupage = 0; - } - else if(uni == '1') { - if(chaosUnlocked) dialog::do_if_confirmed([] { - stop_game_and_switch_mode(rg::chaos); - start_game(); - }); - } - else if(lid >= 0 && lid < isize(landlist)) { - eLand nland = landlist[lid]; - if(landvisited[nland]) dialog::do_if_confirmed([nland] { - stop_game_and_switch_mode(tactic::on ? rg::tactic : rg::nothing); - firstland = specialland = nland; - start_game(); - }); - } - else if(uni == '2' || sym == SDLK_F1) gotoHelp(euchelp); - else if(doexiton(sym, uni)) popScreen(); - }; + dialog::addSelItem(XLAT("variations"), gp::operation_name(), 'v'); + dialog::add_action([] { + if(euclid6) ; + else if(archimedean) arcm::next_variation(); + else if(euclid4) dialog::do_if_confirmed([] { + set_variation(PURE ? eVariation::bitruncated : eVariation::pure); + start_game(); + }); + else // if(S3 == 3) + gp::configure(); + }); } + + + if(euwrap || geometry == gFieldQuotient) { + dialog::addItem(XLAT("advanced parameters"), '4'); + dialog::add_action([] { + if(archimedean) + pushScreen(arcm::show); + else if(geometry == gCrystal) + pushScreen(crystal::show); + else if(euwrap) + prepare_torusconfig(), + pushScreen(showTorusConfig); + else if(geometry == gFieldQuotient) + pushScreen(showQuotientConfig); + }); + } + else dialog::addBreak(100); + + dialog::addBreak(50); + + dialog::addSelItem(XLAT("land"), XLAT1(linf[specialland].name), 'l'); + dialog::add_action([] { pushScreen(ge_land_selection); }); + dialog::addBoolItem(XLAT("pattern"), specialland == laCanvas, 'p'); + if(specialland == laCanvas) dialog::lastItem().value = patterns::whichCanvas; + dialog::add_action([] { pushScreen(patterns::showPrePattern); }); + validity_info(); + dialog::addSelItem(XLAT("projection"), current_proj_name(), '1'); + dialog::add_action([] { pushScreen(conformal::model_menu); }); + + dialog::addBreak(50); + + dialog::addItem(XLAT("take picture"), 's'); + dialog::add_action([] { pushScreen(shot::menu); }); + dialog::addHelp(); + dialog::addBack(); + + dialog::addBreak(150); + + string fgname = XLAT(ginf[geometry].tiling_name); + if(qstring != "none") fgname += " " + XLAT(qstring); + if(!euclid6) fgname = gp::operation_name() + " " + fgname; + + dialog::addTitle(XLAT("info about: %1", fgname), 0xFFFFFF, 150); + + dialog::addSelItem(XLAT("faces per vertex"), spf, 0); + + dialog::addSelItem(XLAT("size of the world"), + binarytiling ? fts4(8 * M_PI * sqrt(2) * log(2) / vid.binary_width) + " exp(∞)" : + archimedean ? arcm::current.world_size() : + (archimedean && sphere) ? its(isize(currentmap->allcells())) : + geometry == gCrystal ? "∞^" + its(ts/2) : + worldsize < 0 ? (nom%denom ? its(nom)+"/"+its(denom) : its(-worldsize)) + " exp(∞)": + (euwrap && !fulltorus) ? "∞" : + worldsize == 0 ? "∞²" : + its(worldsize), + '3'); + + dialog::add_action([] { + if(!viewdists) { enable_viewdists(); pushScreen(viewdist_configure_dialog); } + else if(viewdists) viewdists = false; + }); + + if(bounded) { + dialog::addSelItem(XLAT("Euler characteristics"), its(euler), 0); + if(nonorientable) + dialog::addSelItem(XLAT("demigenus"), its(2-euler), 0); + else + dialog::addSelItem(XLAT("genus"), its((2-euler)/2), 0); + } + else dialog::addBreak(200); + + switch(ginf[geometry].cclass) { + case 0: + dialog::addSelItem(XLAT("Curvature"), XLAT("hyperbolic"), 0); + break; + + case 1: + dialog::addSelItem(XLAT("Curvature"), XLAT("flat"), 0); + break; + + case 2: + dialog::addSelItem(XLAT("Curvature"), XLAT("spherical"), 0); + break; + } + + dialog::display(); } void runGeometryExperiments() { diff --git a/hyper.h b/hyper.h index 20266791..20a234e0 100644 --- a/hyper.h +++ b/hyper.h @@ -3499,8 +3499,6 @@ transmatrix rpushxto0(const hyperpoint& H); transmatrix spintox(const hyperpoint& H); transmatrix ypush(ld alpha); -extern int ewhichscreen; - #if CAP_SURFACE namespace surface { diff --git a/menus.cpp b/menus.cpp index 656824b9..2df73efd 100644 --- a/menus.cpp +++ b/menus.cpp @@ -779,7 +779,6 @@ void showStartMenu() { clearMessages(); welcomeMessage(); pushScreen(showEuclideanMenu); - ewhichscreen = 2; } else if(uni == 'c' || uni == 'i' || uni == 's' || uni == 'C' || uni == '7') { if(uni == 'C' && !chaosUnlocked) { diff --git a/pattern2.cpp b/pattern2.cpp index ee8bdc28..f408a54a 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -1910,7 +1910,7 @@ namespace patterns { if(cgroup != cpUnknown && cgroup < isize(cpatterns)) for(int j=0; j