diff --git a/attack.cpp b/attack.cpp index 6c9447a5..f3971189 100644 --- a/attack.cpp +++ b/attack.cpp @@ -758,7 +758,7 @@ EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) { if(m == moWaterElemental && c->item == itNone) c->item = itOrbWater; - if(m == moPirate && isOnCIsland(c) && c->item == itNone && ( + if(m == moPirate && (isOnCIsland(c) || ls::hv_structure()) && c->item == itNone && ( eubinary || (c->master->alt && celldistAlt(c) <= 2-getDistLimit()) || isHaunted(c->land)) && !cryst) { diff --git a/bigstuff.cpp b/bigstuff.cpp index 7e53b983..bdd5ee29 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -1657,9 +1657,12 @@ EX void start_camelot(cell *c) { if(alt) { altmap::radius(alt) = rtr; altmap::orig_land(alt) = c->land; + horodisk_land[alt] = laCamelot; } } +EX map horodisk_land; + EX void build_horocycles(cell *c, cell *from) { bool deepOcean = deep_ocean_at(c, from); @@ -1708,10 +1711,18 @@ EX void build_horocycles(cell *c, cell *from) { if(c->land == laCaribbean && can_start_horo(c)) create_altmap(c, horo_gen_distance(), hsA); + if(ls::horodisk_structure() && can_start_horo(c)) { + auto m = create_altmap(c, horo_gen_distance(), hsA); + if(m) { + horodisk_land[m] = getNewLand(laCrossroads); + clearing::bpdata[m].root = NULL; + } + } + if(c->land == laCanvas && can_start_horo(c) && ls::any_order()) create_altmap(c, horo_gen_distance(), hsA); - if(c->land == laPalace && can_start_horo(c) && !princess::generating && !shmup::on && multi::players == 1 && !weirdhyperbolic && + if(c->land == laPalace && can_start_horo(c) && !princess::generating && !shmup::on && multi::players == 1 && !weirdhyperbolic && !ls::hv_structure() && (princess::forceMouse ? canReachPlayer(from, moMouse) : (hrand(2000) < (peace::on ? 100 : 20))) && (princess::challenge || kills[moVizier] || peace::on)) { @@ -1966,12 +1977,31 @@ EX void moreBigStuff(cell *c) { else c->wall = waSea; } + + if(ls::horodisk_structure()) { + if(have_alt(c) && masterAlt(c) <= 0) { + gen_alt(c); + preventbarriers(c); + } + if(have_alt(c) && celldistAlt(c) <= 0) { + eLand l = horodisk_land[c->master->alt->alt]; + setland(c, l); + if(l == laWhirlpool && celldistAlt(c) >= -1) { + setland(c, laOcean); + c->landparam = 30; + } + if(l == laCaribbean) generateTreasureIsland(c); + if(isEquidLand(l)) c->landparam = 1-celldistAlt(c); + } + else + setland(c, laCrossroads); + } extend_alt(c, laPalace, laPalace, false, PRADIUS1); extend_alt(c, laCanvas, laCanvas); - if(extend_alt(c, laStorms, laStorms, false)) { + if(extend_alt(c, laStorms, laStorms, false) && !ls::hv_structure()) { int d = celldistAlt(c); if(d <= -2) { c->wall = eubinary ? waCharged : (altmap::which(c->master->alt->alt) & 1) ? waCharged : waGrounded; @@ -1990,10 +2020,12 @@ EX void moreBigStuff(cell *c) { c->wall = waColumn; } - else if(extend_alt(c, laTemple, laRlyeh)) + else if(extend_alt(c, laTemple, laRlyeh) && !ls::hv_structure()) gen_temple(c); - if(extend_alt(c, laClearing, laOvergrown)) { + if(c->land == laTemple && ls::hv_structure()) gen_temple(c); + + if(extend_alt(c, laClearing, laOvergrown) && !ls::hv_structure()) { if(in_single_horo(c, laClearing)) { c->land = laClearing, c->wall = waNone; } @@ -2001,11 +2033,16 @@ EX void moreBigStuff(cell *c) { c->wall = waSmallTree, c->monst = moNone, c->item = itNone, c->landparam = 1; } - if(extend_alt(c, laMountain, laJungle) && in_single_horo(c, laMountain)) { + if(c->land == laClearing && ls::hv_structure()) { + if(celldistAlt(c) >= -1) + c->wall = waSmallTree, c->monst = moNone, c->item = itNone, c->landparam = 1; + } + + if(extend_alt(c, laMountain, laJungle) && in_single_horo(c, laMountain) && !ls::hv_structure()) { c->land = laMountain, c->wall = waNone; } - if(extend_alt(c, laWhirlpool, laOcean) && in_single_horo(c, laWhirlpool)) + if(!ls::horodisk_structure() && extend_alt(c, laWhirlpool, laOcean) && in_single_horo(c, laWhirlpool)) c->land = laWhirlpool, c->wall = waSea, c->monst = moNone, c->item = itNone; } diff --git a/complex.cpp b/complex.cpp index 2de76a18..bc8049b1 100644 --- a/complex.cpp +++ b/complex.cpp @@ -907,6 +907,8 @@ EX namespace clearing { c->mondir = 0; return; } + + if(c->land == laClearing && ls::hv_structure() && celldistAlt(c) >= -1) return; if(!eubinary && !horo_ok()) return; // cell *oc = c; @@ -4080,10 +4082,18 @@ EX namespace dungeon { rdepths[i] = c2 && c3 && c4 && (c2->landflags == 3 || c3->landflags == 3 || c4->landflags == 3); if(c2) generate_around(c2); if(c3) generate_around(c3); - c2 = ts::left_parent(c2, coastvalEdge); - c3 = ts::right_parent(c3, coastvalEdge); - if(!c2) { towerError(c); return; } - if(!c3) { towerError(c); return; } + + if(ls::horodisk_structure()) { + c2 = ts::left_child(c2, celldistAlt); + c3 = ts::right_child(c3, celldistAlt); + if(!c2 || !c3) return; + } + else { + c2 = ts::left_parent(c2, coastvalEdge); + c3 = ts::right_parent(c3, coastvalEdge); + if(!c2) { towerError(c); return; } + if(!c3) { towerError(c); return; } + } } } @@ -4106,10 +4116,17 @@ EX namespace dungeon { if(c3 && c5 && c5->landflags == 3 && c3->landflags != 3 && c5 == ts::right_of(c3, coastvalEdge)) c->wall = waLadder; buildEquidistant(c4); buildEquidistant(c5); - if(c2) c2 = ts::left_parent(c2, coastvalEdge); - if(c3) c3 = ts::right_parent(c3, coastvalEdge); - if(c4) c4 = ts::left_parent(c4, coastvalEdge); - if(c5) c5 = ts::right_parent(c5, coastvalEdge); + if(ls::horodisk_structure()) { + c2 = ts::left_child(c2, celldistAlt); + c3 = ts::right_child(c3, celldistAlt); + if(!c2 || !c3) return; + } + else { + if(c2) c2 = ts::left_parent(c2, coastvalEdge); + if(c3) c3 = ts::right_parent(c3, coastvalEdge); + if(c4) c4 = ts::left_parent(c4, coastvalEdge); + if(c5) c5 = ts::right_parent(c5, coastvalEdge); + } } } } @@ -4161,10 +4178,17 @@ EX namespace dungeon { switchcount++; generate_around(c2); generate_around(c3); - c2 = ts::left_parent(c2, coastvalEdge); - c3 = ts::right_parent(c3, coastvalEdge); - if(!c2) { towerError(c); return 0; } - if(!c3) { towerError(c); return 0; } + if(ls::horodisk_structure()) { + c2 = ts::left_child(c2, celldistAlt); + c3 = ts::right_child(c3, celldistAlt); + if(!c2 || !c3) return 0; + } + else { + c2 = ts::left_parent(c2, coastvalEdge); + c3 = ts::right_parent(c3, coastvalEdge); + if(!c2) { towerError(c); return 0; } + if(!c3) { towerError(c); return 0; } + } } } } diff --git a/landgen.cpp b/landgen.cpp index ef01f1f5..9437c9af 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -276,7 +276,7 @@ EX void place_random_gate_continuous(cell *c) { } EX void giantLandSwitch(cell *c, int d, cell *from) { - bool fargen = d == min(BARLEV, 9); + bool fargen = d == min(BARLEV, ls::horodisk_structure() ? 8 : 9); switch(c->land) { case laPrairie: // ------------------------------------------------------------- @@ -405,7 +405,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { } else { - if(d == 9) { + if(d == (ls::horodisk_structure() ? 8 : 9)) { cell *c2 = NONSTDVAR ? c->master->c7 : c; if(cdist50(c2) == 3 && polarb50(c2)) c->wall = waPalace; @@ -453,7 +453,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { } // note: Princess Challenge brings back the normal Palace generation - bool lookingForPrincess = !euclid && c->master->alt && !princess::challenge; + bool lookingForPrincess = !euclid && c->master->alt && !princess::challenge && !ls::horodisk_structure(); bool pgate = false; if(PURE || GOLDBERG) { @@ -551,7 +551,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { } ONEMPTY { - bool lookingForPrincess0 = !euclid && c->master->alt; + bool lookingForPrincess0 = !euclid && c->master->alt && !ls::horodisk_structure(); bool lookingForPrincess = lookingForPrincess0 && !princess::challenge; int hardness = lookingForPrincess ? 5 : items[itPalace] + yendor::hardness(); @@ -1982,7 +1982,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { for(int i=0; itype; i++) { cell *c2 = c->move(i); if(c2 && c2->wall == waRose) nww++; - if(c2 && !ls::any_chaos()) for(int j=0; jtype; j++) { + if(c2 && !ls::any_chaos() && !ls::hv_structure()) for(int j=0; jtype; j++) { cell *c3 = c2->move(j); // note: c3->land is required for Android -- // not strictly equivalent since another land there might be not yet generated @@ -2089,6 +2089,12 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { case laOcean: if(d >= 8) c->wall = waSea; if(d == 7 && !safety) { + + if(ls::horodisk_structure() && c->master->alt && horodisk_land[c->master->alt->alt] == laWhirlpool) { + if(hrand(100) < 10) c->wall = waBoat; + return; + } + bool placecolumn = false; if(c->landparam % temple_layer_size() == 0 && c->landparam <= 24) { int q = 0; @@ -2261,6 +2267,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { case laClearing: if(d == 7) { clearing::generate(c); + if(ls::horodisk_structure() && celldistAlt(c) >= -1) c->monst = moNone; if(pseudohept(c)) { int d = -celldistAlt(c); if(hrand_monster(2500) < items[itMutant2] + yendor::hardness() - 10 && !reptilecheat) @@ -2460,6 +2467,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { int freq = 4000; if(ls::single() && specialland == laCrossroads5 && !racing::on) freq = 250; + if(ls::hv_structure() && hrand(10000) < 10) { c->monst = moPirate; } if(hrand_monster(freq) < items[itHyperstone] && !c->monst) { // only interesting monsters here! eMonster cm = crossroadsMonster(); @@ -2533,7 +2541,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { case laEclectic: { - if(d >= 9) c->wall = waChasm; + if(d >= (ls::hv_structure() ? 8 : 9)) c->wall = waChasm; if(d == 8) wfc::schedule(c); diff --git a/landlock.cpp b/landlock.cpp index f219bacd..fb903721 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -532,7 +532,7 @@ EX eLand getNewLand(eLand old) { // the intermediate lands if(all_unlocked || gold() >= R30) { tab[cnt++] = laCrossroads; - tab[cnt++] = geometry ? laMirrorOld : laMirror; + tab[cnt++] = (geometry || ls::hv_structure()) ? laMirrorOld : laMirror; tab[cnt++] = laOcean; tab[cnt++] = laLivefjord; if(all_unlocked || kills[moVizier]) tab[cnt++] = laEmerald; @@ -548,7 +548,7 @@ EX eLand getNewLand(eLand old) { if(all_unlocked || rlyehComplete()) tab[cnt++] = laRlyeh; else if(ls::std_chaos() && (old == laWarpCoast || old == laLivefjord || old == laOcean)) tab[cnt++] = laRlyeh; - if((all_unlocked || items[itStatue] >= U5) && ls::std_chaos()) + if((all_unlocked || items[itStatue] >= U5) && (ls::std_chaos() || ls::horodisk_structure())) tab[cnt++] = laTemple; if(old == laCrossroads || old == laCrossroads2) tab[cnt++] = laOcean; if(old == laOcean) tab[cnt++] = laCrossroads; @@ -563,6 +563,9 @@ EX eLand getNewLand(eLand old) { tab[cnt++] = laDual; tab[cnt++] = laSnakeNest; } + + if(landUnlocked(laMountain)) tab[cnt++] = laMountain; + if(landUnlocked(laClearing)) tab[cnt++] = laClearing; if(landUnlocked(laTrollheim)) { if(isTrollLand(old)) LIKELY tab[cnt++] = laTrollheim; @@ -731,6 +734,7 @@ namespace lv { land_validity_t not_in_shmup = {0, q0, "This land is not available in the shmup mode."}; land_validity_t not_in_multi = {0, q0, "This land is not available in multiplayer."}; land_validity_t single_only = {2, q0 | switch_to_single, "Available in single land mode only." }; + land_validity_t not_in_hv = { 0, q0, "Does not work in horodisk/Voronoi mode."}; } // old Daily Challenges should keep their validity forever @@ -853,6 +857,8 @@ EX land_validity_t& land_validity(eLand l) { if(l == laBurial && !shmup::on) return not_implemented; if(l == laMirrorOld && !shmup::on) return not_implemented; } + + if(ls::hv_structure() && among(l, laPrairie, laIvoryTower, laDungeon, laEndorian, laBrownian, laTortoise, laElementalWall)) return not_in_hv; if(l == laBrownian) { if(quotient || !hyperbolic || cryst) return dont_work; @@ -935,12 +941,14 @@ EX land_validity_t& land_validity(eLand l) { if(l == laWhirlwind && hyperbolic_not37) return pattern_incompatibility; + bool better_mirror = !geometry && STDVAR && !ls::hv_structure(); + // available only in non-standard geometries - if(l == laMirrorOld && !geometry && STDVAR) + if(l == laMirrorOld && better_mirror) return better_version_exists; // available only in standard geometry - if(l == laMirror && (geometry || NONSTDVAR)) + if(l == laMirror && !better_mirror) return not_implemented; // Halloween needs bounded world (can be big bounded) diff --git a/system.cpp b/system.cpp index 7c7b9737..9038d1c1 100644 --- a/system.cpp +++ b/system.cpp @@ -1770,6 +1770,7 @@ auto cgm = addHook(hooks_clearmemory, 40, [] () { crush_next.clear(); crush_now.clear(); rosemap.clear(); + horodisk_land.clear(); for(auto &am: adj_memo) am.clear(); }) + addHook(hooks_gamedata, 0, [] (gamedata* gd) {