1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-24 17:10:36 +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
cell *createMov(cell *c, int d) {
if(d<0 || d>= c->type) {
printf("ERROR createmov\n");
}
if(euclid && !c->mov[d]) {
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)); )
if(c->mov[t]->mov[c->spn(t)] != NULL &&
c->mov[t]->mov[c->spn(t)] != c) {
printf("type = %d %d -> %d\n", c->type, t, c->spn(t));
printf("cell error\n");
exit(1);
}

View File

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

114
graph.cpp
View File

@ -2187,12 +2187,9 @@ int countMinesAround(cell *c) {
return mines;
}
transmatrix applyPatterndir(cell *c, char patt = patterns::whichPattern) {
transmatrix V = ddspin(c, patterns::patterndir(c, patt), S42);
if(patterns::reflectPatternAt(c, patt))
return V * Mirror;
transmatrix applyPatterndir(cell *c, const patterns::patterninfo& si) {
transmatrix V = ddspin(c, si.dir, S42);
if(si.reflect) return V * Mirror;
return V;
}
@ -2238,42 +2235,40 @@ void drawZebraFloor(const transmatrix& V, cell *c, int col) {
qfloor(c, V, PLAINFLOOR, col); return;
}
int i = zebra40(c);
i &= ~3;
auto si = patterns::getpatterninfo(c, 'z', patterns::SPF_SYM0123);
int j;
if(nontruncated) j = 4;
else if(i >=4 && i < 16) j = 2;
else if(i >= 16 && i < 28) j = 1;
else if(i >= 28 && i < 40) j = 3;
else if(si.id >=4 && si.id < 16) j = 2;
else if(si.id >= 16 && si.id < 28) j = 1;
else if(si.id >= 28 && si.id < 40) j = 3;
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 drawReptileFloor(const transmatrix& V, cell *c, int col, bool usefloor) {
int i = zebra40(c);
i &= ~3;
auto si = patterns::getpatterninfo(c, 'z', patterns::SPF_SYM0123);
int j;
if(!wmescher) j = 4;
else if(nontruncated) j = 0;
else if(i < 4) j = 0;
else if(i >=4 && i < 16) j = 1;
else if(i >= 16 && i < 28) j = 2;
else if(i >= 28 && i < 40) j = 3;
else if(si.id < 4) j = 0;
else if(si.id >=4 && si.id < 16) j = 1;
else if(si.id >= 16 && si.id < 28) j = 2;
else if(si.id >= 28 && si.id < 40) j = 3;
else j = 4;
transmatrix V2 = V * applyPatterndir(c, 'z');
transmatrix D = applyPatterndir(c, si);
transmatrix V2 = V * D;
if(wmescher) {
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
queuepoly(V2, shReptile[j][0], darkena(col, 0, 0xFF));
}
@ -2317,23 +2312,25 @@ void drawReptileFloor(const transmatrix& V, cell *c, int col, bool usefloor) {
}
void drawEmeraldFloor(const transmatrix& V, cell *c, int col) {
if(!euclid && !nontruncated) {
auto si = patterns::getpatterninfo(c, 'f', patterns::SPF_SYM0123);
int j = -1;
if(!euclid && !nontruncated) {
int i = emeraldval(c) & ~3;
if(i == 8) j = 0;
else if(i == 12) j = 1;
else if(i == 16) j = 2;
else if(i == 20) j = 3;
else if(i == 28) j = 4;
else if(i == 36) j = 5;
if(si.id == 8) j = 0;
else if(si.id == 12) j = 1;
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);
if(j >= 0)
qfloor(c, V, applyPatterndir(c, 'f'), shEmeraldFloor[j], col);
else
qfloor(c, V, CAVEFLOOR, col);
}
@ -2856,8 +2853,10 @@ void floorShadow(cell *c, const transmatrix& V, int col, bool warp) {
else
queuepolyat(V, shTriheptaFloorShadow[ctof(c)], col, PPR_WALLSHADOW);
}
else
queuepolyat(V * applyPatterndir(c), shTriheptaFloorShadow[ctof(c)], col, PPR_WALLSHADOW);
else {
auto si = patterns::getpatterninfo(c, 0, 0);
queuepolyat(V * applyPatterndir(c, si), shTriheptaFloorShadow[ctof(c)], col, PPR_WALLSHADOW);
}
}
else if(c->land == laDual && !nontruncated) {
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) {
if(warp) {
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))
queuepolyat(V * pispin, shTriheptaFloor[ctof(c)], col, prio);
else
queuepolyat(V, shTriheptaFloor[ctof(c)], col, prio);
}
else
queuepolyat(V * applyPatterndir(c), shTriheptaFloor[sphere ? ctof(c) : patterns::nopattern(c)], col, prio);
else {
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) {
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) {
if(warp) {
if(euclid) {
if(ishex1(c))
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);
auto si = patterns::getpatterninfo(c, 0, 0);
qfloor(c, V, applyPatterndir(c, si), shTriheptaFloor[si.id], col);
}
else if(c->land == laDual && !nontruncated)
qfloor_eswap(c, V, shBigTriangle, col);
@ -3503,7 +3494,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
// floor
#if CAP_EDIT
transmatrix Vpdir = V * applyPatterndir(c);
auto si = patterns::getpatterninfo0(c);
#endif
bool eoh = euclid || nontruncated;
@ -3518,7 +3509,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
}
#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));
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) {
int np = patterns::nopattern(c);
if(c->landparam == 1337) np = 0; // for the achievement screenshot
if(np < 13)
qfloor(c, Vf, applyPatterndir(c), shTriheptaFloor[np], darkena(fcol, fd, 0xFF));
auto si = patterns::getpatterninfo(c, 0, 0);
if(si.id < 13)
qfloor(c, Vf, applyPatterndir(c, si), shTriheptaFloor[si.id], darkena(fcol, fd, 0xFF));
else
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) {
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);
/* transmatrix V2 = V * applyPatterndir(c);
qfloor(c, V2, shNecro, 0x80808080);
qfloor(c, V2, shStatue, 0x80808080); */
}
#endif
@ -4582,7 +4572,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
#if CAP_EDIT
if((cmode & sm::MAP) && lmouseover && darken == 0 &&
!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);
}

45
hyper.h
View File

@ -654,17 +654,46 @@ extern struct SDL_Surface *s;
namespace patterns {
extern char whichShape;
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 int displaycodes;
int generateCanvas(cell *c);
int realpattern(cell *c, char w = whichPattern);
int patterndir(cell *c, char w = whichPattern);
bool reflectPatternAt(cell *c, char p = whichPattern);
int subpattern(cell *c, char w = whichPattern);
struct patterninfo {
int id;
int dir;
bool reflect;
};
patterninfo getpatterninfo(cell *c, char pat, int sub);
patterninfo getpatterninfo0(cell *c) {
return getpatterninfo(c, whichPattern, subpattern_flags);
}
}
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, 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, class... U> bool among(T x, T 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) { return x == y; }
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);
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);
extern ld tessf, crossf, hexf, hcrossf, hexhexdist, hexvdist, hepvdist, rhexf;
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 a46 (S3 == 4 && S7 == 6)
#define a47 (S3 == 4 && S7 == 7)
#define a457 (S3 == 4 && S7 != 6)
#define a467 (S3 == 4 && S7 >= 6)
#define a38 (S7 == 8)
#define sphere4 (sphere && S7 == 4)

View File

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

View File

@ -24,14 +24,8 @@ bool ishex1(cell *c) {
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) {
if(euclid) return eupattern(c);
if(a46) return val46(c);
if(sphere) return 0;
if(ctof(c))
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) {
if(a38) return val38(c);
if(euclid) return eufifty(c) * 32;
if(sphere || S7>7 || S6>6) return 0;
if(ctof(c))
@ -180,10 +168,14 @@ int fiftyval049(cell *c) {
int dir_truncated457(cell *c) {
int wset = 0;
for(int i=0; i<4; i++)
if(zebra40(createMov(c, i*2))&2) wset |= (1<<i);
if(wset == 0) return -8;
if(wset == 15) return -10;
int has1 = 0;
for(int i=0; i<4; i++) {
int z = zebra40(createMov(c, i*2));
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 == 6) return 3;
if(wset == 12) return 5;
@ -191,14 +183,37 @@ int dir_truncated457(cell *c) {
return 0;
}
int val46(cell *c);
int zebra40(cell *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(a4) {
int ws = dir_truncated457(c);
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(euclid) return eupattern(c);
@ -349,17 +364,13 @@ int getHemisphere(cell *c, int which) {
}
}
struct sphereinfo {
int id;
int dir;
bool reflect;
};
namespace patterns {
sphereinfo valsphere(cell *c) {
sphereinfo si;
void valSibling(cell *c, patterninfo& si, int sub) {
if(ctof(c)) {
int d = c->master->fieldval;
si.id = (d < siblings[d]) ? 0 : 1;
if(sub & SPF_ROT) si.id = 0;
for(int i=0; i<S7; i++) {
int di = c->master->move[i]->fieldval;
if(di == siblings[d]) si.dir = i;
@ -387,32 +398,14 @@ sphereinfo valsphere(cell *c) {
else {
si.id = 8;
si.dir = 0; // whatever
sphereinfo si2 = valsphere(c->mov[0]);
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;
}
}
return si;
}
namespace patterns {
int nopattern(cell *c) {
if(isWarped(c) && !euclid) {
int u = ishept(c)?1:0;
int qhex = 0;
for(int v=0; v<c->type; v++) if(c->mov[v] && !isWarped(c->mov[v])) {
u += 2;
if(!ishept(c->mov[v])) qhex++;
}
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) {
@ -421,131 +414,226 @@ namespace patterns {
return neighborId(c, c2);
}
int realpattern(cell *c, char code) {
switch(code) {
case 'z':
return zebra40(c); // 4 to 43
case 'f':
return emeraldval(c); // 44 to 99
case 'p': {
if(a46) return val46(c);
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);
void applySym0123(int& i, int sub) {
bool sym01 = sub & SPF_SYM01;
bool sym02 = sub & SPF_SYM02;
bool sym03 = sub & SPF_SYM03;
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;
}
int patterndir46(cell *c, int bits) {
void val46(cell *c, patterninfo &si, int sub) {
int bits = (sub & SPF_CHANGEROT) ? 1 : 2;
if(ctof(c)) {
si.id = c->master->emeraldval >> 1;
applySym0123(si.id, sub);
int b = c->master->emeraldval & bits;
return (b&1) ^ (b & 2 ? 1 : 0);
si.dir = (b&1) ^ (b & 2 ? 1 : 0);
}
else {
if(sub & SPF_TWOCOL) si.id = 4;
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(ctof(c)) return c->master->fiftyval | (c->master->fiftyval & 8 ? 0 : 2);
return 0;
}
// if(a46) return patterndir46(c, w == PAT_ZEBRA ? 3 : w == PAT_PALACE ? 2 : 1);
int patterndir457(cell *c) {
if(!ctof(c)) {
int d = dir_truncated457(c);
if(d >= 0) return d;
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)) {
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))
return i;
return 0;
si.dir = i;
}
bool reflectPatternAt(cell *c, char p) {
if(p == 'p' && sphere) return valsphere(c).reflect;
if(p == 'p' && polarb50(c)) return true;
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));
else {
int d = dir_truncated457(c);
if(d >= 0) si.dir = d;
else si.dir = (zebra40(createMov(c, 0)) & 4) ? 2 : 0;
}
}
return false;
void val38(cell *c, patterninfo &si, int sub) {
bool symRotation = sub & SPF_ROT;
bool sym01 = sub & SPF_TWOCOL;
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 patterndir(cell *c, char w) {
if(w != 'H') {
if(a46) return patterndir46(c, w == 'z' ? 3 : w == 'p' ? 2 : 1);
if(a4) return patterndir457(c);
if(a38) return patterndir38(c);
if(sphere) return valsphere(c).dir;
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;
}
switch(w) {
case 'z': {
int t = zebra40(c);
if(euclid) return (t*4) % 6;
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);
}
int t4 = t>>2, tcdir = 0;
void val_warped(cell *c, patterninfo& si) {
// use val_all for nicer rotation
val_all(c, si, 0);
if(nontruncated) tcdir = t^1;
// get id:
if(stdhyperbolic && isWarped(c)) {
int u = ishept(c)?1:0;
int qhex = 0;
for(int v=0; v<c->type; v++) if(c->mov[v] && !isWarped(c->mov[v])) {
u += 2;
if(!ishept(c->mov[v])) qhex++;
}
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;
else if(t4 == 10) tcdir = t-20;
else if(t4 >= 4 && t4 < 7) tcdir = 40 + (t&3);
else if(t4 >= 1 && t4 < 4) tcdir = t+12;
else if(t4 >= 7 && t4 < 10) tcdir = t-24;
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;
int subpattern_flags;
patterninfo getpatterninfo(cell *c, char pat, int sub) {
bool symRotation = sub & SPF_ROT;
patterninfo si;
si.dir = 0; si.reflect = false; si.id = ctof(c);
if(pat == PAT_ZEBRA && stdhyperbolic) {
si.id = zebra40(c); // 4 to 43
int t4 = si.id>>2, tcdir = 0;
if(nontruncated) tcdir = si.id^1;
else if(t4 == 10) tcdir = si.id-20;
else if(t4 >= 4 && t4 < 7) tcdir = 40 + (si.id&3);
else if(t4 >= 1 && t4 < 4) tcdir = si.id+12;
else if(t4 >= 7 && t4 < 10) tcdir = si.id-24;
for(int i=0; i<c->type; i++) if(c->mov[i] && zebra40(c->mov[i]) == tcdir)
return i;
si.dir = i;
// printf("fail to fintd %d -> %d\n", t, tcdir);
applySym0123(si.id, sub);
return 0;
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;
}
}
case 'f': {
int t = emeraldval(c);
if(euclid) return 0;
int tcdir = 0, tbest = (t&3);
else if(pat == PAT_EMERALD && (stdhyperbolic || a38)) {
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((t&3) == (t2&3) && t2 > tbest)
if((si.id&3) == (t2&3) && t2 > tbest)
tbest = t2, tcdir = i;
}
}
return tcdir;
si.dir = tcdir;
}
applySym0123(si.id, sub);
}
case 'p': {
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 tcdir = -1, tbest = -1;
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) {
@ -553,118 +641,51 @@ namespace patterns {
if(t2 > tbest) tbest = t2, tcdir = i;
}
}
return tcdir;
si.dir = tcdir;
applySym0123(si.id, sub);
if(symRotation && si.id >= 3)
si.id -= ((si.id/4-1) % 7) * 4;
}
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(pat == PAT_PALACE && euclid) {
si.id = fiftyval049(c);
}
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(pat == PAT_DOWN) {
si.id = towerval(c);
si.dir = downdir(c);
}
else if(u == 4 || u == 10) {
for(int i=0; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
return i;
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(u == 6) {
for(int i=1; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
return i;
else if(sphere && pat == PAT_SIBLING) {
val_all(c, si, sub);
}
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(a457 && pat == PAT_ZEBRA) {
val_all(c, si, sub);
}
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(pat == PAT_COLORING && (a46 || euclid)) {
val_all(c, si, sub);
}
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
val_warped(c, si);
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;
}
char whichPattern = 0;
bool symRotation, sym01, sym02, sym03;
int subpattern(int i, char w) {
if(euclid) {
if(w == 'p')
return i;
if(w == 'z' || w == 'f')
return (symRotation && (i<3)) ? 0 : i;
}
if(a38 && w == 'p') {
if(sym01 && i == 5) i = 4;
if(symRotation && i < 4) i = 0;
return i;
}
if(w == 'z' || w == 'f' || w == 'p') {
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) {
if(a4 && !a46) {
if(i >= 4 && i < 7) i -= 4;
}
else {
if(i >= 8 && i < 12) i -= 4;
if(i >= 12 && i < 16) i -= 8;
if(i >= 20 && i < 24) i -= 4;
if(i >= 24 && i < 28) i -= 8;
if(i >= 32 && i < 36) i -= 4;
if(i >= 36 && i < 40) i -= 8;
}
}
if(w == 'p' && stdhyperbolic && symRotation && i >= 3)
i -= ((i/4-1) % 7) * 4;
return i;
}
int subpattern(cell *c, char w) {
return subpattern(realpattern(c, w), w);
return si;
}
}
@ -689,12 +710,16 @@ int geosupport_graveyard() {
int pattern_threecolor(cell *c) {
if(a38) {
int i = val38(c);
patterns::patterninfo si;
patterns::val38(c, si, 0);
int i = si.id;
if(nontruncated) return i;
else return i < 4 ? 0 : (1+(i&1));
}
if(a46 && !nontruncated) {
int i = val46(c);
patterns::patterninfo si;
patterns::val46(c, si, 0);
int i = si.id;
return i >> 2;
}
if(S7 == 4) {
@ -861,7 +886,7 @@ namespace patterns {
col[2] /= 4;
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;
}
if(whichCanvas == 'T') {
@ -920,51 +945,62 @@ namespace patterns {
}
dialog::init();
if(a46) {
dialog::addBoolItem(XLAT("two colors"), (whichPattern == 'f'), 'f');
dialog::addBoolItem(XLAT("two colors rotated"), (whichPattern == 'z'), 'z');
}
else if(a4) {
dialog::addBoolItem(XLAT("Zebra Pattern"), (whichPattern == 'z'), 'z');
}
else if(a38) {
dialog::addBoolItem(XLAT("Zebra Pattern"), (whichPattern == 'z'), 'z');
dialog::addBoolItem(XLAT("broken Emerald Pattern"), (whichPattern == 'f'), 'f');
dialog::addBoolItem(XLAT("rotated pattern"), (whichPattern == 'p'), 'p');
}
else if(euclid) {
dialog::addBoolItem(XLAT("three colors"), (whichPattern == 'f'), 'f');
dialog::addBoolItem(XLAT("Palace Pattern"), (whichPattern == 'p'), 'p');
dialog::addBoolItem(XLAT("three colors rotated"), (whichPattern == 'z'), 'z');
}
else if(sphere) {
dialog::addBoolItem(XLAT("siblings"), (whichPattern == 'p'), 'p');
}
else {
if(!stdhyperbolic)
dialog::addInfo("patterns do not work correctly in this geometry!");
if(stdhyperbolic || a4)
dialog::addBoolItem(XLAT("Zebra Pattern"), (whichPattern == PAT_ZEBRA), PAT_ZEBRA);
if(stdhyperbolic)
dialog::addBoolItem(XLAT("Emerald Pattern"), (whichPattern == PAT_EMERALD), PAT_EMERALD);
else if(a38)
dialog::addBoolItem(XLAT("broken Emerald Pattern"), (whichPattern == PAT_EMERALD), PAT_EMERALD);
if(stdhyperbolic || euclid)
dialog::addBoolItem(XLAT("Palace Pattern"), (whichPattern == PAT_PALACE), PAT_PALACE);
if(a38 || a46 || euclid)
dialog::addBoolItem(XLAT("coloring"), (whichPattern == PAT_COLORING), PAT_COLORING);
if(sphere)
dialog::addBoolItem(XLAT("siblings"), (whichPattern == PAT_SIBLING), PAT_SIBLING);
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)
dialog::addBoolItem(XLAT("torus pattern"), (whichPattern == 'F'), 'F');
dialog::addBoolItem(XLAT("torus pattern"), (whichPattern == PAT_FIELD), PAT_FIELD);
else if(sphere)
dialog::addBoolItem(XLAT("single cells"), (whichPattern == 'F'), 'F');
dialog::addBoolItem(XLAT("single cells"), (whichPattern == PAT_FIELD), PAT_FIELD);
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(whichPattern == 'F') ;
else if(!euclid) {
dialog::addBoolItem(XLAT("rotational symmetry"), (symRotation), '0');
dialog::addBoolItem(XLAT("symmetry 0-1"), (sym01), '1');
dialog::addBoolItem(XLAT("symmetry 0-2"), (sym02), '2');
dialog::addBoolItem(XLAT("symmetry 0-3"), (sym03), '3');
if(
(whichPattern == PAT_EMERALD && (stdhyperbolic || a38)) ||
(whichPattern == PAT_PALACE && stdhyperbolic) ||
(whichPattern == PAT_ZEBRA && stdhyperbolic) ||
(whichPattern == PAT_SIBLING && sphere) ||
(whichPattern == PAT_ZEBRA && a457)) {
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 (simplified)"), (displaycodes == 2), 's');
@ -982,21 +1018,19 @@ namespace patterns {
keyhandler = [] (int sym, int 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;
else whichPattern = uni;
mapeditor::modelcell.clear();
}
else if(uni == '0') symRotation = !symRotation;
else if(uni == '1') sym01 = !sym01;
else if(uni == '2') sym02 = !sym02;
else if(uni == '3') sym03 = !sym03;
else if(uni >= '0' && uni <= '5')
subpattern_flags ^= (1 << (uni - '0'));
else if(uni == '6' || uni == '7' || uni == '8') {
if(whichShape == uni) whichShape = 0;
else whichShape = uni;
}
else if(uni == '3') sym03 = !sym03;
else if(uni == 'd') displaycodes = displaycodes == 1 ? 0 : 1;
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.
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--;

View File

@ -990,6 +990,8 @@ hpcshape
shTerraArmor1, shTerraArmor2, shTerraArmor3, shTerraHead, shTerraFace,
shJiangShi, shJiangShiDress, shJiangShiCap1, shJiangShiCap2,
shAsymmetric,
shDodeca;
#define USERLAYERS 32
@ -1039,7 +1041,6 @@ hyperpoint turtlevertex(int u, double x, double y, double z) {
return hpxd(scale, x, y, z);
}
void finishshape() {
last->e = qhpc;
double area = 0;
@ -1793,6 +1794,8 @@ void buildpolys() {
bshape(shLeafFloor[0], PPR_FLOOR_DRAGON, 1*spzoom6, 313);
bshape(shLeafFloor[1], PPR_FLOOR_DRAGON, 1*spzoomd7, 314);
bshape(shAsymmetric, PPR_TEXT, scalef, 374);
bshape(shTriheptaFloor[2], PPR_FLOOR, scalef, 32);
bshape(shTriheptaFloor[3], PPR_FLOOR, scalef, 33);
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, 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
};

View File

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