From 50f37a6b634c82a9b7128375089847863b411ec5 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sat, 1 Dec 2018 23:53:03 +0100 Subject: [PATCH] crystal:: started working on lands (Camelot done) and distances --- crystal.cpp | 178 +++++++++++++++++++++++++++++++++++++++++++++----- geometry2.cpp | 2 + hyper.h | 8 ++- landgen.cpp | 5 +- 4 files changed, 172 insertions(+), 21 deletions(-) diff --git a/crystal.cpp b/crystal.cpp index e01dc2f6..f9b69ced 100644 --- a/crystal.cpp +++ b/crystal.cpp @@ -18,10 +18,15 @@ typedef array ldcoord; static const ldcoord ldc0 = {}; ldcoord told(coord c) { ldcoord a; for(int i=0; i> 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 hcoords; map heptagon_at; +map landmemo; +unordered_map> distmemo; +map 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; imaster->c7 != c) { - ldcoord res = ldc0; - for(int i=0; itype; 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; itype; 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; amaster]; coord co2 = hcoords[c2->master]; int result = 0; for(int a=0; agamestart()) 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 mmax + 2.5) continue; + + for(int k=0; 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; diff --git a/geometry2.cpp b/geometry2.cpp index 651a91e0..6f329dc1 100644 --- a/geometry2.cpp +++ b/geometry2.cpp @@ -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; diff --git a/hyper.h b/hyper.h index 752f8138..c5dd6ed7 100644 --- a/hyper.h +++ b/hyper.h @@ -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 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); diff --git a/landgen.cpp b/landgen.cpp index c42a1ce6..80b5f572 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -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);