irr:: celldist and (circular, not yet horocyclic) celldistAlt

This commit is contained in:
Zeno Rogue 2018-07-20 02:58:47 +02:00
parent 35bb9ea95b
commit f7e5f470dc
5 changed files with 77 additions and 9 deletions

View File

@ -105,10 +105,8 @@ bool grailWasFound(cell *c) {
void generateAlts(heptagon *h, int levs, bool link_cdata) {
if(!h->alt) return;
if(!irr::on) {
preventbarriers(h->c7);
for(int i=0; i<S7; i++) preventbarriers(h->c7->mov[i]);
}
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++)
@ -167,6 +165,10 @@ heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special) {
if(weirdhyperbolic) {
if(c->bardir == NOBARRIERS) return NULL;
forCellEx(c1, c) if(c1->bardir == NOBARRIERS) return NULL;
if(irr::on)
for(int i=0; i<S7; i++)
if(createStep(c->master, i)->c7->bardir != NODIR)
return NULL;
}
// check for non-crossing
@ -1082,8 +1084,8 @@ void buildBigStuff(cell *c, cell *from) {
buildBarrier4(c, bd, 0, getNewLand(c->land), c->land); */
}
if((!chaosmode) && bearsCamelot(c->land) && ctof(c) &&
(quickfind(laCamelot) || peace::on || (hrand(I2000) < 200 && horo_ok() &&
if((!chaosmode) && bearsCamelot(c->land) && is_master(c) &&
(quickfind(laCamelot) || peace::on || (hrand(I2000) < 200 && ((irr::on && hyperbolic) || horo_ok()) &&
items[itEmerald] >= U5 && !tactic::on))) {
int rtr = newRoundTableRadius();
heptagon *alt = createAlternateMap(c, rtr+14, hsOrigin);

View File

@ -1085,9 +1085,9 @@ int celldist(cell *c) {
return eudist(decodeId(c->master));
}
if(sphere) return celldistance(c, currentmap->gamestart());
if(irr::on) return irr::celldist(c, false);
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;
@ -1113,6 +1113,7 @@ int celldistAlt(cell *c) {
return celldist(c) - 3;
}
if(!c->master->alt) return 0;
if(irr::on) return irr::celldist(c, true);
if(ctof(c)) return c->master->alt->distance;
if(gp::on) return gp::compute_dist(c, celldistAlt);
int dx[MAX_S3]; dx[0] = 0;

View File

@ -6927,7 +6927,7 @@ ld circlesizeD[10000];
int lastsize;
bool sizes_known() {
return euclid || (geometry == gNormal && !gp::on);
return euclid || (geometry == gNormal && !gp::on && !irr::on);
}
void computeSizes() {

View File

@ -326,7 +326,7 @@ enum hstate { hsOrigin, hsA, hsB, hsError, hsA0, hsA1, hsB0, hsB1, hsC };
struct heptagon {
// automaton state
hstate s : 6;
int dm4: 2;
unsigned int dm4: 2;
// we are spin[i]-th neighbor of move[i]
uint32_t spintable;
int spin(int d) { return tspin(spintable, d); }
@ -2587,6 +2587,7 @@ namespace irr {
bool supports(eGeometry g);
void visual_creator();
unsigned char density_code();
int celldist(cell *c, bool alts);
}
extern hrmap *currentmap;

View File

@ -413,6 +413,7 @@ bool draw_cell_schematics(cell *c, transmatrix V) {
struct heptinfo {
heptspin base;
vector<cell*> subcells;
vector<int> celldists[2];
};
map<heptagon*, heptinfo> periodmap;
@ -492,6 +493,69 @@ void link_cell(cell *c, int d) {
tsetspin(c2->spintable, sc.spin[d], d);
}
int hdist(heptagon *h1, heptagon *h2) {
if(h1 == h2) return 0;
for(int i=0; i<S7; i++) if(h1->move[i] == h2) return 1;
return 2;
}
// compute celldist or celldistalt for all the subcells of h.
// We use the following algorithm:
// - assume that everything is computed for all the adjacent heptagons of h which are closer to the origin
// - consider h and its two neighbors which are in the same distance to the origin ('siblings')
// - compute celldists for all the cells in these three heptagons, by bfs, based on the 'parent' heptagons adjacent to h
// - record the computed distances for h, but not for its siblings
void compute_distances(heptagon *h, bool alts) {
auto dm4 = [alts, h] (heptagon *h1) -> unsigned {
if(!alts) return h1->dm4;
if(alts && !h1->alt) return 100; // error
if(alts && h1->alt->alt != h->alt->alt) return 100; // error
return h1->alt->dm4;
};
unsigned cdm = dm4(h), pdm = (cdm-1)&3;
vector<heptagon*> hs;
hs.push_back(h);
for(int i=0; i<S7; i++) if(dm4(createStep(h, i)) == cdm)
hs.push_back(h->move[i]);
vector<vector<int>*> to_clear;
for(auto hx: hs) {
auto &hi = periodmap[hx];
int ct = isize(hi.subcells);
auto& cd = hi.celldists[alts];
if(cd.empty() && hx != h) to_clear.push_back(&cd);
cd.resize(ct, 2000000000);
if(h == hx && (alts ? h->alt->s == hsOrigin : h->s == hsOrigin))
cd[0] = 0;
}
while(true) {
bool changed = false;
for(auto hx: hs) {
auto& hi = periodmap[hx];
auto& cd = hi.celldists[alts];
for(int i=0; i<isize(hi.subcells); i++)
forCellCM(c2, hi.subcells[i])
if(among(dm4(c2->master), cdm, pdm) && hdist(h, c2->master) < 2) {
int d = irr::celldist(c2, alts) + 1;
if(d < cd[i]) cd[i] = d, changed = true;
}
}
if(!changed) break;
}
for(auto x: to_clear) x->clear();
// for(int i: cd) printf(" %d", i); printf("\n");
}
int celldist(cell *c, bool alts) {
heptagon *master = c->master;
auto &hi = periodmap[master];
if(isize(hi.celldists[alts]) == 0)
compute_distances(master, alts);
return hi.celldists[alts][cells[cellindex[c]].localindex];
}
eGeometry orig_geometry;
void start_game_on_created_map() {