1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-01 03:46:16 +00:00
hyperrogue/heptagon.cpp

329 lines
9.2 KiB
C++
Raw Normal View History

2015-08-08 13:57:52 +00:00
// Hyperbolic Rogue
// Copyright (C) 2011-2012 Zeno Rogue, see 'hyper.cpp' for details
// heptagon here refers to underlying heptagonal tesselation
// (which you can see by changing the conditions in graph.cpp)
#define MIRR(x) x.mirrored
2017-10-27 18:07:58 +00:00
int fixrot(int a) { return (a+MODFIXER)% S7; }
int fix42(int a) { return (a+MODFIXER)% S42; }
2015-08-08 13:57:52 +00:00
struct heptagon;
struct cell;
cell *newCell(int type, heptagon *master);
2017-03-23 10:53:57 +00:00
// spintable functions
int tspin(uint32_t& t, int d) {
return (t >> (d<<2)) & 7;
}
int tmirror(uint32_t& t, int d) {
return (t >> ((d<<2)+3)) & 1;
}
void tsetspin(uint32_t& t, int d, int spin) {
t &= ~(15 << (d<<2));
t |= spin << (d<<2);
}
2016-08-26 09:58:03 +00:00
2015-08-08 13:57:52 +00:00
struct heptagon {
// automaton state
2017-07-04 13:38:33 +00:00
hstate s : 6;
int dm4: 2;
2015-08-08 13:57:52 +00:00
// we are spin[i]-th neighbor of move[i]
2017-03-23 10:53:57 +00:00
uint32_t spintable;
int spin(int d) { return tspin(spintable, d); }
int mirror(int d) { return tmirror(spintable, d); }
void setspin(int d, int sp) { tsetspin(spintable, d, sp); }
2015-08-08 13:57:52 +00:00
// neighbors; move[0] always goes towards origin,
// and then we go clockwise
2017-10-27 18:07:58 +00:00
heptagon* move[MAX_EDGE];
2015-08-08 13:57:52 +00:00
// distance from the origin
short distance;
2016-01-02 10:09:13 +00:00
// emerald/wineyard generator
short emeraldval;
// fifty generator
short fiftyval;
// zebra generator (1B actually)
short zebraval;
2017-03-23 10:53:57 +00:00
// field id
int fieldval;
2016-08-26 09:58:03 +00:00
// evolution data
short rval0, rval1;
struct cdata *cdata;
2016-01-02 10:09:13 +00:00
// central cell
2015-08-08 13:57:52 +00:00
cell *c7;
// associated generator of alternate structure, for Camelot and horocycles
heptagon *alt;
2016-01-02 10:09:13 +00:00
// functions
heptagon*& modmove(int i) { return move[fixrot(i)]; }
2017-03-23 10:53:57 +00:00
unsigned char gspin(int i) { return spin(fixrot(i)); }
2015-08-08 13:57:52 +00:00
};
// the automaton is used to generate each heptagon in an unique way
// (you can see the tree obtained by changing the conditions in graph.cpp)
// from the origin we can go further in any direction, and from other heptagons
// we can go in directions 3 and 4 (0 is back to origin, so 3 and 4 go forward),
// and sometimes in direction 5
hstate transition(hstate s, int dir) {
2017-03-23 10:53:57 +00:00
if(sphere) {
if(S7 == 4) {
if(s == hsOrigin) return dir == 0 ? hsB0 : hsB1;
}
if(S7 == 3) {
if(s == hsOrigin) return hsB1;
}
if(s == hsOrigin) return dir == 0 ? hsA0 : hsA1;
if(s == hsA0 && dir == 2) return hsB0;
if(s == hsA1 && dir == 2) return hsB1;
if(s == hsB0 && dir == S7-2) return hsC;
return hsError;
}
2017-10-28 23:57:34 +00:00
else if(S6 == 8) {
2017-10-28 08:04:28 +00:00
if(s == hsOrigin) return hsA;
if(s == hsA && (dir >= 2 && dir < S7-1)) return hsA;
if(s == hsA && (dir == S7-1)) return hsB;
if(s == hsB && (dir >= 2 && dir < S7-2)) return hsA;
if(s == hsB && (dir == S7-2)) return hsB;
}
2017-03-23 10:53:57 +00:00
else {
if(s == hsOrigin) return hsA;
2017-10-27 18:07:58 +00:00
if(s == hsA && dir >= 3 && dir <= S7-3) return hsA;
if(s == hsA && dir == S7-2) return hsB;
2017-10-28 23:57:34 +00:00
if(s == hsB && dir >= 3 && dir <= S7-4) return hsA;
2017-10-27 18:07:58 +00:00
if(s == hsB && dir == S7-3) return hsB;
2017-03-23 10:53:57 +00:00
}
2015-08-08 13:57:52 +00:00
return hsError;
}
// create h->move[d] if not created yet
heptagon *createStep(heptagon *h, int d);
2017-10-27 18:07:58 +00:00
/*
int indent = 0;
struct indenter {
indenter() { indent += 2; }
~indenter() { indent -= 2; }
};
template<class... T> auto iprintf(T... t) { for(int i=0; i<indent; i++) putchar(' '); return printf(t...); }
*/
2017-10-28 23:57:34 +00:00
#define COMPUTE -1000000
2015-08-08 13:57:52 +00:00
// create a new heptagon
2017-10-28 23:57:34 +00:00
heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0, int fixdistance = COMPUTE) {
2015-08-08 13:57:52 +00:00
heptagon *h = new heptagon;
h->alt = NULL;
h->s = s;
2017-10-27 18:07:58 +00:00
for(int i=0; i<MAX_EDGE; i++) h->move[i] = NULL;
2017-03-23 10:53:57 +00:00
h->spintable = 0;
h->move[pard] = parent; tsetspin(h->spintable, pard, d);
parent->move[d] = h; tsetspin(parent->spintable, d, pard);
2015-08-08 13:57:52 +00:00
if(parent->c7) {
2017-10-27 18:07:58 +00:00
h->c7 = newCell(S7, h);
2016-08-26 09:58:03 +00:00
h->rval0 = h->rval1 = 0; h->cdata = NULL;
h->emeraldval = emerald_heptagon(parent->emeraldval, d);
h->zebraval = zebra_heptagon(parent->zebraval, d);
h->fieldval = currfp.connections[fieldpattern::btspin(parent->fieldval, d)];
if(parent->s == hsOrigin)
h->fiftyval = firstfiftyval(d);
else
h->fiftyval = nextfiftyval(parent->fiftyval, parent->move[0]->fiftyval, d);
2015-08-08 13:57:52 +00:00
}
else {
h->c7 = NULL;
2016-01-02 10:09:13 +00:00
h->emeraldval = 0;
h->fiftyval = 0;
2015-08-08 13:57:52 +00:00
}
2016-01-02 10:09:13 +00:00
//generateEmeraldval(parent);
//generateEmeraldval(h);
2015-08-08 13:57:52 +00:00
if(pard == 0) {
2017-07-04 13:38:33 +00:00
h->dm4 = parent->dm4+1;
2017-10-28 23:57:34 +00:00
if(fixdistance != COMPUTE) h->distance = fixdistance;
else if(purehepta) h->distance = parent->distance + 1;
else if(parent->s == hsOrigin) h->distance = parent->distance + 2;
else if(S3 == 4) {
h->distance = parent->distance + 2;
if(h->spin(0) == 2 || (h->spin(0) == 3 && S7 <= 5))
h->distance = min<short>(h->distance, createStep(h->move[0], 0)->distance + 3);
if(h->spin(0) == 2 && h->move[0]) {
int d = h->spin(0);
int d1 = (d+S7-1)%S7;
heptagon* h1 = createStep(h->move[0], d1);
if(h1->distance <= h->move[0]->distance)
h->distance = h->move[0]->distance+1;
}
if((h->s == hsB && h->move[0]->s == hsB) || h->move[0]->s == hsA) {
int d = h->spin(0);
heptagon* h1 = createStep(h->move[0], (d+1)%S7);
if(h1->distance <= h->move[0]->distance)
h->distance = h->move[0]->distance+1;
}
if(h->spin(0) == S7-1)
h->distance = min(
h->move[0]->move[0]->distance + 2,
createStep(h, S7-1)->distance + 1
);
}
else if(h->spin(0) == S7-2)
2015-08-08 13:57:52 +00:00
h->distance = parent->distance + 1;
2017-10-28 23:57:34 +00:00
else if(h->spin(0) == S7-3 && h->move[0]->s == hsB)
h->distance = createStep(h->move[0], (h->spin(0)+2)%S7)->distance + 3;
2015-08-08 13:57:52 +00:00
else h->distance = parent->distance + 2;
}
2017-07-04 13:38:33 +00:00
else {
h->distance = parent->distance - (purehepta?1:2);
2017-10-28 23:57:34 +00:00
if(S3 == 4 && S7 == 5) {
if(h->s == hsOrigin) {
printf("had to cheat!\n");
h->distance = parent->distance - 2;
}
else {
h->distance = parent->distance - 1;
buildHeptagon(h, 2, hsA, 0, h->distance + 2);
buildHeptagon(h, 4, hsB, 0, h->distance);
}
}
2017-07-04 13:38:33 +00:00
h->dm4 = parent->dm4-1;
}
2015-08-08 13:57:52 +00:00
return h;
}
2017-10-28 08:04:28 +00:00
void connectHeptagons(heptagon *h1, int d1, heptagon *h2, int d2) {
h1->move[d1] = h2;
h1->setspin(d1, d2);
h2->move[d2] = h1;
h2->setspin(d2, d1);
}
2017-10-28 23:57:34 +00:00
int recsteps;
void breakpoint() {
// printf("Breakpoint!\n");
}
2015-08-08 13:57:52 +00:00
void addSpin(heptagon *h, int d, heptagon *from, int rot, int spin) {
rot = fixrot(rot);
createStep(from, rot);
2017-10-28 08:04:28 +00:00
int fr = fixrot(from->spin(rot) + spin);
connectHeptagons(h, d, from->move[rot], fr);
/* h->move[d] = from->move[rot];
h->setspin(d, fr);
h->move[d]->move[fr] = h;
h->move[d]->setspin(fr, d); */
2016-01-02 10:09:13 +00:00
//generateEmeraldval(h->move[d]); generateEmeraldval(h);
2015-08-08 13:57:52 +00:00
}
2016-08-26 09:58:03 +00:00
extern int hrand(int);
2017-10-28 08:04:28 +00:00
heptagon *createStep(heptagon *h, int d);
// a structure used to walk on the heptagonal tesselation
// (remembers not only the heptagon, but also direction)
struct heptspin {
heptagon *h;
int spin;
bool mirrored;
heptspin() { mirrored = false; }
};
2017-10-28 23:57:34 +00:00
int lrecsteps;
2017-10-28 08:04:28 +00:00
heptspin hsstep(const heptspin &hs, int spin) {
2017-10-28 23:57:34 +00:00
recsteps++;
if(recsteps % 5 == 0 && recsteps > lrecsteps) lrecsteps = recsteps, breakpoint();
2017-10-28 08:04:28 +00:00
createStep(hs.h, hs.spin);
2017-10-28 23:57:34 +00:00
recsteps--;
2017-10-28 08:04:28 +00:00
heptspin res;
res.h = hs.h->move[hs.spin];
res.mirrored = hs.mirrored ^ hs.h->mirror(hs.spin);
res.spin = fixrot(hs.h->spin(hs.spin) + (MIRR(res)?-spin:spin));
return res;
}
heptspin hsspin(const heptspin &hs, int val) {
heptspin res;
res.h = hs.h;
res.spin = fixrot(hs.spin + (MIRR(hs)?-val:val));
res.mirrored = hs.mirrored;
return res;
}
2015-08-08 13:57:52 +00:00
heptagon *createStep(heptagon *h, int d) {
d = fixrot(d);
2017-03-23 10:53:57 +00:00
if(!h->move[0] && h->s != hsOrigin) {
2017-10-28 23:57:34 +00:00
// cheating:
int pard;
if(S3 == 3)
pard = 3 + hrand(2);
else if(S3 == 4 && S7 == 5)
pard = 3; // to do: randomize
else if(S3 == 4)
pard = 3;
buildHeptagon(h, 0, h->distance < -1000 ? hsOrigin : hsA, pard);
2015-08-08 13:57:52 +00:00
}
if(h->move[d]) return h->move[d];
if(h->s == hsOrigin) {
buildHeptagon(h, d, hsA);
}
2017-10-28 23:57:34 +00:00
else if(S3 == 4) {
2017-10-28 08:04:28 +00:00
if(d == 1) {
heptspin hs;
hs.h = h;
hs.spin = 0;
hs.mirrored = false;
hs = hsstep(hs, -1);
hs = hsstep(hs, -1);
hs = hsstep(hs, -1);
connectHeptagons(h, d, hs.h, hs.spin);
}
else if(h->s == hsB && d == S7-1) {
heptspin hs;
hs.h = h;
hs.spin = 0;
hs.mirrored = false;
hs = hsstep(hs, 1);
hs = hsstep(hs, 1);
hs = hsstep(hs, 1);
connectHeptagons(h, d, hs.h, hs.spin);
}
else
buildHeptagon(h, d, transition(h->s, d));
}
2015-08-08 13:57:52 +00:00
else if(d == 1) {
2017-03-23 10:53:57 +00:00
addSpin(h, d, h->move[0], h->spin(0)-1, -1);
2015-08-08 13:57:52 +00:00
}
2017-10-27 18:07:58 +00:00
else if(d == S7-1) {
2017-03-23 10:53:57 +00:00
addSpin(h, d, h->move[0], h->spin(0)+1, +1);
2015-08-08 13:57:52 +00:00
}
else if(d == 2) {
2017-03-23 10:53:57 +00:00
createStep(h->move[0], h->spin(0)-1);
2017-10-27 18:07:58 +00:00
addSpin(h, d, h->move[0]->modmove(h->spin(0)-1), S7-2 + h->move[0]->gspin(h->spin(0)-1), -1);
2015-08-08 13:57:52 +00:00
}
2017-10-27 18:07:58 +00:00
else if(d == S7-2 && h->s == hsB) {
2017-03-23 10:53:57 +00:00
createStep(h->move[0], h->spin(0)+1);
addSpin(h, d, h->move[0]->modmove(h->spin(0)+1), 2 + h->move[0]->gspin(h->spin(0)+1), +1);
2015-08-08 13:57:52 +00:00
}
else
2017-10-27 18:07:58 +00:00
buildHeptagon(h, d, (d == S7-2 || (h->s == hsB && d == S7-3)) ? hsB : hsA);
2015-08-08 13:57:52 +00:00
return h->move[d];
}
// display the coordinates of the heptagon
void backtrace(heptagon *pos) {
if(pos->s == hsOrigin) return;
2015-08-08 13:57:52 +00:00
backtrace(pos->move[0]);
2017-03-23 10:53:57 +00:00
printf(" %d", pos->spin(0));
2015-08-08 13:57:52 +00:00
}
void hsshow(const heptspin& t) {
printf("ORIGIN"); backtrace(t.h); printf(" (spin %d)\n", t.spin);
}
2017-10-28 08:04:28 +00:00