mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-09-01 18:27:55 +00:00
generators included
This commit is contained in:
14
generators/README.md
Normal file
14
generators/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
For completeness, this directory contains various programs used for generating various tables in HyperRogue.
|
||||
|
||||
* Quotient space tables (in `hrmap_quotient` in `cell.cpp`) have been generated with `bring.cpp`, `schmutz.cpp`, `quartic.cpp`, `macbeath.cpp`, and (for Minimal) manually.
|
||||
|
||||
* Pattern rules (in `patterns.cpp`) have been generated with patterngen.cpp.
|
||||
|
||||
* Precomputed windmaps (`windcodes*` in `complex.cpp`) have been generated by the disabled code in `windmap::create()`.
|
||||
|
||||
* Embedded font (`fonttable` in `nofont.cpp`) has been generated with `-DCAP_CREATEFONT=1`.
|
||||
|
||||
* Vector graphics (`polydata[]` in `polygons.cpp`) have been generated in the Vector Graphics Editor. Press the Shift+S to generate the data in the required format. (Replace `ID` with `NEWSHAPE, id`.)
|
||||
|
||||
Some of these programs are standalone, while some need to be compiled with HyperRogue. These programs are not maintained (they are written once and forgotten), so (in the latter case)
|
||||
it is likely that they do no longer work; however, they are still included for reference.
|
122
generators/bring.cpp
Normal file
122
generators/bring.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
// Bring's Surface generator
|
||||
// Copyright (C) 2018 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int isize(const auto x) { return x.size(); }
|
||||
|
||||
int mul(int a, int b) {
|
||||
int p = 0;
|
||||
for(int i=0; i<3; i++) if((a>>i)&1)
|
||||
for(int j=0; j<3; j++) if((b>>j)&1)
|
||||
p ^= (1<<(i+j));
|
||||
|
||||
for(int z=4; z>=0; z--)
|
||||
if(p&(8<<z)) p ^= (11<<z);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int elements = 0;
|
||||
|
||||
vector<array<int, 5>> s5_elements;
|
||||
|
||||
map<array<int, 5>, int> back;
|
||||
|
||||
int multable[504][504];
|
||||
|
||||
int mpow(int a, int n) {
|
||||
int z = a;
|
||||
while(n > 1) z = multable[a][z], n--;
|
||||
return z;
|
||||
}
|
||||
|
||||
int inset[504];
|
||||
|
||||
int main() {
|
||||
array<int, 5> ar;
|
||||
for(int i=0; i<5; i++) ar[i] = i;
|
||||
|
||||
do {
|
||||
back[ar] = isize(s5_elements);
|
||||
s5_elements.push_back(ar);
|
||||
}
|
||||
while(next_permutation(ar.begin(), ar.end()));
|
||||
|
||||
for(int a=0; a<120; a++)
|
||||
for(int b=0; b<120; b++) {
|
||||
array<int, 5> res;
|
||||
for(int i=0; i<5; i++)
|
||||
res[i] = s5_elements[a] [ s5_elements[b][i] ];
|
||||
multable[a][b] = back[res];
|
||||
}
|
||||
|
||||
int id;
|
||||
|
||||
for(int a=0; a<120; a++)
|
||||
if(multable[a][a] == a) id = a;
|
||||
|
||||
printf("id = %d\n", id);
|
||||
|
||||
int xid = 0;
|
||||
|
||||
int sols = 0;
|
||||
|
||||
for(int R=0; R<120; R++)
|
||||
for(int P=0; P<120; P++) {
|
||||
if(P == 0 && mpow(R, 5) == id) printf("deg5 R\n");
|
||||
if(multable[P][P] != id) continue;
|
||||
if(mpow(multable[R][P], 4) != id) continue;
|
||||
if(mpow(R, 5) != id) continue;
|
||||
xid++;
|
||||
vector<int> allels = {id};
|
||||
inset[id] = xid;
|
||||
for(int i=0; i<isize(allels); i++) {
|
||||
for(int m: {P, R}) {
|
||||
int im = allels[i];
|
||||
int a = multable[im][m];
|
||||
// printf("%d x %d = %d\n", im, m, a);
|
||||
if(inset[a] != xid) inset[a] = xid, allels.push_back(a);
|
||||
}
|
||||
}
|
||||
if(isize(allels) != 120) continue;
|
||||
printf("R = %d P = %d count = %d\n", R, P, isize(allels));
|
||||
for(int a: s5_elements[R]) printf("%d ", a); printf("// ");
|
||||
for(int a: s5_elements[P]) printf("%d ", a); printf("\n");
|
||||
sols++;
|
||||
|
||||
array<int, 120> cellid;
|
||||
array<int, 120> bycellid;
|
||||
|
||||
for(int a=0; a<120; a++) cellid[a] = 0;
|
||||
|
||||
int ncell = 0;
|
||||
for(int a=0; a<120; a++) if(cellid[a] == 0) {
|
||||
int b = a;
|
||||
for(int s=0; s<5; s++) cellid[b] = ncell + s, bycellid[ncell + s] = b, b = multable[b][R];
|
||||
ncell += 5;
|
||||
}
|
||||
|
||||
printf("ncell = %d\n", ncell);
|
||||
|
||||
for(int a=0; a<24; a++) {
|
||||
printf("/* %03d */ ", a);
|
||||
for(int b=0; b<5; b++) {
|
||||
printf("%d, ", cellid[multable[bycellid[5*a+b]][P]]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("solutions = %d\n", sols);
|
||||
|
||||
return 0;
|
||||
}
|
132
generators/macbeath.cpp
Normal file
132
generators/macbeath.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
// Fricke-Macbeath Surface generator
|
||||
// Copyright (C) 2018 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int isize(const auto x) { return x.size(); }
|
||||
|
||||
int mul(int a, int b) {
|
||||
int p = 0;
|
||||
for(int i=0; i<3; i++) if((a>>i)&1)
|
||||
for(int j=0; j<3; j++) if((b>>j)&1)
|
||||
p ^= (1<<(i+j));
|
||||
|
||||
for(int z=4; z>=0; z--)
|
||||
if(p&(8<<z)) p ^= (11<<z);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int multable[8][8];
|
||||
|
||||
int elements = 0;
|
||||
|
||||
vector<array<int, 4>> psl_elements;
|
||||
|
||||
int multable_psl[504][504];
|
||||
|
||||
map<array<int, 4>, int> back;
|
||||
|
||||
int mpow(int a, int n) {
|
||||
int z = a;
|
||||
while(n > 1) z = multable_psl[a][z], n--;
|
||||
return z;
|
||||
}
|
||||
|
||||
int inset[504];
|
||||
|
||||
int main() {
|
||||
for(int a=0; a<8; a++) {
|
||||
for(int b=0; b<8; b++) printf("%d ", mul(a, b));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for(int a=0; a<8; a++)
|
||||
for(int b=0; b<8; b++)
|
||||
multable[a][b] = mul(a, b);
|
||||
|
||||
for(int a=0; a<8; a++)
|
||||
for(int b=0; b<8; b++)
|
||||
for(int c=0; c<8; c++)
|
||||
for(int d=0; d<8; d++)
|
||||
if((multable[a][d] ^ multable[b][c]) == 1) {
|
||||
array<int, 4> arr = { a, b, c, d};
|
||||
psl_elements.emplace_back(arr);
|
||||
}
|
||||
|
||||
printf("elements = %d\n", isize(psl_elements));
|
||||
|
||||
for(int a=0; a<504; a++) back[psl_elements[a]] = a;
|
||||
|
||||
for(int a=0; a<504; a++)
|
||||
for(int b=0; b<504; b++) {
|
||||
auto pa = psl_elements[a];
|
||||
auto pb = psl_elements[b];
|
||||
array<int, 4> pc;
|
||||
for(int s=0; s<4; s++) {
|
||||
int s0 = s&2;
|
||||
int s1 = s&1;
|
||||
pc[s] = (multable[pa[s0]][pb[s1]] ^ multable[pa[s0^1]][pb[s1^2]]);
|
||||
}
|
||||
multable_psl[a][b] = back[pc];
|
||||
}
|
||||
|
||||
int id;
|
||||
|
||||
for(int a=0; a<504; a++)
|
||||
if(multable_psl[a][a] == a) id = a;
|
||||
|
||||
printf("id = %d\n", id);
|
||||
|
||||
int xid = 0;
|
||||
|
||||
for(int R=0; R<504; R++)
|
||||
for(int P=0; P<504; P++) {
|
||||
if(multable_psl[P][P] != id) continue;
|
||||
if(mpow(multable_psl[R][P], 3) != id) continue;
|
||||
if(mpow(R, 7) != id) continue;
|
||||
xid++;
|
||||
vector<int> allels = {id};
|
||||
inset[id] = xid;
|
||||
for(int i=0; i<isize(allels); i++) {
|
||||
for(int m: {P, R}) {
|
||||
int im = allels[i];
|
||||
int a = multable_psl[im][m];
|
||||
// printf("%d x %d = %d\n", im, m, a);
|
||||
if(inset[a] != xid) inset[a] = xid, allels.push_back(a);
|
||||
}
|
||||
}
|
||||
printf("R = %d P = %d count = %d\n", R, P, isize(allels));
|
||||
|
||||
array<int, 504> cellid;
|
||||
array<int, 504> bycellid;
|
||||
|
||||
for(int a=0; a<504; a++) cellid[a] = 0;
|
||||
|
||||
int ncell = 0;
|
||||
for(int a=0; a<504; a++) if(cellid[a] == 0) {
|
||||
int b = a;
|
||||
for(int s=0; s<7; s++) cellid[b] = ncell + s, bycellid[ncell + s] = b, b = multable_psl[b][R];
|
||||
ncell += 7;
|
||||
}
|
||||
|
||||
printf("ncell = %d\n", ncell);
|
||||
|
||||
for(int a=0; a<72; a++) {
|
||||
printf("/* %03d */ ", a);
|
||||
for(int b=0; b<7; b++) {
|
||||
printf("%d, ", cellid[multable_psl[bycellid[7*a+b]][P]]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
448
generators/patterngen.cpp
Normal file
448
generators/patterngen.cpp
Normal file
@@ -0,0 +1,448 @@
|
||||
// Hyperbolic Rogue pattern generator
|
||||
|
||||
// Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
namespace hr {
|
||||
|
||||
void spill50(cell *c, eWall w, int r) {
|
||||
c->wall = w;
|
||||
if(r) for(int i=0; i<c->type; i++) spill50(createMov(c, i), w, r-1);
|
||||
}
|
||||
|
||||
int style = 3;
|
||||
|
||||
struct state50 {
|
||||
bool polarity1;
|
||||
bool polarity2;
|
||||
color_t color, color2, wc2;
|
||||
};
|
||||
|
||||
void progress(cell *c, state50 s);
|
||||
|
||||
#include <map>
|
||||
|
||||
map<cell*, state50> map50;
|
||||
|
||||
void initPatternFifty(cell *c) {
|
||||
state50 s;
|
||||
s.polarity1 = 0;
|
||||
s.polarity2 = 0;
|
||||
s.color = 0;
|
||||
s.color2 = 1;
|
||||
s.wc2 = 0;
|
||||
map50[c] = s;
|
||||
}
|
||||
|
||||
int par;
|
||||
|
||||
int haverule[1<<24][8];
|
||||
|
||||
void saveCode(heptagon *H1, int d, heptagon *H2) {
|
||||
|
||||
/*
|
||||
if(!H1 || !H2) return;
|
||||
if(H1->move[d] != H2) exit(1);
|
||||
|
||||
int h1 = H1->fiftyval;
|
||||
int h2 = H2->fiftyval;
|
||||
|
||||
if(!h1 || !h2) return;
|
||||
|
||||
if(haverule[h1][d] && haverule[h1][d] != h2) {
|
||||
printf("rule conflict: %06x, %d, %06x/%06x\n",
|
||||
h1, d, h2, haverule[h1][d]);
|
||||
// exit(1);
|
||||
}
|
||||
|
||||
if(!haverule[h1][d]) {
|
||||
haverule[h1][d] = h2;
|
||||
|
||||
printf("RULE50(0x%06x, %d, 0x%06x)\n", h1, d, h2);
|
||||
} */
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void saveCode(cell *c) {
|
||||
|
||||
/* heptagon *hept = c->master;
|
||||
|
||||
if(hept != &origin)
|
||||
saveCode(hept->move[0], hept->spin[0], hept); */
|
||||
|
||||
bool allcodes = c->master->fiftyval >= 0;
|
||||
|
||||
for(int i=0; i<7; i++)
|
||||
if(c->master->move[i] && c->master->move[i]->fiftyval >= 0) ;
|
||||
else allcodes = false;
|
||||
|
||||
if(allcodes) {
|
||||
printf("RULE50(0x%03x", c->master->fiftyval);
|
||||
int rulebase = 0;
|
||||
for(int i=0; i<7; i++)
|
||||
if(c->master->move[i]->fiftyval < c->master->move[rulebase]->fiftyval)
|
||||
rulebase = i;
|
||||
for(int i=0; i<7; i++) printf(", 0x%03x", c->master->move[(rulebase+i)%7]->fiftyval);
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
// hept->fiftyused = true;
|
||||
}
|
||||
|
||||
void encode(cell *c, state50 s, int mod, int spn) {
|
||||
/*int i = 0;
|
||||
i *= 16; i += s.color;
|
||||
i *= 16; i += s.color2;
|
||||
i *= 16; i += s.polarity1;
|
||||
i *= 16; i += s.polarity2;
|
||||
i *= 16; i += mod;
|
||||
i *= 16; i += spn;
|
||||
if(c->master->fiftyval) { printf("multiply 50val\n"); exit(1); }
|
||||
c->master->fiftyval = i; c->master->fiftyused = false; */
|
||||
|
||||
c->master->fiftyval =
|
||||
s.color + s.polarity1 * 8 + s.polarity2 * 16 + mod * 32;
|
||||
// s.color * 16 + (s.polarity1 ? 128 : 0) + (s.polarity2 ? 256 :0) + mod;
|
||||
|
||||
saveCode(c);
|
||||
for(int i=0; i<7; i++)
|
||||
saveCode(createStep(c->master, i)->c7);
|
||||
|
||||
/* for(int i=0; i<7; i++) if(c->master->move[i]) {
|
||||
saveCode(c->master, i, c->master->move[i]);
|
||||
saveCode(c->master->move[i], c->master->spin[i], c->master);
|
||||
} */
|
||||
}
|
||||
|
||||
eWall colorwalls[4] = {waCIsland, waCIsland2, waMineOpen, waDeadfloor };
|
||||
|
||||
void patternFiftyAt(cell *c) {
|
||||
if(!map50.count(c)) return;
|
||||
|
||||
state50 s = map50[c];
|
||||
|
||||
// c->wall = waCIsland;
|
||||
|
||||
// if(c->heat > ii) return;
|
||||
|
||||
// printf("pfifty %p\n", c);
|
||||
|
||||
if(style == 1 && s.polarity2) {
|
||||
spill50(c, waCamelot, 3);
|
||||
spill50(c, waNone, 2);
|
||||
|
||||
for(int i=0; i<c->type; i++) {
|
||||
cellwalker cw(c, i);
|
||||
cellwalker cw1 = cw + wstep + 4 + wstep;
|
||||
(cw1+3+wstep).at->wall = waFloorA;
|
||||
(cw1+4+wstep).at->wall = waFloorA;
|
||||
}
|
||||
}
|
||||
|
||||
/*switch(ii) {
|
||||
case 0:
|
||||
spill50(c, waNone, 3);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
spill50(c, waNone, 3);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
spill50(c, waNone, 3);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
spill50(c, waNone, 3);
|
||||
break;
|
||||
} */
|
||||
|
||||
if(style == 2) {
|
||||
spill50(c, waCavefloor, 2);
|
||||
spill50(c, waFloorA, 1);
|
||||
}
|
||||
|
||||
if(style == 3) {
|
||||
spill50(c, colorwalls[s.color], 3);
|
||||
// c->item = itGold;
|
||||
// if(s.polarity2) return;
|
||||
}
|
||||
|
||||
encode(c, s, 0, 0);
|
||||
|
||||
int sgn = s.polarity2 ? 1 : -1;
|
||||
int sgn1 = s.polarity1 ? 1 : -1;
|
||||
|
||||
color_t col2 = s.color2, sw = s.wc2;
|
||||
|
||||
while(col2 != 7-s.color) {
|
||||
sw += (s.polarity1?1:-1); sw %= 7;
|
||||
while(true) { col2++; col2 &= 7; if(col2 != s.color) break; }
|
||||
}
|
||||
|
||||
for(int i=0; i<c->type; i++) {
|
||||
auto cw = cellwalker(c, sw) + (sgn1 * i) + wstep + (sgn * 4) + wstep;
|
||||
if(cw.spin < 0 || cw.spin >= 7 || cw.at->type != 7) exit(1);
|
||||
encode(cw.c, s, 1+i, cw.spin);
|
||||
}
|
||||
|
||||
for(int i=0; i<c->type; i++) {
|
||||
auto cw = cellwalker(c, sw) + (sgn1 * i) + wstep + 3 + wstep + 3 + wstep;
|
||||
if(cw.spin < 0 || cw.spin >= 7 || cw.at->type != 7) exit(1);
|
||||
encode(cw.c, s, 8+i, cw.spin);
|
||||
}
|
||||
|
||||
// c->heat = s.color +
|
||||
|
||||
for(int i=0; i<c->type; i++) {
|
||||
cellwalker cw(c, s.wc2);
|
||||
cw += (sgn1 * i);
|
||||
cw += wstep;
|
||||
if(style == 0) cw.at->wall = waCamelot;
|
||||
// cw.at->item = itSilver;
|
||||
cw += (sgn*4); //6
|
||||
cw += wstep; if(style == 0) cw.at->wall = waFloorA;
|
||||
|
||||
// cw.at->item = itSilver;
|
||||
cw += (sgn*4); //7
|
||||
cw += wstep; if(style == 0) cw.at->wall = waFloorA;
|
||||
// cw.at->item = itSilver;
|
||||
cw += (3); //6
|
||||
cw += wstep; if(style == 0) cw.at->wall = waFloorA;
|
||||
// cw.at->item = itSilver;
|
||||
cw += (3); //6
|
||||
cw += wstep; if(style == 0) cw.at->wall = waFloorA;
|
||||
// cw.at->item = itSilver;
|
||||
cw += (sgn*3); //7
|
||||
cw += wstep; if(style == 0) cw.at->wall = waCamelot;
|
||||
// cw.at->item = itSilver;
|
||||
cw += (sgn*2); //6
|
||||
cw += wstep; // cw.at->item = itGold;
|
||||
// setdist(cw.c, 8, NULL);
|
||||
state50 s2 = s; s2.polarity1 = !s.polarity1;
|
||||
s2.wc2 = (cw.spin + sgn1 * i + sgn + 42) % 7;
|
||||
progress(cw.c, s2);
|
||||
// printf("heat set %f\n", cw.at->heat);
|
||||
}
|
||||
|
||||
int newcol = s.color2;
|
||||
|
||||
// if(s.polarity2) return;
|
||||
|
||||
for(int i=0; i<c->type; i++) {
|
||||
cellwalker cw(c, s.wc2);
|
||||
cw += (sgn1 * i);
|
||||
cw += wstep; // cw.at->item = itSilver;
|
||||
// cw.at->item = itDiamond;
|
||||
cw += (3); // 6
|
||||
cw += wstep; // cw.at->item = itSilver;
|
||||
// cw.at->item = itDiamond;
|
||||
cw += (sgn*4); // 6
|
||||
cw += wstep; // cw.at->item = itSilver;
|
||||
// cw.at->item = itDiamond;
|
||||
cw += (sgn*2); // 6
|
||||
cw += wstep; // cw.at->item = itSilver;
|
||||
// cw.at->item = itDiamond;
|
||||
cw += (3); // 6
|
||||
cw += wstep; // cw.at->item = itSilver;
|
||||
// cw.at->item = itDiamond;
|
||||
cw += (sgn*3); // 7
|
||||
cw += wstep; // cw.at->item = itSilver;
|
||||
// cw.at->item = itDiamond;
|
||||
cw += (sgn*4); // 6
|
||||
cw += wstep; // cw.at->item = itSilver;
|
||||
// setdist(cw.c, 8, NULL);
|
||||
state50 s2 = s;
|
||||
s2.polarity2 = !s.polarity2;
|
||||
if(s.polarity2) s2.polarity1 = !s.polarity1;
|
||||
s2.color2 = s2.color;
|
||||
s2.color = newcol;
|
||||
s2.wc2 = cw.spin;
|
||||
progress(cw.c, s2);
|
||||
while(true) { newcol++; newcol &= 7; if(newcol != s2.color && newcol != s.color) break; }
|
||||
// printf("heat set %f\n", cw.at->heat);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void progress(cell *c, state50 s) {
|
||||
|
||||
while(s.wc2) {
|
||||
s.wc2 += (s.polarity1?1:-1); s.wc2 %= 7;
|
||||
while(true) { s.color2++; s.color2 &= 7; if(s.color2 != s.color) break; }
|
||||
}
|
||||
|
||||
if(map50.count(c)) {
|
||||
state50 s2 = map50[c];
|
||||
if(s2.polarity1 != s.polarity1 || s2.polarity2 != s.polarity2) {
|
||||
printf("Polarity mismatch!\n");
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
if(s2.color != s.color || s2.color2 != s.color2 || s2.wc2 != s.wc2)
|
||||
printf("%d:%d color= %dv%d color2= %dv%d wc2= %dv%d\n",
|
||||
s.polarity1, s.polarity2,
|
||||
s.color, s2.color,
|
||||
s.color2, s2.color2,
|
||||
s.wc2, s2.wc2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
map50[c] = s;
|
||||
if(c->mpdist <= 7)
|
||||
patternFiftyAt(c);
|
||||
}
|
||||
|
||||
long long Q; int qconflict;
|
||||
|
||||
string allconflict;
|
||||
|
||||
void setzebra(cellwalker cwb, int it, int type, string pathcode, int xmods) {
|
||||
// printf("spin=%d type=%d\n", cwb.spin, type);
|
||||
|
||||
if(cwb.spin != 1 && cwb.spin != 3 && cwb.spin != 5) {
|
||||
printf("S WRONG SPIN %d\n", cwb.spin);
|
||||
exit(1);
|
||||
}
|
||||
if(type < 0 || type > 3) {
|
||||
printf("S WRONG TYPE %d\n", type);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cwb.at->tmp = cwb.spin + 16 * type;
|
||||
}
|
||||
|
||||
void zebra(cellwalker cwb, int it, int type, string pathcode, int xmods) {
|
||||
if(!it) return;
|
||||
if(cwb.spin != 1 && cwb.spin != 3 && cwb.spin != 5) {
|
||||
printf("WRONG SPIN %d\n", cwb.spin);
|
||||
exit(1);
|
||||
}
|
||||
if(type < 0 || type > 3) {
|
||||
printf("WRONG TYPE %d\n", type);
|
||||
exit(1);
|
||||
}
|
||||
// printf("%p+%d = 0%s\n", cwb.c, cwb.spin, pathcode.c_str());
|
||||
bool redraw = false;
|
||||
// int qval = Q + 99;
|
||||
// redraw = cwb.at->heat == qval;
|
||||
// cwb.at->heat = qval;
|
||||
eWall w = colorwalls[type];
|
||||
cwb.at->wall = w;
|
||||
for(int i=0; i<6; i+=2) {
|
||||
cellwalker cw = cwb;
|
||||
cw += (i);
|
||||
cw.at->heat = 4 + type + 4 * 9;
|
||||
cw += wstep; cw += (3); cw.at->wall = w;
|
||||
int i0 = i; if(type&2 && i0) i0 = 6-i0; i0 /= 2;
|
||||
cw.at->heat = 4 + type + 4 * (3+i0);
|
||||
cw += wstep; cw += (3); cw.at->wall = w;
|
||||
cw.at->heat = 4 + type + 4 * i0;
|
||||
cw += wstep; cw += (3); cw.at->wall = w;
|
||||
cw.at->heat = 4 + type + 4 * (6+i0);
|
||||
cw += wstep; cw += (-3);
|
||||
cw += wstep; cw += (-3);
|
||||
cw += wstep; cw += (-3);
|
||||
cw += wstep; cw += (-i);
|
||||
cw += (0);
|
||||
setzebra(cw, it-1, type ^ 1, pathcode +'+'+char('A'+i)+char('0'+type), xmods*2);
|
||||
}
|
||||
|
||||
for(int i=0; i<6; i+=2) {
|
||||
cellwalker cw = cwb;
|
||||
cw += ((type&2)?-i:i);
|
||||
cw += wstep; cw += (3);
|
||||
cw += wstep; cw += (5);
|
||||
if(xmods < 2) {
|
||||
if(cw.at->item && cw.at->item != (1+i) && redraw && i==0) {
|
||||
qconflict++;
|
||||
// allconflict += pathcode; allconflict += "-";
|
||||
// cwb.at->item = itPalace;
|
||||
// printf("Conflict at %p\n", cwb.at);
|
||||
}
|
||||
// cw.at->item = eItem(1 + i);
|
||||
// cw.at->heat = 4 + type + 4 * (i/2);
|
||||
}
|
||||
cw += wstep; cw += (1);
|
||||
if(type < 2) {
|
||||
// cw += (i);
|
||||
cw += (i);
|
||||
}
|
||||
else {
|
||||
cw += (-i);
|
||||
}
|
||||
// cw += (((Q >> (4*type)) & 12));
|
||||
setzebra(cw, it-1, 2^type, pathcode + '+'+char('a'+i)+char('0'+type), xmods+1);
|
||||
}
|
||||
}
|
||||
|
||||
void zebraPattern() {
|
||||
// int bqc = 99;
|
||||
|
||||
/* for(Q=0; Q<65536; Q++) {
|
||||
if((Q & (Q>>1)) & 0x5555) continue;
|
||||
qconflict = false;
|
||||
cellwalker cw(cwt);
|
||||
cw += wstep; cw += (1);
|
||||
qconflict = 0;
|
||||
allconflict = "";
|
||||
zebra(cw, 3, 0, "");
|
||||
if(qconflict < bqc) bqc = qconflict;
|
||||
// if(qconflict == bqc)
|
||||
printf("%X - X-%sX\n", Q, allconflict.c_str());
|
||||
}
|
||||
|
||||
Q = 0xFFFB; */
|
||||
|
||||
cellwalker cw(cwt);
|
||||
cw += wstep; cw += (1);
|
||||
setzebra(cw, 7, 0, "", -999);
|
||||
// cw.at->
|
||||
// printf("Conflicts: %d\n", qconflict);
|
||||
}
|
||||
|
||||
int bspin(heptagon *h) {
|
||||
vector<int> xv;
|
||||
xv.push_back(999);
|
||||
int besti = -1;
|
||||
for(int i=0; i<7; i++) {
|
||||
vector<int> yv;
|
||||
for(int j=0; j<7; j++) yv.push_back(int(h->move[(i+j)%7]->c7->heat+.1));
|
||||
if(yv < xv) xv = yv, besti = i;
|
||||
}
|
||||
return besti;
|
||||
}
|
||||
|
||||
void buildAutomatonRule(heptagon *h) {
|
||||
if(!h->c7->heat) return;
|
||||
for(int i=0; i<7; i++) if(!h->move[i]) return;
|
||||
for(int i=0; i<7; i++) for(int j=0; j<7; j++)
|
||||
if(!h->move[i]->move[j] || !h->move[i]->move[j]->c7->heat)
|
||||
return;
|
||||
int bi = bspin(h);
|
||||
printf("RULEZEBRA(%2d", int(h->c7->heat+.1));
|
||||
for(int j=0; j<7; j++) {
|
||||
heptagon *h2 = h->move[(bi+j)%7];
|
||||
int bi2 = bspin(h2);
|
||||
printf(", %2d%d", int(h2->c7->heat+.1), fix7(bi2 - h->spin[(bi+j)%7]));
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
void buildAutomatonRule(cell *c) {
|
||||
if(c->type == 7)
|
||||
buildAutomatonRule(c->master);
|
||||
else {
|
||||
int ii[3];
|
||||
for(int i=0; i<6; i+=2) if(!c->move(i) || !c->move(i)->heat || c->move(i)->type != 7) return;
|
||||
for(int i=0; i<6; i+=2) ii[i/2] = int(c->move(i)->heat);
|
||||
int z;
|
||||
for(int r=0; r<2; r++)
|
||||
if(ii[1] < ii[0] || ii[2] < ii[0])
|
||||
z = ii[0], ii[0] = ii[1], ii[1] = ii[2], ii[2] = z;
|
||||
printf("RULEZEBRA6(%d,%d,%d,%d)\n", int(c->heat), int(ii[0]), int(ii[1]), int(ii[2]));
|
||||
}
|
||||
}
|
||||
|
||||
// #define BUILDZEBRA
|
||||
}
|
105
generators/quartic.cpp
Normal file
105
generators/quartic.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
// this generates data for Klein's Quartic (-geo 0 -quartic) and Bolza surface (in -geo 7 -quartic) and 2x Bolza (-geo7 -quartic2)
|
||||
// Copyright (C) 2018 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
#include "../init.cpp"
|
||||
|
||||
using namespace hr;
|
||||
|
||||
int qty;
|
||||
|
||||
namespace hr {
|
||||
cellwalker& operator += (cellwalker& cw, int spin);
|
||||
cellwalker& operator += (cellwalker& cw, wstep_t);
|
||||
}
|
||||
|
||||
void recursive(cell *c, int col, int dir, int dbl) {
|
||||
c->landparam = col;
|
||||
c->mondir = dir;
|
||||
c->monst = moButterfly;
|
||||
if(S7 == 7) {
|
||||
for(int i=0; i<7; i++) {
|
||||
for(int j=3; j<5; j++) {
|
||||
cellwalker cw(c, dir + i);
|
||||
for(int u=0; u<4; u++) {
|
||||
cw += wstep;
|
||||
cw += j;
|
||||
}
|
||||
cw += -dir;
|
||||
if(cw.c->landparam == -1) recursive(cw.c, col^dbl, dir, dbl);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(S7 == 8) {
|
||||
for(int i=0; i<8; i++) {
|
||||
cellwalker cw(c, dir);
|
||||
cw += i;
|
||||
cw += wstep;
|
||||
cw += 4;
|
||||
cw += wstep;
|
||||
cw += (4-i);
|
||||
// if(cw.c->landparam == -1) recursive(cw.c, (col ^ 1));
|
||||
if(cw.c->landparam == -1) recursive(cw.c, col ^ dbl, cw.spin, dbl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generate_quartic(bool dbl) {
|
||||
celllister clgen(cwt.c, S7==7?10:8, 1000000, NULL);
|
||||
int d;
|
||||
for(cell *c1: clgen.lst) { c1->landparam = -1; d = celldist(c1); }
|
||||
for(cell *c1: clgen.lst) if(c1->landparam == -1) {
|
||||
recursive(c1, qty, 0, dbl);
|
||||
qty++;
|
||||
if(dbl) qty++;
|
||||
}
|
||||
vector<unsigned> colors;
|
||||
for(cell *c1: clgen.lst) {
|
||||
if(celldist(c1) >= d-1) continue;
|
||||
if(c1->mov[c1->mondir]->landparam > c1->mov[c1->mondir ^ 4]->landparam)
|
||||
c1->mondir ^= 4;
|
||||
}
|
||||
|
||||
if(0) for(cell *c1: clgen.lst) {
|
||||
if(celldist(c1) >= d-2) continue;
|
||||
vector<int> connections;
|
||||
cellwalker cw(c1, c1->mondir);
|
||||
for(int i=0; i<S7; i++) {
|
||||
cellwalker cwx = cw; cwx += wstep;
|
||||
connections.push_back(cwx.c->landparam * S7 + (cwx.spin - cwx.c->mondir + MODFIXER) % S7);
|
||||
cw += 1;
|
||||
}
|
||||
printf("/* %03d */", c1->landparam);
|
||||
for(int i=0; i<S7; i++) printf(" %d,", connections[i]);
|
||||
printf("\n");
|
||||
}
|
||||
printf("qty = %d\n", qty);
|
||||
for(int i=0; i<qty; i++) colors.push_back(hrand(0x1000000));
|
||||
for(cell *c1: clgen.lst) {
|
||||
c1->landparam = colors[c1->landparam % qty];
|
||||
}
|
||||
}
|
||||
|
||||
int readArgs() {
|
||||
using namespace arg;
|
||||
|
||||
if(0) ;
|
||||
else if(argis("-quartic")) {
|
||||
PHASE(3);
|
||||
start_game();
|
||||
generate_quartic(0);
|
||||
}
|
||||
else if(argis("-quartic2")) {
|
||||
PHASE(3);
|
||||
start_game();
|
||||
generate_quartic(1);
|
||||
}
|
||||
else return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto hook = addHook(hooks_args, 100, readArgs);
|
||||
|
||||
// Bolza:: genus 2 => Euler characteristic -2
|
||||
// octagon: -2/6
|
||||
// ~> 6 octagons
|
||||
|
112
generators/schmutz.cpp
Normal file
112
generators/schmutz.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
// Schmutz's Surface generator
|
||||
// Copyright (C) 2018 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void dualize(vector<int>& t) {
|
||||
int N = t.size();
|
||||
/*
|
||||
printf("N = %d\n", N);
|
||||
|
||||
printf("pre dual:\n");
|
||||
for(int a=0; a<N; a++) {
|
||||
printf("%3d, ", t[a]);
|
||||
if(a % 12 == 11) printf("\n");
|
||||
}
|
||||
|
||||
printf("post dual:\n");
|
||||
*/
|
||||
|
||||
vector<int> tmap(N, -1);
|
||||
vector<int> trmap(N, -1);
|
||||
int s = 0;
|
||||
for(int i=0; i<N; i++) if(tmap[i] == -1) {
|
||||
int j = i;
|
||||
for(int k=0; k<12; k++) {
|
||||
tmap[j] = s;
|
||||
trmap[s] = j;
|
||||
s++;
|
||||
int oj = j;
|
||||
j = t[j];
|
||||
j = (j % 3 == 2) ? (j-2) : (j+1);
|
||||
// printf("%d -> %d\n", oj, j);
|
||||
}
|
||||
if(j != i) printf("not equal\n"), exit(1);
|
||||
// printf("OK\n");
|
||||
}
|
||||
// for(int a: tmap) printf("%d ", a); printf("\n");
|
||||
// for(int a: trmap) printf("%d ", a); printf("\n");
|
||||
vector<int> res(N, -1);
|
||||
for(int i=0; i<N; i++) {
|
||||
// printf("i=%d\n", i);
|
||||
res[i] = tmap[t[trmap[i]]];
|
||||
}
|
||||
// for(int a: res) printf("%d ", a); printf("\n");
|
||||
t = res;
|
||||
|
||||
for(int i=0; i<N; i++) {
|
||||
int a = i;
|
||||
for(int s=0; s<3; s++) {
|
||||
a = res[a];
|
||||
a++;
|
||||
if(a % 12 == 0) a -= 12;
|
||||
}
|
||||
if(a != i) { printf("bug\n"); exit(1); }
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
vector<int> triangles;
|
||||
|
||||
for(int a=0; a<12; a++) {
|
||||
triangles.emplace_back(3 * ((a+1) % 12) + 1);
|
||||
triangles.emplace_back(3 * ((a+11) % 12));
|
||||
triangles.emplace_back(36 + (a%4) * 3 + 2 - (a/4));
|
||||
}
|
||||
|
||||
for(int a=0; a<12; a++)
|
||||
triangles.emplace_back(0);
|
||||
|
||||
for(int a=0; a<36; a++) if(triangles[a] >= 36) triangles[triangles[a]] = a;
|
||||
|
||||
dualize(triangles);
|
||||
|
||||
for(int a=0; a<48; a++) {
|
||||
if(a % 12 == 0) printf("\n");
|
||||
printf("%3d, ", triangles[a]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
triangles.clear();
|
||||
|
||||
for(int a=0; a<12; a++) {
|
||||
triangles.emplace_back(3 * ((a+1) % 12) + 1);
|
||||
triangles.emplace_back(3 * ((a+11) % 12));
|
||||
triangles.emplace_back(36 + 3 * a);
|
||||
}
|
||||
|
||||
for(int a=0; a<12; a++) {
|
||||
triangles.emplace_back(3 * a + 2);
|
||||
triangles.emplace_back(36 + (3 * a + 36 - 15 + 2) % 36);
|
||||
triangles.emplace_back(36 + (3 * a + 36 + 15 + 1) % 36);
|
||||
}
|
||||
|
||||
dualize(triangles);
|
||||
|
||||
for(int a=0; a<12*2*3; a++) {
|
||||
if(a % 12 == 0) printf("\n");
|
||||
printf("%3d, ", triangles[a]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user