From 645a64e8c98f26d5d498448fb9c43259561127d3 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Tue, 4 Apr 2017 11:13:15 +0200 Subject: [PATCH] expansion, ctrl+E cheat, fix with distance calculation --- cell.cpp | 757 ++++++++++++--------- complex.cpp | 8 +- conformal.cpp | 14 +- dialogs.cpp | 46 +- game.cpp | 6 +- graph.cpp | 108 ++- heptagon.cpp | 9 +- hyperroid/app/src/main/AndroidManifest.xml | 2 +- init.cpp | 6 +- landgen.cpp | 8 +- mapeditor.cpp | 4 +- menus.cpp | 17 +- polygons.cpp | 4 +- rogueviz.cpp | 4 +- system.cpp | 133 ++-- 15 files changed, 684 insertions(+), 442 deletions(-) diff --git a/cell.cpp b/cell.cpp index 1798fda0..8df66e74 100644 --- a/cell.cpp +++ b/cell.cpp @@ -1,9 +1,10 @@ - // Hyperbolic Rogue -- cells // Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details // cells the game is played on +#define DEBMEM(x) // { x fflush(stdout); } + int fix6(int a) { return (a+96)% 6; } int fix7(int a) { return (a+420)%S7; } @@ -61,8 +62,260 @@ typedef unsigned short eucoord; #include +struct cdata { + int val[4]; + int bits; + }; + +// list all cells in distance at most maxdist, or until when maxcount cells are reached + +struct celllister { + vector lst; + vector tmps; + vector dists; + + bool listed(cell *c) { + return c->aitmp >= 0 && c->aitmp < size(lst) && lst[c->aitmp] == c; + } + + void add(cell *c, int d) { + if(listed(c)) return; + c->aitmp = size(lst); + tmps.push_back(c->aitmp); + lst.push_back(c); + dists.push_back(d); + } + + int getdist(cell *c) { return dists[c->aitmp]; } + + ~celllister() { + for(int i=0; iaitmp = tmps[i]; + } + + celllister(cell *orig, int maxdist, int maxcount, cell *breakon) { + lst.clear(); + tmps.clear(); + dists.clear(); + add(orig, 0); + cell *last = orig; + for(int i=0; i= maxcount || dists[i]+1 == maxdist) break; + last = lst[size(lst)-1]; + maxdist--; + } + } + } + }; + +// -- hrmap --- + +#include + +struct hrmap { + virtual heptagon *getOrigin() { return NULL; } + virtual cell *gamestart() { return getOrigin()->c7; } + virtual ~hrmap() { printf("removing %s\n", typeid(this).name()); }; + virtual vector& allcells() { return dcal; } + virtual void verify() { } + }; + +hrmap *currentmap; +vector allmaps; + +// --- auxiliary hyperbolic map for horocycles --- +struct hrmap_alternate : hrmap { + heptagon *origin; + hrmap_alternate(heptagon *o) { origin = o; } + ~hrmap_alternate() { clearfrom(origin); } + }; + +// --- hyperbolic geometry --- + +struct hrmap_hyperbolic : hrmap { + heptagon *origin; + hrmap_hyperbolic() { + origin = new heptagon; + heptagon& h = *origin; + h.s = hsOrigin; + h.emeraldval = 98; + h.zebraval = 40; + h.fiftyval = 0; + h.fieldval = 0; + h.rval0 = h.rval1 = 0; + h.cdata = NULL; + for(int i=0; i<7; i++) h.move[i] = NULL; + h.spintable = 0; + h.alt = NULL; + h.distance = 0; + h.c7 = newCell(7, origin); + } + heptagon *getOrigin() { return origin; } + ~hrmap_hyperbolic() { + DEBMEM ( verifycells(origin); ) + clearfrom(origin); + } + void verify() { verifycells(origin); } + }; + +// --- spherical geometry --- + +int spherecells() { + if(S7 == 5) return (elliptic?6:12); + if(S7 == 4) return (elliptic?3:6); + if(S7 == 3) return 4; + if(S7 == 2) return (elliptic?1:2); + if(S7 == 1) return 1; + return 12; + } + +struct hrmap_spherical : hrmap { + heptagon *dodecahedron[12]; + + hrmap_spherical() { + for(int i=0; imove[i] = dodecahedron[i+1]; + dodecahedron[0]->setspin(i, 0); + dodecahedron[i+1]->move[0] = dodecahedron[0]; + dodecahedron[i+1]->setspin(0, i); + + dodecahedron[i+1]->move[1] = dodecahedron[(i+S7-1)%S7+1]; + dodecahedron[i+1]->setspin(1, S7-1); + dodecahedron[i+1]->move[S7-1] = dodecahedron[(i+1)%S7+1]; + dodecahedron[i+1]->setspin(S7-1, 1); + + if(S7 == 5 && elliptic) { + dodecahedron[i+1]->move[2] = dodecahedron[(i+2)%S7+1]; + dodecahedron[i+1]->setspin(2, 3 + 8); + dodecahedron[i+1]->move[3] = dodecahedron[(i+3)%S7+1]; + dodecahedron[i+1]->setspin(3, 2 + 8); + } + + else if(S7 == 5) { + dodecahedron[6]->move[i] = dodecahedron[7+i]; + dodecahedron[6]->setspin(i, 0); + dodecahedron[7+i]->move[0] = dodecahedron[6]; + dodecahedron[7+i]->setspin(0, i); + + dodecahedron[i+7]->move[1] = dodecahedron[(i+4)%5+7]; + dodecahedron[i+7]->setspin(1, 4); + dodecahedron[i+7]->move[4] = dodecahedron[(i+1)%5+7]; + dodecahedron[i+7]->setspin(4, 1); + + dodecahedron[i+1]->move[2] = dodecahedron[7+(10-i)%5]; + dodecahedron[i+1]->setspin(2, 2); + dodecahedron[7+(10-i)%5]->move[2] = dodecahedron[1+i]; + dodecahedron[7+(10-i)%5]->setspin(2, 2); + + dodecahedron[i+1]->move[3] = dodecahedron[7+(9-i)%5]; + dodecahedron[i+1]->setspin(3, 3); + dodecahedron[7+(9-i)%5]->move[3] = dodecahedron[i+1]; + dodecahedron[7+(9-i)%5]->setspin(3, 3); + } + if(S7 == 4) { + dodecahedron[5]->move[3-i] = dodecahedron[i+1]; + dodecahedron[5]->setspin(3-i, 2); + dodecahedron[i+1]->move[2] = dodecahedron[5]; + dodecahedron[i+1]->setspin(2, 3-i); + } + } + } + + heptagon *getOrigin() { return dodecahedron[0]; } + + ~hrmap_spherical() { + for(int i=0; i (currentmap); + if(!s) return NULL; + return s->dodecahedron[i]; + } + +// --- euclidean geometry --- + cell*& euclideanAtCreate(eucoord x, eucoord y); +struct hrmap_euclidean : hrmap { + + cell *gamestart() { + return euclideanAtCreate(0,0); + } + + struct euclideanSlab { + cell* a[256][256]; + euclideanSlab() { + for(int y=0; y<256; y++) for(int x=0; x<256; x++) + a[y][x] = NULL; + } + ~euclideanSlab() { + for(int y=0; y<256; y++) for(int x=0; x<256; x++) + if(a[y][x]) delete a[y][x]; + } + }; + + euclideanSlab* euclidean[256][256]; + + hrmap_euclidean() { + for(int y=0; y<256; y++) for(int x=0; x<256; x++) + euclidean[y][x] = NULL; + } + + cell*& at(eucoord x, eucoord y) { + euclideanSlab*& slab = euclidean[y>>8][x>>8]; + if(!slab) slab = new hrmap_euclidean::euclideanSlab; + return slab->a[y&255][x&255]; + } + + map eucdata; + + ~hrmap_euclidean() { + for(int y=0; y<256; y++) for(int x=0; x<256; x++) + if(euclidean[y][x]) { + delete euclidean[y][x]; + euclidean[y][x] = NULL; + } + eucdata.clear(); + } + }; + union heptacoder { heptagon *h; struct { eucoord x; eucoord y; } c; @@ -79,6 +332,145 @@ heptagon* encodeMaster(eucoord x, eucoord y) { return u.h; } +// --- quotient geometry --- + +namespace quotientspace { + struct code { + int c[8]; + }; + + bool operator == (const code& c1, const code &c2) { + for(int i=0; i<8; i++) if(c1.c[i] != c2.c[i]) return false; + return true; + } + + bool operator < (const code& c1, const code &c2) { + for(int i=0; i<8; i++) if(c1.c[i] != c2.c[i]) return c1.c[i] < c2.c[i]; + return false; + } + + int cod(heptagon *h) { + return zebra40(h->c7); + } + + code get(heptspin hs) { + code res; + res.c[0] = cod(hs.h); + for(int i=1; i<8; i++) { + res.c[i] = cod(hsstep(hs, 0).h); + hs = hsspin(hs, 1); + } + return res; + } + + int rvadd = 0, rvdir = 1; + + int rv(int x) { return (rvadd+x*rvdir) % 7; } + +struct hrmap_quotient : hrmap { + + hrmap_hyperbolic base; + + vector celllist; + + cell *origin; + + map reachable; + vector bfsq; + + vector connections; + + void add(const heptspin& hs) { + code g = get(hs); + if(!reachable.count(g)) { + reachable[g] = bfsq.size(); + bfsq.push_back(hs); + add(hsspin(hs, 1)); + } + } + + vector allh; + + hrmap_quotient() { + + if(quotient == 2) { + connections = fp43.connections; + } + else { + heptspin hs; hs.h = base.origin; hs.spin = 0; + reachable.clear(); + bfsq.clear(); + connections.clear(); + add(hs); + + for(int i=0; i<(int)bfsq.size(); i++) { + hs = hsstep(bfsq[i], 0); + add(hs); + connections.push_back(reachable[get(hs)]); + } + + } + + int TOT = connections.size() / 7; + printf("heptagons = %d\n", TOT); + printf("all cells = %d\n", TOT*10/3); + if(!TOT) exit(1); + allh.resize(TOT); + for(int i=0; ialt = base.origin; + + for(int i=0; ialt = NULL; + } + if(true) { + h->s = hsOrigin; + h->emeraldval = 0; + h->zebraval = 0; + h->fiftyval = 0; + h->fieldval = 7*i; + h->rval0 = h->rval1 = 0; h->cdata = NULL; + h->distance = 0; + h->c7 = newCell(7, h); + } + for(int j=0; j<7; j++) { + h->move[rv(j)] = allh[connections[i*7+j]/7]; + h->setspin(rv(j), rv(connections[i*7+j]%7)); + } + } + + for(int i=0; iemeraldval = allh[i]->alt->emeraldval; + allh[i]->zebraval = allh[i]->alt->zebraval; + allh[i]->fiftyval = allh[i]->alt->fiftyval; + allh[i]->distance = allh[i]->alt->distance; + /* for(int j=0; j<7; j++) + allh[i]->move[j]->alt = createStep(allh[i]->alt, j); */ + } + + celllister cl(gamestart(), 100, 100000000, NULL); + celllist = cl.lst; + } + + heptagon *getOrigin() { return allh[0]; } + + ~hrmap_quotient() { + for(int i=0; i& allcells() { return celllist; } + }; + + }; + +// --- general --- + // very similar to createMove in heptagon.cpp cell *createMov(cell *c, int d) { @@ -193,32 +585,17 @@ void eumerge(cell* c1, cell *c2, int s1, int s2) { c2->mov[s2] = c1; tsetspin(c2->spintable, s2, s1); } -struct euclideanSlab { - cell* a[256][256]; - euclideanSlab() { - for(int y=0; y<256; y++) for(int x=0; x<256; x++) - a[y][x] = NULL; - } - ~euclideanSlab() { - for(int y=0; y<256; y++) for(int x=0; x<256; x++) - if(a[y][x]) delete a[y][x]; - } - }; - -euclideanSlab* euclidean[256][256]; - // map, cell*> euclidean; cell*& euclideanAt(eucoord x, eucoord y) { - euclideanSlab*& slab(euclidean[y>>8][x>>8]); - if(!slab) slab = new euclideanSlab; - return slab->a[y&255][x&255]; + hrmap_euclidean* euc = dynamic_cast (currentmap); + return euc->at(x, y); } cell*& euclideanAtCreate(eucoord x, eucoord y) { - cell*& c ( euclideanAt(x,y) ); + cell*& c = euclideanAt(x,y); if(!c) { - c = newCell(6, &origin); + c = newCell(6, NULL); c->master = encodeMaster(x,y); euclideanAt(x,y) = c; eumerge(c, euclideanAt(x+1,y), 0, 3); @@ -231,104 +608,20 @@ cell*& euclideanAtCreate(eucoord x, eucoord y) { return c; } -int spherecells() { - if(S7 == 5) return (elliptic?6:12); - if(S7 == 4) return (elliptic?3:6); - if(S7 == 3) return 4; - if(S7 == 2) return (elliptic?1:2); - if(S7 == 1) return 1; - return 12; - } - // initializer (also inits origin from heptagon.cpp) void initcells() { DEBB(DF_INIT, (debugfile,"initcells\n")); - if(sphere) { - for(int i=0; iemeraldval = } -#define DEBMEM(x) // { x fflush(stdout); } - void clearcell(cell *c) { if(!c) return; DEBMEM ( printf("c%d %p\n", c->type, c); ) @@ -380,7 +673,7 @@ void clearfrom(heptagon *at) { at->move[i] = NULL; } clearHexes(at); - if(at != &origin) delete at; + delete at; } //printf("maxq = %d\n", maxq); } @@ -400,11 +693,12 @@ void verifycell(cell *c) { } void verifycells(heptagon *at) { - for(int i=0; i<7; i++) if(at->move[i] && at->move[i]->move[at->spin(i)] && at->move[i]->move[at->spin(i)] != at) { + for(int i=0; imove[i] && at->move[i]->move[at->spin(i)] && at->move[i]->move[at->spin(i)] != at) { printf("hexmix error %p [%d s=%d] %p %p\n", at, i, at->spin(i), at->move[i], at->move[i]->move[at->spin(i)]); } - if(!sphere && !quotient) for(int i=0; i<7; i++) if(at->move[i] && at->spin(i) == 0 && at->move[i] != &origin) - verifycells(at->move[i]); + if(!sphere && !quotient) + for(int i=0; i<7; i++) if(at->move[i] && at->spin(i) == 0 && at->s != hsOrigin) + verifycells(at->move[i]); verifycell(at->c7); } @@ -807,12 +1101,6 @@ map spins; #define RVAL_MASK 0x10000000 #define DATA_MASK 0x20000000 -struct cdata { - int val[4]; - int bits; - }; - -map eucdata; cdata orig_cdata; void affect(cdata& d, short rv, signed char signum) { @@ -835,9 +1123,9 @@ void setHeptagonRval(heptagon *h) { cdata *getHeptagonCdata(heptagon *h) { if(h->cdata) return h->cdata; - if(sphere || quotient) h = &origin; + if(sphere || quotient) h = currentmap->gamestart()->master; - if(h == &origin) { + if(h == currentmap->gamestart()->master) { return h->cdata = new cdata(orig_cdata); } @@ -907,14 +1195,15 @@ cdata *getHeptagonCdata(heptagon *h) { cdata *getEuclidCdata(heptagon *h) { eucoord x, y; - if(eucdata.count(h)) return &(eucdata[h]); + hrmap_euclidean* euc = dynamic_cast (currentmap); + if(euc->eucdata.count(h)) return &(euc->eucdata[h]); decodeMaster(h, x, y); if(x == 0 && y == 0) { cdata xx; for(int i=0; i<4; i++) xx.val[i] = 0; xx.bits = 0; - return &(eucdata[h] = xx); + return &(euc->eucdata[h] = xx); } int ord = 1, bid = 0; while(!((x|y)&ord)) ord <<= 1, bid++; @@ -946,7 +1235,7 @@ cdata *getEuclidCdata(heptagon *h) { if(gbit) xx.bits |= (1<eucdata[h] = xx); } // impossible! @@ -981,52 +1270,6 @@ eLand getCLand(cell *c) { return land_scape[b & 31]; } -// list all cells in distance at most maxdist, or until when maxcount cells are reached - -struct celllister { - vector lst; - vector tmps; - vector dists; - - bool listed(cell *c) { - return c->aitmp >= 0 && c->aitmp < size(lst) && lst[c->aitmp] == c; - } - - void add(cell *c, int d) { - if(listed(c)) return; - c->aitmp = size(lst); - tmps.push_back(c->aitmp); - lst.push_back(c); - dists.push_back(d); - } - - int getdist(cell *c) { return dists[c->aitmp]; } - - ~celllister() { - for(int i=0; iaitmp = tmps[i]; - } - - celllister(cell *orig, int maxdist, int maxcount, cell *breakon) { - lst.clear(); - tmps.clear(); - dists.clear(); - add(orig, 0); - cell *last = orig; - for(int i=0; i= maxcount || dists[i]+1 == maxdist) break; - last = lst[size(lst)-1]; - maxdist--; - } - } - } - }; - cell *heptatdir(cell *c, int d) { if(d&1) { cell *c2 = createMov(c, d); @@ -1098,6 +1341,9 @@ int celldistance(cell *c1, cell *c2) { forCellEx(c, cl2) if(isNeighbor(c, cr1)) return d+2; forCellEx(c, cl1) if(isNeighbor(c, cr2)) return d+2; + forCellEx(ca, cl2) forCellEx(cb, cr1) if(isNeighbor(ca, cb)) return d+3; + forCellEx(ca, cl1) forCellEx(cb, cr2) if(isNeighbor(ca, cb)) return d+3; + int d1 = celldist(cl1), d2 = celldist(cl2); if(d1 >= d2) { @@ -1117,28 +1363,9 @@ int celldistance(cell *c1, cell *c2) { } } -void clearHyperbolicMemory() { - DEBMEM ( verifycells(&origin); ) - clearfrom(&origin); - for(int i=0; itype != 6) { int id = c->master->fiftyval; @@ -1187,133 +1398,3 @@ int getHemisphere(cell *c, int which) { } } -namespace quotientspace { - - vector allcells; - - struct code { - int c[8]; - }; - - bool operator == (const code& c1, const code &c2) { - for(int i=0; i<8; i++) if(c1.c[i] != c2.c[i]) return false; - return true; - } - - bool operator < (const code& c1, const code &c2) { - for(int i=0; i<8; i++) if(c1.c[i] != c2.c[i]) return c1.c[i] < c2.c[i]; - return false; - } - - map reachable; - vector bfsq; - - int cod(heptagon *h) { - return zebra40(h->c7); - } - - code get(heptspin hs) { - code res; - res.c[0] = cod(hs.h); - for(int i=1; i<8; i++) { - res.c[i] = cod(hsstep(hs, 0).h); - hs = hsspin(hs, 1); - } - return res; - } - - vector connections; - - int rvadd = 0, rvdir = 1; - - int rv(int x) { return (rvadd+x*rvdir) % 7; } // if(x) return 7-x; else return x; } - - void add(const heptspin& hs) { - code g = get(hs); - if(!reachable.count(g)) { - reachable[g] = bfsq.size(); - bfsq.push_back(hs); - add(hsspin(hs, 1)); - } - } - - vector allh; - - void clear() { - clearfrom(origin.alt); - for(int i=0; imove[i] = NULL; - origin.alt->c7 = newCell(7, origin.alt); - - for(int i=0; ialt = NULL; - h->s = hsOrigin; - h->emeraldval = 0; - h->zebraval = 0; - h->fiftyval = 0; - h->fieldval = 7*i; - h->rval0 = h->rval1 = 0; h->cdata = NULL; - h->distance = 0; - h->c7 = newCell(7, h); - } - for(int j=0; j<7; j++) { - h->move[rv(j)] = allh[connections[i*7+j]/7]; - h->setspin(rv(j), rv(connections[i*7+j]%7)); - } - } - - for(int i=0; iemeraldval = allh[i]->alt->emeraldval; - allh[i]->zebraval = allh[i]->alt->zebraval; - allh[i]->fiftyval = allh[i]->alt->fiftyval; - allh[i]->distance = allh[i]->alt->distance; - /* for(int j=0; j<7; j++) - allh[i]->move[j]->alt = createStep(allh[i]->alt, j); */ - } - - celllister cl(origin.c7, 100, 100000000, NULL); - allcells = cl.lst; - } - } - diff --git a/complex.cpp b/complex.cpp index fb35df3f..84c209d0 100644 --- a/complex.cpp +++ b/complex.cpp @@ -1600,7 +1600,7 @@ namespace heat { vinefires.clear(); rosefires.clear(); - vector& allcells = quotient ? quotientspace::allcells : dcal; + vector& allcells = currentmap->allcells(); int dcs = size(allcells); @@ -1760,7 +1760,7 @@ namespace heat { } void dryforest() { - vector& allcells = quotient ? quotientspace::allcells : dcal; + vector& allcells = currentmap->allcells(); int dcs = size(allcells); for(int i=0; i& allcells = quotient ? quotientspace::allcells : dcal; + vector& allcells = currentmap->allcells(); int dcs = size(allcells); vector bringlife; @@ -2708,7 +2708,7 @@ namespace ca { void simulate() { if(cwt.c->land != laCA) return; - vector& allcells = quotient ? quotientspace::allcells : dcal; + vector& allcells = currentmap->allcells(); int dcs = size(allcells); bool willlive[dcs]; for(int i=0; iat = Id; m->base = c; v.push_back(m); - if(c == origin.c7) break; + if(c == currentmap->gamestart()) break; for(int i=0; itype; i++) if(celldist(c->mov[i]) < celldist(c)) { c = c->mov[i]; @@ -586,12 +586,18 @@ namespace conformal { setvideomode(); } */ } - else if(sym == 'x' && pmodel == mdPolygonal) + else if(sym == 'x' && pmodel == mdPolygonal) { dialog::editNumber(polygonal::SI, 3, 10, 1, 4, XLAT("polygon sides"), ""); - else if(sym == 'y' && pmodel == mdPolygonal) + dialog::sidedialog = true; + } + else if(sym == 'y' && pmodel == mdPolygonal) { dialog::editNumber(polygonal::STAR, -1, 1, .1, 0, XLAT("star factor"), ""); - else if(sym == 'n' && pmodel == mdPolygonal) + dialog::sidedialog = true; + } + else if(sym == 'n' && pmodel == mdPolygonal) { dialog::editNumber(polygonal::deg, 2, MSI-1, 1, 2, XLAT("degree of the approximation"), ""); + dialog::sidedialog = true; + } else if(sym == 'x' && pmodel == mdPolynomial) { polygonal::maxcoef = max(polygonal::maxcoef, polygonal::coefid); int ci = polygonal::coefid + 1; diff --git a/dialogs.cpp b/dialogs.cpp index ed8a40f3..865e64dd 100644 --- a/dialogs.cpp +++ b/dialogs.cpp @@ -167,13 +167,20 @@ namespace dialog { addBreak(brk); } + int dcenter, dwidth; + + bool sidedialog; + int displayLong(string str, int siz, int y, bool measure) { int last = 0; int lastspace = 0; - int xs = vid.xres * 618/1000; - int xo = vid.xres * 186/1000; + int xs, xo; + if(sidescreen) + xs = dwidth - vid.fsize, xo = vid.xres + vid.fsize; + else + xs = vid.xres * 618/1000, xo = vid.xres * 186/1000; for(int i=0; i<=size(str); i++) { int ls = 0; @@ -196,7 +203,7 @@ namespace dialog { y += siz/2; return y; } - + int tothei, dialogwidth, dfsize, dfspace, leftwidth, rightwidth, innerwidth, itemx, keyx, valuex; string highlight_text; @@ -223,9 +230,9 @@ namespace dialog { int fwidth = innerwidth + leftwidth + rightwidth; dialogwidth = max(dialogwidth, fwidth); - itemx = (vid.xres - fwidth) / 2 + leftwidth; - keyx = (vid.xres - fwidth) / 2 + leftwidth - dfsize/2; - valuex = (vid.xres - fwidth) / 2 + leftwidth + innerwidth + dfsize/2; + itemx = dcenter - fwidth / 2 + leftwidth; + keyx = dcenter - fwidth / 2 + leftwidth - dfsize/2; + valuex = dcenter - fwidth / 2 + leftwidth + innerwidth + dfsize/2; } void display() { @@ -238,7 +245,16 @@ namespace dialog { dfsize *= 3; #endif dfspace = dfsize * 5/4; + + dcenter = vid.xres/2; + dwidth = vid.xres; measure(); + + if(sidescreen) { + dwidth = vid.xres - vid.yres; + dcenter = (vid.xres + dwidth) / 2; + } + while(tothei > vid.yres - 5 * vid.fsize) { int adfsize = int(dfsize * sqrt((vid.yres - 5. * vid.fsize) / tothei)); if(adfsize < dfsize-1) dfsize = adfsize + 1; @@ -246,7 +262,7 @@ namespace dialog { dfspace = dfsize * 5/4; measure(); } - while(dialogwidth > vid.xres) { + while(dialogwidth > dwidth) { int adfsize = int(dfsize * sqrt(vid.xres * 1. / dialogwidth)); if(adfsize < dfsize-1) dfsize = adfsize + 1; else dfsize--; // keep dfspace @@ -267,7 +283,7 @@ namespace dialog { tothei += dfspace * I.scale / 100; int mid = (top + tothei) / 2; if(I.type == diTitle || I.type == diInfo) { - displayfr(vid.xres/2, mid, 2, dfsize * I.scale/100, I.body, I.color, 8); + displayfr(dcenter, mid, 2, dfsize * I.scale/100, I.body, I.color, 8); } else if(I.type == diItem) { bool xthis = (mousey >= top && mousey < tothei); @@ -291,9 +307,15 @@ namespace dialog { } else if(I.type == diSlider) { bool xthis = (mousey >= top && mousey < tothei); - displayfr(vid.xres*1/4, mid, 2, dfsize * I.scale/100, "(", I.color, 16); - displayfr(vid.xres*1/4 + double(vid.xres/2 * I.param), mid, 2, dfsize * I.scale/100, "#", I.color, 8); - displayfr(vid.xres*3/4, mid, 2, dfsize * I.scale/100, ")", I.color, 0); + int sl, sr; + if(sidescreen) + sl = vid.yres + vid.fsize*2, sr = vid.xres - vid.fsize*2; + else + sl = vid.xres/4, sr = vid.xres*3/4; + int sw = sr-sl; + displayfr(sl, mid, 2, dfsize * I.scale/100, "(", I.color, 16); + displayfr(sl + double(sw * I.param), mid, 2, dfsize * I.scale/100, "#", I.color, 8); + displayfr(sr, mid, 2, dfsize * I.scale/100, ")", I.color, 0); if(xthis) getcstat = I.key, inslider = true; } } @@ -480,11 +502,13 @@ namespace dialog { ne.scale = ne.inverse_scale = identity; ne.intval = NULL; ne.positive = false; + sidedialog = false; } void editNumber(int& x, int vmin, int vmax, int step, int dft, string title, string help) { editNumber(ne.intbuf, vmin, vmax, step, dft, title, help); ne.intbuf = x; ne.intval = &x; ne.s = its(x); + sidedialog = true; } string disp(ld x) { if(ne.intval) return its((int) (x+.5)); else return fts(x); } diff --git a/game.cpp b/game.cpp index f7335487..4accb285 100644 --- a/game.cpp +++ b/game.cpp @@ -348,9 +348,9 @@ bool pseudohept(cell *c) { if(purehepta) { if(sphere) return - c->master == &dodecahedron[3] || - c->master == &dodecahedron[5] || - c->master == &dodecahedron[6]; + c->master == getDodecahedron(3) || + c->master == getDodecahedron(5) || + c->master == getDodecahedron(6); int z = zebra40(c); return z == 5 || z == 8 || z == 15; } diff --git a/graph.cpp b/graph.cpp index 8c0bc43c..c52af32d 100644 --- a/graph.cpp +++ b/graph.cpp @@ -2821,7 +2821,12 @@ bool bugsNearby(cell *c, int dist = 2) { int minecolors[8] = { 0xFFFFFF, 0xF0, 0xF060, 0xF00000, - 0x60, 0x600000, 0x00C0C0, 0 + 0x60, 0x600000, 0x00C0C0, 0x000000 + }; + +int distcolors[8] = { + 0xFFFFFF, 0xF0, 0xF060, 0xF00000, + 0xA0A000, 0xA000A0, 0x00A0A0, 0xFFD500 }; const char* minetexts[8] = { @@ -3012,6 +3017,8 @@ transmatrix pushone() { return euclid ? eupush(1, 0) : xpush(sphere?.5 : 1); } void drawMovementArrows(cell *c, transmatrix V) { + if(viewdists) return; + for(int d=0; d<8; d++) { movedir md = vectodir(spin(-d * M_PI/4) * tC0(pushone())); @@ -3725,7 +3732,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { ivoryz = isGravityLand(c->land); transmatrix& gm = gmatrix[c]; - bool orig = (gm[2][2] == 0 || fabs(gm[2][2]-1) >= fabs(V[2][2]-1)) - 1e-8; + bool orig = (gm[2][2] == 0 || fabs(gm[2][2]-1) >= fabs(V[2][2]-1) - 1e-8); if(sphere && vid.alpha > 1) { long double d = V[2][2]; @@ -3735,7 +3742,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { if(sphere && vid.alpha <= 1) { if(V[2][2] < -.8) return; } - + if(orig) gm = V; ld dist0 = hdist0(tC0(V)) - 1e-6; @@ -3859,6 +3866,19 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { int wcol, fcol, asciicol; setcolors(c, wcol, fcol); + + if(viewdists) { + int cd = celldistance(c, cwt.c); + string label = its(cd); + // string label = its(fieldpattern::getriverdistleft(c)) + its(fieldpattern::getriverdistright(c)); + int dc = distcolors[cd&7]; + wcol = gradient(wcol, dc, 0, .4, 1); + fcol = gradient(fcol, dc, 0, .4, 1); + /* queuepolyat(V, shFloor[ct6], darkena(gradient(0, distcolors[cd&7], 0, .25, 1), fd, 0xC0), + PPR_TEXT); */ + queuestr(V, (cd > 9 ? .6 : 1) * .2, label, 0xFF000000 + distcolors[cd&7], 1); + } + asciicol = wcol; if(c->land == laNone && c->wall == waNone) @@ -4316,12 +4336,6 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { #ifndef NOEDIT - if(viewdists) { - string label = its(celldistance(c, cwt.c)); - // string label = its(fieldpattern::getriverdistleft(c)) + its(fieldpattern::getriverdistright(c)); - queuestr(V, .5, label, 0xFFFFFFFF); - } - if(cmode == emMapEditor && mapeditor::displaycodes) { int labeli = mapeditor::displaycodes == 1 ? mapeditor::realpattern(c) : mapeditor::subpattern(c); @@ -4353,7 +4367,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { queuestr(V, .6, buf, col); #endif } - + if(realred(c->wall) && !wmspatial) { int s = snakelevel(c); if(s >= 1) @@ -5859,6 +5873,8 @@ void describeMouseover() { if(webdisplay & 8) { out += " LP:" + itsh(c->landparam)+"/"+its(turncount); + + out += " CD:" + its(celldist(c)); out += " D:" + its(c->mpdist); @@ -6375,6 +6391,8 @@ void centerpc(ld aspd) { void drawmovestar(double dx, double dy) { + if(viewdists) return; + DEBB(DF_GRAPH, (debugfile,"draw movestar\n")); if(!playerfound) return; @@ -6574,6 +6592,8 @@ void checkpanjoy(double t) { int realradius; +bool sidescreen; + void calcparam() { DEBB(DF_GRAPH, (debugfile,"calc param\n")); vid.xcenter = vid.xres / 2; @@ -6585,10 +6605,18 @@ void calcparam() { realradius = min(realradius, vid.radius); + sidescreen = false; + if(vid.xres < vid.yres) { vid.radius = int(vid.scale * vid.xcenter) - (ISIOS ? 10 : 2); vid.ycenter = vid.yres - realradius - vid.fsize - (ISIOS ? 10 : 0); } + else { + if(vid.xres >= vid.yres * 4/3 && dialog::sidedialog && cmode == emNumber) + sidescreen = true; + if(viewdists && cmode == emNormal && vid.xres >= vid.yres * 4/3) sidescreen = true; + if(sidescreen) vid.xcenter = vid.yres/2; + } ld eye = vid.eye; if(pmodel || rug::rugged) eye = 0; vid.beta = 1 + vid.alpha + eye; @@ -7069,6 +7097,42 @@ void drawStats() { #ifdef ROGUEVIZ if(rogueviz::on) return; #endif + if(viewdists && sidescreen) { + dialog::init(""); + int qty[64]; + vector& ac = currentmap->allcells(); + for(int i=0; i<64; i++) qty[i] = 0; + for(int i=0; i= 0 && d < 64) qty[d]++; + } + if(geometry == gNormal) + for(int i=purehepta?6:8; i<=15; i++) + qty[i] = + purehepta ? + 3*qty[i-1] - qty[i-2] + : qty[i-1] + qty[i-2] + qty[i-3] - qty[i-4]; + if(geometry == gEuclid) + for(int i=8; i<=15; i++) qty[i] = 6*i; + for(int i=0; i<64; i++) if(qty[i]) + dialog::addInfo(its(qty[i]), distcolors[i&7]); + if(geometry == gNormal && !purehepta) { + dialog::addBreak(200); + dialog::addInfo("a(d+4) = a(d+3) + a(d+2) + a(d+1) - a(d)", 0xFFFFFF); + dialog::addInfo("a(d) ~ 1.72208^d", 0xFFFFFF); + } + if(geometry == gNormal && purehepta) { + dialog::addBreak(200); + dialog::addInfo("a(d+2) = 3a(d+1) - a(d+2)", 0xFFFFFF); + dialog::addInfo("a(d) ~ 2.61803^d", 0xFFFFFF); + } + if(geometry == gEuclid) { + dialog::addBreak(300); + dialog::addInfo("a(n) = 6n", 0xFFFFFF); + } + dialog::display(); + } + if(sidescreen) return; instat = false; bool portrait = vid.xres < vid.yres; int colspace = portrait ? (vid.yres - vid.xres - vid.fsize*3) : (vid.xres - vid.yres - 16) / 2; @@ -7402,7 +7466,8 @@ void drawscreen() { if(cmode != emNormal && cmode != emDraw && cmode != emCustomizeChar) darken = 2; if(cmode == emQuit && !canmove) darken = 0; if(cmode == emOverview) darken = 16; - if(cmode == emNumber && dialog::lastmode == em3D) darken = 0; + + if(sidescreen) darken = 0; #ifndef NOEDIT if(cmode == emMapEditor && !mapeditor::subscreen && !mapeditor::choosefile) darken = 0; @@ -7581,17 +7646,20 @@ void setvideomode() { void restartGraph() { DEBB(DF_INIT, (debugfile,"restartGraph\n")); - if(euclid) { - centerover = euclideanAtCreate(0,0); - } - else { - viewctr.h = &origin; - viewctr.spin = 0; - viewctr.mirrored = false; - } + View = Id; webdisplay = 0; - if(sphere) View = spin(-M_PI/2); + if(currentmap) { + if(euclid) { + centerover = euclideanAtCreate(0,0); + } + else { + viewctr.h = currentmap->getOrigin(); + viewctr.spin = 0; + viewctr.mirrored = false; + } + if(sphere) View = spin(-M_PI/2); + } } void resetview() { diff --git a/heptagon.cpp b/heptagon.cpp index b6b53fb5..205f9379 100644 --- a/heptagon.cpp +++ b/heptagon.cpp @@ -95,11 +95,6 @@ hstate transition(hstate s, int dir) { return hsError; } -heptagon dodecahedron[12]; -#define origin (dodecahedron[0]) - -vector allAlts; - // create h->move[d] if not created yet heptagon *createStep(heptagon *h, int d); @@ -118,7 +113,7 @@ heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0) { h->zebraval = zebra_heptagon(parent->zebraval, d); h->fieldval = fp43.connections[fieldpattern::btspin(parent->fieldval, d)]; h->rval0 = h->rval1 = 0; h->cdata = NULL; - if(parent == &origin || parent == origin.alt) + if(parent->s == hsOrigin) h->fiftyval = fiftytable[0][d]; else h->fiftyval = nextfiftyval(parent->fiftyval, parent->move[0]->fiftyval, d); @@ -211,7 +206,7 @@ heptspin hsspin(const heptspin &hs, int val) { // display the coordinates of the heptagon void backtrace(heptagon *pos) { - if(pos == &origin) return; + if(pos->s == hsOrigin) return; backtrace(pos->move[0]); printf(" %d", pos->spin(0)); } diff --git a/hyperroid/app/src/main/AndroidManifest.xml b/hyperroid/app/src/main/AndroidManifest.xml index 64f6ef73..eca0e8a7 100644 --- a/hyperroid/app/src/main/AndroidManifest.xml +++ b/hyperroid/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ diff --git a/init.cpp b/init.cpp index 0c9af0ff..cb5e78d4 100644 --- a/init.cpp +++ b/init.cpp @@ -1,6 +1,6 @@ -#define VER "9.4d" -#define VERNUM 9404 -#define VERNUM_HEX 0x9404 +#define VER "9.4e" +#define VERNUM 9405 +#define VERNUM_HEX 0x9405 #define GEN_M 0 #define GEN_F 1 diff --git a/landgen.cpp b/landgen.cpp index 8cc7f3cd..0dd11416 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -4895,7 +4895,7 @@ void setdist(cell *c, int d, cell *from) { c->monst = moMonkey; else if(hrand(80000) < 5 + items[itRuby] + hard) c->monst = moEagle; - else if(ishept(c) && c != origin.c7 && hrand(4000) < 300 + items[itRuby] && !c->monst) { + else if(ishept(c) && c != currentmap->gamestart() && hrand(4000) < 300 + items[itRuby] && !c->monst) { int hardchance = items[itRuby] + hard; if(hardchance > 25) hardchance = 25; bool hardivy = hrand(100) < hardchance; @@ -5224,7 +5224,7 @@ bool haveOrbPower() { if(itemclass(c->item) == IC_ORB) return true; } else if(sphere) for(int i=0; ic7; if(itemclass(c->item) == IC_ORB) return true; forCellEx(c2, c) if(itemclass(c2->item) == IC_ORB) return true; } @@ -5233,7 +5233,7 @@ bool haveOrbPower() { bool haveKraken() { for(int i=0; ic7; if(c->monst == moKrakenH || c->monst == moKrakenT) return true; } return false; @@ -5617,7 +5617,7 @@ heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special) { } heptagon *alt = new heptagon; - allAlts.push_back(alt); + allmaps.push_back(new hrmap_alternate(alt)); //printf("new alt {%p}\n", alt); alt->s = firststate; alt->emeraldval = 0; diff --git a/mapeditor.cpp b/mapeditor.cpp index a2d36911..6275d846 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -155,7 +155,7 @@ namespace mapstream { int rspin; if(size(cellbyid) == 0) { - c = origin.c7; + c = currentmap->gamestart(); rspin = 0; } else { @@ -202,7 +202,7 @@ namespace mapstream { int32_t whereami = loadInt(); if(whereami >= 0 && whereami < size(cellbyid)) cwt.c = cellbyid[whereami]; - else cwt.c = origin.c7; + else cwt.c = currentmap->gamestart(); for(int i=0; igamestart(); cwt.spin = 0; cwt.mirrored = false; cwt.c->land = (euclid || sphere) ? euclidland : firstland; chaosAchieved = false; @@ -113,13 +113,12 @@ void initgame() { setdist(cwt.c, i, NULL); if(tactic::trailer) safety = false; - if(sphere) verifyDodecahedron(); - else verifycells(&origin); + currentmap->verify(); } if(quotient && generateAll(firstland)) { - for(int i=0; iallcells()); i++) + setdist(currentmap->allcells()[i], 8, NULL); } @@ -844,34 +843,85 @@ void loadsave() { } #endif -void restartGame(char switchWhat) { +namespace gamestack { + + struct gamedata { + hrmap *hmap; + cellwalker cwt; + heptspin viewctr; + transmatrix View; + eGeometry geometry; + }; + + vector gd; + + bool pushed() { return size(gd); } + + void push() { + if(geometry) { + printf("ERROR: push implemented only in non-hyperbolic geometry\n"); + exit(1); + } + gamedata gdn; + gdn.hmap = currentmap; + gdn.cwt = cwt; + gdn.viewctr = viewctr; + gdn.View = View; + gdn.geometry = geometry; + gd.push_back(gdn); + } + + void pop() { + gamedata& gdn = gd[size(gd)-1]; + currentmap = gdn.hmap; + cwt = gdn.cwt; + viewctr = gdn.viewctr; + View = gdn.View; + geometry = gdn.geometry; + resetGeometry(); + gd.pop_back(); + bfs(); + } + + }; + +void restartGame(char switchWhat, bool push) { DEBB(DF_INIT, (debugfile,"restartGame\n")); - achievement_final(true); -#ifndef NOSAVE - saveStats(); -#endif - for(int i=0; itype; i++) { - cell *c2 = cwt.c->mov[i]; - if(passable(c2, NULL, P_MONSTER)) { - eMonster mo[2] = { moRedTroll, moDarkTroll }; - c2->monst = mo[hrand(2)]; - } + if(geometry) { + restartGame(0, false); + } + else { + euclidland = cwt.c->land; + printf("target geometry = %d\n", targetgeometry); + restartGame('g', true); } return true; } @@ -1299,6 +1348,10 @@ bool applyCheat(char u, cell *c = NULL) { return true; } #ifdef LOCAL + if(u == 'K'-64) { + printf("viewctr = %p.%d\n", viewctr.h, viewctr.spin); + display(View); + } if(u == 'D'-64) { cheater = 0; autocheat = 0; return true;