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

crystal:: made global variables into hrmap_crystal attributes

This commit is contained in:
Zeno Rogue 2018-12-02 11:14:10 +01:00
parent 9b6136fb41
commit 7da2f2b84a

View File

@ -272,112 +272,134 @@ coord add(coord c, lwalker a, int val) {
return c; return c;
} }
map<heptagon*, coord> hcoords;
map<coord, heptagon*> heptagon_at;
map<int, eLand> landmemo;
unordered_map<cell*, unordered_map<cell*, int>> distmemo;
map<cell*, ldcoord> sgc;
crystal_structure cs;
coord add(coord c, int cname, int val) { coord add(coord c, int cname, int val) {
int dim = (cname>>1); int dim = (cname>>1);
c[dim] = (c[dim] + (cname&1?val:-val)); c[dim] = (c[dim] + (cname&1?val:-val));
return c; return c;
} }
lwalker makewalker(crystal_structure& cs, coord c, int d) { ld hypot2(crystal_structure& cs, ldcoord co1, ldcoord co2) {
lwalker a(cs); int result = 0;
a.id = 0; for(int a=0; a<cs.dim; a++) result += (co1[a] - co2[a]) * (co1[a] - co2[a]);
for(int i=0; i<cs.dim; i++) if(c[i] & FULLSTEP) a.id += (1<<i); return result;
a.spin = d;
return a;
} }
void crystalstep(heptagon *h, int d); void crystalstep(heptagon *h, int d);
heptagon *get_heptagon_at(coord c, int deg) { static const int Modval = 64;
if(heptagon_at.count(c)) return heptagon_at[c];
heptagon*& h = heptagon_at[c];
h = tailored_alloc<heptagon> (deg);
h->alt = NULL;
h->cdata = NULL;
h->c7 = newCell(deg, h);
h->distance = 0;
for(int i=0; i<cs.dim; i++) h->distance += abs(c[i]);
h->distance /= 2;
hcoords[h] = c;
// for(int i=0; i<6; i++) crystalstep(h, i);
return h;
}
ldcoord get_coord(cell *c) { struct east_structure {
auto b = sgc.emplace(c, ldc0); map<coord, int> data;
ldcoord& res = b.first->second; int Xmod, cycle;
if(b.second) { int zeroshift;
if(c->master->c7 != c) { int coordid;
for(int i=0; i<c->type; i+=2) };
res = res + told(hcoords[c->cmove(i)->master]);
res = res * 2 / c->type;
}
else
res = told(hcoords[c->master]);
}
return res;
}
struct hrmap_crystal : hrmap { struct hrmap_crystal : hrmap {
heptagon *getOrigin() { return get_heptagon_at(c0, S7); } heptagon *getOrigin() { return get_heptagon_at(c0, S7); }
map<heptagon*, coord> hcoords;
map<coord, heptagon*> heptagon_at;
map<int, eLand> landmemo;
unordered_map<cell*, unordered_map<cell*, int>> distmemo;
map<cell*, ldcoord> sgc;
cell *camelot_center;
crystal_structure cs;
east_structure east;
lwalker makewalker(coord c, int d) {
lwalker a(cs);
a.id = 0;
for(int i=0; i<cs.dim; i++) if(c[i] & FULLSTEP) a.id += (1<<i);
a.spin = d;
return a;
}
hrmap_crystal() { hrmap_crystal() {
cs.build(); cs.build();
} }
~hrmap_crystal() { ~hrmap_crystal() {
hcoords.clear(); clearfrom(getOrigin());
heptagon_at.clear();
distmemo.clear();
landmemo.clear();
sgc.clear();
} }
void verify() { } heptagon *get_heptagon_at(coord c, int deg) {
}; if(heptagon_at.count(c)) return heptagon_at[c];
heptagon*& h = heptagon_at[c];
hrmap *new_map() { h = tailored_alloc<heptagon> (deg);
return new hrmap_crystal; h->alt = NULL;
} h->cdata = NULL;
h->c7 = newCell(deg, h);
h->distance = 0;
for(int i=0; i<cs.dim; i++) h->distance += abs(c[i]);
h->distance /= 2;
hcoords[h] = c;
// for(int i=0; i<6; i++) crystalstep(h, i);
return h;
}
ldcoord get_coord(cell *c) {
auto b = sgc.emplace(c, ldc0);
ldcoord& res = b.first->second;
if(b.second) {
if(c->master->c7 != c) {
for(int i=0; i<c->type; i+=2)
res = res + told(hcoords[c->cmove(i)->master]);
res = res * 2 / c->type;
}
else
res = told(hcoords[c->master]);
}
return res;
}
coord long_representant(cell *c);
bool is_bi(coord co) { int get_east(cell *c);
void build_east(int cid);
void verify() { }
void prepare_east();
};
hrmap_crystal *crystal_map() {
return (hrmap_crystal*) currentmap;
}
bool is_bi(crystal_structure& cs, coord co) {
for(int i=0; i<cs.dim; i++) if(co[i] & HALFSTEP) return true; for(int i=0; i<cs.dim; i++) if(co[i] & HALFSTEP) return true;
return false; return false;
} }
void create_step(heptagon *h, int d) { void create_step(heptagon *h, int d) {
auto m = crystal_map();
if(geometry != gCrystal) return; if(geometry != gCrystal) return;
if(!hcoords.count(h)) { if(!m->hcoords.count(h)) {
printf("not found\n"); printf("not found\n");
return; return;
} }
auto co = hcoords[h]; auto co = m->hcoords[h];
if(is_bi(co)) { if(is_bi(m->cs, co)) {
heptspin hs(h, d); heptspin hs(h, d);
(hs + 1 + wstep + 1).cpeek(); (hs + 1 + wstep + 1).cpeek();
return; return;
} }
auto lw = makewalker(cs, co, d); auto lw = m->makewalker(co, d);
if(!add_bitruncation) { if(!add_bitruncation) {
auto c1 = add(co, lw, FULLSTEP); auto c1 = add(co, lw, FULLSTEP);
auto lw1 = lw+wstep; auto lw1 = lw+wstep;
h->c.connect(d, heptspin(get_heptagon_at(c1, S7), lw1.spin)); h->c.connect(d, heptspin(m->get_heptagon_at(c1, S7), lw1.spin));
} }
else { else {
auto coc = add(add(co, lw, HALFSTEP), lw+1, HALFSTEP); auto coc = add(add(co, lw, HALFSTEP), lw+1, HALFSTEP);
auto hc = get_heptagon_at(coc, 8); auto hc = m->get_heptagon_at(coc, 8);
for(int a=0; a<8; a+=2) { for(int a=0; a<8; a+=2) {
hc->c.connect(a, heptspin(h, lw.spin)); hc->c.connect(a, heptspin(h, lw.spin));
if(h->modmove(lw.spin-1)) { if(h->modmove(lw.spin-1)) {
@ -385,7 +407,7 @@ void create_step(heptagon *h, int d) {
} }
co = add(co, lw, FULLSTEP); co = add(co, lw, FULLSTEP);
lw = lw + wstep + (-1); lw = lw + wstep + (-1);
h = get_heptagon_at(co, S7); h = m->get_heptagon_at(co, S7);
} }
} }
} }
@ -396,7 +418,8 @@ array<array<int,2>, MAX_EDGE> distlimit_table = {{
}}; }};
color_t colorize(cell *c) { color_t colorize(cell *c) {
ldcoord co = get_coord(c); auto m = crystal_map();
ldcoord co = m->get_coord(c);
color_t res; color_t res;
res = 0; res = 0;
for(int i=0; i<3; i++) for(int i=0; i<3; i++)
@ -415,16 +438,18 @@ bool crystal_cell(cell *c, transmatrix V) {
if(view_coordinates && cheater) for(int i=0; i<S7; i++) { if(view_coordinates && cheater) for(int i=0; i<S7; i++) {
auto m = crystal_map();
if(c->master->c7 == c) { if(c->master->c7 == c) {
transmatrix V1 = cellrelmatrix(c, i); transmatrix V1 = cellrelmatrix(c, i);
ld dist = hdist0(V1 * C0); ld dist = hdist0(V1 * C0);
ld alpha = -atan2(V1 * C0); ld alpha = -atan2(V1 * C0);
transmatrix T = V * spin(alpha) * xpush(dist*.3); transmatrix T = V * spin(alpha) * xpush(dist*.3);
auto co = hcoords[c->master]; auto co = m->hcoords[c->master];
int our_id = 0; int our_id = 0;
for(int a=0; a<MAXDIM; a++) if(co[a] & FULLSTEP) our_id += (1<<a); for(int a=0; a<MAXDIM; a++) if(co[a] & FULLSTEP) our_id += (1<<a);
int cx = cs.cmap[our_id][i]; int cx = m->cs.cmap[our_id][i];
int coordcolors[MAXDIM] = {0x4040D0, 0x40D040, 0xD04040, 0xFFD500, 0xF000F0, 0x00F0F0, 0xF0F0F0 }; int coordcolors[MAXDIM] = {0x4040D0, 0x40D040, 0xD04040, 0xFFD500, 0xF000F0, 0x00F0F0, 0xF0F0F0 };
@ -441,22 +466,19 @@ bool crystal_cell(cell *c, transmatrix V) {
return false; return false;
} }
ld hypot2(ldcoord co1, ldcoord co2) {
int result = 0;
for(int a=0; a<cs.dim; a++) result += (co1[a] - co2[a]) * (co1[a] - co2[a]);
return result;
}
int precise_distance(cell *c1, cell *c2) { int precise_distance(cell *c1, cell *c2) {
if(c1 == c2) return 0; if(c1 == c2) return 0;
auto m = crystal_map();
if(PURE && !add_bitruncation) { if(PURE && !add_bitruncation) {
coord co1 = hcoords[c1->master]; coord co1 = m->hcoords[c1->master];
coord co2 = hcoords[c2->master]; coord co2 = m->hcoords[c2->master];
int result = 0; int result = 0;
for(int a=0; a<cs.dim; a++) result += abs(co1[a] - co2[a]); for(int a=0; a<m->cs.dim; a++) result += abs(co1[a] - co2[a]);
return result / FULLSTEP; return result / FULLSTEP;
} }
auto& distmemo = m->distmemo;
if(c2 == currentmap->gamestart()) swap(c1, c2); if(c2 == currentmap->gamestart()) swap(c1, c2);
else if(isize(distmemo[c2]) > isize(distmemo[c1])) swap(c1, c2); else if(isize(distmemo[c2]) > isize(distmemo[c1])) swap(c1, c2);
@ -471,8 +493,8 @@ int precise_distance(cell *c1, cell *c2) {
if(zmin+1 < zmax-1) println(hlog, "zmin < zmax"); if(zmin+1 < zmax-1) println(hlog, "zmin < zmax");
if(zmin+1 == zmax-1) return distmemo[c1][c2] = zmin+1; if(zmin+1 == zmax-1) return distmemo[c1][c2] = zmin+1;
ldcoord co1 = get_coord(c1); ldcoord co1 = m->get_coord(c1);
ldcoord co2 = get_coord(c2) - co1; ldcoord co2 = m->get_coord(c2) - co1;
// draw a cylinder from co1 to co2, and find the solution by going through that cylinder // draw a cylinder from co1 to co2, and find the solution by going through that cylinder
@ -494,11 +516,11 @@ int precise_distance(cell *c1, cell *c2) {
return distmemo[c1][c2] = distmemo[c2][c1] = 1 + steps; return distmemo[c1][c2] = distmemo[c2][c1] = 1 + steps;
} }
auto h = get_coord(c3) - co1; auto h = m->get_coord(c3) - co1;
ld dot = (h|mul); ld dot = (h|mul);
if(dot > mmax + 2.5) continue; if(dot > mmax + 2.5) continue;
for(int k=0; k<cs.dim; k++) if(abs(h[k] - dot * mul[k]) > 4.1) goto next3; for(int k=0; k<m->cs.dim; k++) if(abs(h[k] - dot * mul[k]) > 4.1) goto next3;
cl.add(c3); cl.add(c3);
next3: ; next3: ;
} }
@ -508,137 +530,142 @@ int precise_distance(cell *c1, cell *c2) {
return 999999; return 999999;
} }
cell *camelot_center;
ld space_distance(cell *c1, cell *c2) { ld space_distance(cell *c1, cell *c2) {
ldcoord co1 = get_coord(c1); auto m = crystal_map();
ldcoord co2 = get_coord(c2); ldcoord co1 = m->get_coord(c1);
return sqrt(hypot2(co1, co2)); ldcoord co2 = m->get_coord(c2);
return sqrt(hypot2(m->cs, co1, co2));
} }
int dist_relative(cell *c) { int dist_relative(cell *c) {
auto m = crystal_map();
auto& cc = m->camelot_center;
int r = roundTableRadius(NULL); int r = roundTableRadius(NULL);
cell *start = currentmap->gamestart(); cell *start = m->gamestart();
if(!camelot_center) { if(!cc) {
printf("Finding Camelot center..."); printf("Finding Camelot center...");
camelot_center = start; cc = start;
while(precise_distance(camelot_center, start) < r + 5) while(precise_distance(cc, start) < r + 5)
camelot_center = camelot_center->cmove(hrand(camelot_center->type)); cc = cc->cmove(hrand(cc->type));
} }
if(PURE && !add_bitruncation) if(PURE && !add_bitruncation)
return precise_distance(c, camelot_center) - r; return precise_distance(c, cc) - r;
ld sdmul = (r+5) / space_distance(camelot_center, start); ld sdmul = (r+5) / space_distance(cc, start);
ld dis = space_distance(camelot_center, c) * sdmul; ld dis = space_distance(cc, c) * sdmul;
println(hlog, "dis = ", dis); println(hlog, "dis = ", dis);
if(dis < r) if(dis < r)
return int(dis) - r; return int(dis) - r;
else { else {
forCellCM(c1, c) if(space_distance(camelot_center, c1) * sdmul < r) forCellCM(c1, c) if(space_distance(cc, c1) * sdmul < r)
return 0; return 0;
return int(dis) + 1 - r; return int(dis) + 1 - r;
} }
} }
struct ddbuilder { coord hrmap_crystal::long_representant(cell *c) {
map<coord, int> data; auto& coordid = east.coordid;
static const int Modval = 64; auto co = roundcoord(get_coord(c) * Modval/4);
int Xmod, cycle; for(int s=0; s<coordid; s++) co[s] = gmod(co[s], Modval);
int zeroshift; for(int s=coordid+1; s<cs.dim; s++) {
int coordid; int v = gdiv(co[s], Modval);
co[s] -= v * Modval;
co[coordid] += v * Modval;
}
return co;
}
int hrmap_crystal::get_east(cell *c) {
auto& coordid = east.coordid;
auto& Xmod = east.Xmod;
auto& data = east.data;
auto& cycle = east.cycle;
coord co = long_representant(c);
int cycles = gdiv(co[coordid], Xmod);
co[coordid] -= cycles * Xmod;
return data[co] + cycle * cycles;
}
void hrmap_crystal::build_east(int cid) {
auto& coordid = east.coordid;
auto& Xmod = east.Xmod;
auto& data = east.data;
auto& cycle = east.cycle;
coord long_representant(cell *c) { coordid = cid;
auto co = roundcoord(get_coord(c) * Modval/4); map<coord, int> full_data;
for(int s=0; s<coordid; s++) co[s] = gmod(co[s], Modval); manual_celllister cl;
for(int s=coordid+1; s<cs.dim; s++) {
int v = gdiv(co[s], Modval); for(int i=0; i<(1<<cid); i++) {
co[s] -= v * Modval; auto co = c0;
co[coordid] += v * Modval; for(int j=0; j<cid; j++) co[j] = ((i>>j)&1) * 2;
} cell *cc = get_heptagon_at(co, cs.dir)->c7;
return co; cl.add(cc);
} }
int get_level(cell *c) { map<coord, int> stepat;
coord co = long_representant(c);
int cycles = gdiv(co[coordid], Xmod);
co[coordid] -= cycles * Xmod;
return data[co] + cycle * cycles;
}
void build(int cid) { int steps = 0, nextstep = isize(cl.lst);
coordid = cid;
map<coord, int> full_data;
manual_celllister cl;
for(int i=0; i<(1<<cid); i++) {
auto co = c0;
for(int j=0; j<cid; j++) co[j] = ((i>>j)&1) * 2;
cell *cc = get_heptagon_at(co, cs.dir)->c7;
cl.add(cc);
}
map<coord, int> stepat;
int steps = 0, nextstep = isize(cl.lst); cycle = 0;
int incycle = 0;
cycle = 0; int needcycle = 16 + nextstep;
int incycle = 0; int elongcycle = 0;
int needcycle = 16 + nextstep;
int elongcycle = 0;
Xmod = Modval;
int modmul = 1;
for(int i=0; i<isize(cl.lst); i++) {
if(incycle > needcycle * modmul) break;
if(i == nextstep) steps++, nextstep = isize(cl.lst);
cell *c = cl.lst[i];
auto co = long_representant(c); Xmod = Modval;
if(co[coordid] < -Modval) continue;
if(full_data.count(co)) continue;
full_data[co] = steps;
auto co1 = co; co1[coordid] -= Xmod;
auto co2 = co; co2[coordid] = gmod(co2[coordid], Xmod);
if(full_data.count(co1)) { int modmul = 1;
int ncycle = steps - full_data[co1];
if(ncycle != cycle) incycle = 1, cycle = ncycle; for(int i=0; i<isize(cl.lst); i++) {
else incycle++; if(incycle > needcycle * modmul) break;
int dd = gdiv(co[coordid], Xmod); if(i == nextstep) steps++, nextstep = isize(cl.lst);
// println(hlog, co, " set data at ", co2, " from ", data[co2], " to ", steps - dd * cycle, " at step ", steps); cell *c = cl.lst[i];
data[co2] = steps - dd * cycle;
elongcycle++;
if(elongcycle > 2 * needcycle * modmul) Xmod += Modval, elongcycle = 0, modmul++;
}
else incycle = 0, needcycle++, elongcycle = 0;
forCellCM(c1, c) cl.add(c1);
}
zeroshift = 0;
zeroshift = -get_level(cl.lst[0]);
println(hlog, "cycle found: ", cycle, " Xmod = ", Xmod, " on list: ", isize(cl.lst), " zeroshift: ", zeroshift); auto co = long_representant(c);
if(co[coordid] < -Modval) continue;
if(full_data.count(co)) continue;
full_data[co] = steps;
auto co1 = co; co1[coordid] -= Xmod;
auto co2 = co; co2[coordid] = gmod(co2[coordid], Xmod);
if(full_data.count(co1)) {
int ncycle = steps - full_data[co1];
if(ncycle != cycle) incycle = 1, cycle = ncycle;
else incycle++;
int dd = gdiv(co[coordid], Xmod);
// println(hlog, co, " set data at ", co2, " from ", data[co2], " to ", steps - dd * cycle, " at step ", steps);
data[co2] = steps - dd * cycle;
elongcycle++;
if(elongcycle > 2 * needcycle * modmul) Xmod += Modval, elongcycle = 0, modmul++;
}
else incycle = 0, needcycle++, elongcycle = 0;
forCellCM(c1, c) cl.add(c1);
} }
}; east.zeroshift = 0;
east.zeroshift = -get_east(cl.lst[0]);
ddbuilder ddb;
println(hlog, "cycle found: ", cycle, " Xmod = ", Xmod, " on list: ", isize(cl.lst), " zeroshift: ", east.zeroshift);
}
void hrmap_crystal::prepare_east() {
if(east.data.empty()) build_east(1);
}
int dist_alt(cell *c) { int dist_alt(cell *c) {
if(specialland == laCamelot && camelot_center) { auto m = crystal_map();
if(specialland == laCamelot && m->camelot_center) {
if(PURE && !add_bitruncation) if(PURE && !add_bitruncation)
return precise_distance(c, camelot_center); return precise_distance(c, m->camelot_center);
if(c == camelot_center) return 0; if(c == m->camelot_center) return 0;
return 1 + int(space_distance(camelot_center, c)); return 1 + int(4 * space_distance(m->camelot_center, c));
} }
else { else {
if(ddb.data.empty()) ddb.build(1); m->prepare_east();
return ddb.get_level(c); return m->get_east(c);
} }
} }
@ -650,6 +677,8 @@ void init_rotation() {
for(int i=0; i<MAXDIM; i++) for(int i=0; i<MAXDIM; i++)
for(int j=0; j<MAXDIM; j++) for(int j=0; j<MAXDIM; j++)
crug_rotation[i][j] = i == j ? 1/2. : 0; crug_rotation[i][j] = i == j ? 1/2. : 0;
auto& cs = crystal_map()->cs;
if(ho & 1) { if(ho & 1) {
for(int i=cs.dim-1; i>=1; i--) { for(int i=cs.dim-1; i>=1; i--) {
@ -679,6 +708,7 @@ hyperpoint coord_to_flat(ldcoord co) {
} }
void switch_z_coordinate() { void switch_z_coordinate() {
auto& cs = crystal_map()->cs;
for(int i=0; i<cs.dim; i++) { for(int i=0; i<cs.dim; i++) {
ld tmp = crug_rotation[i][2]; ld tmp = crug_rotation[i][2];
for(int u=2; u<cs.dim-1; u++) crug_rotation[i][u] = crug_rotation[i][u+1]; for(int u=2; u<cs.dim-1; u++) crug_rotation[i][u] = crug_rotation[i][u+1];
@ -700,13 +730,15 @@ void build_rugdata() {
rug::clear_model(); rug::clear_model();
rug::good_shape = true; rug::good_shape = true;
rug::vertex_limit = 0; rug::vertex_limit = 0;
auto m = crystal_map();
for(const auto& gp: gmatrix) { for(const auto& gp: gmatrix) {
cell *c = gp.first; cell *c = gp.first;
const transmatrix& V = gp.second; const transmatrix& V = gp.second;
rugpoint *v = addRugpoint(tC0(V), 0); rugpoint *v = addRugpoint(tC0(V), 0);
auto co = get_coord(c); auto co = m->get_coord(c);
v->flat = coord_to_flat(co); v->flat = coord_to_flat(co);
v->valid = true; v->valid = true;
@ -716,9 +748,9 @@ void build_rugdata() {
p[i] = addRugpoint(V * get_corner_position(c, i), 0); p[i] = addRugpoint(V * get_corner_position(c, i), 0);
p[i]->valid = true; p[i]->valid = true;
if(VALENCE == 4) if(VALENCE == 4)
p[i]->flat = coord_to_flat((get_coord(c->cmove(i)) + get_coord(c->cmodmove(i-1))) / 2); p[i]->flat = coord_to_flat((m->get_coord(c->cmove(i)) + m->get_coord(c->cmodmove(i-1))) / 2);
else else
p[i]->flat = coord_to_flat((get_coord(c->cmove(i)) + get_coord(c->cmodmove(i-1)) + co) / 3); p[i]->flat = coord_to_flat((m->get_coord(c->cmove(i)) + m->get_coord(c->cmodmove(i-1)) + co) / 3);
} }
for(int i=0; i<c->type; i++) addTriangle(v, p[i], p[(i+1) % c->type]); for(int i=0; i<c->type; i++) addTriangle(v, p[i], p[(i+1) % c->type]);
@ -726,6 +758,8 @@ void build_rugdata() {
} }
eLand getCLand(int x) { eLand getCLand(int x) {
auto& landmemo = crystal_map()->landmemo;
if(landmemo.count(x)) return landmemo[x]; if(landmemo.count(x)) return landmemo[x];
if(x > 0) return landmemo[x] = getNewLand(landmemo[x-1]); if(x > 0) return landmemo[x] = getNewLand(landmemo[x-1]);
if(x < 0) return landmemo[x] = getNewLand(landmemo[x+1]); if(x < 0) return landmemo[x] = getNewLand(landmemo[x+1]);
@ -734,8 +768,9 @@ eLand getCLand(int x) {
void set_land(cell *c) { void set_land(cell *c) {
setland(c, specialland); setland(c, specialland);
auto m = crystal_map();
auto co = get_coord(c); auto co = m->get_coord(c);
auto co1 = roundcoord(co * 60); auto co1 = roundcoord(co * 60);
int cv = co1[0]; int cv = co1[0];
@ -813,6 +848,10 @@ int readArgs() {
return 0; return 0;
} }
hrmap *new_map() {
return new hrmap_crystal;
}
auto crystalhook = addHook(hooks_args, 100, readArgs) auto crystalhook = addHook(hooks_args, 100, readArgs)
+ addHook(hooks_drawcell, 100, crystal_cell); + addHook(hooks_drawcell, 100, crystal_cell);