1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-25 01:20:37 +00:00

improvements to patterns; codenumbers also display directions

This commit is contained in:
Zeno Rogue 2017-12-09 08:06:41 +01:00
parent 4fa764c175
commit 9933f373d2
10 changed files with 529 additions and 463 deletions

View File

@ -524,6 +524,9 @@ void cwrevstep(cellwalker& cw) {
// very similar to createMove in heptagon.cpp // very similar to createMove in heptagon.cpp
cell *createMov(cell *c, int d) { cell *createMov(cell *c, int d) {
if(d<0 || d>= c->type) {
printf("ERROR createmov\n");
}
if(euclid && !c->mov[d]) { if(euclid && !c->mov[d]) {
eucoord x, y; eucoord x, y;
@ -641,6 +644,7 @@ void clearcell(cell *c) {
DEBMEM ( printf("mov %p [%p] S%d\n", c->mov[t], c->mov[t]->mov[c->spn(t)], c->spn(t)); ) DEBMEM ( printf("mov %p [%p] S%d\n", c->mov[t], c->mov[t]->mov[c->spn(t)], c->spn(t)); )
if(c->mov[t]->mov[c->spn(t)] != NULL && if(c->mov[t]->mov[c->spn(t)] != NULL &&
c->mov[t]->mov[c->spn(t)] != c) { c->mov[t]->mov[c->spn(t)] != c) {
printf("type = %d %d -> %d\n", c->type, t, c->spn(t));
printf("cell error\n"); printf("cell error\n");
exit(1); exit(1);
} }

View File

@ -82,12 +82,9 @@ int arg::readCommon() {
shift(); shift();
char *c = args(); char *c = args();
using namespace patterns; using namespace patterns;
sym01 = sym02 = sym03 = symRotation = false; subpattern_flags = 0;
while(*c) { while(*c) {
if(*c == '1') sym01 = true; if(*c >= '0' && *c <= '9') subpattern_flags ^= (*c - '0');
else if(*c == '2') sym02 = true;
else if(*c == '3') sym03 = true;
else if(*c == '0') symRotation = true;
else whichPattern = *c; else whichPattern = *c;
c++; c++;
} }

118
graph.cpp
View File

@ -2187,12 +2187,9 @@ int countMinesAround(cell *c) {
return mines; return mines;
} }
transmatrix applyPatterndir(cell *c, char patt = patterns::whichPattern) { transmatrix applyPatterndir(cell *c, const patterns::patterninfo& si) {
transmatrix V = ddspin(c, patterns::patterndir(c, patt), S42); transmatrix V = ddspin(c, si.dir, S42);
if(si.reflect) return V * Mirror;
if(patterns::reflectPatternAt(c, patt))
return V * Mirror;
return V; return V;
} }
@ -2238,42 +2235,40 @@ void drawZebraFloor(const transmatrix& V, cell *c, int col) {
qfloor(c, V, PLAINFLOOR, col); return; qfloor(c, V, PLAINFLOOR, col); return;
} }
int i = zebra40(c); auto si = patterns::getpatterninfo(c, 'z', patterns::SPF_SYM0123);
i &= ~3;
int j; int j;
if(nontruncated) j = 4; if(nontruncated) j = 4;
else if(i >=4 && i < 16) j = 2; else if(si.id >=4 && si.id < 16) j = 2;
else if(i >= 16 && i < 28) j = 1; else if(si.id >= 16 && si.id < 28) j = 1;
else if(i >= 28 && i < 40) j = 3; else if(si.id >= 28 && si.id < 40) j = 3;
else j = 0; else j = 0;
qfloor(c, V, applyPatterndir(c, 'z'), shZebra[j], col); qfloor(c, V, applyPatterndir(c, si), shZebra[j], col);
} }
void qplainfloor(cell *c, bool warp, const transmatrix &V, int col); void qplainfloor(cell *c, bool warp, const transmatrix &V, int col);
void drawReptileFloor(const transmatrix& V, cell *c, int col, bool usefloor) { void drawReptileFloor(const transmatrix& V, cell *c, int col, bool usefloor) {
int i = zebra40(c); auto si = patterns::getpatterninfo(c, 'z', patterns::SPF_SYM0123);
i &= ~3;
int j; int j;
if(!wmescher) j = 4; if(!wmescher) j = 4;
else if(nontruncated) j = 0; else if(nontruncated) j = 0;
else if(i < 4) j = 0; else if(si.id < 4) j = 0;
else if(i >=4 && i < 16) j = 1; else if(si.id >=4 && si.id < 16) j = 1;
else if(i >= 16 && i < 28) j = 2; else if(si.id >= 16 && si.id < 28) j = 2;
else if(i >= 28 && i < 40) j = 3; else if(si.id >= 28 && si.id < 40) j = 3;
else j = 4; else j = 4;
transmatrix V2 = V * applyPatterndir(c, 'z'); transmatrix D = applyPatterndir(c, si);
transmatrix V2 = V * D;
if(wmescher) { if(wmescher) {
if(usefloor) if(usefloor)
qfloor(c, V, applyPatterndir(c, 'z'), shReptile[j][0], darkena(col, 0, 0xFF)); qfloor(c, V, D, shReptile[j][0], darkena(col, 0, 0xFF));
else else
queuepoly(V2, shReptile[j][0], darkena(col, 0, 0xFF)); queuepoly(V2, shReptile[j][0], darkena(col, 0, 0xFF));
} }
@ -2317,24 +2312,26 @@ void drawReptileFloor(const transmatrix& V, cell *c, int col, bool usefloor) {
} }
void drawEmeraldFloor(const transmatrix& V, cell *c, int col) { void drawEmeraldFloor(const transmatrix& V, cell *c, int col) {
int j = -1;
if(!euclid && !nontruncated) { if(!euclid && !nontruncated) {
int i = emeraldval(c) & ~3; auto si = patterns::getpatterninfo(c, 'f', patterns::SPF_SYM0123);
if(i == 8) j = 0;
else if(i == 12) j = 1; int j = -1;
else if(i == 16) j = 2;
else if(i == 20) j = 3; if(si.id == 8) j = 0;
else if(i == 28) j = 4; else if(si.id == 12) j = 1;
else if(i == 36) j = 5; else if(si.id == 16) j = 2;
else if(si.id == 20) j = 3;
else if(si.id == 28) j = 4;
else if(si.id == 36) j = 5;
if(j >= 0) {
qfloor(c, V, applyPatterndir(c, si), shEmeraldFloor[j], col);
return;
}
} }
int ct6 = ctof(c); int ct6 = ctof(c);
qfloor(c, V, CAVEFLOOR, col);
if(j >= 0)
qfloor(c, V, applyPatterndir(c, 'f'), shEmeraldFloor[j], col);
else
qfloor(c, V, CAVEFLOOR, col);
} }
double fanframe; double fanframe;
@ -2856,8 +2853,10 @@ void floorShadow(cell *c, const transmatrix& V, int col, bool warp) {
else else
queuepolyat(V, shTriheptaFloorShadow[ctof(c)], col, PPR_WALLSHADOW); queuepolyat(V, shTriheptaFloorShadow[ctof(c)], col, PPR_WALLSHADOW);
} }
else else {
queuepolyat(V * applyPatterndir(c), shTriheptaFloorShadow[ctof(c)], col, PPR_WALLSHADOW); auto si = patterns::getpatterninfo(c, 0, 0);
queuepolyat(V * applyPatterndir(c, si), shTriheptaFloorShadow[ctof(c)], col, PPR_WALLSHADOW);
}
} }
else if(c->land == laDual && !nontruncated) { else if(c->land == laDual && !nontruncated) {
if(euclid && ishex1(c)) if(euclid && ishex1(c))
@ -2873,17 +2872,15 @@ void floorShadow(cell *c, const transmatrix& V, int col, bool warp) {
void plainfloor(cell *c, bool warp, const transmatrix &V, int col, int prio) { void plainfloor(cell *c, bool warp, const transmatrix &V, int col, int prio) {
if(warp) { if(warp) {
if(euclid) { if(euclid) {
/* if(ishex1(c))
queuepolyat(V * pispin * applyPatterndir(c), shTriheptaFloor[0], col, prio);
else
queuepolyat(V * applyPatterndir(c), shTriheptaFloor[ctof(c)], col, prio); */
if(ishex1(c)) if(ishex1(c))
queuepolyat(V * pispin, shTriheptaFloor[ctof(c)], col, prio); queuepolyat(V * pispin, shTriheptaFloor[ctof(c)], col, prio);
else else
queuepolyat(V, shTriheptaFloor[ctof(c)], col, prio); queuepolyat(V, shTriheptaFloor[ctof(c)], col, prio);
} }
else else {
queuepolyat(V * applyPatterndir(c), shTriheptaFloor[sphere ? ctof(c) : patterns::nopattern(c)], col, prio); auto si = patterns::getpatterninfo(c, 0, 0);
queuepolyat(V * applyPatterndir(c, si), shTriheptaFloor[sphere ? ctof(c) : si.id], col, prio);
}
} }
else if(c->land == laDual && !nontruncated) { else if(c->land == laDual && !nontruncated) {
if(euclid && ishex1(c)) if(euclid && ishex1(c))
@ -2900,14 +2897,8 @@ void qfloor_eswap(cell *c, const transmatrix& V, const hpcshape& sh, int col);
void qplainfloor(cell *c, bool warp, const transmatrix &V, int col) { void qplainfloor(cell *c, bool warp, const transmatrix &V, int col) {
if(warp) { if(warp) {
if(euclid) { auto si = patterns::getpatterninfo(c, 0, 0);
if(ishex1(c)) qfloor(c, V, applyPatterndir(c, si), shTriheptaFloor[si.id], col);
qfloor(c, V, applyPatterndir(c) * pispin, shTriheptaFloor[0], col);
else
qfloor(c, V, applyPatterndir(c), shTriheptaFloor[ctof(c)], col);
}
else
qfloor(c, V, applyPatterndir(c), shTriheptaFloor[sphere ? ctof(c) : patterns::nopattern(c)], col);
} }
else if(c->land == laDual && !nontruncated) else if(c->land == laDual && !nontruncated)
qfloor_eswap(c, V, shBigTriangle, col); qfloor_eswap(c, V, shBigTriangle, col);
@ -3503,7 +3494,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
// floor // floor
#if CAP_EDIT #if CAP_EDIT
transmatrix Vpdir = V * applyPatterndir(c); auto si = patterns::getpatterninfo0(c);
#endif #endif
bool eoh = euclid || nontruncated; bool eoh = euclid || nontruncated;
@ -3518,7 +3509,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
} }
#if CAP_EDIT #if CAP_EDIT
if(mapeditor::drawUserShape(Vpdir, mapeditor::cellShapeGroup(), patterns::realpattern(c), if(mapeditor::drawUserShape(V * applyPatterndir(c, si), mapeditor::cellShapeGroup(), si.id,
darkena(fcol, fd, (cmode & sm::DRAW) ? 0xC0 : 0xFF), c)); darkena(fcol, fd, (cmode & sm::DRAW) ? 0xC0 : 0xFF), c));
else if(patterns::whichShape == '7') { else if(patterns::whichShape == '7') {
@ -3675,10 +3666,9 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
} }
else if(isWarped(c) && !nontruncated && !shmup::on) { else if(isWarped(c) && !nontruncated && !shmup::on) {
int np = patterns::nopattern(c); auto si = patterns::getpatterninfo(c, 0, 0);
if(c->landparam == 1337) np = 0; // for the achievement screenshot if(si.id < 13)
if(np < 13) qfloor(c, Vf, applyPatterndir(c, si), shTriheptaFloor[si.id], darkena(fcol, fd, 0xFF));
qfloor(c, Vf, applyPatterndir(c), shTriheptaFloor[np], darkena(fcol, fd, 0xFF));
else else
qfloor(c, Vf, shFloor[ctof(c)], darkena(fcol, fd, 0xFF)); qfloor(c, Vf, shFloor[ctof(c)], darkena(fcol, fd, 0xFF));
} }
@ -3905,14 +3895,14 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
if(patterns::displaycodes) { if(patterns::displaycodes) {
int labeli = patterns::displaycodes == 1 ? patterns::realpattern(c) : patterns::subpattern(c); int pf = patterns::displaycodes == 2 ? patterns::subpattern_flags : 0;
string label = its(labeli); auto si = patterns::getpatterninfo(c, patterns::whichPattern, pf);
queuepoly(V * applyPatterndir(c,si), shAsymmetric, darkena(0x000000, 0, 0xC0));
string label = its(si.id);
queuestr(V, .5, label, 0xFF000000 + forecolor); queuestr(V, .5, label, 0xFF000000 + forecolor);
/* transmatrix V2 = V * applyPatterndir(c);
qfloor(c, V2, shNecro, 0x80808080);
qfloor(c, V2, shStatue, 0x80808080); */
} }
#endif #endif
@ -4582,7 +4572,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
#if CAP_EDIT #if CAP_EDIT
if((cmode & sm::MAP) && lmouseover && darken == 0 && if((cmode & sm::MAP) && lmouseover && darken == 0 &&
!mouseout() && !mouseout() &&
(patterns::whichPattern ? patterns::subpattern(c) == patterns::subpattern(lmouseover) : c == lmouseover)) { (patterns::whichPattern ? patterns::getpatterninfo0(c).id == patterns::getpatterninfo0(lmouseover).id : c == lmouseover)) {
queuecircle(V, .78, 0x00FFFFFF); queuecircle(V, .78, 0x00FFFFFF);
} }

45
hyper.h
View File

@ -654,17 +654,46 @@ extern struct SDL_Surface *s;
namespace patterns { namespace patterns {
extern char whichShape; extern char whichShape;
extern char whichPattern; extern char whichPattern;
extern bool symRotation, sym01, sym02, sym03;
static const char PAT_WARP = 0;
static const char PAT_ZEBRA = 'z';
static const char PAT_EMERALD = 'f';
static const char PAT_PALACE = 'p';
static const char PAT_FIELD = 'F';
static const char PAT_DOWN = 'H';
static const char PAT_COLORING = 'C';
static const char PAT_SIBLING = 'S';
extern int subpattern_flags;
static const int SPF_ROT = 1;
static const int SPF_SYM01 = 2;
static const int SPF_SYM02 = 4;
static const int SPF_SYM03 = 8;
static const int SPF_CHANGEROT = 16;
static const int SPF_TWOCOL = 32;
static const int SPF_SYM0123 = 14;
extern char whichCanvas; extern char whichCanvas;
extern int displaycodes; extern int displaycodes;
int generateCanvas(cell *c); int generateCanvas(cell *c);
int realpattern(cell *c, char w = whichPattern);
int patterndir(cell *c, char w = whichPattern); struct patterninfo {
bool reflectPatternAt(cell *c, char p = whichPattern); int id;
int subpattern(cell *c, char w = whichPattern); int dir;
bool reflect;
};
patterninfo getpatterninfo(cell *c, char pat, int sub);
patterninfo getpatterninfo0(cell *c) {
return getpatterninfo(c, whichPattern, subpattern_flags);
}
} }
namespace mapeditor { namespace mapeditor {
@ -1598,8 +1627,8 @@ void pushThumper(cell *th, cell *cto);
template<class T> T pick(T x, T y) { return hrand(2) ? x : y; } template<class T> T pick(T x, T y) { return hrand(2) ? x : y; }
template<class T> T pick(T x, T y, T z) { switch(hrand(3)) { case 0: return x; case 1: return y; case 2: return z; } return x; } template<class T> T pick(T x, T y, T z) { switch(hrand(3)) { case 0: return x; case 1: return y; case 2: return z; } return x; }
template<class T> T pick(T x, T y, T z, T v) { switch(hrand(4)) { case 0: return x; case 1: return y; case 2: return z; case 3: return v; } return x; } template<class T> T pick(T x, T y, T z, T v) { switch(hrand(4)) { case 0: return x; case 1: return y; case 2: return z; case 3: return v; } return x; }
template<class T, class... U> bool among(T x, T y) { return x == y; } template<class T, class V, class... U> bool among(T x, V y) { return x == y; }
template<class T, class... U> bool among(T x, T y, U... u) { return x==y || among(x,u...); } template<class T, class V, class... U> bool among(T x, V y, U... u) { return x==y || among(x,u...); }
eLand getNewSealand(eLand old); eLand getNewSealand(eLand old);
bool createOnSea(eLand old); bool createOnSea(eLand old);
@ -2335,3 +2364,5 @@ void queueline(const hyperpoint& H1, const hyperpoint& H2, int col, int prf = 0,
hyperpoint ddi0(ld dir, ld dist); hyperpoint ddi0(ld dir, ld dist);
extern ld tessf, crossf, hexf, hcrossf, hexhexdist, hexvdist, hepvdist, rhexf; extern ld tessf, crossf, hexf, hcrossf, hexhexdist, hexvdist, hepvdist, rhexf;
unsigned char& part(int& col, int i); unsigned char& part(int& col, int i);
transmatrix applyPatterndir(cell *c, const patterns::patterninfo& si);

View File

@ -356,6 +356,7 @@ void addMessage(string s, char spamtype = 0);
#define a45 (S3 == 4 && S7 == 5) #define a45 (S3 == 4 && S7 == 5)
#define a46 (S3 == 4 && S7 == 6) #define a46 (S3 == 4 && S7 == 6)
#define a47 (S3 == 4 && S7 == 7) #define a47 (S3 == 4 && S7 == 7)
#define a457 (S3 == 4 && S7 != 6)
#define a467 (S3 == 4 && S7 >= 6) #define a467 (S3 == 4 && S7 >= 6)
#define a38 (S7 == 8) #define a38 (S7 == 8)
#define sphere4 (sphere && S7 == 4) #define sphere4 (sphere && S7 == 4)

View File

@ -28,8 +28,8 @@ namespace mapeditor {
void applyModelcell(cell *c) { void applyModelcell(cell *c) {
if(patterns::whichPattern == 'H') return; if(patterns::whichPattern == 'H') return;
int i = patterns::realpattern(c); auto si = patterns::getpatterninfo0(c);
cell *c2 = modelcell[i]; cell *c2 = modelcell[si.id];
if(c2) { if(c2) {
c->wall = c2->wall; c->wall = c2->wall;
c->land = c2->land; c->land = c2->land;
@ -40,8 +40,11 @@ namespace mapeditor {
c->mondir = c2->mondir; c->mondir = c2->mondir;
c->stuntime = c2->stuntime; c->stuntime = c2->stuntime;
c->hitpoints = c2->hitpoints; c->hitpoints = c2->hitpoints;
if(c2->mondir != NODIR) if(c2->mondir != NODIR) {
c->mondir = (c2->mondir - patterns::patterndir(c2) + patterns::patterndir(c) + MODFIXER) % c->type; auto si2 = patterns::getpatterninfo0(c2);
c->mondir = (c2->mondir - si2.dir + si.dir + MODFIXER) % c->type;
// todo reflect
}
} }
} }
#endif #endif
@ -238,7 +241,7 @@ namespace mapstream {
c->hitpoints = loadChar(); c->hitpoints = loadChar();
if(patterns::whichPattern) if(patterns::whichPattern)
mapeditor::modelcell[patterns::realpattern(c)] = c; mapeditor::modelcell[patterns::getpatterninfo0(c).id] = c;
} }
int32_t whereami = loadInt(); int32_t whereami = loadInt();
@ -498,13 +501,15 @@ namespace mapeditor {
if(drawcell == cwt.c) return vid.cs.charid; if(drawcell == cwt.c) return vid.cs.charid;
if(drawcell->monst) return drawcell->monst; if(drawcell->monst) return drawcell->monst;
if(drawcell->item) return drawcell->item; if(drawcell->item) return drawcell->item;
return patterns::subpattern(drawcell); return patterns::getpatterninfo0(drawcell).id;
} }
bool editingShape(int group, int id) { bool editingShape(int group, int id) {
if(group != mapeditor::drawcellShapeGroup()) return false; if(group != mapeditor::drawcellShapeGroup()) return false;
if(group < 3) return id == drawcellShapeID(); if(group < 3) return id == drawcellShapeID();
return patterns::subpattern(id, patterns::whichPattern) == patterns::subpattern(drawcell); // todo fix this
return id == drawcellShapeID();
// return patterns::getpatterninfo0(id).id == patterns::getpatterninfo0(drawcell).id;
} }
void editCell(const pair<cellwalker, cellwalker>& where) { void editCell(const pair<cellwalker, cellwalker>& where) {
@ -649,16 +654,17 @@ namespace mapeditor {
c3->aitmp = sval, v.push_back(c3); c3->aitmp = sval, v.push_back(c3);
} }
auto si = patterns::getpatterninfo0(where.c);
int cdir = where.spin; int cdir = where.spin;
if(cdir >= 0) if(cdir >= 0) cdir = cdir - si.dir;
cdir = cdir - patterns::patterndir(where.c);
int sp = patterns::subpattern(where.c);
for(cell* c2: v) for(cell* c2: v) {
if(patterns::subpattern(c2) == sp) { auto si2 = patterns::getpatterninfo0(c2);
editAt(cellwalker(c2, cdir>=0 ? fixdir(cdir + patterns::patterndir(c2), c2) : -1)); if(si2.id == si.id) {
modelcell[patterns::realpattern(c2)] = c2; editAt(cellwalker(c2, cdir>=0 ? fixdir(cdir + si2.dir, c2) : -1));
modelcell[si2.id] = c2;
} }
}
} }
cellwalker mouseover_cw(bool fix) { cellwalker mouseover_cw(bool fix) {
@ -903,7 +909,7 @@ namespace mapeditor {
default: default:
line1 = XLAT("floor/pattern"); line1 = XLAT("floor/pattern");
line2 = "#" + its(patterns::subpattern(drawcell)); line2 = "#" + its(patterns::getpatterninfo0(drawcell).id);
break; break;
} }

View File

@ -24,14 +24,8 @@ bool ishex1(cell *c) {
else return c->type != S6; else return c->type != S6;
} }
int val46(cell *c) {
return ctof(c) ? c->master->emeraldval :
((c->master->emeraldval & 1) ^ ((c->master->emeraldval & 2)>>1) ^ (c->spin(0)&1)) ? 8 : 4;
}
int emeraldval(cell *c) { int emeraldval(cell *c) {
if(euclid) return eupattern(c); if(euclid) return eupattern(c);
if(a46) return val46(c);
if(sphere) return 0; if(sphere) return 0;
if(ctof(c)) if(ctof(c))
return c->master->emeraldval >> 3; return c->master->emeraldval >> 3;
@ -68,13 +62,7 @@ int eufifty(cell *c) {
} }
} }
int val38(cell *c) {
if(ctof(c)) return (c->master->fiftyval >> 1) & 3;
else return 4 ^ (c->master->fiftyval & 1) ^ (c->spin(0) & 1);
}
int fiftyval(cell *c) { int fiftyval(cell *c) {
if(a38) return val38(c);
if(euclid) return eufifty(c) * 32; if(euclid) return eufifty(c) * 32;
if(sphere || S7>7 || S6>6) return 0; if(sphere || S7>7 || S6>6) return 0;
if(ctof(c)) if(ctof(c))
@ -180,10 +168,14 @@ int fiftyval049(cell *c) {
int dir_truncated457(cell *c) { int dir_truncated457(cell *c) {
int wset = 0; int wset = 0;
for(int i=0; i<4; i++) int has1 = 0;
if(zebra40(createMov(c, i*2))&2) wset |= (1<<i); for(int i=0; i<4; i++) {
if(wset == 0) return -8; int z = zebra40(createMov(c, i*2));
if(wset == 15) return -10; if(z&1) has1 = 1;
if(z&2) wset |= (1<<i);
}
if(wset == 0) return -8-has1;
if(wset == 15) return -10-has1;
if(wset == 3) return 1; if(wset == 3) return 1;
if(wset == 6) return 3; if(wset == 6) return 3;
if(wset == 12) return 5; if(wset == 12) return 5;
@ -191,14 +183,37 @@ int dir_truncated457(cell *c) {
return 0; return 0;
} }
int val46(cell *c);
int zebra40(cell *c) { int zebra40(cell *c) {
if(euclid) return eupattern(c); if(euclid) return eupattern(c);
else if(a46) return val46(c); else if(a46) {
int v = val46(c);
if(v<4) return v;
else return 4+(v-4)/2;
}
else if(ctof(c)) return (c->master->zebraval/10); else if(ctof(c)) return (c->master->zebraval/10);
else if(a4) { else if(a4) {
int ws = dir_truncated457(c); int ws = dir_truncated457(c);
if(ws < 0) return -ws; if(ws < 0) return -ws;
return 16 + (ws/2); int tot = 0;
array<int, 4> zebras;
for(int i=0; i<4; i++) {
zebras[i] = zebra40(createMov(c, i*2));
tot += zebras[i];
}
// break cycles
int cod = 0;
int mo = 0; for(int i=0; i<4; i++) if(zebras[i] < zebras[mo]) mo = i;
for(int i=0; i<4; i++) for(int j=1; j<i; j++)
if(zebras[(mo+i)&3] < zebras[(mo+j)&3]) cod ^= 4;
if(tot == 0+2+4+6) return 16+cod;
if(tot == 1+3+5+7) return 19+cod;
if(tot == 0+1+2+3) return 18+cod;
if(tot == 4+5+6+7) return 17+cod;
return 24;
} }
else if(sphere) return 0; else if(sphere) return 0;
else if(euclid) return eupattern(c); else if(euclid) return eupattern(c);
@ -349,70 +364,48 @@ int getHemisphere(cell *c, int which) {
} }
} }
struct sphereinfo { namespace patterns {
int id;
int dir;
bool reflect;
};
sphereinfo valsphere(cell *c) { void valSibling(cell *c, patterninfo& si, int sub) {
sphereinfo si; if(ctof(c)) {
if(ctof(c)) { int d = c->master->fieldval;
int d = c->master->fieldval; si.id = (d < siblings[d]) ? 0 : 1;
si.id = (d < siblings[d]) ? 0 : 1; if(sub & SPF_ROT) si.id = 0;
for(int i=0; i<S7; i++) { for(int i=0; i<S7; i++) {
int di = c->master->move[i]->fieldval; int di = c->master->move[i]->fieldval;
if(di == siblings[d]) si.dir = i; if(di == siblings[d]) si.dir = i;
}
si.reflect = false;
}
else {
int ids = 0, tids = 0, td = 0;
for(int i=0; i<S3; i++) {
int d = c->mov[i*2]->master->fieldval;
ids |= (1<<d); tids += d;
}
for(int i=0; i<S3; i++) {
int d = c->mov[i*2]->master->fieldval;
if(ids & (1<<siblings[d])) td += d;
}
if(td) {
si.id = 4;
for(int i=0; i<S3; i++) {
int d = c->mov[i*2]->master->fieldval;
if(!(ids & (1<<siblings[d]))) si.dir = 2*i;
} }
si.reflect = false; si.reflect = false;
} }
else { else {
si.id = 8; int ids = 0, tids = 0, td = 0;
si.dir = 0; // whatever for(int i=0; i<S3; i++) {
sphereinfo si2 = valsphere(c->mov[0]); int d = c->mov[i*2]->master->fieldval;
int di = si2.dir - c->spin(0); ids |= (1<<d); tids += d;
di %= S7; }
if(di<0) di += S7; for(int i=0; i<S3; i++) {
si.reflect = di > S7/2; int d = c->mov[i*2]->master->fieldval;
} if(ids & (1<<siblings[d])) td += d;
} }
return si; if(td) {
} si.id = 4;
for(int i=0; i<S3; i++) {
namespace patterns { int d = c->mov[i*2]->master->fieldval;
if(!(ids & (1<<siblings[d]))) si.dir = 2*i;
int nopattern(cell *c) { }
if(isWarped(c) && !euclid) { si.reflect = false;
int u = ishept(c)?1:0; }
int qhex = 0; else {
for(int v=0; v<c->type; v++) if(c->mov[v] && !isWarped(c->mov[v])) { si.id = 8;
u += 2; si.dir = 0; // whatever
if(!ishept(c->mov[v])) qhex++; patterninfo si2;
valSibling(c->mov[0], si2, sub);
int di = si2.dir - c->spin(0);
di %= S7;
if(di<0) di += S7;
si.reflect = di > S7/2;
} }
if(u == 8 && qhex == 2) return 12;
if(u == 2 && qhex == 1) return 8;
if(u == 6 && qhex == 2) return 10;
return u;
} }
return ishept(c) ? 1 : ishex1(c) ? 2 : 0; // 0 to 1
} }
int downdir(cell *c, cellfunction *cf = coastvalEdge) { int downdir(cell *c, cellfunction *cf = coastvalEdge) {
@ -421,250 +414,278 @@ namespace patterns {
return neighborId(c, c2); return neighborId(c, c2);
} }
int realpattern(cell *c, char code) { void applySym0123(int& i, int sub) {
switch(code) { bool sym01 = sub & SPF_SYM01;
case 'z': bool sym02 = sub & SPF_SYM02;
return zebra40(c); // 4 to 43 bool sym03 = sub & SPF_SYM03;
case 'f': if((sym01?1:0)+(sym02?1:0)+(sym03?1:0) >= 2) i &= ~3;
return emeraldval(c); // 44 to 99 if(sym01 && (i&1)) i ^= 1;
case 'p': { if(sym02 && (i&2)) i ^= 2;
if(a46) return val46(c); if(sym03 && (i&2)) i ^= 3;
if(a38) return val38(c);
if(sphere) return valsphere(c).id;
int i = fiftyval049(c);
i *= 4;
if(polara50(c)) i|=1;
if(polarb50(c)) i|=2;
return i;
}
case 'H':
return towerval(c);
case 'F': {
if(euclid)
// use the torus ID
return fieldpattern::fieldval_uniq(c);
else if(nontruncated)
// use the actual field codes
return fieldpattern::fieldval(c).first;
else
// use the small numbers from windmap
return windmap::getId(c);
}
}
return nopattern(c);
} }
int patterndir46(cell *c, int bits) { void val46(cell *c, patterninfo &si, int sub) {
if(ctof(c)) { int bits = (sub & SPF_CHANGEROT) ? 1 : 2;
int b = c->master->emeraldval & bits; if(ctof(c)) {
return (b&1) ^ (b & 2 ? 1 : 0); si.id = c->master->emeraldval >> 1;
} applySym0123(si.id, sub);
int b = c->master->emeraldval & bits;
si.dir = (b&1) ^ (b & 2 ? 1 : 0);
}
else {
if(sub & SPF_TWOCOL) si.id = 4;
else else
return ((c->mov[0]->master->emeraldval + c->spin(0)) & 1) ? 2 : 0; si.id = ((c->master->emeraldval & 1) ^ ((c->master->emeraldval & 2)>>1) ^ (c->spin(0)&1)) ? 8 : 4;
si.dir = ((c->mov[0]->master->emeraldval + c->spin(0)) & 1) ? 2 : 0;
if(createMov(c, si.dir)->master->emeraldval & 4)
si.dir += 4;
} }
}
int patterndir38(cell *c) { // if(a46) return patterndir46(c, w == PAT_ZEBRA ? 3 : w == PAT_PALACE ? 2 : 1);
if(ctof(c)) return c->master->fiftyval | (c->master->fiftyval & 8 ? 0 : 2);
return 0; void val457(cell *c, patterninfo &si, int sub) {
si.id = zebra40(c);
applySym0123(si.id, sub);
if(sub & SPF_ROT) {
if(si.id >= 4 && si.id < 7) si.id -= 4;
if(si.id >= 20 && si.id < 23) si.id -= 4;
} }
if(ctof(c)) {
int patterndir457(cell *c) {
if(!ctof(c)) {
int d = dir_truncated457(c);
if(d >= 0) return d;
return 0;
}
for(int i=0; i<c->type; i++) for(int i=0; i<c->type; i++)
if((zebra40(createStep(c->master, i + S7/2)->c7)&2) == (zebra40(createStep(c->master, i + 1 + S7/2)->c7)&2)) if((zebra40(createStep(c->master, i + S7/2)->c7)&2) == (zebra40(createStep(c->master, i + 1 + S7/2)->c7)&2))
return i; si.dir = i;
return 0;
} }
else {
bool reflectPatternAt(cell *c, char p) { int d = dir_truncated457(c);
if(p == 'p' && sphere) return valsphere(c).reflect; if(d >= 0) si.dir = d;
if(p == 'p' && polarb50(c)) return true; else si.dir = (zebra40(createMov(c, 0)) & 4) ? 2 : 0;
if(p == 0) {
int np = nopattern(c);
if(np == 4) {
int d = patterndir(c);
return !isWarped(createMov(c, (d+1)%6));
}
if(np == 12) {
int d = patterndir(c);
return !isWarped(createMov(c, (d+1)%6));
}
}
return false;
} }
}
int patterndir(cell *c, char w) { void val38(cell *c, patterninfo &si, int sub) {
if(w != 'H') { bool symRotation = sub & SPF_ROT;
if(a46) return patterndir46(c, w == 'z' ? 3 : w == 'p' ? 2 : 1); bool sym01 = sub & SPF_TWOCOL;
if(a4) return patterndir457(c);
if(a38) return patterndir38(c);
if(sphere) return valsphere(c).dir;
}
switch(w) {
case 'z': {
int t = zebra40(c);
if(euclid) return (t*4) % 6; if(ctof(c)) {
if(!symRotation)
si.id = (c->master->fiftyval >> 1) & 3;
si.dir = c->master->fiftyval | (c->master->fiftyval & 8 ? 0 : 2);
}
else {
if(sym01)
si.id = 4;
else
si.id = 4 ^ (c->master->fiftyval & 1) ^ (c->spin(0) & 1);
}
}
int t4 = t>>2, tcdir = 0; void valEuclid(cell *c, patterninfo &si, int sub) {
bool symRotation = sub & SPF_ROT;
si.id = ishept(c) ? 1 : ishex1(c) ? 2 : 0;
if(sub & SPF_CHANGEROT)
si.dir = (zebra40(c)*4) % 6;
if(symRotation) si.id = 0;
}
if(nontruncated) tcdir = t^1; void val_all(cell *c, patterninfo &si, int sub) {
if(a46) val46(c, si, sub);
else if(a38) val38(c, si, sub);
else if(sphere) valSibling(c, si, sub);
else if(euclid) valEuclid(c, si, sub);
else if(a4) val457(c, si, sub);
}
else if(t4 == 10) tcdir = t-20; void val_warped(cell *c, patterninfo& si) {
else if(t4 >= 4 && t4 < 7) tcdir = 40 + (t&3); // use val_all for nicer rotation
else if(t4 >= 1 && t4 < 4) tcdir = t+12; val_all(c, si, 0);
else if(t4 >= 7 && t4 < 10) tcdir = t-24;
for(int i=0; i<c->type; i++) if(c->mov[i] && zebra40(c->mov[i]) == tcdir) // get id:
return i; if(stdhyperbolic && isWarped(c)) {
int u = ishept(c)?1:0;
// printf("fail to fintd %d -> %d\n", t, tcdir); int qhex = 0;
for(int v=0; v<c->type; v++) if(c->mov[v] && !isWarped(c->mov[v])) {
return 0; u += 2;
} if(!ishept(c->mov[v])) qhex++;
case 'f': {
int t = emeraldval(c);
if(euclid) return 0;
int tcdir = 0, tbest = (t&3);
for(int i=0; i<c->type; i++) {
cell *c2 = c->mov[i];
if(c2) {
int t2 = emeraldval(c2);
if((t&3) == (t2&3) && t2 > tbest)
tbest = t2, tcdir = i;
}
}
return tcdir;
}
case 'p': {
int tcdir = -1, tbest = -1;
int pa = polara50(c);
int pb = polarb50(c);
for(int i=0; i<c->type; i++) {
cell *c2 = c->mov[i];
if(c2 && polara50(c2) == pa && polarb50(c2) == pb) {
int t2 = fiftyval049(c2);
if(t2 > tbest) tbest = t2, tcdir = i;
}
}
return tcdir;
}
case 'H':
return downdir(c);
case 0: {
if(euclid) return 0;
int u = nopattern(c);
if(u == 6) {
for(int i=1; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
return i;
}
else if(u == 2 || u == 3 || u == 8) {
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,i)))
return i;
}
else if(u == 4 || u == 10) {
for(int i=0; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
return i;
}
else if(u == 6) {
for(int i=1; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
return i;
}
else if(u == 5) {
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+3)%7)) && !isWarped(createMov(c,(i+4)%7)))
return i;
}
else if(u == 9) {
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+2)%7)) && !isWarped(createMov(c,(i+5)%7)))
return i;
}
else if(u == 11) {
for(int i=0; i<c->type; i++) if(isWarped(createMov(c,(i)%7)) && isWarped(createMov(c,(i+1)%7)))
return i;
}
else if(u == 12) {
for(int i=0; i<c->type; i+=2) if(isWarped(createMov(c,i)))
return i;
}
else if(u == 7) {
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+1)%7)) && !isWarped(createMov(c,(i+6)%7)))
return i;
}
else if(u < 2) return 0;
#if LOCAL
printf("unhandled: u=%d\n", u);
#endif
}
} }
return 0; if(u == 8 && qhex == 2) si.id = 12;
else if(u == 2 && qhex == 1) si.id = 8;
else if(u == 6 && qhex == 2) si.id = 10;
si.id = u;
if(u == 6) {
for(int i=1; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
si.dir = i;
}
else if(u == 2 || u == 3 || u == 8) {
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,i)))
si.dir = i;
}
else if(u == 4 || u == 10) {
for(int i=0; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
si.dir = i;
if(u == 4)
si.reflect = !isWarped(createMov(c, (si.dir+1)%6));
}
else if(u == 6) {
for(int i=1; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
si.dir = i;
}
else if(u == 5) {
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+3)%7)) && !isWarped(createMov(c,(i+4)%7)))
si.dir = i;
}
else if(u == 9) {
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+2)%7)) && !isWarped(createMov(c,(i+5)%7)))
si.dir = i;
}
else if(u == 11) {
for(int i=0; i<c->type; i++) if(isWarped(createMov(c,(i)%7)) && isWarped(createMov(c,(i+1)%7)))
si.dir = i;
}
else if(u == 12) {
for(int i=0; i<c->type; i+=2) if(isWarped(createMov(c,i))) {
si.dir = i;
si.reflect = !isWarped(createMov(c, (i+1)%6));
}
}
else if(u == 7) {
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+1)%7)) && !isWarped(createMov(c,(i+6)%7)))
si.dir = i;
}
}
else {
si.id = ishept(c) ? 1 : 0;
if(euclid) si.dir = ishex1(c) ? 3 : 0;
}
} }
char whichPattern = 0; char whichPattern = 0;
bool symRotation, sym01, sym02, sym03; int subpattern_flags;
int subpattern(int i, char w) { patterninfo getpatterninfo(cell *c, char pat, int sub) {
if(euclid) { bool symRotation = sub & SPF_ROT;
if(w == 'p')
return i;
if(w == 'z' || w == 'f')
return (symRotation && (i<3)) ? 0 : i;
}
if(a38 && w == 'p') { patterninfo si;
if(sym01 && i == 5) i = 4; si.dir = 0; si.reflect = false; si.id = ctof(c);
if(symRotation && i < 4) i = 0;
return i;
}
if(w == 'z' || w == 'f' || w == 'p') { if(pat == PAT_ZEBRA && stdhyperbolic) {
if((sym01?1:0)+(sym02?1:0)+(sym03?1:0) >= 2) i &= ~3;
if(sym01 && (i&1)) i ^= 1;
if(sym02 && (i&2)) i ^= 2;
if(sym03 && (i&2)) i ^= 3;
}
if(w == 'z' && symRotation) { si.id = zebra40(c); // 4 to 43
if(a4 && !a46) { int t4 = si.id>>2, tcdir = 0;
if(i >= 4 && i < 7) i -= 4;
} if(nontruncated) tcdir = si.id^1;
else {
if(i >= 8 && i < 12) i -= 4; else if(t4 == 10) tcdir = si.id-20;
if(i >= 12 && i < 16) i -= 8; else if(t4 >= 4 && t4 < 7) tcdir = 40 + (si.id&3);
if(i >= 20 && i < 24) i -= 4; else if(t4 >= 1 && t4 < 4) tcdir = si.id+12;
if(i >= 24 && i < 28) i -= 8; else if(t4 >= 7 && t4 < 10) tcdir = si.id-24;
if(i >= 32 && i < 36) i -= 4;
if(i >= 36 && i < 40) i -= 8; for(int i=0; i<c->type; i++) if(c->mov[i] && zebra40(c->mov[i]) == tcdir)
si.dir = i;
applySym0123(si.id, sub);
if(symRotation) {
if(si.id >= 8 && si.id < 12) si.id -= 4;
if(si.id >= 12 && si.id < 16) si.id -= 8;
if(si.id >= 20 && si.id < 24) si.id -= 4;
if(si.id >= 24 && si.id < 28) si.id -= 8;
if(si.id >= 32 && si.id < 36) si.id -= 4;
if(si.id >= 36 && si.id < 40) si.id -= 8;
} }
} }
if(w == 'p' && stdhyperbolic && symRotation && i >= 3) else if(pat == PAT_EMERALD && (stdhyperbolic || a38)) {
i -= ((i/4-1) % 7) * 4; si.id = emeraldval(c); // 44 to 99
if(!euclid) {
int tcdir = 0, tbest = (si.id&3);
for(int i=0; i<c->type; i++) {
cell *c2 = c->mov[i];
if(c2) {
int t2 = emeraldval(c2);
if((si.id&3) == (t2&3) && t2 > tbest)
tbest = t2, tcdir = i;
}
}
si.dir = tcdir;
}
applySym0123(si.id, sub);
}
return i; else if(pat == PAT_PALACE && stdhyperbolic) {
} int i = fiftyval049(c);
i *= 4;
if(polara50(c)) i|=1;
if(polarb50(c)) i|=2;
si.id = i;
int subpattern(cell *c, char w) { int tcdir = -1, tbest = -1;
return subpattern(realpattern(c, w), w); int pa = polara50(c);
int pb = polarb50(c);
si.reflect = pb;
for(int i=0; i<c->type; i++) {
cell *c2 = c->mov[i];
if(c2 && polara50(c2) == pa && polarb50(c2) == pb) {
int t2 = fiftyval049(c2);
if(t2 > tbest) tbest = t2, tcdir = i;
}
}
si.dir = tcdir;
applySym0123(si.id, sub);
if(symRotation && si.id >= 3)
si.id -= ((si.id/4-1) % 7) * 4;
}
else if(pat == PAT_PALACE && euclid) {
si.id = fiftyval049(c);
}
else if(pat == PAT_DOWN) {
si.id = towerval(c);
si.dir = downdir(c);
}
else if(pat == PAT_FIELD) {
if(euclid)
// use the torus ID
si.id = fieldpattern::fieldval_uniq(c);
else if(nontruncated)
// use the actual field codes
si.id = fieldpattern::fieldval(c).first;
else
// use the small numbers from windmap
si.id = windmap::getId(c);
// todo dir
}
else if(sphere && pat == PAT_SIBLING) {
val_all(c, si, sub);
}
else if(a457 && pat == PAT_ZEBRA) {
val_all(c, si, sub);
}
else if(pat == PAT_COLORING && (a46 || euclid)) {
val_all(c, si, sub);
}
else
val_warped(c, si);
return si;
} }
} }
@ -689,12 +710,16 @@ int geosupport_graveyard() {
int pattern_threecolor(cell *c) { int pattern_threecolor(cell *c) {
if(a38) { if(a38) {
int i = val38(c); patterns::patterninfo si;
patterns::val38(c, si, 0);
int i = si.id;
if(nontruncated) return i; if(nontruncated) return i;
else return i < 4 ? 0 : (1+(i&1)); else return i < 4 ? 0 : (1+(i&1));
} }
if(a46 && !nontruncated) { if(a46 && !nontruncated) {
int i = val46(c); patterns::patterninfo si;
patterns::val46(c, si, 0);
int i = si.id;
return i >> 2; return i >> 2;
} }
if(S7 == 4) { if(S7 == 4) {
@ -861,7 +886,7 @@ namespace patterns {
col[2] /= 4; col[2] /= 4;
return (0x202020 + col[0] + (col[1] << 8) + (col[2] << 16)) >> (err?2:0); return (0x202020 + col[0] + (col[1] << 8) + (col[2] << 16)) >> (err?2:0);
} }
if(whichCanvas == 'F') { if(whichCanvas == PAT_FIELD) {
return pseudohept(c) ? 0x202020 : 0xC0C0C0; return pseudohept(c) ? 0x202020 : 0xC0C0C0;
} }
if(whichCanvas == 'T') { if(whichCanvas == 'T') {
@ -920,51 +945,62 @@ namespace patterns {
} }
dialog::init(); dialog::init();
if(a46) { if(stdhyperbolic || a4)
dialog::addBoolItem(XLAT("two colors"), (whichPattern == 'f'), 'f'); dialog::addBoolItem(XLAT("Zebra Pattern"), (whichPattern == PAT_ZEBRA), PAT_ZEBRA);
dialog::addBoolItem(XLAT("two colors rotated"), (whichPattern == 'z'), 'z');
} if(stdhyperbolic)
else if(a4) { dialog::addBoolItem(XLAT("Emerald Pattern"), (whichPattern == PAT_EMERALD), PAT_EMERALD);
dialog::addBoolItem(XLAT("Zebra Pattern"), (whichPattern == 'z'), 'z'); else if(a38)
} dialog::addBoolItem(XLAT("broken Emerald Pattern"), (whichPattern == PAT_EMERALD), PAT_EMERALD);
else if(a38) {
dialog::addBoolItem(XLAT("Zebra Pattern"), (whichPattern == 'z'), 'z'); if(stdhyperbolic || euclid)
dialog::addBoolItem(XLAT("broken Emerald Pattern"), (whichPattern == 'f'), 'f'); dialog::addBoolItem(XLAT("Palace Pattern"), (whichPattern == PAT_PALACE), PAT_PALACE);
dialog::addBoolItem(XLAT("rotated pattern"), (whichPattern == 'p'), 'p');
} if(a38 || a46 || euclid)
else if(euclid) { dialog::addBoolItem(XLAT("coloring"), (whichPattern == PAT_COLORING), PAT_COLORING);
dialog::addBoolItem(XLAT("three colors"), (whichPattern == 'f'), 'f');
dialog::addBoolItem(XLAT("Palace Pattern"), (whichPattern == 'p'), 'p'); if(sphere)
dialog::addBoolItem(XLAT("three colors rotated"), (whichPattern == 'z'), 'z'); dialog::addBoolItem(XLAT("siblings"), (whichPattern == PAT_SIBLING), PAT_SIBLING);
}
else if(sphere) {
dialog::addBoolItem(XLAT("siblings"), (whichPattern == 'p'), 'p');
}
else {
if(!stdhyperbolic)
dialog::addInfo("patterns do not work correctly in this geometry!");
dialog::addBoolItem(XLAT("Emerald Pattern"), (whichPattern == 'f'), 'f');
dialog::addBoolItem(XLAT("Palace Pattern"), (whichPattern == 'p'), 'p');
dialog::addBoolItem(XLAT("Zebra Pattern"), (whichPattern == 'z'), 'z');
}
if(euclid) if(euclid)
dialog::addBoolItem(XLAT("torus pattern"), (whichPattern == 'F'), 'F'); dialog::addBoolItem(XLAT("torus pattern"), (whichPattern == PAT_FIELD), PAT_FIELD);
else if(sphere) else if(sphere)
dialog::addBoolItem(XLAT("single cells"), (whichPattern == 'F'), 'F'); dialog::addBoolItem(XLAT("single cells"), (whichPattern == PAT_FIELD), PAT_FIELD);
else else
dialog::addBoolItem(XLAT("field pattern"), (whichPattern == 'F'), 'F'); dialog::addBoolItem(XLAT("field pattern"), (whichPattern == PAT_FIELD), PAT_FIELD);
if(whichPattern == 'f' && stdhyperbolic) symRotation = true; if(
if(whichPattern == 'F') ; (whichPattern == PAT_EMERALD && (stdhyperbolic || a38)) ||
else if(!euclid) { (whichPattern == PAT_PALACE && stdhyperbolic) ||
dialog::addBoolItem(XLAT("rotational symmetry"), (symRotation), '0'); (whichPattern == PAT_ZEBRA && stdhyperbolic) ||
dialog::addBoolItem(XLAT("symmetry 0-1"), (sym01), '1'); (whichPattern == PAT_SIBLING && sphere) ||
dialog::addBoolItem(XLAT("symmetry 0-2"), (sym02), '2'); (whichPattern == PAT_ZEBRA && a457)) {
dialog::addBoolItem(XLAT("symmetry 0-3"), (sym03), '3'); dialog::addBoolItem(XLAT("rotational symmetry"), subpattern_flags & SPF_ROT, '0');
}
if((euclid && whichPattern == PAT_COLORING) ||
(a38 && whichPattern == PAT_COLORING))
dialog::addBoolItem(XLAT("edit all three colors"), subpattern_flags & SPF_ROT, '0');
if(euclid && whichPattern == PAT_COLORING)
dialog::addBoolItem(XLAT("rotate the color groups"), subpattern_flags & SPF_CHANGEROT, '4');
if((a38 && whichPattern == PAT_COLORING && !nontruncated) ||
(a46 && whichPattern == PAT_COLORING && !nontruncated)
)
dialog::addBoolItem(XLAT("edit both truncated colors"), subpattern_flags & SPF_TWOCOL, '5');
if(
(whichPattern == PAT_EMERALD && (stdhyperbolic || a38)) ||
(whichPattern == PAT_PALACE && stdhyperbolic) ||
(whichPattern == PAT_ZEBRA && stdhyperbolic) ||
(whichPattern == PAT_COLORING && a46) ||
(whichPattern == PAT_ZEBRA && a457)
) {
dialog::addBoolItem(XLAT("symmetry 0-1"), subpattern_flags & SPF_SYM01, '1');
dialog::addBoolItem(XLAT("symmetry 0-2"), subpattern_flags & SPF_SYM02, '2');
dialog::addBoolItem(XLAT("symmetry 0-3"), subpattern_flags & SPF_SYM03, '3');
} }
else
dialog::addBoolItem(XLAT("edit all three colors"), (symRotation), '0');
dialog::addBoolItem(XLAT("display pattern codes (full)"), (displaycodes == 1), 'd'); dialog::addBoolItem(XLAT("display pattern codes (full)"), (displaycodes == 1), 'd');
dialog::addBoolItem(XLAT("display pattern codes (simplified)"), (displaycodes == 2), 's'); dialog::addBoolItem(XLAT("display pattern codes (simplified)"), (displaycodes == 2), 's');
@ -982,21 +1018,19 @@ namespace patterns {
keyhandler = [] (int sym, int uni) { keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni); dialog::handleNavigation(sym, uni);
if(uni == 'f' || uni == 'p' || uni == 'z' || uni == 'H' || uni == 'F') { if(among(uni, PAT_EMERALD, PAT_PALACE, PAT_ZEBRA, PAT_DOWN, PAT_FIELD, PAT_COLORING, PAT_SIBLING)) {
if(whichPattern == uni) whichPattern = 0; if(whichPattern == uni) whichPattern = 0;
else whichPattern = uni; else whichPattern = uni;
mapeditor::modelcell.clear(); mapeditor::modelcell.clear();
} }
else if(uni == '0') symRotation = !symRotation; else if(uni >= '0' && uni <= '5')
else if(uni == '1') sym01 = !sym01; subpattern_flags ^= (1 << (uni - '0'));
else if(uni == '2') sym02 = !sym02;
else if(uni == '3') sym03 = !sym03;
else if(uni == '6' || uni == '7' || uni == '8') { else if(uni == '6' || uni == '7' || uni == '8') {
if(whichShape == uni) whichShape = 0; if(whichShape == uni) whichShape = 0;
else whichShape = uni; else whichShape = uni;
} }
else if(uni == '3') sym03 = !sym03;
else if(uni == 'd') displaycodes = displaycodes == 1 ? 0 : 1; else if(uni == 'd') displaycodes = displaycodes == 1 ? 0 : 1;
else if(uni == 's') displaycodes = displaycodes == 2 ? 0 : 2; else if(uni == 's') displaycodes = displaycodes == 2 ? 0 : 2;
@ -1281,3 +1315,10 @@ namespace linepatterns {
} }
}; };
int val46(cell *c) {
patterns::patterninfo si;
patterns::val46(c, si, 0);
return si.id;
}

View File

@ -7,7 +7,7 @@
// rules for the emeraldvalues of heptagons. // rules for the emeraldvalues of heptagons.
int emerald_heptagon(int parent, int dir) { int emerald_heptagon(int parent, int dir) {
if(a46) return parent ^ (dir & 1) ^ 2; if(a46) return parent ^ (dir & 1) ^ 2 ^ (((parent^dir) & 1) << 2);
if(S7 == 8 && dir > 3) dir--; if(S7 == 8 && dir > 3) dir--;

View File

@ -990,6 +990,8 @@ hpcshape
shTerraArmor1, shTerraArmor2, shTerraArmor3, shTerraHead, shTerraFace, shTerraArmor1, shTerraArmor2, shTerraArmor3, shTerraHead, shTerraFace,
shJiangShi, shJiangShiDress, shJiangShiCap1, shJiangShiCap2, shJiangShi, shJiangShiDress, shJiangShiCap1, shJiangShiCap2,
shAsymmetric,
shDodeca; shDodeca;
#define USERLAYERS 32 #define USERLAYERS 32
@ -1039,7 +1041,6 @@ hyperpoint turtlevertex(int u, double x, double y, double z) {
return hpxd(scale, x, y, z); return hpxd(scale, x, y, z);
} }
void finishshape() { void finishshape() {
last->e = qhpc; last->e = qhpc;
double area = 0; double area = 0;
@ -1793,6 +1794,8 @@ void buildpolys() {
bshape(shLeafFloor[0], PPR_FLOOR_DRAGON, 1*spzoom6, 313); bshape(shLeafFloor[0], PPR_FLOOR_DRAGON, 1*spzoom6, 313);
bshape(shLeafFloor[1], PPR_FLOOR_DRAGON, 1*spzoomd7, 314); bshape(shLeafFloor[1], PPR_FLOOR_DRAGON, 1*spzoomd7, 314);
bshape(shAsymmetric, PPR_TEXT, scalef, 374);
bshape(shTriheptaFloor[2], PPR_FLOOR, scalef, 32); bshape(shTriheptaFloor[2], PPR_FLOOR, scalef, 32);
bshape(shTriheptaFloor[3], PPR_FLOOR, scalef, 33); bshape(shTriheptaFloor[3], PPR_FLOOR, scalef, 33);
bshape(shTriheptaFloor[4], PPR_FLOOR, scalef, 34); bshape(shTriheptaFloor[4], PPR_FLOOR, scalef, 34);
@ -3329,6 +3332,8 @@ NEWSHAPE, 371, 1, 1, -0.013726,-0.304365, 0.244972,-0.147728, 0.266167,0.130112,
NEWSHAPE, 372, 1, 1, -0.514563,-0.238476, -0.340659,0.172987, -0.100245,0.368967, 0.214334,0.276255, 0.349294,-0.008293, 0.203063,-0.280225, -0.078470,-0.352806, NEWSHAPE, 372, 1, 1, -0.514563,-0.238476, -0.340659,0.172987, -0.100245,0.368967, 0.214334,0.276255, 0.349294,-0.008293, 0.203063,-0.280225, -0.078470,-0.352806,
NEWSHAPE, 373, 1, 1, -0.019312,0.304743, -0.289045,0.177117, -0.127176,-0.240665, 0.007400,-0.336712, 0.257684,-0.184398, 0.234654,0.191587, NEWSHAPE, 373, 1, 1, -0.019312,0.304743, -0.289045,0.177117, -0.127176,-0.240665, 0.007400,-0.336712, 0.257684,-0.184398, 0.234654,0.191587,
NEWSHAPE, 374, 1, 1, -0.229502,-0.051000, 0.320183,0.006447, 0.148302,0.144065, 0.173317,0.054954, -0.253447,0.021298,
NEWSHAPE NEWSHAPE
}; };

View File

@ -119,15 +119,10 @@ map<int, textureinfo> texture_map;
bool applyTextureMap(cell *c, const transmatrix &V, int col) { bool applyTextureMap(cell *c, const transmatrix &V, int col) {
using namespace patterns; using namespace patterns;
int t = subpattern(c, whichPattern); auto si = getpatterninfo0(c);
try { try {
auto& mi = texture_map.at(t); auto& mi = texture_map.at(si.id);
qfi.spin = Id; qfi.spin = applyPatterndir(c, si);
int d = patterndir(c, whichPattern);
qfi.spin = qfi.spin * spin(-M_PI * 2 * d / c->type);
if(reflectPatternAt(c))
qfi.spin = qfi.spin * Mirror;
int n = mi.vertices.size() / 3; int n = mi.vertices.size() / 3;
@ -160,25 +155,21 @@ void perform_mapping() {
glfont_t& f(textures); int tabid = 1; glfont_t& f(textures); int tabid = 1;
for(auto p: gmatrix) { for(auto p: gmatrix) {
cell *c = p.first; cell *c = p.first;
int t = subpattern(c, whichPattern); auto si = getpatterninfo0(c);
bool replace = false; bool replace = false;
if(!texture_map.count(t)) if(!texture_map.count(si.id))
replace = true; replace = true;
else if(p.second[2][2] < texture_map[t].M[2][2]) else if(p.second[2][2] < texture_map[si.id].M[2][2])
replace = true; replace = true;
if(replace) { if(replace) {
auto& mi = texture_map[t]; auto& mi = texture_map[si.id];
mi.M = p.second; mi.M = p.second;
mi.vertices.clear(); mi.vertices.clear();
mi.tvertices.clear(); mi.tvertices.clear();
int d = patterndir(c, whichPattern); mi.M = mi.M * applyPatterndir(c, si);
if(d)
mi.M = mi.M * spin(-M_PI * 2 * d / c->type);
if(reflectPatternAt(c, whichPattern))
mi.M = mi.M * Mirror;
ld z = ctof(c) ? rhexf : hexvdist; ld z = ctof(c) ? rhexf : hexvdist;
ld base = ctof(c) ? 0 : 0; // -hexshift; ld base = ctof(c) ? 0 : 0; // -hexshift;