1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-02-02 12:19:18 +00:00

crystal:: started working on lands (Camelot done) and distances

This commit is contained in:
Zeno Rogue 2018-12-01 23:53:03 +01:00
parent 000f271552
commit 50f37a6b63
4 changed files with 172 additions and 21 deletions

View File

@ -18,10 +18,15 @@ typedef array<ld, MAXDIM> ldcoord;
static const ldcoord ldc0 = {};
ldcoord told(coord c) { ldcoord a; for(int i=0; i<MAXDIM; i++) a[i] = c[i]; return a; }
coord roundcoord(ldcoord c) { coord a; for(int i=0; i<MAXDIM; i++) a[i] = floor(c[i] + .5); return a; }
// coord roundcoord_modulo(ldcoord c) { coord a; for(int i=0; i<MAXDIM; i++) a[i] = (floor(c[i] + .5) * 61 / 4) % 61; return a; }
ldcoord operator + (ldcoord a, ldcoord b) { ldcoord r; for(int i=0; i<MAXDIM; i++) r[i] = a[i] + b[i]; return r; }
ldcoord operator * (ldcoord a, int v) { ldcoord r; for(int i=0; i<MAXDIM; i++) r[i] = a[i] * v; return r; }
ldcoord operator / (ldcoord a, int v) { ldcoord r; for(int i=0; i<MAXDIM; i++) r[i] = a[i] / v; return r; }
ldcoord operator - (ldcoord a, ldcoord b) { ldcoord r; for(int i=0; i<MAXDIM; i++) r[i] = a[i] - b[i]; return r; }
ldcoord operator * (ldcoord a, ld v) { ldcoord r; for(int i=0; i<MAXDIM; i++) r[i] = a[i] * v; return r; }
ldcoord operator / (ldcoord a, ld v) { ldcoord r; for(int i=0; i<MAXDIM; i++) r[i] = a[i] / v; return r; }
ld operator | (ldcoord a, ldcoord b) { ld r=0; for(int i=0; i<MAXDIM; i++) r += a[i] * b[i]; return r; }
int tocode(int cname) { return (1 << (cname >> 1)); }
@ -245,12 +250,15 @@ struct crystal_structure {
};
struct lwalker {
crystal_structure cs;
crystal_structure& cs;
int id;
int spin;
lwalker(crystal_structure& cs) : cs(cs) {}
void operator = (const lwalker& x) { id = x.id; spin = x.spin; }
};
lwalker operator +(lwalker a, int v) { a.spin = gmod(a.spin + v, a.cs.dir); return a; }
lwalker operator +(lwalker a, wstep_t) {
a.spin = a.cs.cmap[a.id][a.spin];
a.id ^= tocode(a.spin);
@ -260,12 +268,15 @@ lwalker operator +(lwalker a, wstep_t) {
coord add(coord c, lwalker a, int val) {
int code = a.cs.cmap[a.id][a.spin];
c[code>>1] += (code&1) ? val : -val;
c[code>>1] += ((code&1) ? val : -val);
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;
@ -276,8 +287,7 @@ coord add(coord c, int cname, int val) {
}
lwalker makewalker(crystal_structure& cs, coord c, int d) {
lwalker a;
a.cs = cs;
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;
@ -302,14 +312,18 @@ heptagon *get_heptagon_at(coord c, int deg) {
}
ldcoord get_coord(cell *c) {
if(c->master->c7 != c) {
ldcoord res = ldc0;
for(int i=0; i<c->type; i+=2)
res = res + told(hcoords[c->cmove(i)->master]);
return res * 2 / c->type;
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]);
}
else
return told(hcoords[c->master]);
return res;
}
struct hrmap_crystal : hrmap {
@ -319,6 +333,14 @@ struct hrmap_crystal : hrmap {
cs.build();
}
~hrmap_crystal() {
hcoords.clear();
heptagon_at.clear();
distmemo.clear();
landmemo.clear();
sgc.clear();
}
void verify() { }
};
@ -414,20 +436,114 @@ bool crystal_cell(cell *c, transmatrix V) {
return false;
}
int hypot2(coord co1, coord co2) {
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 distance(cell *c1, cell *c2) {
if(true || (PURE && !add_bitruncation)) {
int precise_distance(cell *c1, cell *c2) {
if(c1 == c2) return 0;
if(PURE && !add_bitruncation) {
coord co1 = hcoords[c1->master];
coord co2 = hcoords[c2->master];
int result = 0;
for(int a=0; a<cs.dim; a++) result += abs(co1[a] - co2[a]);
return result / FULLSTEP;
}
if(c2 == currentmap->gamestart()) swap(c1, c2);
else if(isize(distmemo[c2]) > isize(distmemo[c1])) swap(c1, c2);
if(distmemo[c1].count(c2)) return distmemo[c1][c2];
int zmin = 999999, zmax = -99;
forCellEx(c3, c2) if(distmemo[c1].count(c3)) {
int d = distmemo[c1][c3];
if(d < zmin) zmin = d;
if(d > zmax) zmax = d;
}
if(zmin+1 < zmax-1) println(hlog, "zmin < zmax");
if(zmin+1 == zmax-1) return distmemo[c1][c2] = zmin+1;
ldcoord co1 = get_coord(c1);
ldcoord co2 = get_coord(c2) - co1;
// draw a cylinder from co1 to co2, and find the solution by going through that cylinder
ldcoord mul = co2 / sqrt(co2|co2);
ld mmax = (co2|mul);
manual_celllister cl;
cl.add(c2);
int steps = 0;
int nextsteps = 1;
for(int i=0; i<isize(cl.lst); i++) {
if(i == nextsteps) steps++, nextsteps = isize(cl.lst);
cell *c = cl.lst[i];
forCellCM(c3, c) if(!cl.listed(c3)) {
if(c3 == c1) {
return distmemo[c1][c2] = distmemo[c2][c1] = 1 + steps;
}
auto h = get_coord(c3) - co1;
ld dot = (h|mul);
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;
cl.add(c3);
next3: ;
}
}
println(hlog, "Error: distance not found");
return 999999;
}
cell *camelot_center;
ld space_distance(cell *c1, cell *c2) {
ldcoord co1 = get_coord(c1);
ldcoord co2 = get_coord(c2);
return sqrt(hypot2(co1, co2));
}
int dist_relative(cell *c) {
int r = roundTableRadius(NULL);
cell *start = currentmap->gamestart();
if(!camelot_center) {
printf("Finding Camelot center...");
camelot_center = start;
while(precise_distance(camelot_center, start) < r + 5)
camelot_center = camelot_center->cmove(hrand(camelot_center->type));
}
if(PURE && !add_bitruncation)
return precise_distance(c, camelot_center) - r;
ld sdmul = (r+5) / space_distance(camelot_center, start);
ld dis = space_distance(camelot_center, c) * sdmul;
println(hlog, "dis = ", dis);
if(dis < r)
return int(dis) - r;
else {
forCellCM(c1, c) if(space_distance(camelot_center, c1) * sdmul < r)
return 0;
return int(dis) + 1 - r;
}
}
int dist_alt(cell *c) {
if(specialland == laCamelot && camelot_center) {
if(PURE && !add_bitruncation)
return precise_distance(c, camelot_center);
if(c == camelot_center) return 0;
return 1 + int(space_distance(camelot_center, c));
}
return 1;
}
ld crug_rotation[MAXDIM][MAXDIM];
@ -513,6 +629,34 @@ void build_rugdata() {
}
}
eLand getCLand(int 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]);
return landmemo[x] = laCrossroads;
}
void set_land(cell *c) {
setland(c, specialland);
auto co = get_coord(c);
auto co1 = roundcoord(co * 60);
int cv = co1[0];
if(specialland == laCrossroads) {
eLand l1 = getCLand(gdiv(cv, 360));
eLand l2 = getCLand(gdiv(cv+59, 360));
if(l1 != l2) setland(c, laBarrier);
else setland(c, l1);
}
if(specialland == laCamelot) {
setland(c, laCrossroads);
buildCamelot(c);
}
}
int readArgs() {
using namespace arg;

View File

@ -114,7 +114,9 @@ transmatrix calc_relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hin
//bool hsol = false;
//transmatrix sol;
int steps = 0;
while(h1 != h2) {
steps++; if(steps > 100) { println(hlog, "not found"); return Id; }
if(smallbounded && quotient) {
transmatrix T;
ld bestdist = 1e9;

View File

@ -91,7 +91,7 @@ void addMessage(string s, char spamtype = 0);
#define binarytiling (geometry == gBinaryTiling)
#define archimedean (geometry == gArchimedean)
#define eubinary (euclid || binarytiling)
#define eubinary (euclid || binarytiling || geometry == gCrystal)
#define cgclass (ginf[geometry].cclass)
#define euclid (cgclass == gcEuclid)
@ -3392,6 +3392,7 @@ hyperpoint xspinpush0(ld alpha, ld x);
extern FILE *debugfile;
extern int debugflags;
int gmod(int i, int j);
int gdiv(int i, int j);
extern walltype winf[walltypes];
extern vector<landtacinfo> land_tac;
string llts(long long i);
@ -4139,13 +4140,16 @@ namespace arcm {
namespace crystal {
extern bool add_bitruncation;
color_t colorize(cell *c);
int distance(cell *c1, cell *c2);
int precise_distance(cell *c1, cell *c2);
hrmap *new_map();
void create_step(heptagon *h, int d);
void build_rugdata();
void apply_rotation(const transmatrix t);
void switch_z_coordinate();
void next_home_orientation();
void set_land(cell *c);
int dist_alt(cell *c);
int dist_relative(cell *c);
}
hyperpoint get_warp_corner(cell *c, int cid);

View File

@ -2375,7 +2375,7 @@ void setdist(cell *c, int d, cell *from) {
// this fixes the following problem:
// http://steamcommunity.com/app/342610/discussions/0/1470840994970724215/
if(!generatingEquidistant && from && d >= 7 && c->land && !binarytiling && !archimedean) {
if(!generatingEquidistant && from && d >= 7 && c->land && !binarytiling && !archimedean && geometry != gCrystal) {
int cdi = celldist(c);
if(celldist(from) > cdi) {
forCellCM(c2, c) if(celldist(c2) < cdi) {
@ -2413,7 +2413,8 @@ void setdist(cell *c, int d, cell *from) {
#else
if(true) {
#endif
if(sphere || fulltorus) setLandSphere(c);
if(geometry == gCrystal) crystal::set_land(c);
else if(sphere || fulltorus) setLandSphere(c);
else if(euclid) setLandEuclid(c);
else if(quotient) { setland(c, specialland); setLandQuotient(c); }
else if(weirdhyperbolic) setLandWeird(c);