1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-09-01 18:27:55 +00:00

generators included

This commit is contained in:
Zeno Rogue
2018-11-24 00:01:26 +01:00
parent 64da329f8e
commit 9ab64e9d8e
6 changed files with 485 additions and 0 deletions

14
generators/README.md Normal file
View 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
View 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
View 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
View 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
View 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
View 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;
}