irregular grids

This commit is contained in:
Zeno Rogue 2018-07-16 20:05:23 +02:00
parent 4320119d02
commit c8c1e3a346
19 changed files with 829 additions and 84 deletions

View File

@ -105,8 +105,10 @@ bool grailWasFound(cell *c) {
void generateAlts(heptagon *h, int levs, bool link_cdata) {
if(!h->alt) return;
preventbarriers(h->c7);
for(int i=0; i<S7; i++) preventbarriers(h->c7->mov[i]);
if(!irr::on) {
preventbarriers(h->c7);
for(int i=0; i<S7; i++) preventbarriers(h->c7->mov[i]);
}
if(gp::on)
for(int i=0; i<S7; i++) preventbarriers(createStep(h, i)->c7);
for(int i=0; i<S7; i++)
@ -973,7 +975,7 @@ int wallchance(cell *c, bool deepOcean) {
bool horo_ok() {
// do the horocycles work in the current geometry?
// (they work in ALL hyperbolic geometries currently!)
return hyperbolic;
return hyperbolic && !irr::on;
}
bool gp_wall_test() {

View File

@ -6,7 +6,7 @@ namespace hr {
double randd() { return (rand() + .5) / (RAND_MAX + 1.); }
double cellgfxdist(cell *c, int i) {
if(gp::on) return hdist0(tC0(shmup::calc_relative_matrix(c->mov[i], c, i)));
if(gp::on || irr::on) return hdist0(tC0(shmup::calc_relative_matrix(c->mov[i], c, i)));
return nonbitrunc ? tessf * gp::scale : (c->type == 6 && (i&1)) ? hexhexdist : crossf;
}

View File

@ -73,7 +73,10 @@ hrmap_hyperbolic::hrmap_hyperbolic() {
h.alt = NULL;
h.distance = 0;
isnonbitrunc = nonbitrunc;
h.c7 = newCell(S7, origin);
if(irr::on)
irr::link_start(origin);
else
h.c7 = newCell(S7, origin);
}
// --- spherical geometry ---
@ -107,7 +110,7 @@ struct hrmap_spherical : hrmap {
h.spintable = 0;
h.fieldval = i;
for(int i=0; i<S7; i++) h.move[i] = NULL;
h.c7 = newCell(S7, &h);
if(!irr::on) h.c7 = newCell(S7, &h);
}
if(S7 == 5)
siblings = {1, 0, 10, 4, 3, 8, 9, 11, 5, 6, 2, 7};
@ -174,6 +177,13 @@ struct hrmap_spherical : hrmap {
dodecahedron[i+1]->setspin(2, 3-i);
}
}
if(irr::on) {
irr::link_start(dodecahedron[0]);
for(int i=0; i<spherecells(); i++)
for(int j=0; j<S7; j++)
irr::may_link_next(dodecahedron[i], j);
}
}
heptagon *getOrigin() { return dodecahedron[0]; }
@ -717,7 +727,7 @@ struct hrmap_quotient : hrmap {
h->fieldval = S7*i;
h->rval0 = h->rval1 = 0; h->cdata = NULL;
h->distance = 0;
h->c7 = newCell(S7, h);
if(!irr::on) h->c7 = newCell(S7, h);
}
for(int j=0; j<S7; j++) {
int co = connections[i*S7+j];
@ -738,6 +748,13 @@ struct hrmap_quotient : hrmap {
allh[i]->move[j]->alt = createStep(allh[i]->alt, j); */
}
if(irr::on) {
irr::link_start(allh[0]);
for(int i=0; i<TOT; i++)
for(int j=0; j<S7; j++)
irr::may_link_next(allh[i], j);
}
celllister cl(gamestart(), 100, 100000000, NULL);
celllist = cl.lst;
}
@ -827,6 +844,9 @@ cell *createMov(cell *c, int d) {
}
if(c->mov[d]) return c->mov[d];
else if(irr::on) {
irr::link_cell(c, d);
}
else if(nonbitrunc && gp::on) {
gp::extend_map(c, d);
if(!c->mov[d]) {
@ -951,7 +971,8 @@ void clearHexes(heptagon *at) {
delete at->cdata;
at->cdata = NULL;
}
if(at->c7) subcell(at->c7, clearcell);
if(irr::on) irr::clear_links(at);
else if(at->c7) subcell(at->c7, clearcell);
}
void unlink_cdata(heptagon *h) {
@ -1017,7 +1038,7 @@ void verifycell(cell *c) {
}
void verifycells(heptagon *at) {
if(gp::on) return;
if(gp::on || irr::on) return;
for(int i=0; i<S7; i++) if(at->move[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)]);
}
@ -1066,6 +1087,7 @@ int celldist(cell *c) {
if(sphere) return celldistance(c, currentmap->gamestart());
if(ctof(c)) return c->master->distance;
if(gp::on) return gp::compute_dist(c, celldist);
if(irr::on) return c->master->distance;
int dx[MAX_S3];
for(int u=0; u<S3; u++)
dx[u] = createMov(c, u+u)->master->distance;
@ -1400,7 +1422,7 @@ int getCdata(cell *c, int j) {
int jj = 0;
auto ar = gp::get_masters(c);
for(int k=0; k<3; k++)
jj += getHeptagonCdata(ar[k]->master)->val[j];
jj += getHeptagonCdata(ar[k])->val[j];
return jj;
}
}
@ -1411,9 +1433,9 @@ int getBits(cell *c) {
else if(c->type != 6) return getHeptagonCdata(c->master)->bits;
else {
auto ar = gp::get_masters(c);
int b0 = getHeptagonCdata(ar[0]->master)->bits;
int b1 = getHeptagonCdata(ar[1]->master)->bits;
int b2 = getHeptagonCdata(ar[2]->master)->bits;
int b0 = getHeptagonCdata(ar[0])->bits;
int b1 = getHeptagonCdata(ar[1])->bits;
int b2 = getHeptagonCdata(ar[2])->bits;
return (b0 & b1) | (b1 & b2) | (b2 & b0);
}
}
@ -1475,7 +1497,7 @@ int celldistance(cell *c1, cell *c2) {
return 64;
}
if(gp::on || euclid) {
if(gp::on || euclid || irr::on) {
if(saved_distances.count(make_pair(c1,c2)))
return saved_distances[make_pair(c1,c2)];

View File

@ -32,6 +32,7 @@
#include "language.cpp"
#include "cell.cpp"
#include "goldberg.cpp"
#include "irregular.cpp"
#include "pattern2.cpp"
#include "flags.cpp"
#include "yendor.cpp"

View File

@ -3094,7 +3094,7 @@ namespace windmap {
// cw.spin = 0;
neighbors.emplace_back();
auto &v = neighbors.back();
if(gp::on)
if(gp::on || irr::on)
for(int l=0; l<S7; l++) {
heptspin hs(cw.c->master, cw.spin);
hs = hs + l + wstep;

View File

@ -218,9 +218,17 @@ void bshape_regular(floorshape &fsh, int id, int sides, int shift, ld size) {
}
}
namespace irr { void generate_floorshapes(); }
void generate_floorshapes() {
if(irr::on) {
printf("generating irregular floorshapes...\n");
irr::generate_floorshapes();
printf("done\n");
return;
}
if(gp::on) {
return;
}
@ -489,6 +497,103 @@ namespace gp {
}
}
namespace irr {
map<int, matrixlist> usedml;
void generate_floorshapes() {
if(irr::cells.empty()) return;
for(auto pfsh: all_escher_floorshapes) {
auto& fsh = *pfsh;
generate_matrices_scale(1, fsh.noftype);
auto& m = hept_matrices;
/* if(siid == 0)
for(auto& ma: m.v) ma.first = ma.first * pispin; */
fsh.b.resize(irr::sc);
for(int id=0; id<irr::sc; id++) {
auto& vs = irr::cells[id];
int cor = isize(vs.vertices);
m.n.sym = cor;
int i = 0;
for(int d=0; d<m.o.sym; d++) {
hyperpoint center = hpxy(0,0);
for(int c=0; c<cor; c++) {
hyperpoint nlcorner = vs.vertices[(d+c+1) % cor];
hyperpoint nrcorner = vs.vertices[(d+c+2) % cor];
hyperpoint nfar = vs.jpoints[vs.neid[(d+c+1) % cor]];
hyperpoint nlfar = nfar;
hyperpoint nrfar = nfar;
m.v[i].second[c] = build_matrix(center, nlcorner, nrcorner);
m.v[i+1].second[c] = build_matrix(nfar, nlcorner, nrcorner);
m.v[i+2].second[c] = build_matrix(nfar, nlcorner, nlfar);
m.v[i+3].second[c] = build_matrix(nfar, nrcorner, nrfar);
}
i += 4;
}
usedml[id] = m;
m.n.sym = cor;
bshape2(fsh.b[id], fsh.prio, fsh.shapeid2 ? fsh.shapeid2 : fsh.shapeid1, m);
}
}
for(auto pfsh: all_plain_floorshapes) {
auto& fsh = *pfsh;
ld sca = fsh.rad0 / shFullFloor.rad0;
fsh.b.resize(irr::sc);
fsh.shadow.resize(irr::sc);
for(int i=0; i<irr::sc; i++) {
auto& vs = irr::cells[i];
vector<hyperpoint> cornerlist;
int cor = isize(vs.vertices);
for(int j=0; j<cor; j++)
cornerlist.push_back(rspintox(vs.vertices[j]) * xpush(hdist0(vs.vertices[j]) * sca) * C0);
bshape(fsh.b[i], fsh.prio);
for(int i=0; i<=cor; i++) hpcpush(cornerlist[i%cor]);
bshape(fsh.shadow[i], fsh.prio);
for(int i=0; i<=cor; i++)
hpcpush(mid_at(hpxy(0,0), cornerlist[i%cor], SHADMUL));
cell fc;
fc.type = cor;
irr::cellindex[&fc] = i;
// printf("at = %d,%d cor = %d sca = %lf\n", li.relative.first, li.relative.second, cor, sca);
for(int k=0; k<SIDEPARS; k++)
for(int c=0; c<cor; c++) {
fsh.gpside[k][c].resize(irr::sc);
bshape(fsh.gpside[k][c][i], fsh.prio);
hpcpush(iddspin(&fc, c) * cornerlist[c]);
hpcpush(iddspin(&fc, c) * cornerlist[(c+1)%cor]);
chasmifyPoly(dlow_table[k], dhi_table[k], k);
}
}
}
finishshape(); last = NULL;
extra_vertices();
}
}
qfloorinfo qfi;
qfloorinfo qfi_dc;
@ -521,6 +626,13 @@ void draw_shapevec(cell *c, const transmatrix& V, const vector<hpcshape> &shv, i
int id = gp::get_plainshape_id(c);
queuepolyat(V, shv[id], col, prio);
}
else if(irr::on) {
int id = irr::cellindex[c];
if(id < 0 || id >= isize(shv)) {
return;
}
queuepolyat(V, shv[id], col, prio);
}
else if((euclid || gp::on) && ishex1(c))
queuepolyat(V * pispin, shv[0], col, prio);
else if(!(S7&1) && nonbitrunc) {
@ -566,8 +678,13 @@ void viewmat() {
gp::just_matrices = false;
}
// if(gp::on && !gp::usedml.count(cwt.c)) return;
for(auto& v: (pseudohept(cwt.c) ? hept_matrices : hex_matrices).v) {
// for(auto& v: (pseudohept(cwt.c) ? hept_matrices : hex_matrices).v) {
// for(auto& v: (gp::on ? gp::usedml[cwt.c] : pseudohept(cwt.c) ? hept_matrices : hex_matrices).v) {
// hyperpoint h1 = gmatrix[cwt.c] * v.second[0] * hpxyz(1,0,0);
id = irr::cellindex[cwt.c];
for(auto& v: irr::usedml[id].v) {
// for(auto& v: (gp::on ? gp::usedml[cwt.c] : pseudohept(cwt.c) ? hept_matrices : hex_matrices).v) {
hyperpoint h1 = gmatrix[cwt.c] * v.second[0] * hpxyz(1,0,0);
hyperpoint h2 = gmatrix[cwt.c] * v.second[0] * hpxyz(0,1,0);
hyperpoint h3 = gmatrix[cwt.c] * v.second[0] * hpxyz(0,0,1);

View File

@ -170,6 +170,7 @@ void precalc() {
base_distlimit = ginf[geometry].distlimit[nonbitrunc];
gp::compute_geometry();
irr::compute_geometry();
}
transmatrix ddi(ld dir, ld dist) {

View File

@ -857,16 +857,18 @@ namespace hr { namespace gp {
return dmain + length(centerloc-at) - length(centerloc);
}
array<cell*, 3> get_masters(cell *c) {
array<heptagon*, 3> get_masters(cell *c) {
if(gp::on) {
auto li = get_local_info(c);
be_in_triangle(li);
auto cm = c->master;
int i = li.last_dir;
return make_array(cm->c7, createStep(cm, i)->c7, createStep(cm, fix7(i+1))->c7);
return make_array(cm, createStep(cm, i), createStep(cm, fix7(i+1)));
}
else
return make_array(c->mov[0], c->mov[2], c->mov[4]);
else if(irr::on)
return irr::get_masters(c);
else
return make_array(c->mov[0]->master, c->mov[2]->master, c->mov[4]->master);
}
int compute_dist(cell *c, int master_function(cell*)) {

View File

@ -158,6 +158,7 @@ void drawSpeed(const transmatrix& V) {
}
int ctof(cell *c) {
if(irr::on) return irr::ctof(c);
if(nonbitrunc && !gp::on) return 1;
// if(euclid) return 0;
return ishept(c) ? 1 : 0;
@ -232,7 +233,14 @@ void drawLightning(const transmatrix& V) {
}
int displaydir(cell *c, int d) {
if(euclid)
if(irr::on) {
auto id = irr::cellindex[c];
auto& vs = irr::cells[id];
if(d < 0 || d >= c->type) return 0;
auto& p = vs.jpoints[vs.neid[d]];
return -int(atan2(p[1], p[0]) * S84 / 2 / M_PI + MODFIXER + .5);
}
else if(euclid)
return - d * S84 / c->type;
else
return S42 - d * S84 / c->type;
@ -2092,7 +2100,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
Vb = Vb * pispin;
Vb = Vb * xpush(tentacle_length - cellgfxdist(c, c->mondir));
}
else if(gp::on) {
else if(gp::on || irr::on) {
transmatrix T = shmup::calc_relative_matrix(c->mov[c->mondir], c, c->mondir);
Vb = Vb * T * rspintox(tC0(inverse(T))) * xpush(tentacle_length);
}
@ -3076,6 +3084,7 @@ bool noAdjacentChasms(cell *c) {
// does the current geometry allow nice duals
bool has_nice_dual() {
if(irr::on) return false;
if(!nonbitrunc) return true;
if((S7 & 1) == 0) return true;
if(!gp::on) return false;
@ -3171,8 +3180,8 @@ bool placeSidewall(cell *c, int i, int sidepar, const transmatrix& V, int col) {
else prio = PPR_REDWALL-2+4*(sidepar-SIDE_SLEV);
transmatrix V2 = V * ddspin(c, i);
if(gp::on) {
if(gp::on || irr::on) {
draw_shapevec(c, V2, qfi.fshape->gpside[sidepar][i], col, prio);
return false;
}
@ -4024,7 +4033,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
case laSwitch:
set_floor(shSwitchFloor);
if(ctof(c)) for(int i=0; i<c->type; i++)
if(ctof(c) && !gp::on && !irr::on) for(int i=0; i<c->type; i++)
queuepoly(Vf * ddspin(c, i, S6) * xpush(rhexf), shSwitchDisk, darkena(minf[active_switch()].color, fd, 0xFF));
break;
@ -4709,7 +4718,14 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
int prec = sphere ? 3 : 1;
if(gp::on) {
if(irr::on) {
int id = irr::cellindex[c];
auto &vs = irr::cells[id];
for(int t=0; t<c->type; t++)
if(c->mov[t] && c->mov[t] < c)
queueline(V * vs.vertices[t], V * vs.vertices[(1+t)%c->type], gridcolor(c, c->mov[t]), prec);
}
else if(gp::on) {
vid.linewidth *= gp::scale * 2;
if(isWarped(c) && has_nice_dual()) {
if(pseudohept(c)) for(int t=0; t<c->type; t++)

View File

@ -75,7 +75,10 @@ heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0, int fix
h->move[pard] = parent; tsetspin(h->spintable, pard, d);
parent->move[d] = h; tsetspin(parent->spintable, d, pard);
if(parent->c7) {
h->c7 = newCell(S7, h);
if(irr::on)
irr::link_next(parent, d);
else
h->c7 = newCell(S7, h);
h->rval0 = h->rval1 = 0; h->cdata = NULL;
h->emeraldval = emerald_heptagon(parent->emeraldval, d);
h->zebraval = zebra_heptagon(parent->zebraval, d);

18
hyper.h
View File

@ -78,7 +78,7 @@ void addMessage(string s, char spamtype = 0);
#define S3 ginf[geometry].vertex
#define hyperbolic_37 (S7 == 7 && S3 == 3)
#define hyperbolic_not37 ((S7 > 7 || S3 > 3) && hyperbolic)
#define weirdhyperbolic ((S7 > 7 || S3 > 3 || gp::on) && hyperbolic)
#define weirdhyperbolic ((S7 > 7 || S3 > 3 || gp::on || irr::on) && hyperbolic)
#define stdhyperbolic (S7 == 7 && S3 == 3 && !gp::on)
#define cgclass (ginf[geometry].cclass)
@ -2549,6 +2549,20 @@ struct hrmap_hyperbolic : hrmap {
void verify() { verifycells(origin); }
};
namespace quotientspace { hrmap *new_map(); }
namespace irr {
extern bool on;
void link_to_base(heptagon *h, heptspin base);
void link_start(heptagon *h);
void link_next(heptagon *h, int d);
void may_link_next(heptagon *h, int d);
void link_cell(cell *c, int d);
void clear_links(heptagon *h);
bool pseudohept(cell*);
array<heptagon*, 3> get_masters(cell *c);
bool ctof(cell* c);
}
extern hrmap *currentmap;
extern vector<hrmap*> allmaps;
@ -3149,7 +3163,7 @@ namespace gp {
int solve_triangle(int dmain, int d0, int d1, loc at);
array<cell*, 3> get_masters(cell *c);
array<heptagon*, 3> get_masters(cell *c);
}
int get_sightrange();

View File

@ -486,6 +486,8 @@ ld master_to_c7_angle() {
}
transmatrix actualV(const heptspin& hs, const transmatrix& V) {
if(irr::on)
return V * spin(M_PI + 2 * M_PI / S7 * (hs.spin + irr::periodmap[hs.h].base.spin));
return (hs.spin || nonbitrunc) ? V * spin(hs.spin*2*M_PI/S7 + master_to_c7_angle()) : V;
}
@ -564,10 +566,22 @@ void drawrec(const heptspin& hs, hstate s, const transmatrix& V) {
transmatrix V10;
const transmatrix& V1 = hs.mirrored ? (V10 = V * Mirror) : V;
bool draw = c->pathdist < PINFD;
if(gp::on) {
gp::drawrec(c, actualV(hs, V1));
}
else if(irr::on) {
auto& hi = irr::periodmap[hs.h];
transmatrix V0 = actualV(hs, V1);
auto& vc = irr::cells_of_heptagon[hi.base.h];
for(int i=0; i<isize(vc); i++)
if(dodrawcell(hi.subcells[i]) && in_qrange(V0 * irr::cells[vc[i]].pusher))
draw = true,
drawcell(hi.subcells[i], V0 * irr::cells[vc[i]].pusher, 0, false);
}
else {
if(dodrawcell(c)) {
transmatrix V2 = actualV(hs, V1);
@ -585,7 +599,7 @@ void drawrec(const heptspin& hs, hstate s, const transmatrix& V) {
}
}
if(c->pathdist < PINFD && in_qrange(V)) for(int d=0; d<S7; d++) {
if(draw && in_qrange(V)) for(int d=0; d<S7; d++) {
hstate s2 = transition(s, d);
if(s2 == hsError) continue;
heptspin hs2 = hs + d + wstep;

530
irregular.cpp Normal file
View File

@ -0,0 +1,530 @@
namespace hr { namespace irr {
bool on;
int sc = 100;
struct cellinfo {
cell *owner;
vector<hyperpoint> jpoints;
hyperpoint p;
transmatrix pusher, rpusher;
vector<int> neid;
vector<int> spin;
vector<hyperpoint> vertices;
int localindex;
bool is_pseudohept;
int patterndir;
};
map<cell*, int> cellindex;
vector<cellinfo> cells;
ld inner(hyperpoint h1, hyperpoint h2) {
return
hyperbolic ? h1[2] * h2[2] - h1[0] * h2[0] - h1[1] * h2[1] :
h1[2] * h2[2] + h1[0] * h2[0] + h1[1] * h2[1];
}
hyperpoint circumscribe(hyperpoint a, hyperpoint b, hyperpoint c) {
using namespace hyperpoint_vec;
hyperpoint h = C0;
b = b - a;
c = c - a;
if(inner(b,b) < 0) {
b = b / sqrt(-inner(b, b));
c = c + b * inner(c, b);
h = h + b * inner(h, b);
}
else {
b = b / sqrt(inner(b, b));
c = c - b * inner(c, b);
h = h - b * inner(h, b);
}
if(inner(c,c) < 0) {
c = c / sqrt(-inner(c, c));
h = h + c * inner(h, c);
}
else {
c = c / sqrt(inner(c, c));
h = h - c * inner(h, c);
}
if(h[2] < 0) h[0] = -h[0], h[1] = -h[1], h[2] = -h[2];
ld i = inner(h, h);
if(i > 0) h /= sqrt(i);
else h /= -sqrt(-i);
return h;
}
bool clockwise(hyperpoint h1, hyperpoint h2) {
return h1[0] * h2[1] > h1[1] * h2[0];
}
map<heptagon*, vector<int> > cells_of_heptagon;
int runlevel;
vector<ld> edgelens, distlens;
void make_cells_of_heptagon() {
cells_of_heptagon.clear();
for(int i=0; i<isize(cells); i++) {
auto &p1 = cells[i];
auto &vc = cells_of_heptagon[p1.owner->master];
p1.localindex = isize(vc);
vc.push_back(i);
}
}
hrmap *base;
bool gridmaking;
bool step(int delta) {
if(!gridmaking) return false;
timetowait = 0;
auto& all = base->allcells();
auto t = SDL_GetTicks();
while(SDL_GetTicks() < t + 250)
switch(runlevel) {
case 0: {
cells.clear();
cells_of_heptagon.clear();
if(sc <= isize(all) * 2) {
for(auto h: all) {
cellinfo s; s.patterndir = -1;
s.owner = h, s.p = spin(hrand(1000)) * xpush(.01) * C0;
cells.emplace_back(s);
}
}
runlevel++;
break;
}
case 1: {
while(isize(cells) < sc) {
if(SDL_GetTicks() > t + 250) { make_cells_of_heptagon(); return false; }
cellinfo s; s.patterndir = -1;
ld bestval = 0;
for(int j=0; j<10; j++) {
int k = hrand(isize(all));
cell *c = all[k];
hyperpoint h = randomPointIn(c->type);
ld mindist = 1e6;
for(auto p: cells) {
ld val = hdist(h, shmup::calc_relative_matrix(p.owner, c, h) * p.p);
if(val < mindist) mindist = val;
}
if(mindist > bestval) bestval = mindist, s.owner = c, s.p = h;
}
// printf("%lf %p %s\n", bestval, s.owner, display(s.p));
cells.emplace_back(s);
}
make_cells_of_heptagon();
runlevel++;
break;
}
case 2: {
sort(cells.begin(), cells.end(), [] (cellinfo &s1, cellinfo &s2) { return hdist0(s1.p) < hdist0(s2.p); });
make_cells_of_heptagon();
edgelens.clear();
distlens.clear();
int stats[16];
for(int k=0; k<16; k++) stats[k] = 0;
for(int i=0; i<sc; i++) {
auto &p1 = cells[i];
p1.vertices.clear();
p1.neid.clear();
p1.pusher = rgpushxto0(p1.p);
p1.rpusher = gpushxto0(p1.p);
p1.jpoints.clear();
for(int j=0; j<sc; j++) {
auto &p2 = cells[j];
p1.jpoints.push_back(p1.rpusher * shmup::calc_relative_matrix(p2.owner, p1.owner, p1.p) * p2.p);
}
int j = 0;
if(j == i) j = 1;
for(int k=0; k<sc; k++) if(k != i) {
if(hdist(p1.jpoints[k], C0) < hdist(p1.jpoints[j], C0))
j = k;
}
hyperpoint t = mid(p1.jpoints[j], C0);
// p1.vertices.push_back(p1.pusher * t);
int j0 = j;
int oldj = j;
do {
int best_k = -1;
hyperpoint best_h;
for(int k=0; k<sc; k++) if(k != i && k != j && k != oldj) {
hyperpoint h = circumscribe(C0, p1.jpoints[j], p1.jpoints[k]);
if(h[2] < 0) continue;
if(!clockwise(t, h)) continue;
if(best_k == -1)
best_k = k, best_h = h;
else if(clockwise(h, best_h))
best_k = k, best_h = h;
}
p1.vertices.push_back(best_h);
p1.neid.push_back(best_k);
distlens.push_back(hdist0(best_h));
oldj = j, j = best_k, t = best_h;
if(j == -1) break;
if(isize(p1.vertices) == 15) break;
}
while(j != j0);
for(int j=0; j<isize(p1.vertices); j++)
edgelens.push_back(hdist(p1.vertices[j], p1.vertices[(j+1) % isize(p1.vertices)]));
stats[isize(p1.vertices)]++;
}
for(int a=0; a<16; a++) printf("%3d ", stats[a]);
if(isize(edgelens)) {
printf("|");
printf("%4d ", isize(edgelens));
sort(edgelens.begin(), edgelens.end());
for(int a=0; a<=8; a++) printf("%6.3lf", double(edgelens[(a * isize(edgelens) - 1) / 8]));
printf(" | ");
sort(distlens.begin(), distlens.end());
for(int a=0; a<=8; a++) printf("%5.2lf", double(distlens[(a * isize(edgelens) - 1) / 8]));
}
printf("\n");
runlevel++;
break;
}
case 3: {
for(int i=0; i<isize(cells); i++) if(isize(cells[i].vertices) > 8 || isize(cells[i].vertices) < 3) {
cells[i] = cells.back();
i--; cells.pop_back();
}
if(isize(cells) < sc*3/4) runlevel = 0;
else if(isize(cells) < sc) runlevel = 1;
else runlevel++;
break;
}
case 4: {
ld minedge = edgelens[isize(edgelens) / 2] / 5;
if(edgelens[0] < minedge) {
printf("rearranging\n");
for(int i=0; i<isize(cells); i++) {
auto& p1 = cells[i];
using namespace hyperpoint_vec;
hyperpoint h = hpxyz(0, 0, 0);
for(auto v: p1.vertices) h = h + v;
for(int j=0; j<isize(p1.vertices); j++)
if(hdist(p1.vertices[j], p1.vertices[(j+1) % isize(p1.vertices)]) < minedge)
h = h + p1.vertices[j] + p1.vertices[(j+1) % isize(p1.vertices)];
cells[i].p = p1.pusher * normalize(h);
}
runlevel = 2;
break;
}
runlevel++;
break;
}
case 5: {
int notfound = 0;
for(int i=0; i<sc; i++) {
auto &p1 = cells[i];
int N = isize(p1.vertices);
p1.spin.resize(N);
for(int j=0; j<N; j++) {
auto i1 = p1.neid[j];
bool found = false;
for(int k=0; k < isize(cells[i1].vertices); k++)
if(cells[i1].neid[k] == i)
found = true, p1.spin[j] = k;
if(!found) notfound++;
}
}
printf("notfound = %d\n", notfound);
if(notfound) { runlevel = 0; break; }
int heptas = 0;
for(auto p: cells_of_heptagon) {
printf("%p: %d\n", p.first, isize(p.second));
heptas++;
}
if(heptas != isize(all)) {
printf("heptas = %d\n", heptas);
runlevel = 0; break;
}
for(int i=0; i<sc; i++) {
auto &p1 = cells[i];
for(int j: p1.neid) {
auto &p2 = cells[j];
bool ok = p1.owner == p2.owner || isNeighbor(p1.owner, p2.owner);
if(!ok) { printf("far edge\n"); runlevel = 0; return false; }
}
}
runlevel = 10;
for(auto& s: cells) s.is_pseudohept = false;
for(auto& s: cells) {
s.is_pseudohept = true;
for(int i: s.neid) if(cells[i].is_pseudohept) s.is_pseudohept = false;
}
for(auto& s: cells) {
int d = -1;
ld dist = hcrossf / 2;
ld dists[8];
for(int i=0; i<S7; i++) {
dists[i] = hdist(s.p, spin(hexshift - i * ALPHA) * xpush(-hcrossf) * C0);
// shmup::calc_relative_matrix(s.owner->mov[i], s.owner, s.p) * C0);
// spin(2 * M_PI * i / S7) * xpush(hcrossf) * C0);
if(dists[i] < dist)
d = i, dist = dists[i];
}
if(d != -1 && dists[(d+1) % S7] > dists[(d+S7-1) % S7])
d = (d + S7 - 1) % S7;
s.patterndir = d;
}
break;
}
case 10:
return false;
}
return false;
}
void compute_geometry() {
if(irr::on) {
ld scal = sqrt(isize(cells_of_heptagon) * 1. / sc);
crossf *= scal;
hepvdist *= scal;
rhexf *= scal;
}
}
bool draw_cell_schematics(cell *c, transmatrix V) {
if(gridmaking) {
heptagon *h = c->master;
for(int i: cells_of_heptagon[h]) {
auto& p = cells[i];
if(p.owner == c) {
queuestr(V * rgpushxto0(p.p), .1, its(i), isize(p.vertices) > 8 ? 0xFF0000 : 0xFFFFFF);
int N = isize(p.vertices);
for(int j=0; j<N; j++)
queueline(V * p.pusher * p.vertices[j], V * p.pusher * p.vertices[(1+j)%N], 0xFFFFFFFF);
queueline(V * p.p, V * C0, 0xFF0000FF);
if(p.patterndir != -1)
queueline(V * p.p, V * shmup::calc_relative_matrix(c->master->move[p.patterndir]->c7, c, p.p) * C0, 0x00FF00FF);
}
}
}
return false;
}
struct heptinfo {
heptspin base;
vector<cell*> subcells;
};
map<heptagon*, heptinfo> periodmap;
void link_to_base(heptagon *h, heptspin base) {
// printf("linking %p to %p/%d\n", h, base.h, base.spin);
auto &hi = periodmap[h];
hi.base = base;
for(int k: cells_of_heptagon[base.h]) {
cell *c = newCell(isize(cells[k].vertices), h);
hi.subcells.push_back(c);
cellindex[c] = k;
}
h->c7 = hi.subcells[0];
}
void clear_links(heptagon *h) {
auto& hi = periodmap[h];
for(cell *c: hi.subcells) {
for(int i=0; i<c->type; i++) if(c->mov[i]) c->mov[i]->mov[c->spin(i)] = NULL;
cellindex.erase(c);
delete c;
}
h->c7 = NULL;
periodmap.erase(h);
}
void link_start(heptagon *h) {
link_to_base(h, heptspin(cells[0].owner->master, 0));
}
void link_next(heptagon *parent, int d) {
if(!periodmap.count(parent))
link_to_base(parent, heptspin(cells[0].owner->master, 0));
// printf("linking next: %p direction %d [s%d]\n", parent, d, parent->spin(d));
auto *h = parent->move[d];
heptspin hs = periodmap[parent].base + d + wstep - parent->spin(d);
link_to_base(h, hs);
}
void may_link_next(heptagon *parent, int d) {
if(!periodmap.count(parent->move[d]))
link_next(parent, d);
}
void link_cell(cell *c, int d) {
// printf("linking cell: %p direction %d\n", c, d);
int ci = cellindex[c];
auto& sc = cells[ci];
int ci2 = sc.neid[d];
auto& sc2 = cells[ci2];
heptagon *master2 = NULL;
if(sc2.owner == sc.owner) {
master2 = c->master;
// printf("local\n");
}
else {
int dirs = 0;
int os = periodmap[c->master].base.spin;
for(int d=0; d<S7; d++) if(sc2.owner->master == sc.owner->master->move[(os+d)%S7]) {
heptspin hss(c->master, d);
hss += wstep;
master2 = hss.h;
// printf("master2 is %p; base = %p; should be = %p\n", master2, periodmap[master2].base.h, sc2.owner->master);
dirs++;
}
if(dirs != 1) { printf("dirs error\n"); exit(1); }
}
cell *c2 = periodmap[master2].subcells[sc2.localindex];
c->mov[d] = c2;
tsetspin(c->spintable, d, sc.spin[d]);
c2->mov[sc.spin[d]] = c;
tsetspin(c2->spintable, sc.spin[d], d);
}
void show_gridmaker() {
cmode = sm::SIDE;
gamescreen(0);
dialog::init(XLAT("Irregular grid"));
dialog::addSelItem(XLAT("activate"), its(runlevel), 'f');
dialog::display();
if(runlevel == 10) dialog::add_action([] {
popScreen();
pop_game();
for(hrmap *& hm : allmaps) if(hm == base) hm = NULL;
stop_game();
irr::on = true;
nonbitrunc = true;
need_reset_geometry = true;
gridmaking = false;
start_game();
});
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
// no exit
};
}
void create_map() {
push_game();
switch(geometry) {
case gNormal:
geometry = gKleinQuartic;
break;
case gOctagon:
geometry = gBolza2;
break;
default: ;
break;
}
nonbitrunc = true;
need_reset_geometry = true;
start_game();
base = currentmap;
drawthemap();
pushScreen(show_gridmaker);
runlevel = 0;
gridmaking = true;
}
int readArgs() {
using namespace arg;
if(0) ;
else if(argis("-irr")) {
PHASE(3);
shift(); sc = argi();
restart_game();
create_map();
}
else return 1;
return 0;
}
bool pseudohept(cell* c) {
return cells[cellindex[c]].is_pseudohept;
}
bool ctof(cell* c) {
return cells[cellindex[c]].patterndir == -1;
}
array<heptagon*, 3> get_masters(cell *c) {
int d = cells[cellindex[c]].patterndir;
heptspin s = periodmap[c->master].base;
heptspin s0 = heptspin(c->master, 0) + (d - s.spin);
return make_array(s0.h, (s0 + wstep).h, (s0 + 1 + wstep).h);
}
auto hook =
addHook(hooks_args, 100, readArgs) +
addHook(hooks_drawcell, 100, draw_cell_schematics) +
addHook(shmup::hooks_turn, 100, step);
}}
/*
if(mouseover && !ctof(mouseover)) {
for(auto h: gp::get_masters(mouseover))
queueline(shmup::ggmatrix(h->c7)*C0, shmup::ggmatrix(mouseover)*C0, 0xFFFFFFFF);
}
*/

View File

@ -210,14 +210,14 @@ void giantLandSwitch(cell *c, int d, cell *from) {
else {
if(d == 9) {
cell *c2 = gp::on ? c->master->c7 : c;
cell *c2 = (gp::on || irr::on) ? c->master->c7 : c;
if(cdist50(c2) == 3 && polarb50(c2) == 1)
c->wall = waPalace;
}
if(d == 8 && sphere) {
int gs = getHemisphere(c,0);
if(gp::on) {
if(gp::on || irr::on) {
int v = 1;
forCellEx(c2, c) if(getHemisphere(c2, 0) != gs)
v = 2;
@ -583,7 +583,7 @@ void giantLandSwitch(cell *c, int d, cell *from) {
else if(v == 25 || v == 59 || v == 27 || v == 57)
c->wall = waVineHalfB;
else c->wall = waNone;
if(gp::on && cellHalfvine(c)) {
if((gp::on || irr::on) && cellHalfvine(c)) {
c->wall = waNone;
forCellCM(c2, c) if(emeraldval(c2) == (v^1))
c->wall = waVinePlant;

View File

@ -1159,6 +1159,15 @@ land_validity_t& land_validity(eLand l) {
if(isWarped(l) && a4 && gp::on)
return dont_work;
if((isWarped(l) || l == laDual) && irr::on)
return dont_work;
if(irr::on && among(l, laStorms, laPrairie, laBlizzard, laVolcano))
return dont_work;
if(irr::on && among(l, laWhirlpool, laCamelot, laCaribbean, laClearing, laTemple, laHive, laMirror, laMirrorOld, laReptile, laKraken, laBurial))
return dont_work;
// equidistant-based lands
if(isEquidLand(l)) {
// no equidistants supported in chaos mode

View File

@ -826,7 +826,7 @@ void setAppropriateOverview() {
pushScreen(yendor::showMenu);
else if(peace::on)
pushScreen(peace::showMenu);
else if((geometry != gNormal || gp::on) && !chaosmode && !(geometry == gEuclid && isCrossroads(specialland)) && !(weirdhyperbolic && specialland == laCrossroads4)) {
else if((geometry != gNormal || gp::on || irr::on) && !chaosmode && !(geometry == gEuclid && isCrossroads(specialland)) && !(weirdhyperbolic && specialland == laCrossroads4)) {
runGeometryExperiments();
}
else {

View File

@ -49,11 +49,13 @@ bool ishex2(cell *c) {
else return c->type != S6;
}
int emeraldval(heptagon *h) { return h->emeraldval >> 3; }
int emeraldval(cell *c) {
if(euclid) return eupattern(c);
if(sphere) return 0;
if(ctof(c))
return c->master->emeraldval >> 3;
return emeraldval(c->master);
else {
auto ar = gp::get_masters(c);
return emerald_hexagon(
@ -96,9 +98,9 @@ int fiftyval(cell *c) {
else {
auto ar = gp::get_masters(c);
return bitmajority(
fiftyval(ar[0]),
fiftyval(ar[1]),
fiftyval(ar[2])) + 512;
ar[0]->fiftyval,
ar[1]->fiftyval,
ar[2]->fiftyval) + 512;
}
}
@ -109,47 +111,47 @@ int cdist50(cell *c) {
return "0123333332112332223322233211233333322"[eufifty(c)] - '0';
else return "012333321112322232222321123"[eufifty(c)] - '0';
}
if(c->type != 6) return cdist50(fiftyval(c));
if(ctof(c)) return cdist50(c->master->fiftyval);
auto ar = gp::get_masters(c);
int a0 = cdist50(ar[0]);
int a1 = cdist50(ar[1]);
int a2 = cdist50(ar[2]);
int a0 = cdist50(ar[0]->fiftyval);
int a1 = cdist50(ar[1]->fiftyval);
int a2 = cdist50(ar[2]->fiftyval);
if(a0 == 0 || a1 == 0 || a2 == 0) return 1;
return a0+a1+a2-5;
}
int land50(cell *c) {
if(c->type != 6) return land50(fiftyval(c));
else if(sphere || euclid) return 0;
if(sphere || euclid) return 0;
else if(ctof(c)) return land50(fiftyval(c));
else {
auto ar = gp::get_masters(c);
for(int i=0; i<3; i++)
if(cdist50(ar[i]) < 3) return land50(ar[i]);
if(cdist50(ar[i]->fiftyval) < 3) return land50(ar[i]->fiftyval);
return 0;
}
}
int polara50(cell *c) {
if(c->type != 6) return polara50(fiftyval(c));
else if(sphere || euclid || S7>7 || S6>6) return 0;
else if(gp::on) return polara50(fiftyval(c->master->c7));
if(sphere || euclid || S7>7 || S6>6) return 0;
else if(gp::on || irr::on) return polara50(fiftyval(c->master->c7));
else if(ctof(c)) return polara50(fiftyval(c));
else {
auto ar = gp::get_masters(c);
for(int i=0; i<3; i++)
if(cdist50(ar[i]) < 3) return polara50(ar[i]);
if(cdist50(ar[i]->fiftyval) < 3) return polara50(ar[i]->fiftyval);
return 0;
}
}
int polarb50(cell *c) {
if(euclid) return true;
if(c->type != 6) return polarb50(fiftyval(c));
else if(sphere || euclid || S7>7 || S6>6) return true;
else if(gp::on) return polarb50(fiftyval(c->master->c7));
if(sphere || euclid || S7>7 || S6>6) return true;
else if(gp::on || irr::on) return polarb50(fiftyval(c->master->c7));
else if(ctof(c)) return polarb50(fiftyval(c));
else {
auto ar = gp::get_masters(c);
for(int i=0; i<3; i++)
if(cdist50(ar[i]) < 3) return polarb50(ar[i]);
if(cdist50(ar[i]->fiftyval) < 3) return polarb50(ar[i]->fiftyval);
return 0;
}
}
@ -158,30 +160,32 @@ int elhextable[28][3] = {
{0,1,2}, {1,2,9}, {1,9,-1}, {1,8,-1}, {1,-1,-1}
};
int fiftyval049(heptagon *h) {
int i = h->fiftyval / 32;
if(i <= 7) return i;
if(quotient) return 0;
vector<int> allcodes;
for(int k=0; k<7; k++) {
heptagon *h2 = createStep(h, k);
if(polara50(h2->fiftyval) == polara50(h->fiftyval) && polarb50(h2->fiftyval) == polarb50(h->fiftyval))
allcodes.push_back(fiftyval049(h2));
}
int d = allcodes[1] - allcodes[0];
if(d == -1 || d == 6) swap(allcodes[0], allcodes[1]);
// printf("%d,%d: %d\n", allcodes[0], allcodes[1], allcodes[0] + 7);
return allcodes[0] + 7;
}
int fiftyval049(cell *c) {
if(euclid) return fiftyval(c) / 32;
else if(ctof(c)) {
int i = fiftyval(c) / 32;
if(i <= 7) return i;
if(quotient) return 0;
vector<int> allcodes;
for(int k=0; k<7; k++) {
cell *c2 = createStep(c->master, k)->c7;
if(polara50(c2) == polara50(c) && polarb50(c2) == polarb50(c))
allcodes.push_back(fiftyval049(c2));
}
int d = allcodes[1] - allcodes[0];
if(d == -1 || d == 6) swap(allcodes[0], allcodes[1]);
// printf("%d,%d: %d\n", allcodes[0], allcodes[1], allcodes[0] + 7);
return allcodes[0] + 7;
}
else if(ctof(c)) return fiftyval049(c->master);
else if(sphere) return 0;
else {
int a[3], qa=0;
int pa = polara50(c), pb = polarb50(c);
auto ar = gp::get_masters(c);
for(int i=0; i<3; i++)
if(polara50(ar[i]) == pa && polarb50(ar[i]) == pb)
if(polara50(ar[i]->fiftyval) == pa && polarb50(ar[i]->fiftyval) == pb)
a[qa++] = fiftyval049(ar[i]);
// 0-1-2
sort(a, a+qa);
@ -248,6 +252,7 @@ int val46(cell *c);
int zebra40(cell *c) {
if(euclid) return eupattern(c);
else if(irr::on) return c->master->zebraval/10;
else if(a46) {
int v = val46(c);
if(v<4) return v;
@ -285,9 +290,9 @@ int zebra40(cell *c) {
else {
int ii[3], z;
auto ar = gp::get_masters(c);
ii[0] = (ar[0]->master->zebraval/10);
ii[1] = (ar[1]->master->zebraval/10);
ii[2] = (ar[2]->master->zebraval/10);
ii[0] = (ar[0]->zebraval/10);
ii[1] = (ar[1]->zebraval/10);
ii[2] = (ar[2]->zebraval/10);
for(int r=0; r<2; r++)
if(ii[1] < ii[0] || ii[2] < ii[0])
z = ii[0], ii[0] = ii[1], ii[1] = ii[2], ii[2] = z;
@ -304,14 +309,14 @@ int zebra40(cell *c) {
}
int zebra3(cell *c) {
if(c->type != 6) return (c->master->zebraval/10)/4;
else if(sphere || S7>7 || S6>6) return 0;
if(ctof(c)) return (c->master->zebraval/10)/4;
else if(euclid || sphere || S7>7 || S6>6) return 0;
else {
int ii[3];
auto ar = gp::get_masters(c);
ii[0] = (ar[0]->master->zebraval/10)/4;
ii[1] = (ar[1]->master->zebraval/10)/4;
ii[2] = (ar[2]->master->zebraval/10)/4;
ii[0] = (ar[0]->zebraval/10)/4;
ii[1] = (ar[1]->zebraval/10)/4;
ii[2] = (ar[2]->zebraval/10)/4;
if(ii[0] == ii[1]) return ii[0];
if(ii[1] == ii[2]) return ii[1];
if(ii[2] == ii[0]) return ii[2];
@ -328,7 +333,7 @@ pair<int, bool> fieldval(cell *c) {
int fieldval_uniq(cell *c) {
if(sphere) {
if(ctof(c)) return c->master->fieldval;
if(ctof(c) || gp::on || irr::on) return c->master->fieldval;
else return createMov(c, 0)->master->fieldval + 256 * createMov(c,2)->master->fieldval + (1<<16) * createMov(c,4)->master->fieldval;
}
else if(torus) {
@ -338,7 +343,7 @@ int fieldval_uniq(cell *c) {
auto p = cell_to_pair(c);
return gmod(p.first * torusconfig::dx + p.second * torusconfig::dy, torusconfig::qty);
}
if(ctof(c) || gp::on) return c->master->fieldval/S7;
if(ctof(c) || gp::on || irr::on) return c->master->fieldval/S7;
else {
int z = 0;
for(int u=0; u<S6; u+=2)
@ -348,7 +353,7 @@ int fieldval_uniq(cell *c) {
}
int fieldval_uniq_rand(cell *c, int randval) {
if(sphere || torus || euclid)
if(sphere || torus || euclid || gp::on || irr::on)
// we do not care in these cases
return fieldval_uniq(c);
if(ctof(c)) return currfp.gmul(c->master->fieldval, randval)/7;
@ -708,7 +713,8 @@ namespace patterns {
}
void val_all(cell *c, patterninfo &si, int sub, int pat) {
if(a46) val46(c, si, sub, pat);
if(irr::on) si.symmetries = 1;
else if(a46) val46(c, si, sub, pat);
else if(a38) val38(c, si, sub, pat);
else if(sphere) valSibling(c, si, sub, pat);
else if(euclid4) valEuclid4(c, si, sub);
@ -1005,6 +1011,7 @@ namespace patterns {
}
int geosupport_threecolor() {
if(irr::on) return 0;
if(!nonbitrunc && S3 == 3) {
if(S7 % 2) return 1;
return 2;
@ -1019,6 +1026,7 @@ int geosupport_threecolor() {
int geosupport_graveyard() {
// always works in bitrunc geometries
if(!nonbitrunc) return 2;
if(irr::on) return 0;
// always works in patterns supporting three-color
int tc = max(geosupport_threecolor(), gp_threecolor());
@ -1130,6 +1138,7 @@ int pattern_threecolor(cell *c) {
// in the 'pure heptagonal' tiling, returns true for a set of cells
// which roughly corresponds to the heptagons in the normal tiling
bool pseudohept(cell *c) {
if(irr::on) return irr::pseudohept(c);
if(gp::on && gp_threecolor() == 2)
return gp::pseudohept_val(c) == 0;
if(gp::on && gp_threecolor() == 1 && (S7&1) && (S3 == 3))

View File

@ -3313,7 +3313,12 @@ void destroyBoats(cell *c) {
}
transmatrix master_relative(cell *c, bool get_inverse) {
if(gp::on) {
if(irr::on) {
int id = irr::cellindex[c];
ld alpha = 2 * M_PI / S7 * irr::periodmap[c->master].base.spin;
return get_inverse ? irr::cells[id].rpusher * spin(-alpha-master_to_c7_angle()): spin(alpha + master_to_c7_angle()) * irr::cells[id].pusher;
}
else if(gp::on) {
if(c == c->master->c7) {
return spin((get_inverse?-1:1) * master_to_c7_angle());
}

View File

@ -1029,10 +1029,10 @@ namespace gamestack {
bool pushed() { return isize(gd); }
void push() {
if(geometry) {
/* if(geometry) {
printf("ERROR: push implemented only in non-hyperbolic geometry\n");
exit(1);
}
} */
gamedata gdn;
gdn.hmap = currentmap;
gdn.cwt = cwt;