diff --git a/complex.cpp b/complex.cpp index 8610a898..f4711b4c 100644 --- a/complex.cpp +++ b/complex.cpp @@ -917,7 +917,7 @@ EX namespace clearing { // printf("R %4d C %4d\n", celldistAlt(bd.root), celldistAlt(c)); if(celldistAlt(c) > celldistAlt(bd.root)) { stepcount++; - if(stepcount > 100000000) { + if(stepcount > iteration_limit) { printf("buggy #1\n"); bd.buggy = true; return; @@ -937,7 +937,7 @@ EX namespace clearing { } else { bd.dist--; - if(bd.dist < -100000000) { + if(bd.dist < -iteration_limit) { for(int i=0; iitem = itBuggy; for(int i=0; i<(int) rpath.size(); i++) @@ -2562,7 +2562,7 @@ EX namespace dragon { EX cell *target; // actually for all Orb of Control void pullback(cell *c) { - int maxlen = 1000; + int maxlen = iteration_limit; while(maxlen-->0) { auto mi = moveimon(c).rev(); mountmove(mi, true); @@ -2579,7 +2579,7 @@ EX namespace dragon { EX cell *findhead(cell *c) { cell *cor = c; - int maxlen=1000; + int maxlen=iteration_limit; findhead: if(maxlen--<0) return c; if(c->monst == moDragonHead) return c; @@ -2608,7 +2608,7 @@ EX namespace dragon { EX int bodypart(cell *c, cell *head) { int i = 0, j = 0; - int maxlen = 1000; + int maxlen = iteration_limit; while(maxlen-->0) { if(head == c) i = j; j++; @@ -2627,7 +2627,7 @@ EX namespace dragon { int delay = false; kills[moDragonHead]++; int penalty = 0; - int maxlen = 1000; + int maxlen = iteration_limit; while(maxlen-->0) { changes.ccell(c); makeflame(c, 5, false); @@ -2657,7 +2657,7 @@ EX namespace dragon { EX int totalhp(cell *c) { int total = 0; - int maxlen = 1000; + int maxlen = iteration_limit; while(maxlen-->0) { if(!isDragon(c->monst)) { if(!history::includeHistory) printf("dragon bug #4\n"); @@ -2673,7 +2673,7 @@ EX namespace dragon { #define SWAPBITFIELD(x,y,t) { t bak=x; x=y; y=bak; } void pullfront(cell *c, cell *until) { - int maxlen = 1000; + int maxlen = iteration_limit; static vector allcells; allcells.clear(); while(maxlen-->0) { diff --git a/game.cpp b/game.cpp index ca98017d..2d1c5c9e 100644 --- a/game.cpp +++ b/game.cpp @@ -401,37 +401,36 @@ EX void fixWormBug(cell *c) { if(c->monst == moTentacletail || c->monst == moTentacleGhost) c->monst = moTentacle; if(c->monst == moHexSnakeTail) c->monst = moHexSnake; } - + +EX bool isWormhead(eMonster m) { + return among(m, + moTentacle, moWorm, moHexSnake, moWormwait, moTentacleEscaping, + moTentaclewait, moDragonHead); + } + +EX cell *worm_tohead(cell *c) { + for(int i=0; itype; i++) + if(c->move(i) && isWorm(c->move(i)->monst) && c->move(i)->mondir == c->c.spin(i)) + return c->move(i); + return nullptr; + } + EX cell *wormhead(cell *c) { // cell *cor = c; - findhead: - if(c->monst == moTentacle || c->monst == moWorm || c->monst == moHexSnake || - c->monst == moWormwait || c->monst == moTentacleEscaping || c->monst == moTentaclewait || - c->monst == moDragonHead) return c; - for(int i=0; itype; i++) - if(c->move(i) && isWorm(c->move(i)->monst) && c->move(i)->mondir == c->c.spin(i)) { - c = c->move(i); goto findhead; - } + int cnt = 0; + while(cnt < iteration_limit) { + if(isWormhead(c->monst)) + return c; + cell *c1 = worm_tohead(c); + if(!c1) break; + c = c1; + cnt++; + } fixWormBug(c); return c; - } + } -EX int wormpos(cell *c) { - // cell *cor = c; - int cnt = 0; - findhead: - if(c->monst == moTentacle || c->monst == moWorm || c->monst == moHexSnake || - c->monst == moWormwait || c->monst == moTentacleEscaping || c->monst == moTentaclewait || - c->monst == moDragonHead) return cnt; - for(int i=0; itype; i++) - if(c->move(i) && isWorm(c->move(i)->monst) && c->move(i)->mondir == c->c.spin(i)) { - c = c->move(i); cnt++; goto findhead; - } - fixWormBug(c); - return cnt; - } - -// currently works for worms only +/** currently works for worms only */ EX bool sameMonster(cell *c1, cell *c2) { if(!c1 || !c2) return false; if(c1 == c2) return true; diff --git a/heptagon.cpp b/heptagon.cpp index d0379225..bff3e629 100644 --- a/heptagon.cpp +++ b/heptagon.cpp @@ -237,7 +237,7 @@ heptagon *hrmap_standard::create_step(heptagon *h, int d) { pard = 3; // to do: randomize else if(S3 == 4) pard = 3; - buildHeptagon(h, 0, h->distance < -32500 ? hsOrigin : hsA, pard); + buildHeptagon(h, 0, h->distance < -global_distance_limit - 200 ? hsOrigin : hsA, pard); } if(h->move(d)) return h->move(d); if(h->s == hsOrigin) { diff --git a/landgen.cpp b/landgen.cpp index 6c1899d6..0bd45970 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -2899,7 +2899,8 @@ EX void setdist(cell *c, int d, cell *from) { if(d == 7) repairLandgen(c); // the number of tiles in the standard geometry has about 7553 digits! - if(c->master->distance > 32000 || c->master->distance < -32000) { + int gdist = abs(c->master->distance); + if(gdist > global_distance_limit) { c->wall = waNone; c->item = itOrbSafety; } diff --git a/locations.cpp b/locations.cpp index e83c7777..7630f6bd 100644 --- a/locations.cpp +++ b/locations.cpp @@ -288,6 +288,18 @@ struct cdata { int bits; }; +/** Limit on the 'distance' value in heptagon. This value is signed (negative distances are used + in horocycle implementation. Distance is currently a short, and we need a bit of breathing room. + It would not be a technical problem to use a larger type, but 32000 is close to what fits in + the memory of a normal computer. Farlands appear close to this limit. + */ + +constexpr int global_distance_limit = 32000; + +/** This value is used in iterative algorithms to prevent infinite loops created by incorrect + data (e.g., circular dragon). It should be larger than global_distance_limit */ +constexpr int iteration_limit = 10000000; + /** in bitruncated/irregular/Goldberg geometries, heptagons form the * underlying regular tiling (not necessarily heptagonal); in pure * geometries, they correspond 1-1 to tiles; in 'masterless' geometries