diff --git a/bigstuff.cpp b/bigstuff.cpp index f3be0ddd..1874b104 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -659,10 +659,12 @@ int chosenDownId(cell *c, int which, cellfunction* cf) { if(c->move(i)->mpdist > BARLEV && cf == coastvalEdge) setdist(c->move(i), BARLEV, c); if((*cf)(c->move(i)) == d) { + again: int i2 = (i+which+S42)%c->type; createMov(c, i2); - if((*cf)(c->move(i2)) == d) - return i2; + if((*cf)(c->move(i2)) == d) { + i = i2; goto again; + } else return i; } } @@ -1071,6 +1073,11 @@ void buildBigStuff(cell *c, cell *from) { buildBarrierNowall(c, getNewLand(c->land)); } + else if(weirdhyperbolic && yendor::on && yendor::nexttostart) { + if(buildBarrierNowall(c, yendor::nexttostart)) + yendor::nexttostart = laNone; + } + else if(weirdhyperbolic && specialland == laElementalWall && hrand(I10000) < 1000 && gp_wall_test()) buildBarrierNowall(c, getNewLand(c->land)); diff --git a/expansion.cpp b/expansion.cpp index 0a5c9838..ab1e3514 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -24,11 +24,20 @@ bignum& bignum::operator +=(const bignum& b) { return *this; } +bool bignum::operator < (const bignum& b) const { + if(isize(digits) != isize(b.digits)) + return isize(digits) < isize(b.digits); + for(int i = isize(digits)-1; i>=0; i--) + if(digits[i] != b.digits[i]) + return digits[i] < b.digits[i]; + return false; + } + void bignum::addmul(const bignum& b, int factor) { int K = isize(b.digits); if(K > isize(digits)) digits.resize(K); int carry = 0; - for(int i=0; i 0 && carry < -1); i++) { + for(int i=0; i 0 && carry < -1) || (carry == -1 && i < isize(digits)); i++) { if(i >= isize(digits)) digits.push_back(0); long long l = digits[i]; l += carry; @@ -40,6 +49,18 @@ void bignum::addmul(const bignum& b, int factor) { digits[i] = l; } if(carry < 0) digits.back() -= BASE; + while(isize(digits) && digits.back() == 0) digits.pop_back(); + } + +bignum hrand(bignum b) { + bignum res; + int d = isize(b.digits); + while(true) { + res.digits.resize(d); + for(int i=0; i %d\n", old_N, N); for(int g=0; g 1) return BASE; if(digits.empty()) return 0; return digits[0]; } - long long approx_ll() { + long long approx_ll() const { if(isize(digits) > 2) return BASE2; if(digits.empty()) return 0; if(isize(digits) == 1) return digits[0]; diff --git a/yendor.cpp b/yendor.cpp index b3a63f70..3fd224ca 100644 --- a/yendor.cpp +++ b/yendor.cpp @@ -111,6 +111,7 @@ namespace yendor { yendorlevel& clev() { return levels[challenge]; } eLand changeland(int i, eLand l) { + if(l == laIvoryTower) return laNone; if((clev().flags & YF_START_ANY) && i < 20 && l != clev().l) return clev().l; if((clev().flags & YF_END) && i > 80 && l == clev().l) return laIce; return laNone; @@ -164,77 +165,93 @@ namespace yendor { nyi.path[0] = yendor; nyi.howfar = 0; - if(euclid) { - int di = hrand(6); - int dj = (di+1) % 6; - int qty = hrand(YDIST-1); - int tot = 0; - for(int i=0; i= YDIST-1) { - tot -= YDIST-1; - nyi.path[i+1] = createMov(nyi.path[i], di); - } - else - nyi.path[i+1] = createMov(nyi.path[i], dj); - } - } - - else { - bool endorian_change = true; - bool in_endorian = false; - cellwalker lig(yendor, hrand(yendor->type)); - for(int i=0; iland == laEndorian) - in_endorian = true; - else if(!isTechnicalLand(lig.at->land)) - in_endorian = false; - nyi.path[i] = lig.at; - - lig += wstep; - if(inmirror(lig)) lig = mirror::reflect(lig); - lig += 3; - if(lig.at->type == 7) { - if(in_endorian && endorian_change && i >= YDIST - 20) { - // make the last leg a bit more difficult - lig += (hrand(2)*3-1); - endorian_change = false; - } - else - lig += hrand(2); - } - } - nyi.path[YDIST-1] = lig.at; - } - generating = true; - - for(int i=1; iland == laIvoryTower) continue; - eLand ycl = changeland(i, c2->land); - if(ishept(c2) && ycl) { - int bd = 2 + hrand(2) * 3; -// printf("barrier at %d\n", i); - buildBarrier(c2, bd, ycl); - if(c2->bardir != NODIR && c2->bardir != NOBARRIERS) - extendBarrier(c2); + + if(true) { + int t = -1; + bignum full_id; + bool onlychild; + + cellwalker ycw(yendor, hrand(yendor->type)); + ycw--; if(S3 == 3) ycw--; + setdist(nyi.path[0], 7, NULL); + + for(int i=0; i BARLEV-6) { + setdist(nyi.path[i+7-BARLEV], 7, nyi.path[i+6-BARLEV]); + if(challenge && !euclid) { + if(ycw.at->land == laIvoryTower) continue; + eLand ycl = changeland(i, ycw.at->land); + if(ycl) { + if(weirdhyperbolic) { + buildBarrierNowall(ycw.at, ycl); + } + else if(hyperbolic && ishept(ycw.at)) { + int bd = 2 + hrand(2) * 3; + buildBarrier(ycw.at, bd, ycl); + if(ycw.at->bardir != NODIR && ycw.at->bardir != NOBARRIERS) + extendBarrier(ycw.at); + } + } + } } + + if(ycw.at->land == laEndorian) { + // follow the branch in Yendorian + int bestval = -2000; + int best, qbest; + for(int d=0; dtype; d++) { + setdist(ycw.at, 7, ycw.peek()); + cell *c1 = (ycw+d).cpeek(); + int val = d * (ycw.at->type - d); + if(c1->wall == waTrunk) val += (i < YDIST-20 ? 1000 : -1000); + if(val > bestval) qbest = 0, bestval = val; + if(val == bestval) if(hrand(++qbest) == 0) best = d; + } + ycw += best; + } + + else if(sizes_known()) { + if(i == 0) { + t = type_in(expansion, yendor, [yendor] (cell *c) { return celldistance(yendor, c); }); + bignum b = expansion.get_descendants(YDIST-1, t); + full_id = hrand(b); + } + if(i == 1) + onlychild = true; + if(!onlychild) ycw++; + if(S3 == 3) ycw++; + + onlychild = false; + + for(int tch: expansion.children[t]) { + ycw++; + if(i == 1) + tch = type_in(expansion, ycw.cpeek(), [yendor] (cell *c) { return celldistance(yendor, c); }); + auto& sub_id = expansion.get_descendants(YDIST-i-2, tch); + if(full_id < sub_id) { t = tch; break; } + + full_id.addmul(sub_id, -1); + onlychild = true; + } + } + + else { + // stupid + ycw += rev; + } + + if(inmirror(ycw)) ycw = mirror::reflect(ycw); + ycw += wstep; + nyi.path[i+1] = ycw.at; } } nyi.found = false; nyi.foundOrb = false; + setdist(nyi.path[YDIST-1], 7, nyi.path[YDIST-2]); cell *key = nyi.path[YDIST-1]; generating = false;