diff --git a/cell.cpp b/cell.cpp index dd824eb9..5a3dc1c8 100644 --- a/cell.cpp +++ b/cell.cpp @@ -588,23 +588,120 @@ struct hrmap_quotient : hrmap { vector allh; hrmap_quotient() { + + static int symmask = (1<<30); - if(quotient == 2) { - connections = currfp.connections; - } - else { - heptspin hs; hs.h = base.origin; hs.spin = 0; - reachable.clear(); - bfsq.clear(); - connections.clear(); - add(hs); - - for(int i=0; i<(int)bfsq.size(); i++) { - hs = bfsq[i] + wstep; - add(hs); - connections.push_back(reachable[get(hs)]); + connections.clear(); + switch(geometry) { + case gFieldQuotient: { + connections = currfp.connections; + break; } - + + case gZebraQuotient: { + heptspin hs; hs.h = base.origin; hs.spin = 0; + reachable.clear(); + bfsq.clear(); + add(hs); + + for(int i=0; i<(int)bfsq.size(); i++) { + hs = bfsq[i] + wstep; + add(hs); + connections.push_back(reachable[get(hs)]); + } + break; + } + + case gMinimal: { + int altzebra[6][7] = { + { 16,125,111, 45, 32, 56, 20 }, + { 26,102,146,152, 35,124, 00 }, + { 06, 55,143,134,115,101, 10 }, + { 41, 50, 04, 44,123, 14,153 }, + { 51, 30,154,122, 33, 03,112 }, + { 31, 40,113,136,142, 21, 05 } + }; + + // int ok = 0; + for(int a=0; a<6; a++) { + for(int b=0; b<7; b++) { + int s = altzebra[a][b]; + int mirr = s/100; s %= 100; + int which = s/10; s %= 10; + + int shouldbe = a*10+b+mirr*100; + + if(altzebra[which][s] != shouldbe) { + printf("error at %d:%d (is=%d shouldbe=%d)\n", a, b, altzebra[which][s], shouldbe); + } + + connections.push_back(which * 7 + s + (mirr ? symmask : 0) ); + } + } + break; + } + + case gKleinQuartic: { + connections = { + /* 000 */ 7, 14, 21, 28, 35, 42, 49, + /* 001 */ 0, 55, 56, 63, 70, 77, 15, + /* 002 */ 1, 13, 83, 84, 91, 98, 22, + /* 003 */ 2, 20, 104, 105, 112, 119, 29, + /* 004 */ 3, 27, 125, 74, 126, 133, 36, + /* 005 */ 4, 34, 139, 95, 66, 140, 43, + /* 006 */ 5, 41, 146, 116, 87, 147, 50, + /* 007 */ 6, 48, 153, 130, 108, 57, 8, + /* 008 */ 9, 54, 107, 102, 154, 142, 64, + /* 009 */ 10, 62, 141, 39, 94, 161, 71, + /* 010 */ 11, 69, 167, 127, 31, 124, 78, + /* 011 */ 12, 76, 123, 158, 149, 85, 16, + /* 012 */ 17, 82, 148, 46, 115, 163, 92, + /* 013 */ 18, 90, 162, 67, 38, 138, 99, + /* 014 */ 19, 97, 137, 155, 59, 106, 23, + /* 015 */ 24, 103, 58, 53, 129, 165, 113, + /* 016 */ 25, 111, 164, 88, 45, 145, 120, + /* 017 */ 26, 118, 144, 159, 79, 75, 30, + /* 018 */ 32, 73, 166, 109, 52, 152, 134, + /* 019 */ 33, 132, 151, 156, 100, 96, 37, + /* 020 */ 40, 65, 61, 160, 121, 117, 44, + /* 021 */ 47, 86, 81, 157, 135, 131, 51, + /* 022 */ 60, 101, 136, 150, 80, 122, 143, + /* 023 */ 68, 93, 89, 114, 110, 128, 72, + }; + break; + } + + case gBolza: { + connections = { + /* 000 */ 8, 16, 24, 32, 12, 20, 28, 36, + /* 001 */ 0, 35, 47, 21, 4, 39, 43, 17, + /* 002 */ 1, 15, 42, 29, 5, 11, 46, 25, + /* 003 */ 2, 23, 45, 37, 6, 19, 41, 33, + /* 004 */ 3, 31, 40, 9, 7, 27, 44, 13, + /* 005 */ 34, 30, 18, 14, 38, 26, 22, 10, + }; + break; + } + + case gBolza2: { + connections = { +/* 000 */ 16, 32, 48, 64, 24, 40, 56, 72, +/* 001 */ 20, 44, 52, 76, 28, 36, 60, 68, +/* 002 */ 0, 79, 83, 45, 8, 67, 95, 33, +/* 003 */ 4, 71, 87, 37, 12, 75, 91, 41, +/* 004 */ 1, 23, 94, 61, 13, 27, 86, 49, +/* 005 */ 5, 31, 90, 53, 9, 19, 82, 57, +/* 006 */ 2, 39, 85, 77, 10, 43, 89, 65, +/* 007 */ 6, 47, 81, 69, 14, 35, 93, 73, +/* 008 */ 3, 55, 88, 21, 15, 59, 80, 25, +/* 009 */ 7, 63, 92, 29, 11, 51, 84, 17, +/* 010 */ 70, 58, 46, 18, 78, 50, 38, 26, +/* 011 */ 66, 54, 42, 30, 74, 62, 34, 22, + }; + break; + } + + default: break; } int TOT = connections.size() / S7; @@ -632,13 +729,16 @@ struct hrmap_quotient : hrmap { h->c7 = newCell(S7, h); } for(int j=0; jmove[rv(j)] = allh[connections[i*S7+j]/S7]; - h->setspin(rv(j), rv(connections[i*S7+j]%S7)); + int co = connections[i*S7+j]; + bool swapped = co & symmask; + co &= ~symmask; + h->move[rv(j)] = allh[co/S7]; + h->setspin(rv(j), rv(co%S7) + (swapped ? 8 : 0)); } } for(int i=0; iemeraldval = allh[i]->alt->emeraldval; allh[i]->zebraval = allh[i]->alt->zebraval; allh[i]->fiftyval = allh[i]->alt->fiftyval; diff --git a/classes.cpp b/classes.cpp index 50044f32..041b217f 100644 --- a/classes.cpp +++ b/classes.cpp @@ -1658,11 +1658,13 @@ vector randlands = { laOvergrown, laWildWest, laWarpCoast, laRuins, laBull, laDragon, laReptile, laDocks }; +static const int qNONOR = qNONORIENTABLE; + geometryinfo ginf[gGUARD] = { {"standard", "HR", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}}, {"Euclidean", "euclid", 6, 3, 0, gcEuclid, 0, {{7, FORBIDDEN}}}, {"spherical", "sphere", 5, 3, 0, gcSphere, 0, {{SEE_ALL, SEE_ALL}}}, - {"elliptic", "elliptic", 5, 3, qELLIP, gcSphere, 0, {{SEE_ALL, SEE_ALL}}}, + {"elliptic", "elliptic", 5, 3, qNONOR, gcSphere, 0, {{SEE_ALL, SEE_ALL}}}, {"Zebra quotient", "Zebra", 7, 3, qZEBRA, gcHyperbolic, 0x00400, {{7, 5}}}, {"field quotient", "field", 7, 3, qFIELD, gcHyperbolic, 0x00200, {{7, 5}}}, {"torus/Klein bottle", "torus", 6, 3, qTORUS, gcEuclid, 0x00600, {{7, FORBIDDEN}}}, @@ -1673,7 +1675,11 @@ geometryinfo ginf[gGUARD] = { {"cube", "3x4", 4, 3, 0, gcSphere, 0x10000, {{SEE_ALL, SEE_ALL}}}, {"tetrahedron (buggy)", "3x3", 3, 3, 0, gcSphere, 0x10200, {{SEE_ALL, SEE_ALL}}}, {"square grid", "4x4", 4, 4, 0, gcEuclid, 0x10400, {{7, 7}}}, - {"cube/elliptic", "e3x4", 4, 3, qELLIP, gcSphere, 0x10600, {{SEE_ALL, SEE_ALL}}}, + {"cube/elliptic", "e3x4", 4, 3, qNONOR, gcSphere, 0x10600, {{SEE_ALL, SEE_ALL}}}, + {"Klein Quartic", "Klein", 7, 3, qSMALL, gcHyperbolic, 0x18000, {{7, 5}}}, + {"Bolza Surface", "Bolza", 8, 3, qSMALL | qDOCKS, gcHyperbolic, 0x18200, {{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}}}, }; } diff --git a/classes.h b/classes.h index c889d3c7..14f4981b 100644 --- a/classes.h +++ b/classes.h @@ -196,7 +196,10 @@ enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle laSwitch, laMemory, laBrownian }; -enum eGeometry {gNormal, gEuclid, gSphere, gElliptic, gQuotient, gQuotient2, gTorus, gOctagon, g45, g46, g47, gSmallSphere, gTinySphere, gEuclidSquare, gSmallElliptic, gGUARD}; +enum eGeometry { + gNormal, gEuclid, gSphere, gElliptic, gZebraQuotient, gFieldQuotient, gTorus, gOctagon, g45, g46, g47, gSmallSphere, gTinySphere, gEuclidSquare, gSmallElliptic, + gKleinQuartic, gBolza, gBolza2, gMinimal, + gGUARD}; enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere }; @@ -211,10 +214,12 @@ struct geometryinfo { std::array distlimit; // bitrunc, non-bitrunc }; -static const int qZEBRA = 1; +static const int qSMALL = 1; static const int qFIELD = 2; -static const int qELLIP = 4; +static const int qNONORIENTABLE = 4; static const int qTORUS = 8; +static const int qDOCKS = 16; +static const int qZEBRA = 32; // note: dnext assumes that x&7 equals 7 static const int SEE_ALL = 15; diff --git a/commandline.cpp b/commandline.cpp index ce6c42ee..14af33f1 100644 --- a/commandline.cpp +++ b/commandline.cpp @@ -322,8 +322,8 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { showstartmenu current_extra = a; fgeomextras[current_extra].current_prime_id = b; enableFieldChange(); - if(geometry != gQuotient2) { - targetgeometry = gQuotient2; stop_game_and_switch_mode(rg::geometry); + if(geometry != gFieldQuotient) { + targetgeometry = gFieldQuotient; stop_game_and_switch_mode(rg::geometry); } } else if(argis("-tpar")) { diff --git a/complex.cpp b/complex.cpp index 4c700f63..71c34d21 100644 --- a/complex.cpp +++ b/complex.cpp @@ -1062,7 +1062,7 @@ namespace mirror { static const int LIGHTNING = -1; // passed instead of cpid bool noMirrorOn(cell *c) { - return c->monst || (!shmup::on && isPlayerOn(c)) || (geometry != gQuotient2 && geometry != gTorus && c->cpdist > gamerange()); + return c->monst || (!shmup::on && isPlayerOn(c)) || (geometry != gFieldQuotient && geometry != gTorus && c->cpdist > gamerange()); } bool cellMirrorable(cell *c) { diff --git a/fieldpattern.cpp b/fieldpattern.cpp index 7c85080c..f8a4256c 100644 --- a/fieldpattern.cpp +++ b/fieldpattern.cpp @@ -771,7 +771,7 @@ void enableFieldChange() { fgeomextra& gxcur = fgeomextras[current_extra]; fieldpattern::quotient_field_changed = true; nextPrimes(gxcur); - dynamicval g(geometry, gQuotient2); + dynamicval g(geometry, gFieldQuotient); ginf[geometry].sides = ginf[gxcur.base].sides; ginf[geometry].vertex = ginf[gxcur.base].vertex; ginf[geometry].distlimit = ginf[gxcur.base].distlimit; diff --git a/game.cpp b/game.cpp index 6f7d87f7..2186ecc1 100644 --- a/game.cpp +++ b/game.cpp @@ -4274,7 +4274,7 @@ void moveWorm(cell *c) { else addMessage(XLAT("The sandworm explodes!")); playSound(NULL, "explosion"); - if(geometry == gQuotient) + if(geometry == gZebraQuotient) achievement_gain("ZEBRAWORM", rg::geometry); } return; diff --git a/geom-exp.cpp b/geom-exp.cpp index 01b3d7b6..24db27f1 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -75,13 +75,13 @@ void showQuotientConfig() { else if(uni == 'x' || uni == '\n') { targetgeometry = gxcur.base; stop_game_and_switch_mode(rg::geometry); enableFieldChange(); - targetgeometry = gQuotient2; stop_game_and_switch_mode(rg::geometry); + targetgeometry = gFieldQuotient; stop_game_and_switch_mode(rg::geometry); start_game(); } else if(uni == 'c') { targetgeometry = gEuclid; stop_game_and_switch_mode(rg::geometry); fieldpattern::quotient_field_changed = false; - targetgeometry = gQuotient2; stop_game_and_switch_mode(rg::geometry); + targetgeometry = gFieldQuotient; stop_game_and_switch_mode(rg::geometry); start_game(); } else if(doexiton(sym, uni)) @@ -229,6 +229,8 @@ void validity_info() { dialog::addBreak(100); } +bool showquotients; + void showEuclideanMenu() { cmode = sm::SIDE; gamescreen(0); @@ -258,7 +260,7 @@ void showEuclideanMenu() { int ts = ginf[geometry].sides; int tv = ginf[geometry].vertex; int tq = ginf[geometry].quotientstyle; - int nom = (nonbitrunc ? tv : tv+ts) * ((tq & qELLIP) ? 2 : 4); + int nom = (nonbitrunc ? tv : tv+ts) * ((tq & qNONORIENTABLE) ? 2 : 4); int denom = (2*ts + 2*tv - ts * tv); if(gp::on) { @@ -271,11 +273,14 @@ void showEuclideanMenu() { dialog::addBreak(50); for(int i=0; i cg(geometry, eGeometry(i)); + if(!!(quotient || elliptic || torus) != showquotients) continue; + dialog::addBoolItem(XLAT(ginf[i].name), on, 'a'+i); dialog::lastItem().value += validclasses[land_validity(specialland).quality_level]; } + dialog::addBoolItem(XLAT("show quotient spaces"), showquotients, 'u'); dialog::addBreak(50); if(ts == 6 && tv == 3) @@ -286,21 +291,48 @@ void showEuclideanMenu() { dialog::addBoolItem(XLAT("Goldberg"), nonbitrunc, 't'); dialog::lastItem().value = gp::operation_name(); } + dialog::addBreak(25); validity_info(); dialog::addBreak(25); - int worldsize = denom ? nom/denom : 0; - if(tq & qTORUS) worldsize = torusconfig::qty; - if(tq & qZEBRA) worldsize = - gp::on ? 12 + 14 * (gp::area - 1) : - nonbitrunc ? 12 : - 40; - if(tq & qFIELD) { - worldsize = size(currfp.matrices) / ts; - if(gp::on) worldsize = worldsize * (2*tv + ts * (gp::area-1)) / tv / 2; - else if(!nonbitrunc) worldsize = ((ts+tv)*worldsize) / tv; + int worldsize; + + int gar = + gp::on ? gp::area - 1 : + nonbitrunc ? 0 : + 2; + + switch(geometry) { + case gTorus: + worldsize = torusconfig::qty; + break; + + case gZebraQuotient: + worldsize = 12 + 14 * gar; + break; + + case gFieldQuotient: + worldsize = size(currfp.matrices) / ts; + worldsize = worldsize * (2*tv + ts * gar) / tv / 2; + break; + + case gKleinQuartic: + worldsize = 24 + 28 * gar; + break; + + case gBolza: + worldsize = 6 * (2*tv + ts * gar) / tv; + break; + + case gBolza2: + worldsize = 12 * (2*tv + ts * gar) / tv; + break; + + default: + worldsize = denom ? nom/denom : 0; + break; } dialog::addSelItem(XLAT("sides per face"), its(ts), 0); @@ -311,9 +343,11 @@ void showEuclideanMenu() { else if(tq & qFIELD) qstring = "field"; - else if(tq & qELLIP) qstring = "torus"; + else if((tq & qNONORIENTABLE) && sphere) qstring = "elliptic"; else if(tq & qTORUS) qstring = "torus"; + + else if(tq & qSMALL) qstring = ginf[geometry].shortname; dialog::addSelItem(XLAT("quotient space"), XLAT(qstring), 0); @@ -354,6 +388,8 @@ void showEuclideanMenu() { stop_game_and_switch_mode(geometry == targetgeometry ? rg::nothing : rg::geometry); start_game(); } + else if(uni == 'u') + showquotients = !showquotients; else if(uni == 't') { if(euclid6) ; else if(S3 == 3) diff --git a/goldberg.cpp b/goldberg.cpp index 544a3678..3c8f2f53 100644 --- a/goldberg.cpp +++ b/goldberg.cpp @@ -265,7 +265,7 @@ namespace hr { namespace gp { auto& ac2 = set_heptspin(vc[2], hs + 1 + wstep - 4); ac2.mindir = 1; - if(elliptic && param.first == param.second) { + if(nonorientable && param.first == param.second) { int x = param.first; if(ac1.cw.mirrored != hs.mirrored) ac1.cw--; if(ac2.cw.mirrored != hs.mirrored) ac2.cw--; @@ -535,8 +535,8 @@ namespace hr { namespace gp { auto old_tstate_max = texture::config.tstate_max; #endif xy = internal_representation(xy); - if(xy.second && xy.second != xy.first && elliptic) { - addMessage("This does not work in elliptic geometry"); + if(xy.second && xy.second != xy.first && nonorientable) { + addMessage(XLAT("This does not work in non-orientable geometries")); xy.second = 0; } config = human_representation(xy); diff --git a/hyper.h b/hyper.h index 1ba7f8ab..25bf9fe1 100644 --- a/hyper.h +++ b/hyper.h @@ -84,11 +84,12 @@ void addMessage(string s, char spamtype = 0); #define euclid (cgclass == gcEuclid) #define sphere (cgclass == gcSphere) #define hyperbolic (cgclass == gcHyperbolic) -#define elliptic (ginf[geometry].quotientstyle & qELLIP) -#define quotient (ginf[geometry].quotientstyle & (qZEBRA | qFIELD)) +#define nonorientable (ginf[geometry].quotientstyle & qNONORIENTABLE) +#define elliptic (sphere && nonorientable) +#define quotient (ginf[geometry].quotientstyle & (qSMALL | qFIELD | qDOCKS | qZEBRA)) #define torus (ginf[geometry].quotientstyle & qTORUS) #define doall (ginf[geometry].quotientstyle) -#define smallbounded (sphere || (quotient & qZEBRA) || torus) +#define smallbounded (sphere || (quotient & qSMALL) || torus) #define bounded (sphere || quotient || torus) #define a4 (S3 == 4) diff --git a/hypgraph.cpp b/hypgraph.cpp index 637b449d..c71b0aea 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -478,7 +478,7 @@ ld spherity(const transmatrix& V) { } bool confusingGeometry() { - return elliptic || quotient == 1 || torus; + return elliptic || (quotient & qSMALL) || torus; } ld master_to_c7_angle() { diff --git a/landlock.cpp b/landlock.cpp index b31b535b..f536584e 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -1089,10 +1089,10 @@ land_validity_t& land_validity(eLand l) { if(l != laElementalWall) return technical; // not good in Field quotient - if(quotient == 2) - return no_great_walls; - if(quotient == 1) + if(geometry == gZebraQuotient) return special_geo3; + if(quotient) + return no_great_walls; if(weirdhyperbolic) return simplified_walls; // works nice on a big non-tetrahedron-based sphere @@ -1101,7 +1101,7 @@ land_validity_t& land_validity(eLand l) { } // does not agree with the pattern - if(l == laStorms && quotient == 2) + if(l == laStorms && quotient && geometry != gZebraQuotient) return pattern_not_implemented_random; // pattern not implemented @@ -1228,7 +1228,7 @@ land_validity_t& land_validity(eLand l) { // works in most spheres, Zebra quotient, and stdeuc if(l == laWhirlwind) { - if(quotient == 1) + if(geometry == gZebraQuotient) return pattern_compatibility; if(stdeuc) ; else if(S7 == 4 && !nonbitrunc) return special_geo; @@ -1272,7 +1272,7 @@ land_validity_t& land_validity(eLand l) { return ugly_version; } - if(l == laWarpCoast && quotient == 2 && !randomPatternsMode) + if(l == laWarpCoast && quotient && geometry != gZebraQuotient && !randomPatternsMode) return pattern_incompatibility; // laPower and laEmerald and laPalace -> [partial] in quotients and hyperbolic_non37 @@ -1289,7 +1289,7 @@ land_validity_t& land_validity(eLand l) { if(l == laWineyard && (gp::on || sphere) && !randomPatternsMode) return pattern_not_implemented_random; - if(l == laTrollheim && quotient == 2) + if(l == laTrollheim && quotient == qFIELD) return not_enough_space; if(l == laStorms && hyperbolic_not37) @@ -1298,7 +1298,7 @@ land_validity_t& land_validity(eLand l) { if(l == laTrollheim && !stdeuc && !bounded) return some1; - if(l == laReptile && (a38 || a4 || sphere || nonbitrunc || gp::on || quotient == 2)) + if(l == laReptile && (a38 || a4 || sphere || nonbitrunc || gp::on || (quotient && geometry != gZebraQuotient))) return bad_graphics; if((l == laDragon || l == laReptile) && !stdeuc && !smallbounded && !randomPatternsMode) @@ -1321,7 +1321,7 @@ land_validity_t& land_validity(eLand l) { if(l == laCrossroads4 && quotient) return some0; - if(l == laZebra && quotient == 2 && !randomPatternsMode) + if(l == laZebra && quotient && geometry != gZebraQuotient && !randomPatternsMode) return pattern_incompatibility; if(l == laZebra && !(stdeuc || (a4 && nonbitrunc) || a46) && !randomPatternsMode) @@ -1332,7 +1332,7 @@ land_validity_t& land_validity(eLand l) { if(l == laPrairie) { if(gp::on) return not_implemented; - else if(stdeuc || (bigsphere && !nonbitrunc && !elliptic) || (quotient == 2)) ; + else if(stdeuc || (bigsphere && !nonbitrunc && !elliptic) || (geometry == gFieldQuotient)) ; else if(!bounded) return not_implemented; else return unbounded_only; } @@ -1345,11 +1345,15 @@ land_validity_t& land_validity(eLand l) { return full_game; // highlight Zebra-based lands on Zebra Quotient! - if((l == laZebra || l == laWhirlwind || l == laStorms || l == laWarpCoast || l == laWarpSea) && quotient == 1) + if((l == laZebra || l == laWhirlwind || l == laStorms || l == laWarpCoast || l == laWarpSea) && geometry == gZebraQuotient) return pattern_compatibility; // highlight FP-based lands on Field Quotient! - if((l == laPrairie || l == laVolcano || l == laBlizzard) && quotient == 2) + if((l == laPrairie || l == laVolcano || l == laBlizzard) && geometry == gFieldQuotient) + return pattern_compatibility; + + // highlight Docks-based lands on Bolza and Bolza x2! + if(l == laDocks && among(geometry, gBolza, gBolza2)) return pattern_compatibility; // these are highlighted whenever allowed @@ -1380,14 +1384,14 @@ land_validity_t& land_validity(eLand l) { if(l == laMagnetic || l == laBrownian) return land_not_implemented; - if(shmup::on && among(l, laMirror, laMirrorOld) && among(geometry, gElliptic, gQuotient)) + if(shmup::on && among(l, laMirror, laMirrorOld) && among(geometry, gElliptic, gZebraQuotient, gKleinQuartic, gBolza, gBolza2, gMinimal)) return known_buggy; // these don't appear in normal game, but do appear in special modes if(l == laWildWest && !randomPatternsMode) return out_of_theme; - if(l == laIce && !gp::on && hyperbolic_37) + if(l == laIce && !gp::on && hyperbolic_37 && !quotient) return full_game; return ok; diff --git a/mapeditor.cpp b/mapeditor.cpp index 29178df5..ccad5285 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -124,7 +124,7 @@ namespace mapstream { save(torusconfig::dx); save(torusconfig::dy); } - if(geometry == gQuotient2) { + if(geometry == gFieldQuotient) { using namespace fieldpattern; save(quotient_field_changed); if(quotient_field_changed) { @@ -216,7 +216,7 @@ namespace mapstream { load(torusconfig::dx); load(torusconfig::dy); } - if(geometry == gQuotient2) { + if(geometry == gFieldQuotient) { using namespace fieldpattern; load(quotient_field_changed); if(quotient_field_changed) { diff --git a/pattern2.cpp b/pattern2.cpp index 38f46e56..f6511fa6 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -626,7 +626,20 @@ namespace patterns { sp = gp::last_dir(c); sp ^= ishex2(c); } - si.id = 8 * ((c->master->fiftyval & 1) ^ (sp & 1)); + if(geometry == gBolza2) { + patterninfo si0; + patterninfo si1; + patterninfo si2; + val38(c->mov[0], si0, 0, PAT_COLORING); + val38(c->mov[2], si1, 0, PAT_COLORING); + val38(c->mov[4], si2, 0, PAT_COLORING); + if((si0.id+1) % 3 == (si1.id) % 3) + si.id = 8; + else + si.id = 0; + } + else + si.id = 8 * ((c->master->fiftyval & 1) ^ (sp & 1)); if(gp::on && pseudohept(c)) si.id = 4; bool dock = false; for(int i=0; itype; i+=2) { diff --git a/shmup.cpp b/shmup.cpp index a6115aec..bd00484a 100644 --- a/shmup.cpp +++ b/shmup.cpp @@ -1006,13 +1006,13 @@ cell *monster::findbase(const transmatrix& T) { } void monster::rebasePat(const transmatrix& new_pat) { - if(isVirtual) { + if(isVirtual) { at = new_pat; - virtualRebase(this, true); + virtualRebase(this, true); fixmatrix(at); pat = at; return; } - if(geometry == gQuotient || geometry == gTorus) { + if(among(geometry, gZebraQuotient, gTorus, gKleinQuartic, gBolza, gBolza2, gMinimal)) { at = inverse(gmatrix[base]) * new_pat; virtualRebase(this, true); fixmatrix(at); @@ -3408,7 +3408,7 @@ transmatrix calc_relative_matrix(cell *c2, cell *c1, int direction_hint) { //bool hsol = false; //transmatrix sol; while(h1 != h2) { - if(quotient == 1) { + if(quotient & qSMALL) { transmatrix T; hyperpoint hint = ddspin(c1, direction_hint) * xpush(1e-2) * C0; ld bestdist = 1e9; @@ -3427,7 +3427,7 @@ transmatrix calc_relative_matrix(cell *c2, cell *c1, int direction_hint) { if(curdist < bestdist) T = T1, bestdist = curdist; } } - return T; + if(bestdist < 1e8) return T; } for(int d=0; dmove[d] == h1) { int sp = h2->spin(d); diff --git a/yendor.cpp b/yendor.cpp index 745fa92e..10ff9f37 100644 --- a/yendor.cpp +++ b/yendor.cpp @@ -863,9 +863,11 @@ int modecode() { int mct = modecodetable[xcode][np]; +/* if(geometry == gTorus) mct += 512; - if(geometry == gQuotient) mct += 1024; - if(geometry == gQuotient2) mct += 1536; + if(geometry == gZebraQuotient) mct += 1024; + if(geometry == gFieldQuotient) mct += 1536; + */ #if CAP_INV if(inv::on) mct += 2048; #endif