1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
// 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)
// automaton state
enum hstate { hsOrigin, hsA, hsB, hsError };
int fixrot(int a) { return (a+98)% 7; }
int fix42(int a) { return (a+420)% 42; }
struct heptagon;
struct cell;
cell *newCell(int type, heptagon *master);
struct heptagon {
// automaton state
hstate s : 8;
// we are spin[i]-th neighbor of move[i]
unsigned char spin[7];
// neighbors; move[0] always goes towards origin,
// and then we go clockwise
heptagon* move[7];
// distance from the origin
short distance;
heptagon*& modmove(int i) { return move[fixrot(i)]; }
unsigned char& gspin(int i) { return spin[fixrot(i)]; }
cell *c7;
};
// 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) {
if(s == hsOrigin) return hsA;
if(s == hsA && dir >= 3 && dir <= 4) return hsA;
if(s == hsA && dir == 5) return hsB;
if(s == hsB && dir == 4) return hsB;
if(s == hsB && dir == 3) return hsA;
return hsError;
}
heptagon origin;
// create a new heptagon
void buildHeptagon(heptagon *parent, int d, hstate s) {
heptagon *h = new heptagon;
h->s = s;
for(int i=0; i<7; i++) h->move[i] = NULL;
h->move[0] = parent; h->spin[0] = d;
parent->move[d] = h; parent->spin[d] = 0;
h->c7 = newCell(7, h);
h->distance = parent->distance + 1;
}
// create h->move[d] if not created yet
heptagon *createStep(heptagon *h, int d);
void addSpin(heptagon *h, int d, heptagon *from, int rot, int spin) {
rot = fixrot(rot);
createStep(from, rot);
h->move[d] = from->move[rot];
h->spin[d] = fixrot(from->spin[rot] + spin);
h->move[d]->move[fixrot(from->spin[rot] + spin)] = h;
h->move[d]->spin[fixrot(from->spin[rot] + spin)] = d;
}
heptagon *createStep(heptagon *h, int d) {
d = fixrot(d);
if(h->move[d]) return h->move[d];
if(h->s == hsOrigin) {
buildHeptagon(h, d, hsA);
}
else if(d == 1) {
addSpin(h, d, h->move[0], h->spin[0]-1, -1);
}
else if(d == 6) {
addSpin(h, d, h->move[0], h->spin[0]+1, +1);
}
else if(d == 2) {
createStep(h->move[0], h->spin[0]-1);
addSpin(h, d, h->move[0]->modmove(h->spin[0]-1), 5 + h->move[0]->gspin(h->spin[0]-1), -1);
}
else if(d == 5 && h->s == hsB) {
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);
}
else
buildHeptagon(h, d, (d == 5 || (h->s == hsB && d == 4)) ? hsB : hsA);
return h->move[d];
}
// a structure used to walk on the heptagonal tesselation
// (remembers not only the heptagon, but also direction)
struct heptspin {
heptagon *h;
int spin;
};
heptspin hsstep(const heptspin &hs, int spin) {
createStep(hs.h, hs.spin);
heptspin res;
res.h = hs.h->move[hs.spin];
res.spin = fixrot(hs.h->spin[hs.spin] + spin);
return res;
}
heptspin hsspin(const heptspin &hs, int val) {
heptspin res;
res.h = hs.h;
res.spin = fixrot(hs.spin + val);
return res;
}
// display the coordinates of the heptagon
void backtrace(heptagon *pos) {
if(pos == &origin) return;
backtrace(pos->move[0]);
printf(" %d", pos->spin[0]);
}
void hsshow(const heptspin& t) {
printf("ORIGIN"); backtrace(t.h); printf(" (spin %d)\n", t.spin);
}
|