1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-10-31 19:36:16 +00:00

big change: more configuration for the torus (and also Klein bottle)

This commit is contained in:
Zeno Rogue 2017-12-28 16:46:10 +01:00
parent d67ca714fd
commit 11569c693d
21 changed files with 546 additions and 287 deletions

View File

@ -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; i<max_vec; i++) euland[i] = laNone;
euland[0] = euland[1] = euland[max_vec-1] = first;
}
eLand switchable(eLand nearland, eLand farland, int c) {
if(specialland == laCrossroads4) { if(specialland == laCrossroads4) {
if(hrand(15) == 0) if(hrand(15) == 0)
return getNewLand(nearland); return getNewLand(nearland);
@ -755,37 +764,36 @@ eLand switchable(eLand nearland, eLand farland, eucoord c) {
} }
} }
eLand getEuclidLand(eucoord c) { eLand getEuclidLand(int c) {
if(euland[c]) return euland[c]; auto& la = get_euland(c);
if(c == 0 || c == eucoord(-1) || c == 1) if(la) return la;
return euland[c] = specialland; if(get_euland(c-2) && !get_euland(c-1)) getEuclidLand(c-1);
if(euland[eucoord(c-2)] && ! euland[eucoord(c-1)]) getEuclidLand(c-1); if(get_euland(c-1)) return
if(euland[eucoord(c+2)] && ! euland[eucoord(c+1)]) getEuclidLand(c+1); la = switchable(get_euland(c-1), get_euland(c-2), c);
if(euland[eucoord(c-1)]) return if(get_euland(c+2) && !get_euland(c+1)) getEuclidLand(c+1);
euland[c] = switchable(euland[c-1], euland[eucoord(c-2)], c); if(get_euland(c+1)) return
if(euland[eucoord(c+1)]) return la = switchable(get_euland(c+1), get_euland(c+2), c);
euland[c] = switchable(euland[c+1], euland[eucoord(c+2)], c); return la = laCrossroads;
return euland[c] = laCrossroads;
} }
void setLandEuclid(cell *c) { void setLandEuclid(cell *c) {
setland(c, specialland); setland(c, specialland);
if(specialland == laCrossroads) { if(specialland == laCrossroads) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
setland(c, getEuclidLand(y+2*x)); setland(c, getEuclidLand(y+2*x));
} }
if(specialland == laTerracotta) { if(specialland == laTerracotta) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
if((y+2*x) % 16 == 1) { if(((y+2*x) & 15) == 1) {
setland(c, laMercuryRiver); setland(c, laMercuryRiver);
c->wall = waMercury; c->wall = waMercury;
} }
} }
if(specialland == laCrossroads4) { if(specialland == laCrossroads4) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
c->land = getEuclidLand(y); c->land = getEuclidLand(y);
} }
if(specialland == laWhirlpool) { if(specialland == laWhirlpool) {
@ -794,30 +802,29 @@ void setLandEuclid(cell *c) {
} }
if(specialland == laPrincessQuest) setland(c, laPalace); if(specialland == laPrincessQuest) setland(c, laPalace);
if(specialland == laOcean) { if(specialland == laOcean) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
int y0 = y; if(y>50000) y0 -= 65536; y0 += 10; y += 10;
if(y0 == 0) if(y == 0)
{ setland(c, laBarrier); if(ishept(c)) c->land = laRlyeh; } { setland(c, laBarrier); if(ishept(c)) c->land = laRlyeh; }
else if(y0<0) setland(c, laRlyeh); else if(y<0) setland(c, laRlyeh);
else c->landparam = y0; else c->landparam = y;
} }
if(specialland == laIvoryTower || specialland == laDungeon) { if(specialland == laIvoryTower || specialland == laDungeon) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c); y -= 5;
int y0 = y; if(y>50000) y0 -= 65536; y0 = -y0; y0 -= 5; if(y == 0)
if(y0 == 0)
{setland(c, laBarrier); if(ishept(c)) setland(c, laAlchemist); } {setland(c, laBarrier); if(ishept(c)) setland(c, laAlchemist); }
else if(y0<0) setland(c, laAlchemist); else if(y<0) setland(c, laAlchemist);
else { else {
c->landparam = y0; c->landparam = y;
} }
} }
if(specialland == laElementalWall) { if(specialland == laElementalWall) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
int y0 = y; if(y>32768) y0 -= 65536; int x0 = x + (y>>1);
int x0 = x +y/2; int y0 = y;
int id = 0; int id = 0;
if(y0&16) id += 2; if(y0&16) id += 2;
@ -843,10 +850,10 @@ void setLandEuclid(cell *c) {
} }
} }
if(specialland == laCrossroads3) { if(specialland == laCrossroads3) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
int y0 = y; if(y>32768) y0 -= 65536; int y0 = y;
int x0 = x +y/2; int x0 = x + y/2;
x0 += 24; y0 += 8; x0 += 24; y0 += 8;
@ -862,11 +869,11 @@ void setLandEuclid(cell *c) {
} }
} }
if(specialland == laWarpCoast) { if(specialland == laWarpCoast) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
int zz = a4 ? short(x) : 2*short(x)+short(y) + 10; int zz = a4 ? x : 2*x+y + 10;
zz %= 30; if(zz<0) zz += 30; zz = gmod(zz, 30);
if(zz >= 15) if(zz >= 15)
setland(c, laWarpSea); setland(c, laWarpSea);
else else

357
cell.cpp
View File

@ -192,7 +192,20 @@ heptagon *getDodecahedron(int i) {
// --- euclidean geometry --- // --- 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<int, int> 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 { namespace torusconfig {
// the configuration of the torus topology. // the configuration of the torus topology.
@ -208,14 +221,176 @@ namespace torusconfig {
int def_qty = 127*3, dx = 1, def_dy = -11*2; int def_qty = 127*3, dx = 1, def_dy = -11*2;
int qty = def_qty, dy = def_dy; int qty = def_qty, dy = def_dy;
int sdx = 12, sdy = 12;
// new values to change // new values to change
int newqty, newdy; int newqty, newdy, newsdx, newsdy;
int torus_cx, torus_cy; 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<torusmode_info> 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<int, bool> 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<int,bool> (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); int decodeId(heptagon* h);
heptagon* encodeId(int id); 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<class T> 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 { struct hrmap_torus : hrmap {
vector<cell*> all; vector<cell*> all;
@ -229,25 +404,27 @@ struct hrmap_torus : hrmap {
hrmap_torus() { hrmap_torus() {
using namespace torusconfig; using namespace torusconfig;
all.resize(qty); int q = getqty();
for(int i=0; i<qty; i++) { all.resize(q);
all[i] = newCell(6, NULL); for(int i=0; i<q; i++) {
all[i]->master = encodeId(i); all[i] = newCell(8, encodeId(i));
} }
dx %= qty; for(int i=0; i<q; i++) {
dy %= qty; int iv = id_to_vec(i);
for(int i=0; i<qty; i++) { build_euclidean_moves(all[i], iv, [&] (int delta, int d, int d2) {
all[i]->mov[0] = all[(i+dx+2*qty)%qty]; auto im = vec_to_id_mirror(iv + delta);
all[i]->mov[1] = all[(i+dy+2*qty)%qty]; all[i]->mov[d] = all[im.first];
all[i]->mov[2] = all[(i+dy-dx+2*qty)%qty]; tsetspin(all[i]->spintable, d, im.second);
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(cell *c: all) for(int d=0; d<c->type; d++) {
for(int j=0; j<6; j++) cell *c2 = c->mov[d];
tsetspin(all[i]->spintable, j, (j+3) % 6); for(int d2=0; d2<c2->type; d2++)
if(c2->mov[d2] == c)
tsetspin(c->spintable, d, d2 + (8 * c->spin(d)));
} }
celllister cl(gamestart(), 100, 100000000, NULL); celllister cl(gamestart(), 100, 100000000, NULL);
dists.resize(qty); dists.resize(q);
for(int i=0; i<size(cl.lst); i++) for(int i=0; i<size(cl.lst); i++)
dists[decodeId(cl.lst[i]->master)] = cl.dists[i]; dists[decodeId(cl.lst[i]->master)] = 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() { hrmap_torus *torusmap() {
return dynamic_cast<hrmap_torus*> (currentmap); return dynamic_cast<hrmap_torus*> (currentmap);
} }
cell *getTorusId(int id) { /* cell *getTorusId(int id) {
hrmap_torus *cur = torusmap(); hrmap_torus *cur = torusmap();
if(!cur) return NULL; if(!cur) return NULL;
return cur->all[toridMod(id)]; return cur->all[id];
} } */
struct hrmap_euclidean : hrmap { struct hrmap_euclidean : hrmap {
cell *gamestart() { cell *gamestart() {
return euclideanAtCreate(0,0); return euclideanAtCreate(0);
} }
struct euclideanSlab { struct euclideanSlab {
@ -299,8 +469,10 @@ struct hrmap_euclidean : hrmap {
euclidean[y][x] = NULL; euclidean[y][x] = NULL;
} }
cell*& at(eucoord x, eucoord y) { cell*& at(int vec) {
euclideanSlab*& slab = euclidean[y>>8][x>>8]; 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; if(!slab) slab = new hrmap_euclidean::euclideanSlab;
return slab->a[y&255][x&255]; 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 { union heptacoder {
heptagon *h; heptagon *h;
struct { eucoord x; eucoord y; } c;
int id; 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) { int decodeId(heptagon* h) {
heptacoder u; heptacoder u;
u.h = h; return u.id; 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) { heptagon* encodeId(int id) {
heptacoder u; heptacoder u;
u.id = id; u.id = id;
@ -528,11 +713,10 @@ cell *createMov(cell *c, int d) {
} }
if(euclid && !c->mov[d]) { if(euclid && !c->mov[d]) {
eucoord x, y; int id = decodeId(c->master);
decodeMaster(c->master, x, y);
for(int dx=-1; dx<=1; dx++) for(int dx=-1; dx<=1; dx++)
for(int dy=-1; dy<=1; dy++) 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"); } if(!c->mov[d]) { printf("fail!\n"); }
} }
@ -597,43 +781,18 @@ void eumerge(cell* c1, cell *c2, int s1, int s2) {
// map<pair<eucoord, eucoord>, cell*> euclidean; // map<pair<eucoord, eucoord>, cell*> euclidean;
cell*& euclideanAt(eucoord x, eucoord y) { cell*& euclideanAt(int vec) {
if(torus) { printf("euclideanAt called\n"); exit(1); } if(torus) { printf("euclideanAt called\n"); exit(1); }
hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap); hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap);
return euc->at(x, y); return euc->at(vec);
} }
cell*& euclideanAtCreate(eucoord x, eucoord y) { cell*& euclideanAtCreate(int vec) {
cell*& c = euclideanAt(x,y); cell*& c = euclideanAt(vec);
if(!c) { if(!c) {
c = newCell(a4 ? (nontruncated || ((x^y^1) & 1) ? 4 : 8) : 6, NULL); c = newCell(8, encodeId(vec));
c->master = encodeMaster(x,y); euclideanAt(vec) = c;
euclideanAt(x,y) = c; build_euclidean_moves(c, vec, [c,vec] (int delta, int d, int d2) { eumerge(c, euclideanAt(vec + delta), d, d2); });
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);
}
} }
return c; return c;
} }
@ -735,7 +894,7 @@ void verifycells(heptagon *at) {
verifycell(at->c7); verifycell(at->c7);
} }
int eudist(short sx, short sy) { int eudist(int sx, int sy) {
int z0 = abs(sx); int z0 = abs(sx);
int z1 = abs(sy); int z1 = abs(sy);
if(a4) return z0 + z1; if(a4) return z0 + z1;
@ -743,6 +902,11 @@ int eudist(short sx, short sy) {
return max(max(z0,z1), z2); 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 compdist(int dx[]) {
int mi = dx[0]; int mi = dx[0];
for(int u=0; u<S3; u++) mi = min(mi, dx[u]); for(int u=0; u<S3; u++) mi = min(mi, dx[u]);
@ -764,9 +928,7 @@ int celldist(cell *c) {
if(euclid) { if(euclid) {
if(torus) if(torus)
return torusmap()->dists[decodeId(c->master)]; return torusmap()->dists[decodeId(c->master)];
eucoord x, y; return eudist(decodeId(c->master));
decodeMaster(c->master, x, y);
return eudist(x, y);
} }
if(sphere) return celldistance(c, currentmap->gamestart()); if(sphere) return celldistance(c, currentmap->gamestart());
if(ctof(c)) return c->master->distance; if(ctof(c)) return c->master->distance;
@ -787,8 +949,8 @@ int euclidAlt(short x, short y);
int celldistAlt(cell *c) { int celldistAlt(cell *c) {
if(euclid) { if(euclid) {
if(torus) return celldist(c); if(torus) return celldist(c);
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = vec_to_pair(decodeId(c->master));
return euclidAlt(x, y); return euclidAlt(x, y);
} }
if(sphere || quotient) { if(sphere || quotient) {
@ -1046,11 +1208,11 @@ cdata *getEuclidCdata(heptagon *h) {
return &xx; return &xx;
} }
eucoord x, y; int x, y;
hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap); hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap);
if(euc->eucdata.count(h)) return &(euc->eucdata[h]); 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) { if(x == 0 && y == 0) {
cdata xx; cdata xx;
@ -1062,14 +1224,14 @@ cdata *getEuclidCdata(heptagon *h) {
while(!((x|y)&ord)) ord <<= 1, bid++; while(!((x|y)&ord)) ord <<= 1, bid++;
for(int k=0; k<3; k++) { for(int k=0; k<3; k++) {
eucoord x1 = x + (k<2 ? ord : 0); int x1 = x + (k<2 ? ord : 0);
eucoord y1 = y - (k>0 ? ord : 0); int y1 = y - (k>0 ? ord : 0);
if((x1&ord) || (y1&ord)) continue; if((x1&ord) || (y1&ord)) continue;
eucoord x2 = x - (k<2 ? ord : 0); int x2 = x - (k<2 ? ord : 0);
eucoord y2 = y + (k>0 ? ord : 0); int y2 = y + (k>0 ? ord : 0);
cdata *d1 = getEuclidCdata(encodeMaster(x1,y1)); cdata *d1 = getEuclidCdata(encodeId(pair_to_vec(x1,y1)));
cdata *d2 = getEuclidCdata(encodeMaster(x2,y2)); cdata *d2 = getEuclidCdata(encodeId(pair_to_vec(x2,y2)));
cdata xx; cdata xx;
double disp = pow(2, bid/2.) * 6; double disp = pow(2, bid/2.) * 6;
@ -1134,11 +1296,8 @@ int celldistance(cell *c1, cell *c2) {
if(euclid) { if(euclid) {
if(torus) if(torus)
return torusmap()->dists[toridMod(decodeId(c1->master)-decodeId(c2->master))]; return torusmap()->dists[torusconfig::vec_to_id(decodeId(c1->master)-decodeId(c2->master))];
eucoord x1, y1, x2, y2; return eudist(decodeId(c1->master) - decodeId(c2->master));
decodeMaster(c1->master, x1, y1);
decodeMaster(c2->master, x2, y2);
return eudist(x1-x2, y1-y2);
} }
if(sphere || quotient == 1) { if(sphere || quotient == 1) {

View File

@ -1613,7 +1613,7 @@ geometryinfo ginf[gGUARD] = {
{"elliptic", "elliptic", 5, 3, qELLIP, gcSphere, {{SEE_ALL, SEE_ALL}}}, {"elliptic", "elliptic", 5, 3, qELLIP, gcSphere, {{SEE_ALL, SEE_ALL}}},
{"Zebra quotient", "Zebra", 7, 3, qZEBRA, gcHyperbolic, {{7, 5}}}, {"Zebra quotient", "Zebra", 7, 3, qZEBRA, gcHyperbolic, {{7, 5}}},
{"field quotient", "field", 7, 3, qFIELD, 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}}}, {"octagons", "oct", 8, 3, 0, gcHyperbolic, {{6, 4}}},
{"four pentagons", "4x5", 5, 4, 0, gcHyperbolic, {{6, 4}}}, {"four pentagons", "4x5", 5, 4, 0, gcHyperbolic, {{6, 4}}},
{"four hexagons", "4x6", 6, 4, 0, gcHyperbolic, {{5, 3}}}, {"four hexagons", "4x6", 6, 4, 0, gcHyperbolic, {{5, 3}}},

View File

@ -228,13 +228,27 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { showstartmenu
autocheat = true; autocheat = true;
currfp.init(p); currfp.init(p);
} }
else if(argis("-test"))
callhooks(hooks_tests);
else if(argis("-tpar")) { else if(argis("-tpar")) {
torusconfig::torus_mode = torusconfig::tmSingle;
shift(); sscanf(args(), "%d,%d,%d", shift(); sscanf(args(), "%d,%d,%d",
&torusconfig::qty, &torusconfig::qty,
&torusconfig::dx, &torusconfig::dx,
&torusconfig::dy &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")) { else if(argis("-cs")) {
shift(); shift();
fieldpattern::matrix M = currfp.strtomatrix(args()); fieldpattern::matrix M = currfp.strtomatrix(args());
@ -345,6 +359,14 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { showstartmenu
PHASEFROM(2); PHASEFROM(2);
shift(); whatever = argf(); resetGeometry(); 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")) { else if(argis("-rch")) {
PHASEFROM(2); PHASEFROM(2);
reptilecheat = true; autocheat = true; firstland = laReptile; reptilecheat = true; autocheat = true; firstland = laReptile;

View File

@ -12,8 +12,8 @@ namespace whirlwind {
int fzebra3(cell *c) { int fzebra3(cell *c) {
if(euclid) { if(euclid) {
if(torus) return 0; if(torus) return 0;
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
return 1+((((signed short)(y)+int(50000))/3)%3); return 1+((((signed short)(y)+int(50000))/3)%3);
} }
if(S7 == 5) return getHemisphere(c, 0) > 0 ? 1 : 2; if(S7 == 5) return getHemisphere(c, 0) > 0 ? 1 : 2;
@ -809,8 +809,9 @@ namespace clearing {
if(pseudohept(c)) return; if(pseudohept(c)) return;
c->monst = moMutant; c->monst = moMutant;
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
int xco = x * 2 + y + 1; int xco = x * 2 + y + 1;
c->stuntime = (8-xco/2) & 15; c->stuntime = (8-xco/2) & 15;
// 2, 4, 5, 7 // 2, 4, 5, 7
@ -2701,8 +2702,8 @@ namespace prairie {
c->LHU.fi.rval = 0; c->LHU.fi.rval = 0;
} }
else if(euclid) { else if(euclid) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
c->LHU.fi.rval = (y&15); c->LHU.fi.rval = (y&15);
} }
else if(sphere) { else if(sphere) {
@ -3391,8 +3392,8 @@ namespace dungeon {
if(euclid) { if(euclid) {
if(torus) return; if(torus) return;
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x, y) = cell_to_pair(c);
string tab[] = { string tab[] = {
".####...", ".####...",
"L...L...", "L...L...",

View File

@ -30,7 +30,8 @@ movedir joydir;
movedir mousedest; movedir mousedest;
ld shiftmul = 1; ld shiftmul = 1;
cell *mouseover, *mouseover2, *lmouseover, *centerover; cell *mouseover, *mouseover2, *lmouseover;
cellwalker centerover;
ld modist, modist2, centdist; ld modist, modist2, centdist;
int lastt; int lastt;
@ -340,7 +341,7 @@ void handleKeyNormal(int sym, int uni) {
// vid.yshift = 1 - vid.yshift; // vid.yshift = 1 - vid.yshift;
// vid.drawmousecircle = true; // vid.drawmousecircle = true;
} }
if(sym == 'm' && canmove && (centerover == cwt.c ? mouseover : centerover)) if(sym == 'm' && canmove && (centerover == cwt ? mouseover : centerover.c))
performMarkCommand(mouseover); performMarkCommand(mouseover);
} }
@ -351,9 +352,9 @@ void handleKeyNormal(int sym, int uni) {
if(sym == 't' && uni != 'T' && uni != 'T'-64 && canmove) { if(sym == 't' && uni != 'T' && uni != 'T'-64 && canmove) {
if(playermoved && items[itStrongWind]) { if(playermoved && items[itStrongWind]) {
cell *c = whirlwind::jumpDestination(cwt.c); 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; sym = 0; uni = 0;
} }
} }

View File

@ -5795,8 +5795,7 @@ void activateSafety(eLand l) {
firstland = l; firstland = l;
safetyland = l; safetyland = l;
safetyseed = time(NULL); safetyseed = time(NULL);
for(int i=0; i<65536; i++) euland[i] = laNone; clear_euland(firstland);
euland[0] = euland[1] = firstland;
safety = true; avengers = 0; safety = true; avengers = 0;
clearMemory(); clearMemory();
initcells(); initcells();

View File

@ -84,20 +84,76 @@ void showQuotientConfig() {
dialog::display(); dialog::display();
} }
bool torus_chamfer;
void showTorusConfig() { void showTorusConfig() {
cmode = sm::SIDE | sm::TORUSCONFIG; cmode = sm::SIDE | sm::TORUSCONFIG;
gamescreen(2); gamescreen(2);
dialog::init(XLAT("advanced configuration")); dialog::init(XLAT("advanced configuration"));
dialog::addSelItem(XLAT("number of cells (n)"), its(torusconfig::newqty), 'n'); auto& mode = torusconfig::tmodes[torusconfig::newmode];
dialog::addSelItem(XLAT("cell bottom-right from 0 (d)"), its(torusconfig::newdy), 'd');
if(torusconfig::newqty % 3) dialog::addSelItem(XLAT("mode"), XLAT(mode.name), 'm');
dialog::addInfo("best if n is divisible by 3", 0x808080);
if((torusconfig::newdy + 999999) % 3 != 2) bool single = (mode.flags & torusconfig::TF_SINGLE);
dialog::addInfo("best if d+1 is divisible by 3", 0x808080); 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(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'); dialog::addSelItem(XLAT("scale factor"), fts(vid.scale), 'z');
@ -108,22 +164,39 @@ void showTorusConfig() {
dialog::addItem("activate", 'a'); dialog::addItem("activate", 'a');
dialog::addItem("default", 'c'); dialog::addItem("default", 'c');
keyhandler = [] (int sym, int uni) { keyhandler = [=] (int sym, int uni) {
if(uni == 'n') 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)"), ""); dialog::editNumber(torusconfig::newqty, 0, 1000, 3, torusconfig::def_qty, XLAT("number of cells (n)"), "");
else if(uni == 'd') else if(uni == 'd' && single)
dialog::editNumber(torusconfig::newdy, -1000, 1000, 3, -torusconfig::def_dy, XLAT("cell bottom-right from 0 (d)"), ""); dialog::editNumber(torusconfig::newdy, -1000, 1000, 3, -torusconfig::def_dy, XLAT("cell below 0 (d)"), "");
else if((uni == 'a' || uni == '\n') && torusconfig::newqty >= 3 && abs(torusconfig::newdy) < torusconfig::newqty ) { else if(uni == 'x' && !single)
targetgeometry = gEuclid; restartGame('g'); 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::qty = torusconfig::newqty;
torusconfig::dy = torusconfig::newdy; 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') { 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::qty = torusconfig::def_qty;
torusconfig::dy = torusconfig::def_dy; torusconfig::dy = torusconfig::def_dy;
targetgeometry = gTorus; restartGame('g'); targetgeometry = gTorus; restartGame('g', false, true);
} }
else if(uni == 'z') editScale(); else if(uni == 'z') editScale();
#if CAP_RUG #if CAP_RUG
@ -263,6 +336,10 @@ void showEuclideanMenu() {
if(torus) if(torus)
torusconfig::newdy = torusconfig::dy, torusconfig::newdy = torusconfig::dy,
torusconfig::newqty = torusconfig::qty, torusconfig::newqty = torusconfig::qty,
torusconfig::newsdx = torusconfig::sdx,
torusconfig::newsdy = torusconfig::sdy,
torusconfig::newmode = torusconfig::torus_mode,
torus_chamfer = nontruncated,
pushScreen(showTorusConfig); pushScreen(showTorusConfig);
if(quotient==2) pushScreen(showQuotientConfig); if(quotient==2) pushScreen(showQuotientConfig);
} }

View File

@ -3284,12 +3284,12 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
mouseover2 = c; mouseover2 = c;
} }
if(!torus) { if(!euclid) {
double dfc = euclid ? intval(VC0, C0) : VC0[2]; double dfc = euclid ? intval(VC0, C0) : VC0[2];
if(dfc < centdist) { if(dfc < centdist) {
centdist = dfc; 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) { if(cmode & sm::TORUSCONFIG) {
using namespace torusconfig; using namespace torusconfig;
int cd = torus_cx * dx + torus_cy * newdy; string label;
cd %= newqty; if(cd<0) cd += newqty; bool small;
string label = its(cd); if(tmflags() & TF_SINGLE) {
queuestr(V, cd ? .2 : .6, label, cd == 0 ? 0xFFFF0040 : 0xFFFFFFD0, 1); 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; asciicol = wcol;
@ -4744,8 +4753,8 @@ void drawMarkers() {
#if CAP_MODEL #if CAP_MODEL
m = netgen::mode == 0; m = netgen::mode == 0;
#endif #endif
if(centerover && !playermoved && m && !conformal::on) if(centerover.c && !playermoved && m && !conformal::on)
queuecircleat(centerover, .70 - .06 * sin(ticks/200.0), queuecircleat(centerover.c, .70 - .06 * sin(ticks/200.0),
darkena(int(175 + 25 * sin(ticks / 200.0)), 0, 0xFF)); darkena(int(175 + 25 * sin(ticks / 200.0)), 0, 0xFF));
if(multi::players > 1 || multi::alwaysuse) for(int i=0; i<numplayers(); i++) { if(multi::players > 1 || multi::alwaysuse) for(int i=0; i<numplayers(); i++) {
@ -4925,7 +4934,7 @@ void drawthemap() {
modist2 = 1e20; mouseover2 = NULL; modist2 = 1e20; mouseover2 = NULL;
centdist = 1e20; centdist = 1e20;
if(!torus) centerover = NULL; if(!euclid) centerover.c = NULL;
for(int i=0; i<multi::players; i++) { for(int i=0; i<multi::players; i++) {
multi::ccdist[i] = 1e20; multi::ccat[i] = NULL; multi::ccdist[i] = 1e20; multi::ccat[i] = NULL;
@ -5406,7 +5415,7 @@ void restartGraph() {
linepatterns::clearAll(); linepatterns::clearAll();
if(currentmap) { if(currentmap) {
if(euclid) { if(euclid) {
centerover = torus ? getTorusId(0) : euclideanAtCreate(0,0); centerover = vec_to_cellwalker(0);
} }
else { else {
viewctr.h = currentmap->getOrigin(); viewctr.h = currentmap->getOrigin();
@ -5419,7 +5428,7 @@ void restartGraph() {
auto graphcm = addHook(clearmemory, 0, [] () { auto graphcm = addHook(clearmemory, 0, [] () {
DEBB(DF_INIT, (debugfile,"clear graph memory\n")); DEBB(DF_INIT, (debugfile,"clear graph memory\n"));
mouseover = centerover = lmouseover = NULL; mouseover = centerover.c = lmouseover = NULL;
for(int i=0; i<ANIMLAYERS; i++) animations[i].clear(); for(int i=0; i<ANIMLAYERS; i++) animations[i].clear();
gmatrix.clear(); gmatrix0.clear(); gmatrix.clear(); gmatrix0.clear();
flashes.clear(); flashes.clear();
@ -5505,7 +5514,7 @@ void drawBug(const cellwalker& cw, int col) {
} }
cell *viewcenter() { cell *viewcenter() {
if(euclid) return centerover; if(euclid) return centerover.c;
else return viewctr.h->c7; else return viewctr.h->c7;
} }

View File

@ -650,7 +650,7 @@ int windtotal;
void describeMouseover() { void describeMouseover() {
DEBB(DF_GRAPH, (debugfile,"describeMouseover\n")); DEBB(DF_GRAPH, (debugfile,"describeMouseover\n"));
cell *c = mousing ? mouseover : playermoved ? NULL : centerover; cell *c = mousing ? mouseover : playermoved ? NULL : centerover.c;
string& out = mouseovers; string& out = mouseovers;
if(!c || instat || getcstat != '-') { } if(!c || instat || getcstat != '-') { }
else if(c->wall != waInvisibleFloor) { else if(c->wall != waInvisibleFloor) {
@ -701,12 +701,10 @@ void describeMouseover() {
out += " " + describeRPM(c->land); out += " " + describeRPM(c->land);
if(euclid && cheater) { if(euclid && cheater) {
if(torus) { out += " ("+its(cell_to_vec(c))+")";
out += " ("+its(decodeId(c->master))+")"; if(!torus || torusconfig::torus_mode != torusconfig::tmSingle) {
} int x, y;
else { tie(x,y) = cell_to_pair(c);
eucoord x, y;
decodeMaster(c->master, x, y);
out += " ("+its(short(x))+","+its(short(y))+")"; out += " ("+its(short(x))+","+its(short(y))+")";
} }
} }

13
hyper.h
View File

@ -541,7 +541,7 @@ void drawCircle(int x, int y, int size, int color);
void fixcolor(int& col); void fixcolor(int& col);
int displaydir(cell *c, int d); int displaydir(cell *c, int d);
hyperpoint gethyper(ld x, ld y); 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 drawthemap();
void drawfullmap(); void drawfullmap();
bool displaystr(int x, int y, int shift, int size, const char *str, int color, int align); 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 coastval(cell *c, eLand base);
int getHauntedDepth(cell *c); int getHauntedDepth(cell *c);
eLand randomElementalLand(); eLand randomElementalLand();
extern eLand euland[65536];
bool notDippingForExtra(eItem i, eItem x); bool notDippingForExtra(eItem i, eItem x);
void placePrizeOrb(cell *c); void placePrizeOrb(cell *c);
void wandering(); void wandering();
@ -1388,6 +1387,7 @@ void movecost(cell* from, cell *to);
void checkmove(); void checkmove();
transmatrix eumove(ld x, ld y); transmatrix eumove(ld x, ld y);
transmatrix eumove(int vec);
transmatrix eumovedir(int d); transmatrix eumovedir(int d);
int reptilemax(); int reptilemax();
@ -1690,7 +1690,7 @@ template<class T, class U> int addHook(hookset<T>*& m, int prio, const U& hook)
return 0; return 0;
} }
extern purehookset hooks_frame, hooks_stats, clearmemory, hooks_config; extern purehookset hooks_frame, hooks_stats, clearmemory, hooks_config, hooks_tests;
template<class T, class... U> void callhooks(hookset<T> *h, U... args) { template<class T, class... U> void callhooks(hookset<T> *h, U... args) {
if(h) for(auto& p: *h) p.second(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); hrmap *newAltMap(heptagon *o);
#define currfp fieldpattern::getcurrfp() #define currfp fieldpattern::getcurrfp()
@ -2423,3 +2420,7 @@ transmatrix cview();
extern string truncatenames[2]; extern string truncatenames[2];
extern bool need_mouseh; extern bool need_mouseh;
extern int whateveri, whateveri2;
void clear_euland(eLand first);

View File

@ -395,6 +395,12 @@ transmatrix eumove(ld x, ld y) {
return Mat; return Mat;
} }
transmatrix eumove(int vec) {
int x, y;
tie(x,y) = vec_to_pair(vec);
return eumove(x, y);
}
transmatrix eumovedir(int d) { transmatrix eumovedir(int d) {
if(a4) { if(a4) {
d = d & 3; d = d & 3;
@ -426,16 +432,10 @@ ld matrixnorm(const transmatrix& Mat) {
void drawEuclidean() { void drawEuclidean() {
DEBB(DF_GRAPH, (debugfile,"drawEuclidean\n")); DEBB(DF_GRAPH, (debugfile,"drawEuclidean\n"));
sphereflip = Id; sphereflip = Id;
eucoord px=0, py=0; if(!centerover.c) centerover = cwt;
if(!centerover) centerover = cwt.c;
// printf("centerover = %p player = %p [%d,%d]-[%d,%d]\n", lcenterover, cwt.c, // printf("centerover = %p player = %p [%d,%d]-[%d,%d]\n", lcenterover, cwt.c,
// mindx, mindy, maxdx, maxdy); // mindx, mindy, maxdx, maxdy);
int pid; int pvec = cellwalker_to_vec(centerover);
const bool b = torus;
if(b)
pid = decodeId(centerover->master);
else
decodeMaster(centerover->master, px, py);
int minsx = mindx-1, maxsx=maxdx+1, minsy=mindy-1, maxsy=maxdy+1; int minsx = mindx-1, maxsx=maxdx+1, minsy=mindy-1, maxsy=maxdy+1;
mindx=maxdx=mindy=maxdy=0; mindx=maxdx=mindy=maxdy=0;
@ -451,25 +451,16 @@ void drawEuclidean() {
torusconfig::torus_cx = dx; torusconfig::torus_cx = dx;
torusconfig::torus_cy = dy; torusconfig::torus_cy = dy;
reclevel = eudist(dx, dy); reclevel = eudist(dx, dy);
cell *c; cellwalker cw = vec_to_cellwalker(pvec + euclid_getvec(dx, dy));
transmatrix Mat; transmatrix Mat = eumove(dx,dy);
if(b) {
reclevel = eudist(dx, dy); if(!cw.c) continue;
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;
Mat = View0 * Mat; Mat = View0 * Mat;
if(torus) { if(true) {
ld locald = matrixnorm(Mat); 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; // Mat[0][0] = -1;
@ -488,8 +479,8 @@ void drawEuclidean() {
if(dy > maxdy) maxdy = dy; if(dy > maxdy) maxdy = dy;
} }
if(cx >= -cellrad && cy >= -cellrad && cx < vid.xres+cellrad && cy < vid.yres+cellrad) if(cx >= -cellrad && cy >= -cellrad && cx < vid.xres+cellrad && cy < vid.yres+cellrad)
if(dodrawcell(c)) { if(dodrawcell(cw.c)) {
drawcell(c, Mat, 0, false); drawcell(cw.c, cw.mirrored ? Mat * Mirror : Mat, cw.spin, cw.mirrored);
} }
} }
} }
@ -596,7 +587,7 @@ void resetview() {
if(!euclid) if(!euclid)
viewctr.h = cwt.c->master, viewctr.h = cwt.c->master,
viewctr.spin = cwt.spin; viewctr.spin = cwt.spin;
else centerover = cwt.c; else centerover = cwt;
// SDL_LockSurface(s); // SDL_LockSurface(s);
// SDL_UnlockSurface(s); // SDL_UnlockSurface(s);
} }

View File

@ -324,8 +324,8 @@ void giantLandSwitch(cell *c, int d, cell *from) {
c->wall = waCavefloor; c->wall = waCavefloor;
} }
else if(euclid) { else if(euclid) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
if(((y-2)&7) < 4) c->wall = waCavewall; if(((y-2)&7) < 4) c->wall = waCavewall;
else c->wall = waCavefloor; else c->wall = waCavefloor;
} }
@ -407,10 +407,9 @@ void giantLandSwitch(cell *c, int d, cell *from) {
v = hrand(100) < 25 ? 24 : 16; v = hrand(100) < 25 ? 24 : 16;
} }
else if(euclid) { else if(euclid) {
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
int y0 = ((short)y) % 6; int y0 = gmod(y, 6);
if(y0<0) y0+=6;
if(y0 == 3 || y0 == 4) v=24; else v=0; if(y0 == 3 || y0 == 4) v=24; else v=0;
} }
else v = emeraldval(c); else v = emeraldval(c);
@ -466,8 +465,8 @@ void giantLandSwitch(cell *c, int d, cell *from) {
if(d==8) { if(d==8) {
if(torus) ; if(torus) ;
else if(euclid) { else if(euclid) {
eucoord x, y; int x,y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
if(y&1) c->wall = waTrapdoor; if(y&1) c->wall = waTrapdoor;
else c->wall = waNone; else c->wall = waNone;
} }
@ -486,9 +485,9 @@ void giantLandSwitch(cell *c, int d, cell *from) {
if(d==8) { if(d==8) {
if(torus) ; if(torus) ;
else if(euclid) { else if(euclid) {
eucoord x, y; int x,y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
int dy = ((short)y)%3; if(dy<0) dy += 3; int dy = gmod(y, 3);
if(dy == 1) c->wall = waVinePlant; if(dy == 1) c->wall = waVinePlant;
} }
else { else {
@ -1033,9 +1032,9 @@ void giantLandSwitch(cell *c, int d, cell *from) {
if(pid == torusconfig::qty*2/3) c->wall = waGrounded; if(pid == torusconfig::qty*2/3) c->wall = waGrounded;
} }
else if(euclid) { else if(euclid) {
eucoord x, y; int x,y;
decodeMaster(c->master, x, y); tie(x,y) = cell_to_pair(c);
if(short(x+1)%3 == 0 && short(y)%3 == 0) { if((x+1)%3 == 0 && y%3 == 0) {
if(hrand(100) < 50) if(hrand(100) < 50)
c->wall = hrand(2) ? waCharged : waGrounded; c->wall = hrand(2) ? waCharged : waGrounded;
} }
@ -1043,8 +1042,8 @@ void giantLandSwitch(cell *c, int d, cell *from) {
bool sand = false; bool sand = false;
for(int i=0; i<c->type; i++) { for(int i=0; i<c->type; i++) {
createMov(c, i); createMov(c, i);
decodeMaster(c->mov[i]->master, x, y); tie(x,y) = cell_to_pair(c->mov[i]);
if(short(x+1)%3 == 0 && short(y)%3 == 0) sand = true; if((x+1)%3 == 0 && (y)%3 == 0) sand = true;
} }
if(sand && hrand(100) < 20) if(sand && hrand(100) < 20)
c->wall = waSandstone; c->wall = waSandstone;

View File

@ -102,7 +102,7 @@ namespace mapstream {
save(fgeomextras[current_extra].current_prime_id); 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; i<size(cellbyid); i++) { for(int i=0; i<size(cellbyid); i++) {
cell *c = cellbyid[i]; cell *c = cellbyid[i];
if(i) { if(i) {

View File

@ -674,7 +674,7 @@ namespace netgen {
} }
if(!created) { if(!created) {
View = Id; View = Id;
if(centerover) viewctr.h = centerover->master; if(centerover.c) viewctr.h = centerover.c->master;
else viewctr.h = cwt.c->master; else viewctr.h = cwt.c->master;
playermoved = false; playermoved = false;
dataFromHR(); dataFromHR();
@ -690,7 +690,7 @@ namespace netgen {
} }
if(uni == 's') { if(uni == 's') {
View = Id; View = Id;
if(centerover) viewctr.h = centerover->master; if(centerover.c) viewctr.h = centerover.c->master;
else viewctr.h = cwt.c->master; else viewctr.h = cwt.c->master;
playermoved = false; playermoved = false;
} }

View File

@ -3,25 +3,21 @@
// Copyright (C) 2011-2017 Zeno Rogue, see 'hyper.cpp' for details // Copyright (C) 2011-2017 Zeno Rogue, see 'hyper.cpp' for details
int eupattern(cell *c) { int eupattern(cell *c) {
int v = cell_to_vec(c);
if(a4) { if(a4) {
if(torus) return (decodeId(c->master)*2) % 3; int x, y;
eucoord x, y; tie(x,y) = vec_to_pair(v);
decodeMaster(c->master, x, y);
return ((x&1) + 2*(y&1)) % 3; return ((x&1) + 2*(y&1)) % 3;
} }
if(torus) return (decodeId(c->master)*2) % 3; else {
eucoord x, y; return gmod(v*2, 3);
decodeMaster(c->master, x, y); }
short z = (short(y+2*x))%3;
z %= 3;
if(z<0) z += 3;
return z;
} }
int eupattern4(cell *c) { int eupattern4(cell *c) {
if(torus) return 0; int v = cell_to_vec(c);
eucoord x, y; int x, y;
decodeMaster(c->master, x, y); tie(x,y) = vec_to_pair(v);
return (x&1) + ((y&1)) * 2; return (x&1) + ((y&1)) * 2;
} }
@ -58,14 +54,14 @@ unsigned bitmajority(unsigned a, unsigned b, unsigned c) {
} }
int eufifty(cell *c) { int eufifty(cell *c) {
eucoord x, y;
if(torus) { if(torus) {
if(c->land == laWildWest) return decodeId(c->master) % 37; if(c->land == laWildWest) return cell_to_vec(c) % 37;
else return decodeId(c->master) % 27; else return cell_to_vec(c) % 27;
} }
decodeMaster(c->master, x, y); int x, y;
int ix = short(x) + 99999 + short(y); tie(x,y) = cell_to_pair(c);
int iy = short(y) + 99999; int ix = x + 99999 + y;
int iy = y + 99999;
if(c->land == laWildWest) if(c->land == laWildWest)
return (ix + iy * 26 + 28) % 37; return (ix + iy * 26 + 28) % 37;
else { else {
@ -314,12 +310,7 @@ int fieldval_uniq(cell *c) {
return decodeId(c->master); return decodeId(c->master);
} }
else if(euclid) { else if(euclid) {
eucoord x, y; return torusconfig::vec_to_id(cell_to_vec(c));
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;
} }
if(ctof(c)) return c->master->fieldval/S7; if(ctof(c)) return c->master->fieldval/S7;
else { else {

12
rug.cpp
View File

@ -664,10 +664,10 @@ void preset(rugpoint *m) {
double c2 = b->edges[k2].len/blen; double c2 = b->edges[k2].len/blen;
double cz = (c1*c1-c2*c2+1) / 2; 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 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 // c->h = a->h + (b->h-a->h) * cz + ch * ort
hyperpoint ort = (c->flat - a->flat - cz * (b->flat-a->flat)) / ch; 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 // m->h = a->h + (b->h-a->h) * az - ah * ort
hyperpoint res = a->flat + (b->flat-a->flat) * 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); preset_points.emplace_back(hypot(blen * (ah+ch), blen * (az-cz)), c);
q++; 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) { ld sse(hyperpoint h) {
@ -1164,6 +1167,7 @@ void actDraw() {
Uint8 *keystate = SDL_GetKeyState(NULL); Uint8 *keystate = SDL_GetKeyState(NULL);
int qm = 0; int qm = 0;
double alpha = (ticks - lastticks) / 1000.0; double alpha = (ticks - lastticks) / 1000.0;
alpha /= 2.5;
lastticks = ticks; lastticks = ticks;
transmatrix t = Id; transmatrix t = Id;

View File

@ -3328,19 +3328,11 @@ transmatrix &ggmatrix(cell *c) {
if(t[2][2] == 0) { if(t[2][2] == 0) {
if(torus) { if(torus) {
forCellIdEx(c2, i, c) 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); t = ggmatrix(c2) * eumovedir(3+i);
} }
else if(euclid) { else if(euclid) {
eucoord xh, yh, xc, yc; t = gmatrix[centerover.c] * eumove(cell_to_vec(c) - cellwalker_to_vec(centerover));
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]); */
} }
else else
t = actualV(viewctr, cview()) * calc_relative_matrix(c, viewctr.h); t = actualV(viewctr, cview()) * calc_relative_matrix(c, viewctr.h);

View File

@ -151,10 +151,10 @@ void initgame() {
yendor::init(2); yendor::init(2);
for(int i=0; i<65536; i++) euland[i] = laNone; clear_euland(specialland);
if(euclid && specialland == laPrincessQuest) { if(euclid && specialland == laPrincessQuest) {
cell *c = euclideanAtCreate(EPX, EPY); cell *c = euclideanAtCreate(pair_to_vec(EPX, EPY));
princess::generating = true; princess::generating = true;
c->land = laPalace; c->land = laPalace;
for(int j=BARLEV; j>=0; j--) setdist(c, j, NULL); for(int j=BARLEV; j>=0; j--) setdist(c, j, NULL);

View File

@ -641,7 +641,7 @@ void init_textureconfig() {
addsaver(patterns::whichPattern, "pattern", 0); addsaver(patterns::whichPattern, "pattern", 0);
addsaver(patterns::subpattern_flags, "pattern flags", 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); si_save = patterns::getpatterninfo0(ctr);
addsaver(si_save.id, "center type", 1); addsaver(si_save.id, "center type", 1);

View File

@ -55,6 +55,11 @@ int gcd(int i, int j) {
return i ? gcd(j%i, i) : 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 // debug utilities
extern FILE *debugfile; extern FILE *debugfile;
@ -116,3 +121,6 @@ void profile_info() {
#define profile_info() #define profile_info()
#endif #endif
int whateveri, whateveri2;
purehookset hooks_tests;