From 11569c693def319e28dc9a91bd8997d495aebd80 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Thu, 28 Dec 2017 16:46:10 +0100 Subject: [PATCH] big change: more configuration for the torus (and also Klein bottle) --- bigstuff.cpp | 95 +++++++------ cell.cpp | 357 ++++++++++++++++++++++++++++++++++-------------- classes.cpp | 2 +- commandline.cpp | 22 +++ complex.cpp | 17 +-- control.cpp | 9 +- game.cpp | 3 +- geom-exp.cpp | 107 +++++++++++++-- graph.cpp | 33 +++-- help.cpp | 12 +- hyper.h | 13 +- hypgraph.cpp | 45 +++--- landgen.cpp | 31 ++--- mapeditor.cpp | 2 +- netgen.cpp | 4 +- pattern2.cpp | 41 +++--- rug.cpp | 12 +- shmup.cpp | 12 +- system.cpp | 6 +- textures.cpp | 2 +- util.cpp | 8 ++ 21 files changed, 546 insertions(+), 287 deletions(-) diff --git a/bigstuff.cpp b/bigstuff.cpp index 9719f901..8daec051 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -732,9 +732,18 @@ void setLandSphere(cell *c) { } } -eLand euland[65536]; +eLand euland[max_vec]; -eLand switchable(eLand nearland, eLand farland, eucoord c) { +eLand& get_euland(int c) { + return euland[c & (max_vec-1)]; + } + +void clear_euland(eLand first) { + for(int i=0; imaster, x, y); + int x, y; + tie(x,y) = cell_to_pair(c); setland(c, getEuclidLand(y+2*x)); } if(specialland == laTerracotta) { - eucoord x, y; - decodeMaster(c->master, x, y); - if((y+2*x) % 16 == 1) { + int x, y; + tie(x,y) = cell_to_pair(c); + if(((y+2*x) & 15) == 1) { setland(c, laMercuryRiver); c->wall = waMercury; } } if(specialland == laCrossroads4) { - eucoord x, y; - decodeMaster(c->master, x, y); + int x, y; + tie(x,y) = cell_to_pair(c); c->land = getEuclidLand(y); } if(specialland == laWhirlpool) { @@ -794,30 +802,29 @@ void setLandEuclid(cell *c) { } if(specialland == laPrincessQuest) setland(c, laPalace); if(specialland == laOcean) { - eucoord x, y; - decodeMaster(c->master, x, y); - int y0 = y; if(y>50000) y0 -= 65536; y0 += 10; - if(y0 == 0) + int x, y; + tie(x,y) = cell_to_pair(c); + y += 10; + if(y == 0) { setland(c, laBarrier); if(ishept(c)) c->land = laRlyeh; } - else if(y0<0) setland(c, laRlyeh); - else c->landparam = y0; + else if(y<0) setland(c, laRlyeh); + else c->landparam = y; } if(specialland == laIvoryTower || specialland == laDungeon) { - eucoord x, y; - decodeMaster(c->master, x, y); - int y0 = y; if(y>50000) y0 -= 65536; y0 = -y0; y0 -= 5; - if(y0 == 0) + int x, y; + tie(x,y) = cell_to_pair(c); y -= 5; + if(y == 0) {setland(c, laBarrier); if(ishept(c)) setland(c, laAlchemist); } - else if(y0<0) setland(c, laAlchemist); + else if(y<0) setland(c, laAlchemist); else { - c->landparam = y0; + c->landparam = y; } } if(specialland == laElementalWall) { - eucoord x, y; - decodeMaster(c->master, x, y); - int y0 = y; if(y>32768) y0 -= 65536; - int x0 = x +y/2; + int x, y; + tie(x,y) = cell_to_pair(c); + int x0 = x + (y>>1); + int y0 = y; int id = 0; if(y0&16) id += 2; @@ -843,10 +850,10 @@ void setLandEuclid(cell *c) { } } if(specialland == laCrossroads3) { - eucoord x, y; - decodeMaster(c->master, x, y); - int y0 = y; if(y>32768) y0 -= 65536; - int x0 = x +y/2; + int x, y; + tie(x,y) = cell_to_pair(c); + int y0 = y; + int x0 = x + y/2; x0 += 24; y0 += 8; @@ -862,11 +869,11 @@ void setLandEuclid(cell *c) { } } if(specialland == laWarpCoast) { - eucoord x, y; - decodeMaster(c->master, x, y); + int x, y; + tie(x,y) = cell_to_pair(c); - int zz = a4 ? short(x) : 2*short(x)+short(y) + 10; - zz %= 30; if(zz<0) zz += 30; + int zz = a4 ? x : 2*x+y + 10; + zz = gmod(zz, 30); if(zz >= 15) setland(c, laWarpSea); else diff --git a/cell.cpp b/cell.cpp index 8405fb16..b557d111 100644 --- a/cell.cpp +++ b/cell.cpp @@ -192,7 +192,20 @@ heptagon *getDodecahedron(int i) { // --- euclidean geometry --- -cell*& euclideanAtCreate(eucoord x, eucoord y); +cell*& euclideanAtCreate(int vec); + +static const int max_vec = (1<<15); + +int pair_to_vec(int x, int y) { + return x + (y << 15); + } + +pair vec_to_pair(int vec) { + int x = vec & ((1<<15)-1); + int y = (vec >> 15); + if(x >= (1<<14)) x -= (1<<15), y++; + return {x, y}; + } namespace torusconfig { // the configuration of the torus topology. @@ -208,14 +221,176 @@ namespace torusconfig { int def_qty = 127*3, dx = 1, def_dy = -11*2; int qty = def_qty, dy = def_dy; + int sdx = 12, sdy = 12; + // new values to change - int newqty, newdy; + int newqty, newdy, newsdx, newsdy; int torus_cx, torus_cy; + + enum eTorusMode { + tmSingleHex, + tmSingle, + tmSlantedHex, + tmStraight, + tmStraightHex, + tmKlein, + tmKleinHex + }; + + static const flagtype TF_SINGLE = 1; + static const flagtype TF_SIMPLE = 2; + static const flagtype TF_WEIRD = 4; + + static const flagtype TF_HEX = 16; + static const flagtype TF_SQUARE = 32; + + static const flagtype TF_KLEIN = 256; + + struct torusmode_info { + string name; + flagtype flags; + }; + + vector tmodes = { + {"single row (hex)", TF_SINGLE | TF_HEX}, + {"single row (squares)", TF_SINGLE | TF_SQUARE}, + {"parallelogram (hex)", TF_SIMPLE | TF_HEX}, + {"rectangle (squares)", TF_SIMPLE | TF_SQUARE}, + {"rectangle (hex)", TF_WEIRD | TF_HEX}, + {"Klein bottle (squares)", TF_SIMPLE | TF_KLEIN | TF_SQUARE}, + {"Klein bottle (hex)", TF_WEIRD | TF_KLEIN | TF_HEX}, + }; + + eTorusMode torus_mode, newmode; + flagtype tmflags() { return tmodes[torus_mode].flags; } + + int getqty() { + if(tmflags() & TF_SINGLE) + return qty; + else + return sdx * sdy; + } + + int getvec(int x, int y) { + if(tmflags() & TF_SINGLE) + return x * dx + y * dy; + else if(tmflags() & TF_SIMPLE) + return pair_to_vec(x, y); + else + return pair_to_vec(-y - 2 * x, 3 * y); + } + + int id_to_vec(int id, bool mirrored = false) { + if(tmflags() & TF_SINGLE) + return id; + else { + int dx = id % sdx; + int dy = id / sdx; + if(mirrored) + dy = -dy, dx += sdx; + if(tmflags() & TF_SIMPLE) + return pair_to_vec(dx, dy); + else + return pair_to_vec(- 2 * dx - (dy & 1), 3 * dy); + } + } + + pair vec_to_id_mirror(int vec) { + if(tmflags() & TF_SINGLE) { + return {gmod(vec, qty), false}; + } + else { + int x, y; + tie(x,y) = vec_to_pair(vec); + bool mirror = false; + if(tmflags() & TF_KLEIN) { + if(tmflags() & TF_WEIRD) { + x = gmod(x, 4 * sdx); + mirror = x > 0 && x <= 2 * sdx; + } + else { + x = gmod(x, 2 * sdx); + mirror = x >= sdx; + } + if(mirror) y = -y; + } + if(tmflags() & TF_WEIRD) { + y /= 3; x = (x + (y&1)) / -2; + } + x = gmod(x, sdx), y = gmod(y, sdy); + return {y * sdx + x, mirror}; + } + } + + int vec_to_id(int vec) { + return vec_to_id_mirror(vec).first; + } + + void torus_test() { + printf("Testing torus vec_to_pair/pair_to_vec...\n"); + for(int x=-10; x<=10; x++) + for(int y=-10; y<=10; y++) { + auto p = vec_to_pair(pair_to_vec(x, y)); + if(p.first != x || p.second != y) + printf("Failed for (%d,%d) -> [%d] -> (%d,%d)\n", x, y, pair_to_vec(x,y), p.first, p.second); + } + printf("Testing id_to_vec / vec_to_id...\n"); + for(int i=0; i < getqty(); i++) + for(int m=0; m< (torus_mode == tmKlein ? 2 : 1); m++) + if(vec_to_id_mirror(id_to_vec(i, m)) != pair (i,m)) + printf("Failed for id %d.%d [%d] (%d.%d)\n", i, m, id_to_vec(i,m), vec_to_id(id_to_vec(i,m)), vec_to_id_mirror(id_to_vec(i,m)).second); + } + + int tester = addHook(hooks_tests, 0, torus_test); + + void activate() { + if(tmflags() & TF_HEX) + ginf[gTorus].vertex = 3, ginf[gTorus].sides = 6; + else + ginf[gTorus].vertex = 4, ginf[gTorus].sides = 4; + } } int decodeId(heptagon* h); heptagon* encodeId(int id); +int euclid_getvec(int dx, int dy) { + if(torus) return torusconfig::getvec(dx, dy); + else return pair_to_vec(dx, dy); + } + +template void build_euclidean_moves(cell *c, int vec, const T& builder) { + int x, y; + tie(x,y) = vec_to_pair(vec); + c->type = a4 ? (nontruncated || ((x^y^1) & 1) ? 4 : 8) : 6; + + if(c->type == 4) { + int m = nontruncated ? 1 : 2; + builder(euclid_getvec(+1,+0), 0, 2 * m); + builder(euclid_getvec(+0,+1), 1, 3 * m); + builder(euclid_getvec(-1,+0), 2, 0 * m); + builder(euclid_getvec(+0,-1), 3, 1 * m); + } + else if(c->type == 8) { + builder(euclid_getvec(+1,+0), 0, 2); + builder(euclid_getvec(+1,+1), 1, 5); + builder(euclid_getvec(+0,+1), 2, 3); + builder(euclid_getvec(-1,+1), 3, 7); + builder(euclid_getvec(-1,+0), 4, 0); + builder(euclid_getvec(-1,-1), 5, 1); + builder(euclid_getvec(+0,-1), 6, 1); + builder(euclid_getvec(+1,-1), 7, 3); + } + else /* 6 */ { + builder(euclid_getvec(+1,+0), 0, 3); + builder(euclid_getvec(+0,+1), 1, 4); + builder(euclid_getvec(-1,+1), 2, 5); + builder(euclid_getvec(-1,+0), 3, 0); + builder(euclid_getvec(+0,-1), 4, 1); + builder(euclid_getvec(+1,-1), 5, 2); + } + } + struct hrmap_torus : hrmap { vector all; @@ -229,25 +404,27 @@ struct hrmap_torus : hrmap { hrmap_torus() { using namespace torusconfig; - all.resize(qty); - for(int i=0; imaster = encodeId(i); + int q = getqty(); + all.resize(q); + for(int i=0; imov[0] = all[(i+dx+2*qty)%qty]; - all[i]->mov[1] = all[(i+dy+2*qty)%qty]; - all[i]->mov[2] = all[(i+dy-dx+2*qty)%qty]; - all[i]->mov[3] = all[(i-dx+2*qty)%qty]; - all[i]->mov[4] = all[(i-dy+2*qty)%qty]; - all[i]->mov[5] = all[(i-dy+dx+2*qty)%qty]; - for(int j=0; j<6; j++) - tsetspin(all[i]->spintable, j, (j+3) % 6); + for(int i=0; imov[d] = all[im.first]; + tsetspin(all[i]->spintable, d, im.second); + }); + } + for(cell *c: all) for(int d=0; dtype; d++) { + cell *c2 = c->mov[d]; + for(int d2=0; d2type; d2++) + if(c2->mov[d2] == c) + tsetspin(c->spintable, d, d2 + (8 * c->spin(d))); } celllister cl(gamestart(), 100, 100000000, NULL); - dists.resize(qty); + dists.resize(q); for(int i=0; imaster)] = cl.dists[i]; } @@ -257,27 +434,20 @@ struct hrmap_torus : hrmap { } }; -int toridMod(int id) { - using namespace torusconfig; - id %= qty; if(id < 0) id += qty; - return id; - } - hrmap_torus *torusmap() { return dynamic_cast (currentmap); } -cell *getTorusId(int id) { +/* cell *getTorusId(int id) { hrmap_torus *cur = torusmap(); if(!cur) return NULL; - return cur->all[toridMod(id)]; - } - + return cur->all[id]; + } */ struct hrmap_euclidean : hrmap { cell *gamestart() { - return euclideanAtCreate(0,0); + return euclideanAtCreate(0); } struct euclideanSlab { @@ -299,8 +469,10 @@ struct hrmap_euclidean : hrmap { euclidean[y][x] = NULL; } - cell*& at(eucoord x, eucoord y) { - euclideanSlab*& slab = euclidean[y>>8][x>>8]; + cell*& at(int vec) { + auto p = vec_to_pair(vec); + int x = p.first, y = p.second; + euclideanSlab*& slab = euclidean[(y>>8)&255][(x>>8)&255]; if(!slab) slab = new hrmap_euclidean::euclideanSlab; return slab->a[y&255][x&255]; } @@ -317,30 +489,43 @@ struct hrmap_euclidean : hrmap { } }; +cellwalker vec_to_cellwalker(int vec) { + if(!torus) + return cellwalker(euclideanAtCreate(vec), 0, false); + else { + hrmap_torus *cur = torusmap(); + if(!cur) return cellwalker(NULL, 0); + auto p = torusconfig::vec_to_id_mirror(vec); + return cellwalker(cur->all[p.first], 0, p.second); + } + } + +int cellwalker_to_vec(cellwalker cw) { + int id = decodeId(cw.c->master); + if(!torus) return id; + return torusconfig::id_to_vec(id, cw.mirrored); + } + +int cell_to_vec(cell *c) { + int id = decodeId(c->master); + if(!torus) return id; + return torusconfig::id_to_vec(id, false); + } + +auto cell_to_pair(cell *c) { + return vec_to_pair(cell_to_vec(c)); + } + union heptacoder { heptagon *h; - struct { eucoord x; eucoord y; } c; int id; }; -void decodeMaster(heptagon *h, eucoord& x, eucoord& y) { - if(torus) { printf("decodeMaster on torus\n"); exit(1); } - heptacoder u; - u.h = h; x = u.c.x; y = u.c.y; - } - int decodeId(heptagon* h) { heptacoder u; u.h = h; return u.id; } -heptagon* encodeMaster(eucoord x, eucoord y) { - if(torus) { printf("encodeMaster on torus\n"); exit(1); } - heptacoder u; - u.c.x = x; u.c.y = y; - return u.h; - } - heptagon* encodeId(int id) { heptacoder u; u.id = id; @@ -528,11 +713,10 @@ cell *createMov(cell *c, int d) { } if(euclid && !c->mov[d]) { - eucoord x, y; - decodeMaster(c->master, x, y); + int id = decodeId(c->master); for(int dx=-1; dx<=1; dx++) for(int dy=-1; dy<=1; dy++) - euclideanAtCreate(x+dx, y+dy); + euclideanAtCreate(id + pair_to_vec(dx, dy)); if(!c->mov[d]) { printf("fail!\n"); } } @@ -597,43 +781,18 @@ void eumerge(cell* c1, cell *c2, int s1, int s2) { // map, cell*> euclidean; -cell*& euclideanAt(eucoord x, eucoord y) { +cell*& euclideanAt(int vec) { if(torus) { printf("euclideanAt called\n"); exit(1); } hrmap_euclidean* euc = dynamic_cast (currentmap); - return euc->at(x, y); + return euc->at(vec); } -cell*& euclideanAtCreate(eucoord x, eucoord y) { - cell*& c = euclideanAt(x,y); +cell*& euclideanAtCreate(int vec) { + cell*& c = euclideanAt(vec); if(!c) { - c = newCell(a4 ? (nontruncated || ((x^y^1) & 1) ? 4 : 8) : 6, NULL); - c->master = encodeMaster(x,y); - euclideanAt(x,y) = c; - if(c->type == 4) { - int m = nontruncated ? 1 : 2; - eumerge(c, euclideanAt(x+1,y), 0, 2 * m); - eumerge(c, euclideanAt(x,y+1), 1, 3 * m); - eumerge(c, euclideanAt(x-1,y), 2, 0 * m); - eumerge(c, euclideanAt(x,y-1), 3, 1 * m); - } - else if(c->type == 8) { - eumerge(c, euclideanAt(x+1,y), 0, 2); - eumerge(c, euclideanAt(x+1,y+1), 1, 5); - eumerge(c, euclideanAt(x,y+1), 2, 3); - eumerge(c, euclideanAt(x-1,y+1), 3, 7); - eumerge(c, euclideanAt(x-1,y), 4, 0); - eumerge(c, euclideanAt(x-1,y-1), 5, 1); - eumerge(c, euclideanAt(x,y-1), 6, 1); - eumerge(c, euclideanAt(x+1,y-1), 7, 3); - } - else /* 6 */ { - eumerge(c, euclideanAt(x+1,y), 0, 3); - eumerge(c, euclideanAt(x,y+1), 1, 4); - eumerge(c, euclideanAt(x-1,y+1), 2, 5); - eumerge(c, euclideanAt(x-1,y), 3, 0); - eumerge(c, euclideanAt(x,y-1), 4, 1); - eumerge(c, euclideanAt(x+1,y-1), 5, 2); - } + c = newCell(8, encodeId(vec)); + euclideanAt(vec) = c; + build_euclidean_moves(c, vec, [c,vec] (int delta, int d, int d2) { eumerge(c, euclideanAt(vec + delta), d, d2); }); } return c; } @@ -735,7 +894,7 @@ void verifycells(heptagon *at) { verifycell(at->c7); } -int eudist(short sx, short sy) { +int eudist(int sx, int sy) { int z0 = abs(sx); int z1 = abs(sy); if(a4) return z0 + z1; @@ -743,6 +902,11 @@ int eudist(short sx, short sy) { return max(max(z0,z1), z2); } +int eudist(int vec) { + auto p = vec_to_pair(vec); + return eudist(p.first, p.second); + } + int compdist(int dx[]) { int mi = dx[0]; for(int u=0; udists[decodeId(c->master)]; - eucoord x, y; - decodeMaster(c->master, x, y); - return eudist(x, y); + return eudist(decodeId(c->master)); } if(sphere) return celldistance(c, currentmap->gamestart()); if(ctof(c)) return c->master->distance; @@ -787,8 +949,8 @@ int euclidAlt(short x, short y); int celldistAlt(cell *c) { if(euclid) { if(torus) return celldist(c); - eucoord x, y; - decodeMaster(c->master, x, y); + int x, y; + tie(x,y) = vec_to_pair(decodeId(c->master)); return euclidAlt(x, y); } if(sphere || quotient) { @@ -1046,11 +1208,11 @@ cdata *getEuclidCdata(heptagon *h) { return &xx; } - eucoord x, y; + int x, y; hrmap_euclidean* euc = dynamic_cast (currentmap); if(euc->eucdata.count(h)) return &(euc->eucdata[h]); - decodeMaster(h, x, y); + tie(x,y) = vec_to_pair(decodeId(h)); if(x == 0 && y == 0) { cdata xx; @@ -1062,14 +1224,14 @@ cdata *getEuclidCdata(heptagon *h) { while(!((x|y)&ord)) ord <<= 1, bid++; for(int k=0; k<3; k++) { - eucoord x1 = x + (k<2 ? ord : 0); - eucoord y1 = y - (k>0 ? ord : 0); + int x1 = x + (k<2 ? ord : 0); + int y1 = y - (k>0 ? ord : 0); if((x1&ord) || (y1&ord)) continue; - eucoord x2 = x - (k<2 ? ord : 0); - eucoord y2 = y + (k>0 ? ord : 0); + int x2 = x - (k<2 ? ord : 0); + int y2 = y + (k>0 ? ord : 0); - cdata *d1 = getEuclidCdata(encodeMaster(x1,y1)); - cdata *d2 = getEuclidCdata(encodeMaster(x2,y2)); + cdata *d1 = getEuclidCdata(encodeId(pair_to_vec(x1,y1))); + cdata *d2 = getEuclidCdata(encodeId(pair_to_vec(x2,y2))); cdata xx; double disp = pow(2, bid/2.) * 6; @@ -1134,11 +1296,8 @@ int celldistance(cell *c1, cell *c2) { if(euclid) { if(torus) - return torusmap()->dists[toridMod(decodeId(c1->master)-decodeId(c2->master))]; - eucoord x1, y1, x2, y2; - decodeMaster(c1->master, x1, y1); - decodeMaster(c2->master, x2, y2); - return eudist(x1-x2, y1-y2); + return torusmap()->dists[torusconfig::vec_to_id(decodeId(c1->master)-decodeId(c2->master))]; + return eudist(decodeId(c1->master) - decodeId(c2->master)); } if(sphere || quotient == 1) { diff --git a/classes.cpp b/classes.cpp index 0f4e16c3..557f5509 100644 --- a/classes.cpp +++ b/classes.cpp @@ -1613,7 +1613,7 @@ geometryinfo ginf[gGUARD] = { {"elliptic", "elliptic", 5, 3, qELLIP, gcSphere, {{SEE_ALL, SEE_ALL}}}, {"Zebra quotient", "Zebra", 7, 3, qZEBRA, gcHyperbolic, {{7, 5}}}, {"field quotient", "field", 7, 3, qFIELD, gcHyperbolic, {{7, 5}}}, - {"torus", "torus", 6, 3, qTORUS, gcEuclid, {{7, FORBIDDEN}}}, + {"torus/Klein bottle", "torus", 6, 3, qTORUS, gcEuclid, {{7, FORBIDDEN}}}, {"octagons", "oct", 8, 3, 0, gcHyperbolic, {{6, 4}}}, {"four pentagons", "4x5", 5, 4, 0, gcHyperbolic, {{6, 4}}}, {"four hexagons", "4x6", 6, 4, 0, gcHyperbolic, {{5, 3}}}, diff --git a/commandline.cpp b/commandline.cpp index a16c9a63..5cda7f84 100644 --- a/commandline.cpp +++ b/commandline.cpp @@ -228,13 +228,27 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { showstartmenu autocheat = true; currfp.init(p); } + else if(argis("-test")) + callhooks(hooks_tests); else if(argis("-tpar")) { + torusconfig::torus_mode = torusconfig::tmSingle; shift(); sscanf(args(), "%d,%d,%d", &torusconfig::qty, &torusconfig::dx, &torusconfig::dy ); } + else if(argis("-tparx")) { + shift(); sscanf(args(), "%d,%d,%d", + (int*) &torusconfig::torus_mode, + &torusconfig::sdx, + &torusconfig::sdy + ); + if(torusconfig::torus_mode == torusconfig::tmSingle) + torusconfig::qty = torusconfig::sdx, + torusconfig::dy = torusconfig::sdy; + torusconfig::activate(); + } else if(argis("-cs")) { shift(); fieldpattern::matrix M = currfp.strtomatrix(args()); @@ -345,6 +359,14 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { showstartmenu PHASEFROM(2); shift(); whatever = argf(); resetGeometry(); } + else if(argis("-wei")) { + PHASEFROM(2); + shift(); whateveri = argf(); resetGeometry(); + } + else if(argis("-wei2")) { + PHASEFROM(2); + shift(); whateveri2 = argf(); resetGeometry(); + } else if(argis("-rch")) { PHASEFROM(2); reptilecheat = true; autocheat = true; firstland = laReptile; diff --git a/complex.cpp b/complex.cpp index cef53db9..9166b0af 100644 --- a/complex.cpp +++ b/complex.cpp @@ -12,8 +12,8 @@ namespace whirlwind { int fzebra3(cell *c) { if(euclid) { if(torus) return 0; - eucoord x, y; - decodeMaster(c->master, x, y); + int x, y; + tie(x,y) = cell_to_pair(c); return 1+((((signed short)(y)+int(50000))/3)%3); } if(S7 == 5) return getHemisphere(c, 0) > 0 ? 1 : 2; @@ -809,8 +809,9 @@ namespace clearing { if(pseudohept(c)) return; c->monst = moMutant; - eucoord x, y; - decodeMaster(c->master, x, y); + int x, y; + tie(x,y) = cell_to_pair(c); + int xco = x * 2 + y + 1; c->stuntime = (8-xco/2) & 15; // 2, 4, 5, 7 @@ -2701,8 +2702,8 @@ namespace prairie { c->LHU.fi.rval = 0; } else if(euclid) { - eucoord x, y; - decodeMaster(c->master, x, y); + int x, y; + tie(x,y) = cell_to_pair(c); c->LHU.fi.rval = (y&15); } else if(sphere) { @@ -3391,8 +3392,8 @@ namespace dungeon { if(euclid) { if(torus) return; - eucoord x, y; - decodeMaster(c->master, x, y); + int x, y; + tie(x, y) = cell_to_pair(c); string tab[] = { ".####...", "L...L...", diff --git a/control.cpp b/control.cpp index a7708245..597a6347 100644 --- a/control.cpp +++ b/control.cpp @@ -30,7 +30,8 @@ movedir joydir; movedir mousedest; ld shiftmul = 1; -cell *mouseover, *mouseover2, *lmouseover, *centerover; +cell *mouseover, *mouseover2, *lmouseover; +cellwalker centerover; ld modist, modist2, centdist; int lastt; @@ -340,7 +341,7 @@ void handleKeyNormal(int sym, int uni) { // vid.yshift = 1 - vid.yshift; // vid.drawmousecircle = true; } - if(sym == 'm' && canmove && (centerover == cwt.c ? mouseover : centerover)) + if(sym == 'm' && canmove && (centerover == cwt ? mouseover : centerover.c)) performMarkCommand(mouseover); } @@ -351,9 +352,9 @@ void handleKeyNormal(int sym, int uni) { if(sym == 't' && uni != 'T' && uni != 'T'-64 && canmove) { if(playermoved && items[itStrongWind]) { cell *c = whirlwind::jumpDestination(cwt.c); - if(c) centerover = c; + if(c) centerover.c = c; } - targetRangedOrb(centerover, roKeyboard); + targetRangedOrb(centerover.c, roKeyboard); sym = 0; uni = 0; } } diff --git a/game.cpp b/game.cpp index 93029b0f..59df83f8 100644 --- a/game.cpp +++ b/game.cpp @@ -5795,8 +5795,7 @@ void activateSafety(eLand l) { firstland = l; safetyland = l; safetyseed = time(NULL); - for(int i=0; i<65536; i++) euland[i] = laNone; - euland[0] = euland[1] = firstland; + clear_euland(firstland); safety = true; avengers = 0; clearMemory(); initcells(); diff --git a/geom-exp.cpp b/geom-exp.cpp index 0b41db04..ce401b1f 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -84,20 +84,76 @@ void showQuotientConfig() { dialog::display(); } +bool torus_chamfer; + void showTorusConfig() { cmode = sm::SIDE | sm::TORUSCONFIG; gamescreen(2); dialog::init(XLAT("advanced configuration")); - dialog::addSelItem(XLAT("number of cells (n)"), its(torusconfig::newqty), 'n'); - dialog::addSelItem(XLAT("cell bottom-right from 0 (d)"), its(torusconfig::newdy), 'd'); + auto& mode = torusconfig::tmodes[torusconfig::newmode]; - if(torusconfig::newqty % 3) - dialog::addInfo("best if n is divisible by 3", 0x808080); + dialog::addSelItem(XLAT("mode"), XLAT(mode.name), 'm'); + + bool single = (mode.flags & torusconfig::TF_SINGLE); + bool square = (mode.flags & torusconfig::TF_SQUARE); + bool simple = (mode.flags & torusconfig::TF_SIMPLE); + + if(single) { + dialog::addSelItem(XLAT("number of cells (n)"), its(torusconfig::newqty), 'n'); + if(torusconfig::TF_HEX) + dialog::addSelItem(XLAT("cell bottom-right from 0 (d)"), its(torusconfig::newdy), 'd'); + else + dialog::addSelItem(XLAT("cell below 0 (d)"), its(torusconfig::newdy), 'd'); + } + else { + if(torusconfig::newsdx < 1) torusconfig::newsdx = 1; + if(torusconfig::newsdy < 1) torusconfig::newsdy = 1; + dialog::addSelItem(XLAT("width (x)"), its(torusconfig::newsdx), 'x'); + dialog::addSelItem(XLAT("height (y)"), its(torusconfig::newsdy), 'y'); + } - if((torusconfig::newdy + 999999) % 3 != 2) - dialog::addInfo("best if d+1 is divisible by 3", 0x808080); + if(square) dialog::addBoolItem(XLAT("chamfering"), !torus_chamfer, 't'); + else dialog::addInfo("", 100); + + int valid = 2; + + if(single) { + if(square) { + dialog::addInfo("this mode has bad patterns", 0x808080), valid = 1; + if(!torus_chamfer && valid == 1) + dialog::addInfo("incompatible with chamfering", 0x808080), valid = 0; + } + else { + if(torusconfig::newqty % 3) + dialog::addInfo(XLAT("best if %1 is divisible by %2", "n", "3"), 0x808080), valid = 1; + if((torusconfig::newdy + 999999) % 3 != 2) + dialog::addInfo(XLAT("best if %1 is divisible by %2", "d+1", "3"), 0x808080), valid = 1; + } + } + else { + if(square) { + if(torusconfig::newsdx & 1) + dialog::addInfo(XLAT("best if %1 is divisible by %2", "x", "2"), 0x808080), valid = 1; + if(torusconfig::newsdy & 1) + dialog::addInfo(XLAT("best if %1 is divisible by %2", "y", "2"), 0x808080), valid = 1; + if(!torus_chamfer && valid == 1) + dialog::addInfo("incompatible with chamfering", 0x808080), valid = 0; + } + else if(simple) { + if(torusconfig::newsdx & 1) + dialog::addInfo(XLAT("best if %1 is divisible by %2", "x", "3"), 0x808080), valid = 1; + if(torusconfig::newsdy & 1) + dialog::addInfo(XLAT("best if %1 is divisible by %2", "y", "3"), 0x808080), valid = 1; + } + else { + if(torusconfig::newsdx & 1) + dialog::addInfo(XLAT("best if %1 is divisible by %2", "x", "3"), 0x808080), valid = 1; + if(torusconfig::newsdy & 1) + dialog::addInfo(XLAT("best if %1 is divisible by %2", "y", "2"), 0x808080), valid = 0; + } + } dialog::addSelItem(XLAT("scale factor"), fts(vid.scale), 'z'); @@ -108,22 +164,39 @@ void showTorusConfig() { dialog::addItem("activate", 'a'); dialog::addItem("default", 'c'); - keyhandler = [] (int sym, int uni) { - if(uni == 'n') + keyhandler = [=] (int sym, int uni) { + if(uni == 'm') { + int i = torusconfig::newmode + 1; + if(i >= size(torusconfig::tmodes)) i = 0; + torusconfig::newmode = torusconfig::eTorusMode(i); + } + else if(uni == 'n' && single) dialog::editNumber(torusconfig::newqty, 0, 1000, 3, torusconfig::def_qty, XLAT("number of cells (n)"), ""); - else if(uni == 'd') - dialog::editNumber(torusconfig::newdy, -1000, 1000, 3, -torusconfig::def_dy, XLAT("cell bottom-right from 0 (d)"), ""); - else if((uni == 'a' || uni == '\n') && torusconfig::newqty >= 3 && abs(torusconfig::newdy) < torusconfig::newqty ) { - targetgeometry = gEuclid; restartGame('g'); + else if(uni == 'd' && single) + dialog::editNumber(torusconfig::newdy, -1000, 1000, 3, -torusconfig::def_dy, XLAT("cell below 0 (d)"), ""); + else if(uni == 'x' && !single) + dialog::editNumber(torusconfig::newsdx, 0, 1000, square ? 2 : 3, 12, XLAT("width (x)"), ""); + else if(uni == 'y' && !single) + dialog::editNumber(torusconfig::newsdy, 0, 1000, square ? 2 : simple ? 3 : 2, 12, XLAT("height (y)"), ""); + else if(uni == 't') + torus_chamfer = !torus_chamfer; + else if((uni == 'a' || uni == '\n') && torusconfig::newqty >= 3 && valid) { + targetgeometry = gNormal; restartGame('g', false, true); + torusconfig::torus_mode = torusconfig::newmode; torusconfig::qty = torusconfig::newqty; torusconfig::dy = torusconfig::newdy; - targetgeometry = gTorus; restartGame('g'); + torusconfig::sdx = torusconfig::newsdx; + torusconfig::sdy = torusconfig::newsdy; + torusconfig::activate(); + if((square && torus_chamfer) != nontruncated) restartGame('7', false, true); + targetgeometry = gTorus; restartGame('g', false, true); } else if(uni == 'c') { - targetgeometry = gEuclid; restartGame('g'); + targetgeometry = gEuclid; restartGame('g', false, true); + torusconfig::torus_mode = torusconfig::tmSingle; torusconfig::qty = torusconfig::def_qty; torusconfig::dy = torusconfig::def_dy; - targetgeometry = gTorus; restartGame('g'); + targetgeometry = gTorus; restartGame('g', false, true); } else if(uni == 'z') editScale(); #if CAP_RUG @@ -263,6 +336,10 @@ void showEuclideanMenu() { if(torus) torusconfig::newdy = torusconfig::dy, torusconfig::newqty = torusconfig::qty, + torusconfig::newsdx = torusconfig::sdx, + torusconfig::newsdy = torusconfig::sdy, + torusconfig::newmode = torusconfig::torus_mode, + torus_chamfer = nontruncated, pushScreen(showTorusConfig); if(quotient==2) pushScreen(showQuotientConfig); } diff --git a/graph.cpp b/graph.cpp index aa56d345..8a947ead 100644 --- a/graph.cpp +++ b/graph.cpp @@ -3284,12 +3284,12 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { mouseover2 = c; } - if(!torus) { + if(!euclid) { double dfc = euclid ? intval(VC0, C0) : VC0[2]; if(dfc < centdist) { centdist = dfc; - centerover = c; + centerover = cellwalker(c, spinv, mirrored); } } @@ -3380,10 +3380,19 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { if(cmode & sm::TORUSCONFIG) { using namespace torusconfig; - int cd = torus_cx * dx + torus_cy * newdy; - cd %= newqty; if(cd<0) cd += newqty; - string label = its(cd); - queuestr(V, cd ? .2 : .6, label, cd == 0 ? 0xFFFF0040 : 0xFFFFFFD0, 1); + string label; + bool small; + if(tmflags() & TF_SINGLE) { + int cd = torus_cx * dx + torus_cy * newdy; + cd %= newqty; if(cd<0) cd += newqty; + label = its(cd); + small = cd; + } + else { + small = true; + label = its(torus_cx) + "," + its(torus_cy); + } + queuestr(V, small ? .2 : .6, label, small ? 0xFFFFFFD0 : 0xFFFF0040, 1); } asciicol = wcol; @@ -4744,8 +4753,8 @@ void drawMarkers() { #if CAP_MODEL m = netgen::mode == 0; #endif - if(centerover && !playermoved && m && !conformal::on) - queuecircleat(centerover, .70 - .06 * sin(ticks/200.0), + if(centerover.c && !playermoved && m && !conformal::on) + queuecircleat(centerover.c, .70 - .06 * sin(ticks/200.0), darkena(int(175 + 25 * sin(ticks / 200.0)), 0, 0xFF)); if(multi::players > 1 || multi::alwaysuse) for(int i=0; igetOrigin(); @@ -5419,7 +5428,7 @@ void restartGraph() { auto graphcm = addHook(clearmemory, 0, [] () { DEBB(DF_INIT, (debugfile,"clear graph memory\n")); - mouseover = centerover = lmouseover = NULL; + mouseover = centerover.c = lmouseover = NULL; for(int i=0; ic7; } diff --git a/help.cpp b/help.cpp index 3707c090..c63eff53 100644 --- a/help.cpp +++ b/help.cpp @@ -650,7 +650,7 @@ int windtotal; void describeMouseover() { DEBB(DF_GRAPH, (debugfile,"describeMouseover\n")); - cell *c = mousing ? mouseover : playermoved ? NULL : centerover; + cell *c = mousing ? mouseover : playermoved ? NULL : centerover.c; string& out = mouseovers; if(!c || instat || getcstat != '-') { } else if(c->wall != waInvisibleFloor) { @@ -701,12 +701,10 @@ void describeMouseover() { out += " " + describeRPM(c->land); if(euclid && cheater) { - if(torus) { - out += " ("+its(decodeId(c->master))+")"; - } - else { - eucoord x, y; - decodeMaster(c->master, x, y); + out += " ("+its(cell_to_vec(c))+")"; + if(!torus || torusconfig::torus_mode != torusconfig::tmSingle) { + int x, y; + tie(x,y) = cell_to_pair(c); out += " ("+its(short(x))+","+its(short(y))+")"; } } diff --git a/hyper.h b/hyper.h index 927a8ddf..06ad88e5 100644 --- a/hyper.h +++ b/hyper.h @@ -541,7 +541,7 @@ void drawCircle(int x, int y, int size, int color); void fixcolor(int& col); int displaydir(cell *c, int d); hyperpoint gethyper(ld x, ld y); -void resetview(); extern heptspin viewctr; extern cell *centerover; +void resetview(); extern heptspin viewctr; extern cellwalker centerover; void drawthemap(); void drawfullmap(); bool displaystr(int x, int y, int shift, int size, const char *str, int color, int align); @@ -829,7 +829,6 @@ bool isElemental(eLand l); int coastval(cell *c, eLand base); int getHauntedDepth(cell *c); eLand randomElementalLand(); -extern eLand euland[65536]; bool notDippingForExtra(eItem i, eItem x); void placePrizeOrb(cell *c); void wandering(); @@ -1388,6 +1387,7 @@ void movecost(cell* from, cell *to); void checkmove(); transmatrix eumove(ld x, ld y); +transmatrix eumove(int vec); transmatrix eumovedir(int d); int reptilemax(); @@ -1690,7 +1690,7 @@ template int addHook(hookset*& m, int prio, const U& hook) return 0; } -extern purehookset hooks_frame, hooks_stats, clearmemory, hooks_config; +extern purehookset hooks_frame, hooks_stats, clearmemory, hooks_config, hooks_tests; template void callhooks(hookset *h, U... args) { if(h) for(auto& p: *h) p.second(args...); @@ -2252,9 +2252,6 @@ struct celllister { }; -typedef unsigned short eucoord; -void decodeMaster(heptagon *h, eucoord& x, eucoord& y); - hrmap *newAltMap(heptagon *o); #define currfp fieldpattern::getcurrfp() @@ -2423,3 +2420,7 @@ transmatrix cview(); extern string truncatenames[2]; extern bool need_mouseh; + +extern int whateveri, whateveri2; + +void clear_euland(eLand first); diff --git a/hypgraph.cpp b/hypgraph.cpp index cbbdc886..194e3055 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -395,6 +395,12 @@ transmatrix eumove(ld x, ld y) { return Mat; } +transmatrix eumove(int vec) { + int x, y; + tie(x,y) = vec_to_pair(vec); + return eumove(x, y); + } + transmatrix eumovedir(int d) { if(a4) { d = d & 3; @@ -426,16 +432,10 @@ ld matrixnorm(const transmatrix& Mat) { void drawEuclidean() { DEBB(DF_GRAPH, (debugfile,"drawEuclidean\n")); sphereflip = Id; - eucoord px=0, py=0; - if(!centerover) centerover = cwt.c; + if(!centerover.c) centerover = cwt; // printf("centerover = %p player = %p [%d,%d]-[%d,%d]\n", lcenterover, cwt.c, // mindx, mindy, maxdx, maxdy); - int pid; - const bool b = torus; - if(b) - pid = decodeId(centerover->master); - else - decodeMaster(centerover->master, px, py); + int pvec = cellwalker_to_vec(centerover); int minsx = mindx-1, maxsx=maxdx+1, minsy=mindy-1, maxsy=maxdy+1; mindx=maxdx=mindy=maxdy=0; @@ -451,25 +451,16 @@ void drawEuclidean() { torusconfig::torus_cx = dx; torusconfig::torus_cy = dy; reclevel = eudist(dx, dy); - cell *c; - transmatrix Mat; - if(b) { - reclevel = eudist(dx, dy); - c = getTorusId(pid+torusconfig::dx*dx+torusconfig::dy*dy); - Mat = eumove(dx,dy); - } - else { - eucoord x = dx+px; - eucoord y = dy+py; - c = euclideanAt(x,y); - Mat = eumove(x, y); - } - if(!c) continue; + cellwalker cw = vec_to_cellwalker(pvec + euclid_getvec(dx, dy)); + transmatrix Mat = eumove(dx,dy); + + if(!cw.c) continue; + Mat = View0 * Mat; - if(torus) { + if(true) { ld locald = matrixnorm(Mat); - if(locald < centerd) centerd = locald, centerover = c, View = View0 * eumove(dx, dy); + if(locald < centerd) centerd = locald, centerover = cw, View = View0 * eumove(dx, dy); } // Mat[0][0] = -1; @@ -488,8 +479,8 @@ void drawEuclidean() { if(dy > maxdy) maxdy = dy; } if(cx >= -cellrad && cy >= -cellrad && cx < vid.xres+cellrad && cy < vid.yres+cellrad) - if(dodrawcell(c)) { - drawcell(c, Mat, 0, false); + if(dodrawcell(cw.c)) { + drawcell(cw.c, cw.mirrored ? Mat * Mirror : Mat, cw.spin, cw.mirrored); } } } @@ -596,7 +587,7 @@ void resetview() { if(!euclid) viewctr.h = cwt.c->master, viewctr.spin = cwt.spin; - else centerover = cwt.c; + else centerover = cwt; // SDL_LockSurface(s); // SDL_UnlockSurface(s); } diff --git a/landgen.cpp b/landgen.cpp index fa2f6563..cdad857b 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -324,8 +324,8 @@ void giantLandSwitch(cell *c, int d, cell *from) { c->wall = waCavefloor; } else if(euclid) { - eucoord x, y; - decodeMaster(c->master, x, y); + int x, y; + tie(x,y) = cell_to_pair(c); if(((y-2)&7) < 4) c->wall = waCavewall; else c->wall = waCavefloor; } @@ -407,10 +407,9 @@ void giantLandSwitch(cell *c, int d, cell *from) { v = hrand(100) < 25 ? 24 : 16; } else if(euclid) { - eucoord x, y; - decodeMaster(c->master, x, y); - int y0 = ((short)y) % 6; - if(y0<0) y0+=6; + int x, y; + tie(x,y) = cell_to_pair(c); + int y0 = gmod(y, 6); if(y0 == 3 || y0 == 4) v=24; else v=0; } else v = emeraldval(c); @@ -466,8 +465,8 @@ void giantLandSwitch(cell *c, int d, cell *from) { if(d==8) { if(torus) ; else if(euclid) { - eucoord x, y; - decodeMaster(c->master, x, y); + int x,y; + tie(x,y) = cell_to_pair(c); if(y&1) c->wall = waTrapdoor; else c->wall = waNone; } @@ -486,9 +485,9 @@ void giantLandSwitch(cell *c, int d, cell *from) { if(d==8) { if(torus) ; else if(euclid) { - eucoord x, y; - decodeMaster(c->master, x, y); - int dy = ((short)y)%3; if(dy<0) dy += 3; + int x,y; + tie(x,y) = cell_to_pair(c); + int dy = gmod(y, 3); if(dy == 1) c->wall = waVinePlant; } else { @@ -1033,9 +1032,9 @@ void giantLandSwitch(cell *c, int d, cell *from) { if(pid == torusconfig::qty*2/3) c->wall = waGrounded; } else if(euclid) { - eucoord x, y; - decodeMaster(c->master, x, y); - if(short(x+1)%3 == 0 && short(y)%3 == 0) { + int x,y; + tie(x,y) = cell_to_pair(c); + if((x+1)%3 == 0 && y%3 == 0) { if(hrand(100) < 50) c->wall = hrand(2) ? waCharged : waGrounded; } @@ -1043,8 +1042,8 @@ void giantLandSwitch(cell *c, int d, cell *from) { bool sand = false; for(int i=0; itype; i++) { createMov(c, i); - decodeMaster(c->mov[i]->master, x, y); - if(short(x+1)%3 == 0 && short(y)%3 == 0) sand = true; + tie(x,y) = cell_to_pair(c->mov[i]); + if((x+1)%3 == 0 && (y)%3 == 0) sand = true; } if(sand && hrand(100) < 20) c->wall = waSandstone; diff --git a/mapeditor.cpp b/mapeditor.cpp index 265391b2..1e1c47ba 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -102,7 +102,7 @@ namespace mapstream { save(fgeomextras[current_extra].current_prime_id); } } - addToQueue(bounded ? currentmap->gamestart() : cwt.c->master->c7); + addToQueue((bounded || euclid) ? currentmap->gamestart() : cwt.c->master->c7); for(int i=0; imaster; + if(centerover.c) viewctr.h = centerover.c->master; else viewctr.h = cwt.c->master; playermoved = false; dataFromHR(); @@ -690,7 +690,7 @@ namespace netgen { } if(uni == 's') { View = Id; - if(centerover) viewctr.h = centerover->master; + if(centerover.c) viewctr.h = centerover.c->master; else viewctr.h = cwt.c->master; playermoved = false; } diff --git a/pattern2.cpp b/pattern2.cpp index e3ffefc0..b745037b 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -3,25 +3,21 @@ // Copyright (C) 2011-2017 Zeno Rogue, see 'hyper.cpp' for details int eupattern(cell *c) { + int v = cell_to_vec(c); if(a4) { - if(torus) return (decodeId(c->master)*2) % 3; - eucoord x, y; - decodeMaster(c->master, x, y); + int x, y; + tie(x,y) = vec_to_pair(v); return ((x&1) + 2*(y&1)) % 3; } - if(torus) return (decodeId(c->master)*2) % 3; - eucoord x, y; - decodeMaster(c->master, x, y); - short z = (short(y+2*x))%3; - z %= 3; - if(z<0) z += 3; - return z; + else { + return gmod(v*2, 3); + } } int eupattern4(cell *c) { - if(torus) return 0; - eucoord x, y; - decodeMaster(c->master, x, y); + int v = cell_to_vec(c); + int x, y; + tie(x,y) = vec_to_pair(v); return (x&1) + ((y&1)) * 2; } @@ -58,14 +54,14 @@ unsigned bitmajority(unsigned a, unsigned b, unsigned c) { } int eufifty(cell *c) { - eucoord x, y; if(torus) { - if(c->land == laWildWest) return decodeId(c->master) % 37; - else return decodeId(c->master) % 27; + if(c->land == laWildWest) return cell_to_vec(c) % 37; + else return cell_to_vec(c) % 27; } - decodeMaster(c->master, x, y); - int ix = short(x) + 99999 + short(y); - int iy = short(y) + 99999; + int x, y; + tie(x,y) = cell_to_pair(c); + int ix = x + 99999 + y; + int iy = y + 99999; if(c->land == laWildWest) return (ix + iy * 26 + 28) % 37; else { @@ -314,12 +310,7 @@ int fieldval_uniq(cell *c) { return decodeId(c->master); } else if(euclid) { - eucoord x, y; - decodeMaster(c->master, x, y); - int i = (short int)(x) * torusconfig::dx + (short int)(y) * torusconfig::dy; - i %= torusconfig::qty; - if(i<0) i += torusconfig::qty; - return i; + return torusconfig::vec_to_id(cell_to_vec(c)); } if(ctof(c)) return c->master->fieldval/S7; else { diff --git a/rug.cpp b/rug.cpp index 43ecb13f..3c80135f 100644 --- a/rug.cpp +++ b/rug.cpp @@ -664,10 +664,10 @@ void preset(rugpoint *m) { double c2 = b->edges[k2].len/blen; double cz = (c1*c1-c2*c2+1) / 2; - double ch = sqrt(c2*c2 - cz*cz); + double ch = sqrt(c2*c2 - cz*cz + 1e-10); double az = (a1*a1-a2*a2+1) / 2; - double ah = sqrt(a2*a2 - az*az); + double ah = sqrt(a2*a2 - az*az + 1e-10); // c->h = a->h + (b->h-a->h) * cz + ch * ort hyperpoint ort = (c->flat - a->flat - cz * (b->flat-a->flat)) / ch; @@ -675,14 +675,17 @@ void preset(rugpoint *m) { // m->h = a->h + (b->h-a->h) * az - ah * ort hyperpoint res = a->flat + (b->flat-a->flat) * az - ah * ort; - for(int i=0; i<3; i++) h[i] += res[i]; + h += res; preset_points.emplace_back(hypot(blen * (ah+ch), blen * (az-cz)), c); q++; + + printf("A %lf %lf %lf %lf C %lf %lf %lf %lf\n", a1, a2, az, ah, c1, c2, cz, ch); } } - if(q>0) for(int i=0; i<3; i++) m->flat[i] = h[i]/q; + if(q>0) m->flat = h/q; + printf("preset (%d) -> %s\n", q, display(m->flat)); } ld sse(hyperpoint h) { @@ -1164,6 +1167,7 @@ void actDraw() { Uint8 *keystate = SDL_GetKeyState(NULL); int qm = 0; double alpha = (ticks - lastticks) / 1000.0; + alpha /= 2.5; lastticks = ticks; transmatrix t = Id; diff --git a/shmup.cpp b/shmup.cpp index 0c64a2c0..96adfc23 100644 --- a/shmup.cpp +++ b/shmup.cpp @@ -3328,19 +3328,11 @@ transmatrix &ggmatrix(cell *c) { if(t[2][2] == 0) { if(torus) { forCellIdEx(c2, i, c) - if(celldistance(c2, centerover) < celldistance(c, centerover)) + if(celldistance(c2, centerover.c) < celldistance(c, centerover.c)) t = ggmatrix(c2) * eumovedir(3+i); } else if(euclid) { - eucoord xh, yh, xc, yc; - decodeMaster(c->master, xh, yh); - decodeMaster(centerover->master, xc, yc); - short xd(xh-xc), yd(yh-yc); - t = gmatrix[centerover] * eumove(xd, yd); - /* printf("H[%d,%d] C[%d,%d] ", int(xh),int(yh), int(xc),int(yc)); - printf("%d,%d t = \n", xd, yd); display(t); - printf("gmatrix0 = \n"); - display(gmatrix0[c]); */ + t = gmatrix[centerover.c] * eumove(cell_to_vec(c) - cellwalker_to_vec(centerover)); } else t = actualV(viewctr, cview()) * calc_relative_matrix(c, viewctr.h); diff --git a/system.cpp b/system.cpp index 81ffc4f1..a60264d1 100644 --- a/system.cpp +++ b/system.cpp @@ -150,11 +150,11 @@ void initgame() { yendor::lastchallenge = yendor::challenge; yendor::init(2); - - for(int i=0; i<65536; i++) euland[i] = laNone; + clear_euland(specialland); + if(euclid && specialland == laPrincessQuest) { - cell *c = euclideanAtCreate(EPX, EPY); + cell *c = euclideanAtCreate(pair_to_vec(EPX, EPY)); princess::generating = true; c->land = laPalace; for(int j=BARLEV; j>=0; j--) setdist(c, j, NULL); diff --git a/textures.cpp b/textures.cpp index 23f2422d..b791fad8 100644 --- a/textures.cpp +++ b/textures.cpp @@ -641,7 +641,7 @@ void init_textureconfig() { addsaver(patterns::whichPattern, "pattern", 0); addsaver(patterns::subpattern_flags, "pattern flags", 0); - cell *ctr = euclid ? centerover : viewctr.h->c7; + cell *ctr = euclid ? centerover.c : viewctr.h->c7; si_save = patterns::getpatterninfo0(ctr); addsaver(si_save.id, "center type", 1); diff --git a/util.cpp b/util.cpp index 7c59976d..4c9662dc 100644 --- a/util.cpp +++ b/util.cpp @@ -55,6 +55,11 @@ int gcd(int i, int j) { return i ? gcd(j%i, i) : j; } +int gmod(int i, int j) { + i %= j; if(i<0) i += j; + return i; + } + // debug utilities extern FILE *debugfile; @@ -116,3 +121,6 @@ void profile_info() { #define profile_info() #endif +int whateveri, whateveri2; + +purehookset hooks_tests;