1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-27 14:37:16 +00:00

new quotient geometries

This commit is contained in:
Zeno Rogue 2018-06-22 01:48:46 +02:00
parent 742828125e
commit 8f8a259992
16 changed files with 241 additions and 74 deletions

136
cell.cpp
View File

@ -588,23 +588,120 @@ struct hrmap_quotient : hrmap {
vector<heptagon*> 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; j<S7; j++) {
h->move[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; i<TOT; i++) {
generateAlts(allh[i], S3-3, false);
generateAlts(allh[i], geometry == gBolza2 ? 3 : S3-3, false);
allh[i]->emeraldval = allh[i]->alt->emeraldval;
allh[i]->zebraval = allh[i]->alt->zebraval;
allh[i]->fiftyval = allh[i]->alt->fiftyval;

View File

@ -1658,11 +1658,13 @@ vector<eLand> 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}}},
};
}

View File

@ -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<int,2> 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;

View File

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

View File

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

View File

@ -771,7 +771,7 @@ void enableFieldChange() {
fgeomextra& gxcur = fgeomextras[current_extra];
fieldpattern::quotient_field_changed = true;
nextPrimes(gxcur);
dynamicval<eGeometry> g(geometry, gQuotient2);
dynamicval<eGeometry> g(geometry, gFieldQuotient);
ginf[geometry].sides = ginf[gxcur.base].sides;
ginf[geometry].vertex = ginf[gxcur.base].vertex;
ginf[geometry].distlimit = ginf[gxcur.base].distlimit;

View File

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

View File

@ -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<gGUARD; i++) {
dialog::addBoolItem(XLAT(ginf[i].name), geometry == i, 'a'+i);
bool on = geometry == i;
dynamicval<eGeometry> 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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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; i<c->type; i+=2) {

View File

@ -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; d<S7; d++) if(h2->move[d] == h1) {
int sp = h2->spin(d);

View File

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