1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-10 15:59:53 +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;
}

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;
}