diff --git a/bigstuff.cpp b/bigstuff.cpp index a7d4d915..8f832a8b 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -219,7 +219,7 @@ void hrmap::extend_altmap(heptagon *h, int levs, bool link_cdata) { } } -void new_voronoi_root(heptagon *h, int dist, int dir, eLand next, eLand last) { +void new_voronoi_root(heptagon *h, int dist, int dir, eLand next) { heptagon *alt = init_heptagon(h->type); allmaps.push_back(newAltMap(alt)); alt->s = hsA; @@ -231,7 +231,6 @@ void new_voronoi_root(heptagon *h, int dist, int dir, eLand next, eLand last) { altmap::relspin(alt) = dir; hv_land[alt] = next; - hv_last_land[alt] = last; while(alt->distance > -100) { auto alt1 = createStep(alt, 0); @@ -291,13 +290,41 @@ cand_info voronoi_candidate(heptagon *h) { return ci; } +vector list_adjacent_lands(heptagon *h) { + vector res; + for(int i=0; itype; i++) { + heptspin hs = heptspin(h, i); + hs += wstep; + auto alt = hs.at->alt; + if(!alt) continue; + alt = alt->alt; + res.push_back(hv_land.at(alt)); + // go arround the region of alt using the 'butterfly' method, to find the other two lands which seem adjacent + for(int d: {-1, 1}) { + auto hs1 = hs; + for(int i=0; i<100; i++) { + hs1 += d; + hs1 += wstep; + if(!hs1.at->alt) { hs1 += wstep; continue; } + auto alt1 = hs1.at->alt->alt; + if(alt1 != alt) { + res.push_back(hv_land.at(alt1)); break; + } + hs1 += d; + } + } + } + if(res.empty()) return { laBarrier }; + return res; + } + void extend_altmap_voronoi(heptagon *h) { if(h->alt) return; auto ci = voronoi_candidate(h); if(ci.bqty == 0) { - new_voronoi_root(h, -30, hrand(h->type), firstland, laBarrier); + new_voronoi_root(h, -30, hrand(h->type), firstland); return; } else if(ci.bqty > 0 && isize(ci.free_dirs)) { @@ -305,15 +332,15 @@ void extend_altmap_voronoi(heptagon *h) { ld growth = expansion.get_growth(); ld odds = pow(growth, ci.candidate->distance) * isize(ci.free_dirs); if(hrandf() < odds / (1 + odds)) { - eLand last = hv_land[ci.candidate->alt]; - eLand last2 = hv_last_land[ci.candidate->alt]; + vector lands_list = list_adjacent_lands(h); + auto dist = ci.candidate->distance; // in PURE, could be a tie, or the new root could win if(PURE) dist -= hrand(2); // in BITRUNCATED, it could change too.. need a better formula probably if(BITRUNCATED) dist += hrand(3) - 1; // do not care about others... - new_voronoi_root(h, dist, hrand_elt(ci.free_dirs), getNewLand(last, last2), last); + new_voronoi_root(h, dist, hrand_elt(ci.free_dirs), getNewLand2(lands_list)); return; } } @@ -1819,7 +1846,6 @@ EX void start_camelot(cell *c) { EX bool debug_voronoi; EX map hv_land; -EX map hv_last_land; EX void build_horocycles(cell *c, cell *from) { diff --git a/landlock.cpp b/landlock.cpp index 2b1f3147..695ffbc4 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -266,6 +266,20 @@ EX int isRandland(eLand l) { return 0; } +EX int voronoi_sea_category(eLand l) { + if(l == laRlyeh) return rlyehComplete() ? 0 : 2; + if(among(l, laOcean, laWarpCoast, laLivefjord, laDocks)) return 1; + if(among(l, laWhirlpool, laKraken, laWarpSea, laCaribbean)) return 2; + return 0; + } + +EX bool voronoi_sea_incompatible(eLand l1, eLand l2) { + int c1 = voronoi_sea_category(l1); + int c2 = voronoi_sea_category(l2); + if(c1+c2 == 2 && c1 != c2) return true; + return false; + } + EX bool incompatible1(eLand l1, eLand l2) { if(isCrossroads(l1) && isCrossroads(l2)) return true; if(l1 == laJungle && l2 == laMotion) return true; @@ -387,7 +401,7 @@ EX bool all_unlocked = false; EX vector cheatdest_list; -EX eLand getNewLand(eLand old, eLand old2 IS(laBarrier)) { +EX eLand getNewLand(eLand old) { #if CAP_LEGACY if(legacy_racing()) { @@ -399,7 +413,7 @@ EX eLand getNewLand(eLand old, eLand old2 IS(laBarrier)) { eLand l = callhandlers(laNone, hooks_nextland, old); if(l) return l; - if(cheatdest != old && cheatdest != old2 && cheatdest != laElementalWall) if(!isCyclic(cheatdest) && !isTechnicalLand(cheatdest)) return cheatdest; + if(cheatdest != old && cheatdest != laElementalWall) if(!isCyclic(cheatdest) && !isTechnicalLand(cheatdest)) return cheatdest; if(cheatdest_list.size()) { eLand l = cheatdest_list[0]; @@ -413,9 +427,7 @@ EX eLand getNewLand(eLand old, eLand old2 IS(laBarrier)) { while(true) { eLand n = eLand(hrand(landtypes)); if(n == old) continue; - if(n == old2) continue; if(incompatible(n,old)) continue; - if(incompatible(n,old2)) continue; if(!isLandIngame(n)) continue; if(n == laElementalWall || isTechnicalLand(n)) continue; if(n == laWildWest) continue; @@ -427,9 +439,9 @@ EX eLand getNewLand(eLand old, eLand old2 IS(laBarrier)) { if(markOrb(itOrbLuck)) { int i = items[itOrbLuck]; items[itOrbLuck] = 0; - eLand l1 = getNewLand(old, old2); + eLand l1 = getNewLand(old); for(int i=1; i<3; i++) - l1 = pickluck(l1, getNewLand(old, old2)); + l1 = pickluck(l1, getNewLand(old)); items[itOrbLuck] = i; return l1; } @@ -453,9 +465,9 @@ EX eLand getNewLand(eLand old, eLand old2 IS(laBarrier)) { #endif if(tactic::on) return specialland; - if(specialland != old && specialland != old2 && easy_to_find_specialland && specialland != laElementalWall) return specialland; + if(specialland != old && easy_to_find_specialland && specialland != laElementalWall) return specialland; - if(specialland != old && specialland != old2 && easy_specialland && specialland != laElementalWall) { + if(specialland != old && easy_specialland && specialland != laElementalWall) { easy_specialland--; return specialland; } @@ -612,7 +624,7 @@ EX eLand getNewLand(eLand old, eLand old2 IS(laBarrier)) { if(ls::horodisk_structure() && tortoise::seek()) LIKELY tab[cnt++] = laTortoise; eLand n = old; - while(incompatible(n, old) || incompatible(n, old2) || !isLandIngame(n)) { + while(incompatible(n, old) || !isLandIngame(n)) { n = tab[hrand(cnt)]; if(weirdhyperbolic && specialland == laCrossroads4 && isCrossroads(n)) n = laCrossroads4; @@ -621,6 +633,20 @@ EX eLand getNewLand(eLand old, eLand old2 IS(laBarrier)) { return n; } +EX eLand getNewLand2(vector olds) { + for(int i=0;; i++) { + auto old = hrand_elt(olds); + eLand l = getNewLand(old); + // how bad it is + int err = 0; + for(auto o: olds) if(l == o) err += 2000; + for(auto o: olds) if(incompatible(l, o)) err += 1000; + for(auto o: olds) if(voronoi_sea_incompatible(l, o)) err += 100; + // we still allow bad choices if we cannot obtain a good one + if(err <= i) return l; + } + } + EX vector land_over = { laIce, laCaves, laDesert, laHunting, laMotion, laJungle, laAlchemist, laCrossroads, diff --git a/system.cpp b/system.cpp index 95cec637..cd1c6216 100644 --- a/system.cpp +++ b/system.cpp @@ -1787,7 +1787,6 @@ auto cgm = addHook(hooks_clearmemory, 40, [] () { crush_now.clear(); rosemap.clear(); hv_land.clear(); - hv_last_land.clear(); bow::bowpath.clear(); bow::clear_bowpath(); bow::fire_mode = false;