From 4b1b0516f3cb1815d992b3cee08c319b7b00bb28 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sun, 11 Apr 2021 22:15:40 +0200 Subject: [PATCH] choice of the land structure --- achievement.cpp | 21 +++-- bigstuff.cpp | 221 ++++++++++++++++++++++++++-------------------- binary-tiling.cpp | 4 +- celldrawer.cpp | 10 +-- complex.cpp | 18 ++-- config.cpp | 11 +-- debug.cpp | 16 +--- environment.cpp | 2 +- geom-exp.cpp | 15 +--- graph.cpp | 2 +- help.cpp | 2 +- hyper.h | 2 +- inventory.cpp | 6 +- items.cpp | 12 +-- landgen.cpp | 107 +++++++++++----------- landlock.cpp | 140 +++++++++++++++++++++-------- legacy.cpp | 43 ++++++++- mapeffects.cpp | 2 +- menus.cpp | 64 +++++++++----- monstergen.cpp | 2 +- multigame.cpp | 2 +- orbgen.cpp | 4 +- pattern2.cpp | 5 ++ pcmove.cpp | 2 +- quit.cpp | 2 +- scores.cpp | 2 +- system.cpp | 61 ++++++------- yendor.cpp | 12 ++- 28 files changed, 473 insertions(+), 317 deletions(-) diff --git a/achievement.cpp b/achievement.cpp index 97cd96c6..6cdd3c5e 100644 --- a/achievement.cpp +++ b/achievement.cpp @@ -125,7 +125,12 @@ EX bool wrongMode(char flags) { #if CAP_TOUR if(tour::on) return true; #endif - if((!!chaosmode) != (flags == rg::chaos)) return true; + if(flags == rg::special_geometry && !ls::single()) + return true; + if(flags != rg::special_geometry && ineligible_starting_land) + return true; + if(flags == rg::chaos && !ls::std_chaos()) return true; + if(flags != rg::chaos && flags != rg::special_geometry && !ls::nice_walls()) return true; if((numplayers() > 1) != (flags == rg::multi)) return true; return false; } @@ -610,7 +615,10 @@ EX void achievement_score(int cat, int number) { if(geometry != gSphere && geometry != gElliptic) return; } - else if(geometry) return; + else { + if(geometry) return; + if(ineligible_starting_land) return; + } if(CHANGED_VARIATION) return; if(randomPatternsMode) return; if(dual::state) return; @@ -731,7 +739,8 @@ EX void achievement_final(bool really_final) { int specialcode = 0; if(shmup::on) specialcode++; - if(chaosmode) specialcode+=2; + if(ls::std_chaos()) specialcode+=2; + else if(!ls::nice_walls()) return; if(PURE) specialcode+=4; if(numplayers() > 1) specialcode+=8; if(inv::on) specialcode+=16; @@ -742,6 +751,7 @@ EX void achievement_final(bool really_final) { return; } + if(ineligible_starting_land) return; if(geometry) return; if(NONSTDVAR) return; @@ -828,7 +838,8 @@ EX void achievement_victory(bool hyper) { if(yendor::on) return; if(peace::on) return; if(tactic::on) return; - if(chaosmode) return; + if(!ls::nice_walls()) return; + if(!ineligible_starting_land) return; LATE( achievement_victory(hyper); ) DEBB(DF_STEAM, ("after checks")) @@ -904,7 +915,7 @@ EX string get_rich_presence_text() { if(geometry != gNormal || !BITRUNCATED) res = res + full_geometry_name() + " "; - if(chaosmode) res += "chaos "; + if(ls::any_chaos()) res += land_structure_name(false) + " "; // TODO if(shmup::on) res += "shmup "; if(dual::state) res += "dual "; if(randomPatternsMode) res += "random "; diff --git a/bigstuff.cpp b/bigstuff.cpp index bd1b2e84..ba3dfbfa 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -480,7 +480,7 @@ EX cell *buildAnotherEquidistant(cell *c, int radius) { bool oc = c->land == laOcean; // else if(ctof(c) && hrand(10000) < 20 && !isCrossroads(c->land) && gold() >= 200) - if(oc && weirdhyperbolic && specialland == laCrossroads4 && buildBarrierNowall(c2, getNewLand(laOcean))) { + if(oc && ls::no_walls() && buildBarrierNowall(c2, getNewLand(laOcean))) { nowall = true; } else if(oc && pseudohept(c2) && gold() >= R200 && hrand(10) < 2 && buildBarrierNowall(c2, laCrossroads4)) { @@ -488,7 +488,7 @@ EX cell *buildAnotherEquidistant(cell *c, int radius) { // raiseBuggyGeneration(c2, "check"); // return; } - else if(!weirdhyperbolic) buildBarrier(c2, bd); + else if(ls::nice_walls()) buildBarrier(c2, bd); //printf("building barrier II\n"); if(hasbardir(c2)) extendBarrier(c2); @@ -571,7 +571,7 @@ EX void buildEquidistant(cell *c) { } */ if(sphere || euclid) return; eLand b = c->land; - if(chaosmode && !inmirror(b)) return; + if(ls::any_chaos() && !inmirror(b)) return; if(!b) { printf("land missing at %p\n", hr::voidp(c)); describeCell(c); @@ -815,12 +815,10 @@ EX void buildEquidistant(cell *c) { } } - bool chance = true; - if(weirdhyperbolic) { - chance = false; - if(specialland == laCrossroads4) - chance = hrand(100) < 10; - } + bool chance = + ls::no_walls() ? (hrand(100) < 10) : + ls::nice_walls() ? true : + false; if(c->landparam > 30 && b == laOcean && !generatingEquidistant && !hybri && hrand(10) < 5 && chance) buildAnotherEquidistant(c); @@ -972,12 +970,12 @@ bool valid_wall_at(int c) { } EX eLand switchable(eLand nearland, eLand farland, int c) { - if(chaosmode) { + if(ls::std_chaos()) { if(hrand(6) == 0) return getNewLand(nearland); return nearland; } - else if(specialland == laCrossroads4) { + else if(ls::no_walls()) { if((dual::state && nearland == laCrossroads4) || hrand(15) == 0) return getNewLand(nearland); if(nearland == laCrossroads4 && (nonisotropic || hybri)) @@ -1017,15 +1015,15 @@ EX eLand getEuclidLand(int c) { EX void setLandSol(cell *c) { setland(c, specialland); - if(chaosmode) { + if(ls::std_chaos()) { setland(c, getEuclidLand(c->master->distance)); return; } - switch(specialland) { - case laCrossroads4: case laCrossroads: case laCrossroads2: - setland(c, getEuclidLand(c->master->distance)); - if(c->land == laBarrier && c->master->emeraldval % 3) c->wall = waBarrier; - break; + else if(ls::nice_walls()) { + setland(c, getEuclidLand(c->master->distance)); + if(c->land == laBarrier && c->master->emeraldval % 3) c->wall = waBarrier; + } + switch(c->land) { case laTerracotta: if((c->master->distance & 15) == 1) { setland(c, laMercuryRiver); @@ -1045,17 +1043,17 @@ EX void setLandHybrid(cell *c) { auto w = hybrid::get_where(c); auto d = w.second; + bool ps = PIU(pseudohept(w.first)); setland(c, specialland); - if(chaosmode) { - setland(c, getEuclidLand(c->master->distance)); + if(ls::any_nowall()) { + setland(c, getEuclidLand(d)); return; } - bool ps = PIU(pseudohept(w.first)); - switch(specialland) { - case laCrossroads4: case laCrossroads: case laCrossroads2: - setland(c, getEuclidLand(d)); - if(c->land == laBarrier) c->wall = ps ? waNone : waBarrier; - break; + else if(ls::any_wall()) { + setland(c, getEuclidLand(d)); + if(c->land == laBarrier) c->wall = ps ? waNone : waBarrier; + } + switch(c->land) { case laTerracotta: if((d & 15) == 1) { setland(c, laMercuryRiver); @@ -1085,23 +1083,23 @@ EX void setLandHybrid(cell *c) { EX void setLandNil(cell *c) { setland(c, specialland); - if(chaosmode) { + if(ls::patched_chaos()) { int hash = (((c->master->zebraval + 4) >> 3) << 16) + ((c->master->emeraldval + 4) >> 3); auto& l = euland3_hash[hash]; if(l == laNone) l = getNewLand(laNone); setland(c, l); return; } - - switch(specialland) { - case laCrossroads: case laCrossroads4: - setland(c, getEuclidLand(c->master->zebraval)); - if(c->land == laBarrier && c->master->emeraldval % 3) c->wall = waBarrier; - break; - case laCrossroads2: - setland(c, getEuclidLand(c->master->emeraldval)); - if(c->land == laBarrier && c->master->zebraval % 3) c->wall = waBarrier; - break; + else if(ls::nice_walls()) { + setland(c, getEuclidLand(c->master->zebraval)); + if(c->land == laBarrier && c->master->emeraldval % 3) c->wall = waBarrier; + } + else if(ls::no_walls()) { + setland(c, getEuclidLand(c->master->emeraldval)); + if(c->land == laBarrier && c->master->zebraval % 3) c->wall = waBarrier; + } + + switch(c->land) { case laCrossroads3: { int ox = c->master->zebraval - 8; int oy = c->master->emeraldval - 8; @@ -1144,17 +1142,17 @@ EX void setLandEuclid(cell *c) { } #endif setland(c, specialland); - if(specialland == laCrossroads4 || chaosmode) { + if(ls::any_nowall()) { auto co = euc2_coordinates(c); int y = co.second; c->land = getEuclidLand(y); } - if(specialland == laCrossroads) { + if(ls::any_wall()) { auto co = euc2_coordinates(c); int x = co.first, y = co.second; setland(c, getEuclidLand(y+2*x)); } - if(specialland == laTerracotta) { + if(c->land == laTerracotta) { auto co = euc2_coordinates(c); int x = co.first, y = co.second; if(((y+2*x) & 15) == 1) { @@ -1228,7 +1226,7 @@ EX void setLandEuclid(cell *c) { setland(c, laElementalWall); } } - if(specialland == laCrossroads3) { + if(c->land == laCrossroads3) { auto co = euc2_coordinates(c); int x = co.first, y = co.second; int y0 = euc::in(2,4) ? 2 * y - x : y; @@ -1269,46 +1267,42 @@ EX eLand get_euland3(int x) { EX void set_euland3(cell *c, int co10, int co11, int alt, int hash) { - if(chaosmode) { + if(ls::std_chaos()) { setland(c, get_euland3(gdiv(co10, 60))); } - else if(specialland == laCrossroads) { + else if(ls::nice_walls()) { eLand l1 = get_euland3(gdiv(co10, 360)); eLand l2 = get_euland3(gdiv(co10+59, 360)); if(l1 != l2 && hrand(100) < 75) setland(c, laBarrier); else setland(c, l1); } - else if(specialland == laCrossroads2) { + else if(ls::no_walls()) { setland(c, get_euland3(alt/4)); } - else if(specialland == laCrossroads3) { + else if(ls::patched_chaos()) { auto& l = euland3_hash[hash]; if(l == laNone) l = getNewLand(laBarrier); setland(c, l); } - else if(specialland == laCrossroads4) { - setland(c, get_euland3(gdiv(co10, 360))); - } - - else if(specialland == laElementalWall) { + if(c->land == laElementalWall) { setland(c, eLand(laEFire + ((co10 / 240)&1?0:2) + ((co11 / 240)&1?0:1))); } - if(specialland == laCamelot) { + if(c->land == laCamelot) { setland(c, laCrossroads); buildCamelot(c); } - if(specialland == laTerracotta) { + if(c->land == laTerracotta) { if(((alt&15) == 8) && hrand(100) < 90) c->wall = waMercury; } - if(among(specialland, laOcean, laIvoryTower, laDungeon, laEndorian)) { + if(among(c->land, laOcean, laIvoryTower, laDungeon, laEndorian)) { if(alt == 0) c->land = laCrossroads4; else if(alt > 0) @@ -1317,7 +1311,7 @@ EX void set_euland3(cell *c, int co10, int co11, int alt, int hash) { c->landparam = -alt; } - if(specialland == laWarpCoast) { + if(c->land == laWarpCoast) { if(gmod(co10, 240) >= 120) c->land = laWarpSea; } @@ -1325,9 +1319,11 @@ EX void set_euland3(cell *c, int co10, int co11, int alt, int hash) { // the main big stuff function +EX bool easy_to_find_specialland = false; + EX bool quickfind(eLand l) { if(l == cheatdest) return true; - if(l == specialland && (weirdhyperbolic || specialland != laIce || cheater)) return true; + if(l == specialland && easy_to_find_specialland) return true; #if CAP_TOUR if(tour::on && tour::quickfind(l)) return true; #endif @@ -1363,8 +1359,7 @@ EX int wallchance(cell *c, bool deepOcean) { l == laCrossroads2 ? 10000 : l == laCrossroads5 ? 10000 : l == laCrossroads4 ? (weirdhyperbolic ? 5000 : 0) : - (l == laMirror && !yendor::generating) ? 6000 : - l == laTerracotta ? 250 : + (l == laMirror && !yendor::generating) ? 2500 : tactic::on ? 0 : racing::on ? 0 : l == laCaribbean ? 500 : @@ -1433,36 +1428,61 @@ EX bool good_for_wall(cell *c) { } EX bool walls_not_implemented() { + if(sphere || quotient || nonisotropic || (kite::in() && !bt::in()) || experimental) return true; return WDIM == 3 && (cgflags & qIDEAL); } - -EX void buildBigStuff(cell *c, cell *from) { - if(sphere || quotient || nonisotropic || (kite::in() && !bt::in()) || experimental) return; - if(chaosmode > 1) return; + +EX bool nice_walls_available() { + return (geometry == gNormal && (PURE || BITRUNCATED)) || (geometry == gEuclid && !(INVERSE | IRREGULAR)); + } + +EX void build_walls(cell *c, cell *from) { bool deepOcean = deep_ocean_at(c, from); // if(weirdhyperbolic && c->land == laOcean) deepOcean = c->landparam >= 30; // buildgreatwalls - if(hybri) ; /* Great Walls generated via the underlying geometry */ + if(hybri) return; /* Great Walls generated via the underlying geometry */ - else if(walls_not_implemented()); // walls not implemented here + if(walls_not_implemented()) return; // walls not implemented here + + if(ls::chaoticity() >= 60) return; - else if(geometry == gNormal && celldist(c) < 3 && !GOLDBERG) { + if(nice_walls_available()) { + if(ctof(c) && c->land == laMirror && !yendor::generating && hrand(I10000) < 6000) { + int bd = 2 + hrand(2) * 3; + buildBarrier(c, bd, laMirrored); + return; + } + + if(ctof(c) && c->land == laTerracotta && hrand(I10000) < 200) { + int bd = 2 + hrand(2) * 3; + buildBarrier(c, bd, laMirrored); + return; + } + } + + if(ls::single()) return; + + if(geometry == gNormal && celldist(c) < 3 && !GOLDBERG) { if(top_land && c == cwt.at->master->move(3)->c7) { buildBarrierStrong(c, 6, true, top_land); } } - else if(chaosmode) { - if(good_for_wall(c) && hrand(10000) < 9000 && c->land && !inmirror(c) && buildBarrierNowall(c, getNewLand(c->land))) - {} - else if(ctof(c) && c->land == laMirror && hrand(10000) < 2000 && !weirdhyperbolic) { - int bd = 2 + hrand(2) * 3; - buildBarrier(c, bd, laMirrored); + else if(ls::wall_chaos()) { + if(good_for_wall(c) && hrand(10000) < 9000 && c->land && !inmirror(c)) { + int bd = 2 + hrand(2) * 3; + buildBarrier(c, bd); + return; } } + + else if(ls::std_chaos()) { + if(good_for_wall(c) && hrand(10000) < 9000 && c->land && !inmirror(c) && buildBarrierNowall(c, getNewLand(c->land))) + return; + } else if(good_for_wall(c) && isWarpedType(c->land) && hrand(10000) < 3000 && c->land && buildBarrierNowall(c, eLand(c->land ^ laWarpSea ^ laWarpCoast))) ; @@ -1481,7 +1501,7 @@ EX void buildBigStuff(cell *c, cell *from) { buildBarrierNowall(c, laCrossroads4) ; } - else if(weirdhyperbolic && specialland == laCrossroads4 && /*pseudohept(c) &&*/ hrand(I10000 /4) < wallchance(c, deepOcean) && gp_wall_test()) { + else if(ls::no_walls() && hrand(I10000 /4) < wallchance(c, deepOcean) && gp_wall_test()) { buildBarrierNowall(c, getNewLand(c->land)); } @@ -1496,13 +1516,13 @@ EX void buildBigStuff(cell *c, cell *from) { else if(S3 >= OINF && c->land && hrand(I10000) < wallchance(c, deepOcean) && c->bardir != NOBARRIERS) buildBarrierNowall(c, getNewLand(c->land)); - else if(weirdhyperbolic) ; // non-Nowall barriers not implemented yet in weird hyperbolic + else if(!nice_walls_available()) ; // non-Nowall barriers not implemented yet in weird hyperbolic else if(c->land == laCrossroads2 && BITRUNCATED) buildCrossroads2(c); #if CAP_FIELD - else if(c->land == laPrairie && c->LHU.fi.walldist == 0 && !euclid) { + else if(c->land == laPrairie && c->LHU.fi.walldist == 0 && !euclid && ls::nice_walls()) { for(int bd=0; bd<7; bd++) { int fval2 = createStep(c->master, bd)->fieldval; int wd = currfp_gmul(fval2, currfp_inverses(c->fval-1)); @@ -1514,7 +1534,7 @@ EX void buildBigStuff(cell *c, cell *from) { } #endif - else if(ctof(c) && c->land && hrand(I10000) < wallchance(c, deepOcean)) + else if(ctof(c) && c->land && ls::nice_walls() && hrand(I10000) < wallchance(c, deepOcean)) { int bd = 2 + hrand(2) * 3; @@ -1524,25 +1544,33 @@ EX void buildBigStuff(cell *c, cell *from) { /* int bd = 2; buildBarrier4(c, bd, 0, getNewLand(c->land), c->land); */ } - - if((!chaosmode) && bearsCamelot(c->land) && is_master(c) && !bt::in() && - #if MAXMDIM >= 4 - !(hyperbolic && WDIM == 3 && !reg3::in_rule()) && - #endif - (quickfind(laCamelot) || peace::on || (hrand(I2000) < (c->land == laCrossroads4 ? 800 : 200) && horo_ok() && - items[itEmerald] >= U5 && !tactic::on && !racing::on))) { - int rtr = newRoundTableRadius(); - heptagon *alt = createAlternateMap(c, rtr+(hyperbolic && WDIM == 3 ? 11 : 14), hsOrigin); - if(alt) { - alt->emeraldval = rtr; - alt->fiftyval = c->land; - } - } + } - if(!chaosmode) { +EX void build_horocycles(cell *c, cell *from) { + + bool deepOcean = deep_ocean_at(c, from); + + if(!ls::any_order() && !ls::single()) return; + + if(ls::single() && !among(specialland, laTemple, laMountain, laClearing, laStorms, laWhirlpool, laCaribbean, laCanvas, laPrincessQuest, laCamelot)) + return; // buildbigstuff + if(ls::any_order() && bearsCamelot(c->land) && is_master(c) && !bt::in() && + #if MAXMDIM >= 4 + !(hyperbolic && WDIM == 3 && !reg3::in_rule()) && + #endif + (quickfind(laCamelot) || peace::on || (hrand(I2000) < (c->land == laCrossroads4 ? 800 : 200) && horo_ok() && + items[itEmerald] >= U5 && !tactic::on && !racing::on))) { + int rtr = newRoundTableRadius(); + heptagon *alt = createAlternateMap(c, rtr+(hyperbolic && WDIM == 3 ? 11 : 14), hsOrigin); + if(alt) { + alt->emeraldval = rtr; + alt->fiftyval = c->land; + } + } + if(c->land == laRlyeh && ctof(c) && horo_ok() && (quickfind(laTemple) || peace::on || (hrand(I2000) < 100 && items[itStatue] >= U5 && !randomPatternsMode && @@ -1593,13 +1621,18 @@ EX void buildBigStuff(cell *c, cell *from) { celllister cl(c, 5, 1000000, NULL); for(cell *c: cl.lst) if(c->master->alt) currentmap->generateAlts(c->master); } - } + } - if(hasbardir(c)) extendBarrier(c); +EX void buildBigStuff(cell *c, cell *from) { + build_walls(c, from); + + build_horocycles(c, from); + + if(hasbardir(c)) extendBarrier(c); } EX bool openplains(cell *c) { - if(chaosmode) { + if(ls::any_chaos()) { forCellEx(c2, c) if(c2->land != laHunting) return false; return true; } @@ -1774,7 +1807,7 @@ EX void moreBigStuff(cell *c) { } } - if(chaosmode && c->land == laTemple) { + if(ls::any_chaos() && c->land == laTemple) { for(int i=0; itype; i++) if(pseudohept(c) && c->move(i) && c->move(i)->land != laTemple) c->wall = waColumn; @@ -1782,7 +1815,7 @@ EX void moreBigStuff(cell *c) { else if((c->land == laRlyeh && !euclid) || c->land == laTemple) if(!(bt::in() && specialland != laTemple && c->land == laRlyeh)) { if(eubinary || in_s2xe() || (c->master->alt && (tactic::on || masterAlt(c) <= horo_gen_distance()))) { - if(!eubinary && !chaosmode) currentmap->generateAlts(c->master); + if(!eubinary && !ls::any_chaos()) currentmap->generateAlts(c->master); preventbarriers(c); int d = celldistAlt(c); if(d <= 0) { @@ -1912,7 +1945,7 @@ EX vector currentlands; EX void pregen() { currentlands.clear(); - if(chaosmode > 1) + if(ls::any_chaos() && !ls::std_chaos()) for(eLand l: land_over) if(landUnlocked(l) && isLandIngame(l)) currentlands.push_back(l); diff --git a/binary-tiling.cpp b/binary-tiling.cpp index f2a7d2d4..871dfc47 100644 --- a/binary-tiling.cpp +++ b/binary-tiling.cpp @@ -108,13 +108,13 @@ EX namespace bt { if(!parent->emeraldval) parent->emeraldval = currentmap->gamestart()->land; eLand z = eLand(parent->emeraldval); int chance = 0; - if(specialland == laCrossroads4 || parent->emeraldval == laCrossroads4) { + if(ls::no_walls() || parent->emeraldval == laCrossroads4) { eLand x = parent->c7->land; parent->c7->land = z; chance = wallchance(parent->c7, deep_ocean_at(parent->c7, parent->c7)); parent->c7->land = x; } - if(chaosmode) chance = 1000; + if(ls::std_chaos()) chance = 1000; if(chance && hrand(40000) < chance) h->emeraldval = getNewLand(z); else diff --git a/celldrawer.cpp b/celldrawer.cpp index 388010bf..a0351d0d 100644 --- a/celldrawer.cpp +++ b/celldrawer.cpp @@ -100,11 +100,11 @@ void celldrawer::setcolors() { if(c->land == laOcean) fcol = #if CAP_FIELD - (c->landparam > 25 && !chaosmode) ? ( + (c->landparam > 25 && !ls::any_chaos()) ? ( 0x90 + 8 * sintick(1000, windmap::windcodes[windmap::getId(c)] / 256.) ) : #endif - 0x1010C0 + int(32 * sintick(500, (chaosmode ? c->CHAOSPARAM : c->landparam)*.75/M_PI)); + 0x1010C0 + int(32 * sintick(500, (ls::any_chaos() ? c->CHAOSPARAM : c->landparam)*.75/M_PI)); else if(c->land == laOceanWall) fcol = 0x2020FF; else if(c->land == laVariant) @@ -295,7 +295,7 @@ void celldrawer::setcolors() { break; case laTemple: { int d = (eubinary||c->master->alt) ? celldistAlt(c) : 99; - if(chaosmode) + if(ls::any_chaos()) fcol = 0x405090; else if(d % temple_layer_size() == 0) fcol = gradient(0x304080, winf[waColumn].color, 0, 0.5, 1); @@ -445,7 +445,7 @@ void celldrawer::setcolors() { break; case laOcean: - if(chaosmode) + if(ls::any_chaos()) fcol = gradient(0xD0A090, 0xD0D020, 0, c->CHAOSPARAM, 30); else fcol = gradient(0xD0D090, 0xD0D020, -1, sin((double) c->landparam), 1); @@ -1999,7 +1999,7 @@ void celldrawer::draw_wall_full() { #if CAP_SHAPES // floor - if(GDIM == 2 && (c->land != laRose || chaosmode)) { + if(GDIM == 2 && (c->land != laRose || ls::any_chaos())) { int rd = rosedist(c); if(rd == 1) draw_floorshape(c, mmscale(V, cgi.SLEV[2]), cgi.shRoseFloor, 0x80406040, PPR::LIZEYE); diff --git a/complex.cpp b/complex.cpp index 33fdea96..01a9f44b 100644 --- a/complex.cpp +++ b/complex.cpp @@ -1986,11 +1986,11 @@ EX namespace hive { cellwalker bf(c, gdir); int radius = 9; if(getDistLimit() <= 6) radius = 6; - if(chaosmode) radius = 5; - if(chaosmode && getDistLimit() <= 5) radius = 4; + if(ls::any_chaos()) radius = 5; + if(ls::any_chaos() && getDistLimit() <= 5) radius = 4; if(getDistLimit() <= 3) radius = 3; - for(int i=(chaosmode?0:2); iland != laCaves && c2->land != laEmerald) ; + else if(ls::any_chaos() && c2->land != laCaves && c2->land != laEmerald) ; else if(c2->land == laTrollheim) ; // trollheim floor does not count else if(w != waBarrier) hv += 5; @@ -3107,9 +3107,9 @@ EX namespace prairie { c->LHU.fi.walldist = 8; c->LHU.fi.walldist2 = 8; - if(chaosmode) { - c->LHU.fi.rval = 0; - } + if(ls::any_chaos()) { + c->LHU.fi.rval = 0; + } else if(quotient) { // fix cylinder c->LHU.fi.rval = 0; } @@ -3301,7 +3301,7 @@ EX namespace prairie { } EX void move() { - if(chaosmode) return; + if(ls::any_chaos()) return; manual_celllister cl; for(int i=0; iitem && c2->cpdist == distlimit && itemclass(c2->item) == IC_TREASURE && c2->item != itBabyTortoise && - (items[c2->item] >= (chaosmode?10:20) + currentLocalTreasure || getGhostcount() >= 2)) { + (items[c2->item] >= (ls::any_chaos()?10:20) + currentLocalTreasure || getGhostcount() >= 2)) { c2->item = itNone; if(c2->land == laMinefield) { c2->landparam &= ~3; } } diff --git a/geom-exp.cpp b/geom-exp.cpp index f1988b67..038ac4cb 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -151,7 +151,7 @@ EX bool showquotients; string validclasses[4] = {" (X)", " (½)", "", " (!)"}; -void ge_land_selection() { +EX void ge_land_selection() { cmode = sm::SIDE | sm::MAYDARK; gamescreen(0); @@ -210,16 +210,6 @@ void ge_land_selection() { })); }); } - dialog::addBreak(50); - if(chaosUnlocked && !quotient && !euclid && !sphere && !walls_not_implemented()) { - dialog::addItem(XLAT("Chaos mode"), '1'); - dialog::add_action(dual::mayboth([] { - if(chaosUnlocked) dialog::do_if_confirmed([] { - stop_game_and_switch_mode(rg::chaos); - start_game(); - }); - })); - } dialog::addItem(XLAT("next page"), '-'); dialog::addBreak(25); @@ -1006,8 +996,7 @@ EX void showEuclideanMenu() { } dialog::addBreak(100); - dialog::addSelItem(XLAT("land"), XLAT1(linf[specialland].name), 'l'); - dialog::add_action_push(ge_land_selection); + menuitem_land_structure('l'); if(specialland == laMinefield && bounded) { dialog::addSelItem(XLAT("number of mines"), its(bounded_mine_quantity), 'm'); diff --git a/graph.cpp b/graph.cpp index eedd0e9b..53b20946 100644 --- a/graph.cpp +++ b/graph.cpp @@ -3337,7 +3337,7 @@ EX void floorShadow(cell *c, const shiftmatrix& V, color_t col) { EX bool use_warp_graphics() { if(shmup::on) return false; if(geosupport_football() != 2) return false; - if(chaosmode == 3 || chaosmode == 4) return false; + if(ls::chaoticity() >= 75) return false; return true; } diff --git a/help.cpp b/help.cpp index ef9326f9..b8859cc5 100644 --- a/help.cpp +++ b/help.cpp @@ -836,7 +836,7 @@ EX void describeMouseover() { out += XLAT(" (level %1)", its(snakelevel(c))); if(c->land == laDryForest && c->landparam) out += " (" + its(c->landparam)+"/10)"; - if(c->land == laOcean && chaosmode) + if(c->land == laOcean && ls::any_chaos()) out += " (" + its(c->CHAOSPARAM)+"S"+its(c->SEADIST)+"L"+its(c->LANDDIST)+")"; else if(c->land == laOcean && c->landparam <= 25) { if(shmup::on) diff --git a/hyper.h b/hyper.h index eb623a81..3bada3aa 100644 --- a/hyper.h +++ b/hyper.h @@ -429,7 +429,7 @@ extern videopar vid; #define BUGCOLORS 3 -#define big_unlock (inv::on && !chaosmode) +#define big_unlock (inv::on && !ls::any_chaos()) // land completion for shared unlocking #define U5 (big_unlock ? 10 : 5) diff --git a/inventory.cpp b/inventory.cpp index cdf9ba9d..b54406e7 100644 --- a/inventory.cpp +++ b/inventory.cpp @@ -146,7 +146,7 @@ EX namespace inv { } else { bool nextfound = false; - int fst = (chaosmode ? 5 : 10); + int fst = (ls::any_chaos() ? 5 : 10); if(qty >= fst) remaining[o]++; else { if(whichorbinfo == o) { @@ -162,7 +162,7 @@ EX namespace inv { } int last = fst; for(int k=0; k<30 || !nextfound; k++) { - int maxstep = chaosmode ? 10 + 2 * k : 15 + 5 * k; + int maxstep = ls::any_chaos() ? 10 + 2 * k : 15 + 5 * k; if(o == itOrbMirror) maxstep += 5 * (k-1) * (k-2); else @@ -243,7 +243,7 @@ EX namespace inv { for(auto& oi: orbinfos) { if(oi.flags & orbgenflags::OSM_AT10) { eItem it = treasureType(oi.l); - int fst = chaosmode ? 5 : 10; + int fst = ls::any_chaos() ? 5 : 10; if(items[it] >= fst) { remaining[oi.orb]++; } diff --git a/items.cpp b/items.cpp index bc61529a..f6a465b3 100644 --- a/items.cpp +++ b/items.cpp @@ -476,7 +476,7 @@ EX void gainItem(eItem it) { if(it == itHyperstone && items[itHyperstone] == 10) achievement_victory(true); - if(chaosmode && gold() >= 300) + if(ls::any_chaos() && gold() >= 300) achievement_gain_once("CHAOS", rg::chaos); #if ISMOBILE @@ -533,7 +533,7 @@ EX void placeItems(int qty, eItem it) { } EX bool cantGetGrimoire(cell *c2, bool verbose IS(true)) { - if(chaosmode) return false; + if(ls::any_chaos()) return false; if(!eubinary && !c2->master->alt) return false; if(c2->item == itGrimoire && items[itGrimoire] > celldistAlt(c2)/-temple_layer_size()) { if(verbose) @@ -624,13 +624,13 @@ EX void collectMessage(cell *c2, eItem which) { else if(which == itPalace && items[itPalace] == U5-1 && !specialmode && isLandIngame(laDungeon)) { addMessage(XLAT("The rug depicts a man in a deep dungeon, unable to leave.")); } - else if(which == itFeather && items[itFeather] == 25-1 && !specialmode && inv::on && !chaosmode) + else if(which == itFeather && items[itFeather] == 25-1 && !specialmode && inv::on && !ls::any_chaos()) addMessage(XLAT("You feel the presence of free saves on the Crossroads.")); - else if(which == itHell && items[itHell] == 25-1 && !specialmode && inv::on && !chaosmode) + else if(which == itHell && items[itHell] == 25-1 && !specialmode && inv::on && !ls::any_chaos()) addMessage(XLAT("You feel the Orbs of Yendor nearby...")); - else if(which == itHell && items[itHell] == 50-1 && !specialmode && inv::on && !chaosmode) + else if(which == itHell && items[itHell] == 50-1 && !specialmode && inv::on && !ls::any_chaos()) addMessage(XLAT("You feel the Orbs of Yendor in the Crossroads...")); - else if(which == itHell && items[itHell] == 100-1 && !specialmode && inv::on && !chaosmode) + else if(which == itHell && items[itHell] == 100-1 && !specialmode && inv::on && !ls::any_chaos()) addMessage(XLAT("You feel the Orbs of Yendor everywhere...")); else if(which == itBone && items[itBone] % 25 == 24 && !specialmode && inv::on) addMessage(XLAT("You have gained an offensive power!")); diff --git a/landgen.cpp b/landgen.cpp index 2d17c67f..0a99c509 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -35,7 +35,7 @@ EX void doOvergenerate() { EX bool notDippingFor(eItem i) { if(peace::on) return false; - if(chaosmode > 1) return true; + if(ls::chaoticity() >= 60) return true; int v = items[i] - currentLocalTreasure; if(v <= 10) return true; if(v >= 20) return false; @@ -44,7 +44,7 @@ EX bool notDippingFor(eItem i) { EX bool notDippingForExtra(eItem i, eItem x) { if(peace::on) return false; - if(chaosmode > 1) return true; + if(ls::chaoticity() >= 60) return true; int v = items[i] - min(items[x], currentLocalTreasure); if(v <= 10) return true; if(v >= 20) return false; @@ -273,7 +273,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { case laPrairie: // ------------------------------------------------------------- - if(d == 7 && chaosmode) { + if(d == 7 && ls::any_chaos()) { if(hrand_monster(9000) < items[itGreenGrass] - (prairie::isriver(cwt.at) ? 40 : 0) && !safety) c->monst = moGadfly; if(hrand_monster(100) < 5) c->monst = moSleepBull; @@ -894,17 +894,17 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { case laTrollheim: if(fargen) { - if(hrand(50000) < (chaosmode==1?1000:chaosmode?50:5) && c->wall != waBarrier && celldist(c) >= 7 && !safety && !peace::on) { + if(hrand(50000) < (ls::tame_chaos() ? 1000: ls::any_chaos() ?50:5) && c->wall != waBarrier && celldist(c) >= 7 && !safety && !peace::on) { bool okay = true; forCellCM(c2, c) forCellCM(c3, c2) forCellCM(c4, c3) forCellCM(c5, c4) { - cell *cx = chaosmode ? c3 : c5; + cell *cx = ls::any_chaos() ? c3 : c5; if(cx->land != laTrollheim && cx->land != laNone) okay = false; if(cx->bardir != NODIR) okay = false; } if(okay) { forCellCM(c2, c) forCellCM(c3, c2) forCellCM(c4, c3) forCellCM(c5, c4) { - cell *cx = chaosmode ? c3 : c5; + cell *cx = ls::any_chaos() ? c3 : c5; cx->bardir = NOBARRIERS; setland(cx, laTrollheim); } @@ -1575,10 +1575,10 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { ONEMPTY { // depth! int d = - chaosmode ? -15 * items[itGrimoire]: + ls::any_chaos() ? -15 * items[itGrimoire]: (eubinary || c->master->alt) ? celldistAlt(c) : 10; // remember: d is negative - if(chaosmode ? hrand(100) < 25 : d % temple_layer_size() == 0) { + if(ls::any_chaos() ? hrand(100) < 25 : d % temple_layer_size() == 0) { if(hrand_monster(5000) < 20 - 2*d && !c->monst && !peace::on) c->monst = moTentacle, c->mondir = NODIR; } @@ -1593,7 +1593,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { c->monst = moCultistLeader; else if(hrand(5000) < 250 && !peace::on) c->item = itGrimoire; - else if(hrand(5000) < 10 && (chaosmode ? items[itGrimoire] >= treasureForLocal() : -d > temple_layer_size() * 10) && !peace::on && !inv::on) + else if(hrand(5000) < 10 && (ls::any_chaos() ? items[itGrimoire] >= treasureForLocal() : -d > temple_layer_size() * 10) && !peace::on && !inv::on) c->item = itOrbDragon; } } @@ -1615,9 +1615,9 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { ONEMPTY { if(hrand(6000) < PT(120 + (kills[moLesser]), 240) && notDippingFor(itHell)) c->item = itHell; - if(hrand_monster(8000) < 40 + items[itHell] * (chaosmode?4:1) + yendor::hardness()) + if(hrand_monster(8000) < 40 + items[itHell] * (ls::any_chaos()?4:1) + yendor::hardness()) c->monst = moLesser; - else if(hrand_monster(24000) < 40 + items[itHell] * (chaosmode?4:1) + yendor::hardness()) + else if(hrand_monster(24000) < 40 + items[itHell] * (ls::any_chaos()?4:1) + yendor::hardness()) c->monst = moGreater; } break; @@ -1653,7 +1653,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { case laHive: if(fargen) { - if(hrand(2000) < (chaosmode==1 ? 1000 : (PURE && !chaosmode) ?200: chaosmode ? 10 : 2) && !safety) + if(hrand(2000) < (ls::tame_chaos() ? 1000 : (PURE && !ls::any_chaos()) ?200: ls::any_chaos() ? 10 : 2) && !safety) hive::createBugArmy(c); if(hrand(2000) < 100 && !c->wall && !c->item && !c->monst) { int nww = 0; @@ -1918,7 +1918,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { if(hrand(1000) < 150 && celldist(c) >= 3 && !pseudohept(c)) c->wall = waSmallTree; int q = 0; - if(BITRUNCATED && !chaosmode && !weirdhyperbolic) for(int i=0; itype; i++) + if(BITRUNCATED && !ls::any_chaos() && !weirdhyperbolic) for(int i=0; itype; i++) if(c->move(i) && !isWarpedType(c->move(i)->land) && c->move(i)->land != laCrossroads4) q++; if(q == 1) c->wall = waWarpGate; @@ -1927,7 +1927,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { if(c->land == laWarpSea) { c->wall = waSea; int q = 0; - if(BITRUNCATED && !chaosmode) for(int i=0; itype; i++) + if(BITRUNCATED && !ls::any_chaos()) for(int i=0; itype; i++) if(c->move(i) && !isWarpedType(c->move(i)->land)) q++; if(q == 1) c->wall = waWarpGate; } @@ -1994,7 +1994,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 && !chaosmode) for(int j=0; jtype; j++) { + if(c2 && !ls::any_chaos()) 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 @@ -2009,7 +2009,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { } ONEMPTY { if(hrand(2000) < PT(25 + min(kills[moFalsePrincess] + kills[moRoseBeauty] + kills[moRoseLady], 200), 100) && notDippingFor(itRose)) { - if(chaosmode == 3) + if(land_structure == lsTotalChaos) c->item = itRose; else for(int t=0; ttype; t++) if(c->move(t) && c->move(t)->wall == waRose) c->item = itRose; @@ -2118,7 +2118,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { if(placecolumn) c->wall = waColumn; - else if((c->landparam >= 1 && c->landparam <= 25) || chaosmode) { + else if((c->landparam >= 1 && c->landparam <= 25) || ls::any_chaos()) { if(hrand(1000) < 5) c->wall = waBoat; if(hrand(1000) < PT(50 + kills[moAlbatross]/2, 150) && !peace::on) @@ -2292,8 +2292,8 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { chasmify(c); c->wall = shmup::on ? waNone : waChasm; } - int cmf[5] = {0, 1, 3, 5, 10}; - if(inv::on && chaosmode && items[itFeather] && hrand(1000) < cmf[chaosmode] && !c->item && !c->monst) + int cmf[10] = {0, 1, 3, 5, 10, 0, 0, 0, 0, 0}; + if(inv::on && ls::any_chaos() && items[itFeather] && hrand(1000) < cmf[land_structure] && !c->item && !c->monst) c->item = itOrbSafety; } break; @@ -2648,7 +2648,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { c->wall = wetwalls[a]; } bool border = false; - if(!chaosmode) forCellEx(c1, c) if(c1->land != laWet) border = true; + if(ls::any_order()) forCellEx(c1, c) if(c1->land != laWet) border = true; if(border) { if(pseudohept(c)) c->wall = waDeepWater; else c->wall = waShallow; @@ -2756,8 +2756,29 @@ EX void setland_randomwalk(cell *c) { } EX void set_land_for_geometry(cell *c) { - if(0); - else if(chaosmode > 1) ; + + if(!c->land && isize(currentlands)) { + if(land_structure == lsTotalChaos) { + setland(c, currentlands[hrand(isize(currentlands))]); + return; + } + if(ls::patched_chaos() && stdeuc) { /* note: Nil pached chaos done in setLandNil */ + cell *c2 = c; + while(true) { + forCellCM(c3, c2) if(cdist50(c3) < cdist50(c2)) { c2 = c3; goto again; } + break; + again: ; + } + if(!c2->land) setland(c2, currentlands[hrand(isize(currentlands))]); + c->land = c2->land; + return; + } + if(land_structure == lsChaosRW) { + setland_randomwalk(c); + return; + } + } + else if(ls::chaoticity() >= 60) ; #if CAP_CRYSTAL else if(cryst) crystal::set_land(c); #endif @@ -2828,35 +2849,19 @@ EX void setdist(cell *c, int d, cell *from) { } #endif - if(!c->land && from && (WDIM == 3 || !among(from->land, laBarrier, laElementalWall, laHauntedWall, laOceanWall)) && !quotient && !(chaosmode > 1)) { + if(!c->land && from && (WDIM == 3 || !among(from->land, laBarrier, laElementalWall, laHauntedWall, laOceanWall)) && !quotient && ls::chaoticity() < 60) { if(!hasbardir(c)) setland(c, from->land); } - if(c->land == laTemple && !tactic::on && !chaosmode) setland(c, laRlyeh); - if(c->land == laMountain && !tactic::on && !chaosmode) setland(c, laJungle); - if(c->land == laClearing && !tactic::on) setland(c, laOvergrown); - if(c->land == laWhirlpool && !tactic::on && !yendor::on) setland(c, laOcean); - if(c->land == laCamelot && !tactic::on) setland(c, laCrossroads); - if(c->land == laBrownian && !chaosmode) setland(c, laOcean); - - if(chaosmode && !c->land && isize(currentlands)) { - if(chaosmode == 3) setland(c, currentlands[hrand(isize(currentlands))]); - if(chaosmode == 2) { - if(stdeuc) { - cell *c2 = c; - while(true) { - forCellCM(c3, c2) if(cdist50(c3) < cdist50(c2)) { c2 = c3; goto again; } - break; - again: ; - } - if(!c2->land) setland(c2, currentlands[hrand(isize(currentlands))]); - c->land = c2->land; - } - else chaosmode = 4; - } - if(chaosmode == 4) - setland_randomwalk(c); - } + if(c->land == laTemple && ls::any_order()) setland(c, laRlyeh); + if(!ls::single()) { + if(c->land == laMountain) setland(c, laJungle); + if(c->land == laClearing) setland(c, laOvergrown); + if(c->land == laWhirlpool) setland(c, laOcean); + if(c->land == laCamelot) setland(c, laCrossroads); + if(c->land == laBrownian) setland(c, laOcean); + } + #if CAP_DAILY if(!daily::on) { #else @@ -2864,8 +2869,6 @@ EX void setdist(cell *c, int d, cell *from) { #endif set_land_for_geometry(c); } - - // if(chaosmode) setland(c, getCLand(c)); } if(d == BARLEV && c->land == laCanvas) { @@ -2876,11 +2879,11 @@ EX void setdist(cell *c, int d, cell *from) { } #if CAP_FIELD - if(d >= BARLEV-1 && c->land == laPrairie && !chaosmode) + if(d >= BARLEV-1 && c->land == laPrairie && !ls::any_chaos()) prairie::spread(c, from); #endif - if(d < BARLEV && c->land == laPrairie && !c->landparam && !chaosmode) { + if(d < BARLEV && c->land == laPrairie && !c->landparam && !ls::any_chaos()) { printf("d=%d/%d\n", d, BARLEV); raiseBuggyGeneration(c, "No landparam set"); return; diff --git a/landlock.cpp b/landlock.cpp index 7e7c1643..83817a89 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -9,15 +9,8 @@ namespace hr { EX bool in_full_game() { - if(tactic::on) return false; - if(princess::challenge) return false; - if(chaosmode) return true; - if(euclid && isCrossroads(specialland)) return true; - if(weirdhyperbolic && specialland == laCrossroads4) return true; - if(cryst && isCrossroads(specialland)) return true; - if((in_s2xe() || nonisotropic || (hybri && hybrid::under_class() != gcSphere)) && isCrossroads(specialland)) return true; - if(geometry == gNormal && !NONSTDVAR) return true; - return false; + if(ls::single()) return false; + return true; } EX bool nodisplay(eMonster m) { @@ -87,7 +80,84 @@ EX eLand oppositeElement(eLand l, eLand l2) { EX eLand firstland = laIce; EX eLand specialland = laIce; -EX int chaosmode = 0; +#if HDR +enum eLandStructure { lsNiceWalls, lsChaos, lsPatchedChaos, lsTotalChaos, lsChaosRW, lsWallChaos, lsSingle, lsNoWalls, lsGUARD }; +#endif + +EX eLandStructure land_structure; + +EX namespace ls { + +EX bool single() { return land_structure == lsSingle; } + +EX bool any_chaos() { return among(land_structure, lsChaos, lsPatchedChaos, lsWallChaos, lsTotalChaos, lsChaosRW); } +EX bool std_chaos() { return land_structure == lsChaos; } +EX bool wall_chaos() { return land_structure == lsWallChaos; } +EX bool patched_chaos() { return land_structure == lsPatchedChaos; } + +EX bool any_order() { return among(land_structure, lsNiceWalls, lsNoWalls); } +EX bool nice_walls() { return land_structure == lsNiceWalls; } +EX bool no_walls() { return land_structure == lsNoWalls; } + +EX bool any_nowall() { return no_walls() || std_chaos(); } +EX bool any_wall() { return nice_walls() || wall_chaos(); } + +EX int chaoticity() { + if(land_structure == lsTotalChaos) return 100; + if(land_structure == lsChaosRW) return 80; + if(land_structure == lsPatchedChaos) return 60; + if(land_structure == lsChaos) return 40; + if(land_structure == lsWallChaos) return 30; + if(land_structure == lsSingle) return 0; + return 10; + } + +EX bool tame_chaos() { return any_chaos() && chaoticity() < 35; } +EX } + +EX string land_structure_name(bool which) { + switch(land_structure) { + case lsNiceWalls: + return XLAT("standard"); + case lsChaos: + return XLAT("Chaos mode"); + case lsPatchedChaos: + return XLAT("patched Chaos"); + case lsWallChaos: + return XLAT("excessive walls"); + case lsTotalChaos: + return XLAT("total chaos"); + case lsChaosRW: + return XLAT("random-walk chaos"); + case lsSingle: + return which ? XLAT("single land: ") + XLATN(linf[specialland].name) : XLAT("single land"); + case lsNoWalls: + return XLAT("wall-less"); + default: + return "error structure"; + } + } + +EX void fix_land_structure_choice() { + if(bounded) { + if(land_structure != lsTotalChaos && land_structure != lsChaosRW) + land_structure = lsSingle; + } + if(tactic::on || princess::challenge) + land_structure = lsSingle; + if(yendor::on) + land_structure = yendor::get_land_structure(); + if(!nice_walls_available() && land_structure == lsNiceWalls) + land_structure = lsNoWalls; + if(!nice_walls_available() && land_structure == lsWallChaos) + land_structure = lsChaos; + if(walls_not_implemented() && among(land_structure, lsChaos, lsNoWalls)) + land_structure = lsSingle; + if(land_structure == lsPatchedChaos && !(stdeuc || nil || cryst || (euclid && WDIM == 3))) + land_structure = lsSingle; + if(bounded && !among(land_structure, lsChaosRW, lsTotalChaos, lsSingle)) + land_structure = lsSingle; + } EX bool landUnlockedRPM(eLand n) { if(isRandland(n) == 2) return true; @@ -107,6 +177,8 @@ EX bool landUnlocked(eLand l) { back: + if(princess::challenge) return among(l, laPalace, laPrincessQuest); + switch(l) { #define LAND(a,b,c,d,e,f,g) case c: #define REQ(x) x return true; @@ -219,13 +291,13 @@ EX bool incompatible(eLand nw, eLand old) { } EX bool rlyehComplete() { - if(chaosmode) return items[itStatue] >= 1; + if(ls::any_chaos()) return items[itStatue] >= 1; return items[itStatue] >= 10 || items[itGrimoire] >= 10; } bool lchance(eLand l) { if(tactic::on || yendor::on || racing::on || ((geometry || GOLDBERG) && specialland == laElementalWall)) return true; - if(chaosmode) return hrand(100) < 25; + if(ls::any_chaos()) return hrand(100) < 25; return hrand(100) >= 40 * kills[elementalOf(l)] / (elementalKills()+1); } @@ -274,16 +346,13 @@ EX bool createOnSea(eLand old) { old == laWarpSea || old == laCaribbean || old == laKraken || (old == laLivefjord && hrand(2)) || (old == laDocks && hrand(2)) || - (old == laOcean && (chaosmode ? hrand(2) : !generatingEquidistant)); + (old == laOcean && (ls::any_chaos() ? hrand(2) : !generatingEquidistant)); } EX hookset hooks_nextland; EX eLand getNewLand(eLand old) { - if(old == laMirror && !chaosmode && hrand(10) >= ((tactic::on || racing::on) ? 0 : markOrb(itOrbLuck) ? 5 : 2)) return laMirrored; - if(old == laTerracotta && !chaosmode && hrand(5) >= ((tactic::on || racing::on) ? 0 : markOrb(itOrbLuck) ? 2 : 1) && !weirdhyperbolic) return laTerracotta; - eLand l = callhandlers(laNone, hooks_nextland, old); if(l) return l; @@ -291,7 +360,7 @@ EX eLand getNewLand(eLand old) { if(old == laTortoise) return laDragon; - if(yendor::on && chaosmode) { + if(yendor::on && ls::any_chaos()) { while(true) { eLand n = eLand(hrand(landtypes)); if(n == old) continue; @@ -333,8 +402,7 @@ EX eLand getNewLand(eLand old) { #endif if(tactic::on) return specialland; - if((weirdhyperbolic || cheater) && specialland != old && specialland != laCrossroads4 && specialland != laIce && !chaosmode && old != laBarrier && !isCyclic(specialland) && specialland != laBrownian) - return specialland; + if(specialland != old && easy_to_find_specialland) return specialland; if(yendor::on && (yendor::clev().flags & YF_WALLS)) { if(old != yendor::clev().l) return yendor::clev().l; @@ -351,7 +419,7 @@ EX eLand getNewLand(eLand old) { if(old == laDragon && tortoise::seek() && hrand(100) < 50) return laTortoise; - if(isWarpedType(old) && (hrand(100) < 25) && chaosmode) return eLand(old ^ laWarpCoast ^ laWarpSea); + if(isWarpedType(old) && (hrand(100) < 25) && ls::std_chaos()) return eLand(old ^ laWarpCoast ^ laWarpSea); if(createOnSea(old)) return getNewSealand(old); @@ -429,9 +497,9 @@ EX eLand getNewLand(eLand old) { tab[cnt++] = laCrossroads; if(!generatingEquidistant) tab[cnt++] = laCrossroads2; if(rlyehComplete()) tab[cnt++] = laRlyeh; - else if(chaosmode && (old == laWarpCoast || old == laLivefjord || old == laOcean)) + else if(ls::std_chaos() && (old == laWarpCoast || old == laLivefjord || old == laOcean)) tab[cnt++] = laRlyeh; - if(items[itStatue] >= U5 && chaosmode) + if(items[itStatue] >= U5 && ls::std_chaos()) tab[cnt++] = laTemple; if(old == laCrossroads || old == laCrossroads2) tab[cnt++] = laOcean; if(old == laOcean) tab[cnt++] = laCrossroads; @@ -440,11 +508,11 @@ EX eLand getNewLand(eLand old) { } if(gold() >= R90) { - if(!chaosmode) tab[cnt++] = laPrairie; + if(!ls::std_chaos()) tab[cnt++] = laPrairie; if(old == laPrairie) LIKELY tab[cnt++] = laBull; - if(old == laBull && !chaosmode) LIKELY tab[cnt++] = laPrairie; - if(chaosmode && geometry) tab[cnt++] = laDual; - if(chaosmode && geosupport_threecolor()) tab[cnt++] = laSnakeNest; + if(old == laBull && !ls::any_chaos()) LIKELY tab[cnt++] = laPrairie; + if(ls::std_chaos() && geometry) tab[cnt++] = laDual; + if(ls::std_chaos() && geosupport_threecolor()) tab[cnt++] = laSnakeNest; } if(landUnlocked(laTrollheim)) { @@ -799,7 +867,7 @@ EX land_validity_t& land_validity(eLand l) { if(l == laDual && (!has_nice_dual() || nonisotropic)) return dont_work; - if(l == laHaunted && chaosmode) + if(l == laHaunted && ls::std_chaos()) return not_in_chaos; // standard, non-PTM specific @@ -807,11 +875,11 @@ EX land_validity_t& land_validity(eLand l) { return not_in_ptm; // standard non-PTM non-chaos specific - if((l == laCrossroads5 || l == laCrossroads2) && (geometry || chaosmode)) + if((l == laCrossroads5 || l == laCrossroads2) && (geometry || ls::any_chaos())) return some0; // special construction in the Chaos mode - if(chaosmode && (l == laTemple || l == laHive || l == laOcean || l == laHaunted)) + if(ls::any_chaos() && (l == laTemple || l == laHive || l == laOcean || l == laHaunted)) return special_chaos; if(l == laWhirlpool && a4) @@ -842,7 +910,7 @@ EX land_validity_t& land_validity(eLand l) { // equidistant-based lands if(isEquidLand(l)) { // no equidistants supported in chaos mode - if(chaosmode) + if(ls::any_chaos()) return not_in_chaos; // the algorithm fails in Archimedean DUAL if(arcm::in() && DUAL) @@ -864,7 +932,7 @@ EX land_validity_t& land_validity(eLand l) { return ok; } - if(l == laPrincessQuest && chaosmode) + if(l == laPrincessQuest && ls::any_chaos()) return not_in_chaos; if(l == laPrincessQuest && tactic::on) @@ -879,14 +947,14 @@ EX land_validity_t& land_validity(eLand l) { if(l == laPrincessQuest && multi::players > 1) return not_in_multi; - if(l == laMountain && chaosmode) + if(l == laMountain && ls::any_chaos()) return not_in_chaos; - if(l == laBrownian && chaosmode) + if(l == laBrownian && ls::any_chaos()) return not_in_chaos; // works correctly only in some geometries - if(l == laClearing && chaosmode) + if(l == laClearing && ls::any_chaos()) return not_in_chaos; if(l == laClearing) @@ -904,7 +972,7 @@ EX land_validity_t& land_validity(eLand l) { // horocycle-based lands, not available in bounded geometries nor in Chaos mode if(l == laWhirlpool || l == laCamelot || l == laCaribbean || l == laTemple || l == laHive) { - if(chaosmode) { + if(ls::any_chaos()) { if(l == laTemple || l == laHive) return special_chaos; return not_in_chaos; @@ -914,7 +982,7 @@ EX land_validity_t& land_validity(eLand l) { if(INVERSE) return not_implemented; } - if(chaosmode && isCrossroads(l)) + if(ls::any_chaos() && isCrossroads(l)) return not_in_chaos; // this pattern does not work on elliptic and small spheres diff --git a/legacy.cpp b/legacy.cpp index c65624ff..0d8ac0e6 100644 --- a/legacy.cpp +++ b/legacy.cpp @@ -72,7 +72,7 @@ void loadOldConfig(FILE *f) { shmup::loadConfig(f); - aa = rug::renderonce; bb = rug::rendernogl; dd = chaosmode; + aa = rug::renderonce; bb = rug::rendernogl; dd = ls::any_chaos(); int ee = vid.steamscore; #if CAP_RUG double rs = 2/rug::model_distance; @@ -81,7 +81,7 @@ void loadOldConfig(FILE *f) { #endif err=fscanf(f, "%d%d%d%d%lf%d%d", &aa, &bb, &rug::texturesize, &cc, &rs, &ee, &dd); rug::renderonce = aa; rug::rendernogl = bb; - chaosmode = dd; vid.steamscore = ee; + land_structure = (eLandStructure) dd; vid.steamscore = ee; #if CAP_RUG rug::model_distance = 2/rs; #endif @@ -204,7 +204,7 @@ int modecodetable[42][6] = { EX modecode_t legacy_modecode() { if(int(geometry) > 3 || int(variation) > 1) return UNKNOWN; - if(chaosmode > 1) return UNKNOWN; + if(!ls::nice_walls() && !ls::std_chaos()) return UNKNOWN; // compute the old code int xcode = 0; @@ -219,7 +219,7 @@ EX modecode_t legacy_modecode() { if(elliptic) xcode += 6; } - if(chaosmode) xcode += 21; + if(ls::any_chaos()) xcode += 21; int np = numplayers()-1; if(np<0 || np>5) np=5; @@ -238,5 +238,40 @@ EX modecode_t legacy_modecode() { return mct; } +/* legacy options */ +int read_legacy_args() { + using namespace arg; + if(0); + else if(argis("-chaos-circle")) { + PHASEFROM(2); + stop_game(); + land_structure = lsCircleChaos; + } + else if(argis("-chaos-total")) { + PHASEFROM(2); + stop_game(); + land_structure = lsTotalChaos; + } + else if(argis("-chaos-random")) { + PHASEFROM(2); + stop_game(); + land_structure = lsChaosRW; + } + else if(argis("-C") || argis("-C1")) { + PHASEFROM(2); + stop_game(); + land_structure = lsChaos; + } + else if(argis("-C0")) { + PHASEFROM(2); + stop_game(); + land_structure = lsNiceWalls; + } + else return 1; + return 0; + } + +auto ah_legacy = addHook(hooks_args, 0, read_legacy_args); + } diff --git a/mapeffects.cpp b/mapeffects.cpp index 8bb9c503..0d66135c 100644 --- a/mapeffects.cpp +++ b/mapeffects.cpp @@ -637,7 +637,7 @@ EX void checkTide(cell *c) { if(c->land == laOcean) { int t = c->landparam; - if(chaosmode) { + if(ls::any_chaos()) { char& csd(c->SEADIST); if(csd == 0) csd = 7; char& cld(c->LANDDIST); if(cld == 0) cld = 7; int seadist=csd, landdist=cld; diff --git a/menus.cpp b/menus.cpp index e911cb5c..2859113a 100644 --- a/menus.cpp +++ b/menus.cpp @@ -481,7 +481,7 @@ EX void showCreative() { EX void show_chaos() { gamescreen(3); - dialog::init(XLAT("Chaos mode")); + dialog::init(XLAT("land structure")); chaosUnlocked = chaosUnlocked || autocheat; dialog::addHelp( @@ -493,26 +493,42 @@ EX void show_chaos() { dialog::addBreak(100); - dialog::addBoolItem(XLAT("Chaos mode") + " " + ONOFF(false), !chaosmode, 'A'); - dialog::add_action([] { dialog::do_if_confirmed([] { if(chaosUnlocked) restart_game(rg::chaos); }); }); - - if(chaosUnlocked) for(int a=1; a<5; a++) { - if(a > 1 && ISWEB) continue; - if(a == 1 && walls_not_implemented()) continue; - dialog::addBoolItem( - a == 1 ? XLATN("Crossroads IV") : - a == 2 ? XLATN("Palace") : - a == 3 ? XLAT("total chaos") : - XLAT("random walk"), - chaosmode == a, 'A' + a); - dialog::add_action([a] { dialog::do_if_confirmed([a] { - int cm = chaosmode; - stop_game_and_switch_mode(rg::chaos); - if(!chaosmode && cm != a) switch_game_mode(rg::chaos); - if(chaosmode) chaosmode = a; - start_game(); - }); }); + char key = 'a'; + for(int i=0; i dls(land_structure); + auto li = eLandStructure(i); + land_structure = li; + fix_land_structure_choice(); + if(ls::any_chaos() && !chaosUnlocked) continue; + if(li == lsNoWalls && geometry == gNormal && !chaosUnlocked) continue; + if(land_structure == i) { + dialog::addBoolItem(land_structure_name(false), land_structure == dls.backup, key + i); + dialog::add_action(dual::mayboth([li] { + dialog::do_if_confirmed([li] { + stop_game(); + land_structure = li; + start_game(); + }); + })); + } } + + dialog::addBreak(100); + dialog::addSelItem(XLAT("land"), XLAT1(linf[specialland].name), 'l'); + dialog::add_action_push(ge_land_selection); + + dialog::addBreak(100); + if(ineligible_starting_land) + dialog::addInfo("this starting land is not eligible for achievements"); + else if(land_structure == lsNiceWalls) + dialog::addInfo("eligible for most achievements"); + else if(land_structure == lsChaos) + dialog::addInfo("eligible for Chaos mode achievements"); + else if(land_structure == lsSingle) + dialog::addInfo("eligible for special achievements"); + else + dialog::addInfo("not eligible for achievements"); + if(cheater) dialog::addInfo("(but the cheat mode is on)"); dialog::addBreak(100); dialog::addBack(); @@ -643,6 +659,11 @@ EX void mode_higlights() { dialog::addBack(); dialog::display(); } + +EX void menuitem_land_structure(char key) { + dialog::addSelItem(XLAT("land structure"), land_structure_name(true), key); + dialog::add_action_push(show_chaos); + } EX void showChangeMode() { gamescreen(3); @@ -677,8 +698,7 @@ EX void showChangeMode() { mouseovers = XLAT("One wrong move and it is game over!"); multi::cpid = 0; - dialog::addBoolItem(XLAT("Chaos mode"), (chaosmode), 'C'); - dialog::add_action_push(show_chaos); + menuitem_land_structure('l'); dialog::addBoolItem(XLAT("puzzle/exploration mode"), peace::on, 'p'); dialog::add_action_push(peace::showMenu); diff --git a/monstergen.cpp b/monstergen.cpp index 92e0112e..01633f63 100644 --- a/monstergen.cpp +++ b/monstergen.cpp @@ -377,7 +377,7 @@ EX void wandering() { if(smallbounded_generation && !c->item && hrand(5) == 0 && c->land != laHalloween) { if(passable(c, NULL, 0) || specialland == laKraken) { - if(c->land != laGraveyard && (c->land != laMotion || chaosmode || daily::on) && !haveOrbPower() && specialland != laHell) for(int it=0; it<1000 && !c->item; it++) + if(c->land != laGraveyard && (c->land != laMotion || !ls::single() || daily::on) && !haveOrbPower() && specialland != laHell) for(int it=0; it<1000 && !c->item; it++) placeLocalOrbs(c); if(!c->item) c->item = wanderingTreasure(c); if(c->item == itShard) { diff --git a/multigame.cpp b/multigame.cpp index 181171b0..3b023dee 100644 --- a/multigame.cpp +++ b/multigame.cpp @@ -58,7 +58,7 @@ void gamedata_all(gamedata& gd) { gd.store(cwt); gd.store(allmaps); gd.store(shmup::on); - gd.store(chaosmode); + gd.store(land_structure); gd.store(*current_display); gd.store(cgip); gd.store_ptr(vid); diff --git a/orbgen.cpp b/orbgen.cpp index 324d248b..23d9aa3f 100644 --- a/orbgen.cpp +++ b/orbgen.cpp @@ -490,7 +490,7 @@ EX void placePrizeOrb(cell *c) { // 10 not in chaos, less in chaos EX int treasureForLocal() { - return (chaosmode ? 1+hrand(10) : 10); + return (ls::any_chaos() ? 1+hrand(10) : 10); } EX bool extra_safety_for_memory(cell *c) { @@ -521,7 +521,7 @@ EX void placeLocalOrbs(cell *c) { continue; if(!oi.lchance) continue; int ch = hrand(oi.lchance); - if(ch == 1 && chaosmode && hrand(2) == 0 && items[treasureType(oi.l)] * landMultiplier(oi.l) >= (11+hrand(15))) + if(ch == 1 && ls::any_chaos() && hrand(2) == 0 && items[treasureType(oi.l)] * landMultiplier(oi.l) >= (11+hrand(15))) ch = 0; int tc = items[treasureType(oi.l)] * landMultiplier(oi.l); int tcmin = treasureForLocal(); diff --git a/pattern2.cpp b/pattern2.cpp index 9332ba4e..9f0244dd 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -174,6 +174,11 @@ int fiftyval(cell *c) { } EX int cdist50(cell *c) { + if(euclid && S3 == 4) { + auto co = euc2_coordinates(c); + int x = co.first, y = co.second; + return abs(szgmod(x, 5)) + abs(zgmod(y, 5)); + } if(sphere || S7>7 || S6>6) return 0; if(euclid) { if(c->land == laWildWest) diff --git a/pcmove.cpp b/pcmove.cpp index 199ae547..480fe08a 100644 --- a/pcmove.cpp +++ b/pcmove.cpp @@ -1554,7 +1554,7 @@ EX void movecost(cell* from, cell *to, int phase) { bool tortoiseOK = to->land == from->land || to->land == laTortoise || (to->land == laDragon && from->land != laTortoise) || - chaosmode; + ls::any_chaos(); if(tortoise::seek() && !from->item && !tortoiseOK && passable(from, NULL, 0) && (phase & 2)) { changes.ccell(from); diff --git a/quit.cpp b/quit.cpp index 9ef62be2..7ad2c69f 100644 --- a/quit.cpp +++ b/quit.cpp @@ -397,7 +397,7 @@ EX void showMission() { dialog::addInfo(XLAT("Kill a Vizier in the Palace to access Emerald Mine")); else if(items[itEmerald] < U5) dialog::addInfo(XLAT("Collect 5 Emeralds to access Camelot")); - else if(landUnlocked(laHell) && !chaosmode) { + else if(landUnlocked(laHell) && ls::any_order()) { eLand l = nextHyperstone(); if(l) dialog::addInfo( diff --git a/scores.cpp b/scores.cpp index d1df0d40..7defd216 100644 --- a/scores.cpp +++ b/scores.cpp @@ -50,7 +50,7 @@ int modediff(score *S) { if(variation != savevar) diff += 16; if(GOLDBERG && savevar == eVariation::goldberg && (S->box[342] != gp::param.first || S->box[343] != gp::param.second)) diff += 16; - if(S->box[196] != chaosmode) diff += 32; + if(S->box[196] != (int) land_structure) diff += 32; if(S->box[119] != shmup::on) diff += 64; if(pureHardcore() && !isHardcore(S)) diff += 128; if(g != gNormal && S->box[120] != specialland) diff --git a/system.cpp b/system.cpp index e9894f35..c81f5d2a 100644 --- a/system.cpp +++ b/system.cpp @@ -68,13 +68,6 @@ EX bool verless(string v, string cmp) { return v < cmp; } -/** \brief should we set the starting land to specialland */ -bool do_use_special_land() { - return - !safety && - (peace::on || tactic::on || geometry || NONSTDVAR || randomPatternsMode || yendor::on || racing::on); - } - /** \brief Hooks for welcomeMessage. Return true to capture. */ EX hookset hooks_welcome_message; @@ -135,7 +128,7 @@ EX void welcomeMessage() { else addMessage(XLAT("Welcome to HyperRogue!")); - if(do_use_special_land() || firstland != laIce) if(!daily::on) { + if(!safety && !daily::on) { auto lv = land_validity(specialland); if(lv.flags & lv::display_error_message) addMessage(XLAT(lv.msg)); @@ -154,10 +147,14 @@ EX hookset hooks_initgame; /** \brief These hooks are called at the end of initgame. */ EX hookset hooks_post_initgame; +EX bool ineligible_starting_land; + /** \brief initialize the game */ EX void initgame() { DEBBI(DF_INIT, ("initGame")); callhooks(hooks_initgame); + + if(!safety) fix_land_structure_choice(); if(multi::players < 1 || multi::players > MAXPLAYER) multi::players = 1; @@ -175,9 +172,10 @@ EX void initgame() { if(racing::on) racing::apply_seed(); #endif - bool use_special_land = do_use_special_land(); - - if(use_special_land) firstland = specialland; + if(!safety) { + firstland = specialland; + ineligible_starting_land = !landUnlocked(specialland); + } if(firstland == laNone || firstland == laBarrier) firstland = laCrossroads; @@ -214,10 +212,6 @@ EX void initgame() { pregen(); setdist(cwt.at, BARLEV, NULL); - if(!use_special_land && !safety) { - if(firstland != (princess::challenge ? laPalace : laIce)) cheater++; - } - if((tactic::on || yendor::on || peace::on) && isCyclic(firstland)) { #if CAP_COMPLEX2 camelot::anthraxBonus = items[itHolyGrail]; @@ -341,7 +335,7 @@ EX void initgame() { generate_mines(); } - if(specialland == laMotion && bounded && !chaosmode && !daily::on) { + if(specialland == laMotion && bounded && ls::any_order() && !daily::on) { cwt.at->item = itOrbInvis; } @@ -379,9 +373,6 @@ EX void initgame() { #if CAP_COMPLEX2 mine::auto_teleport_charges(); #endif - if(!use_special_land) { - if(firstland != (princess::challenge ? laPalace : laIce)) cheater++; - } welcomeMessage(); } else { @@ -424,7 +415,7 @@ EX namespace scores { /** \brief the amount of boxes reserved for each hr::score item */ #define MAXBOX 500 /** \brief currently used boxes in hr::score */ -#define POSSCORE 388 +#define POSSCORE 389 /** \brief a struct to keep local score from an earlier game */ struct score { /** \brief version used */ @@ -739,7 +730,9 @@ EX void applyBoxes() { applyBoxM(moFalsePrincess); applyBoxM(moRoseLady); applyBoxM(moRoseBeauty); - applyBoxNum(chaosmode, "Chaos mode"); + int ls = (int) land_structure; + applyBoxNum(ls, "land structure"); + land_structure = (eLandStructure) ls; applyBoxNum(multi::players, "shmup players"); if(multi::players < 1 || multi::players > MAXPLAYER) multi::players = 1; @@ -895,6 +888,7 @@ EX void applyBoxes() { list_invorb(); applyBoxNum(saved_modecode, "modecode"); + applyBoxBool(ineligible_starting_land, "ineligible_starting_land"); if(POSSCORE != boxid) printf("ERROR: %d boxes\n", boxid); if(isize(invorb)) { println(hlog, "ERROR: Orbs not taken into account"); exit(1); } @@ -919,7 +913,7 @@ modecode_t fill_modecode() { if(among(geometry, gArchimedean, gProduct, gRotSpace, gArbitrary)) return 6; /* these would not be saved nor loaded correctly */ dynamicval sp3(shmup::on, save.box[119]); - dynamicval sp4(chaosmode, save.box[196]); + dynamicval sp4(land_structure, (eLandStructure) save.box[196]); dynamicval sp5(variation, (eVariation) save.box[186]); dynamicval sp7(gp::param.first, save.box[342]); dynamicval sp8(gp::param.second, save.box[343]); @@ -1077,7 +1071,10 @@ EX void saveStats(bool emergency IS(false)) { fprintf(f, "cells generated: %d\n", cellcount); if(pureHardcore()) fprintf(f, "Pure hardcore mode\n"); if(geometry) fprintf(f, "Geometry: %s/%s/%s\n", gp::operation_name().c_str(), ginf[geometry].tiling_name.c_str(), ginf[geometry].quotient_name.c_str()); - if(chaosmode) fprintf(f, "Chaos mode\n"); + + if(!ls::nice_walls()) + fprintf(f, "land structure: %s\n", land_structure_name(true).c_str()); + if(shmup::on) fprintf(f, "Shoot-em up mode\n"); if(inv::on) fprintf(f, "Inventory mode\n"); if(multi::players > 1) fprintf(f, "Multi-player (%d players)\n", multi::players); @@ -1309,10 +1306,7 @@ EX void set_geometry(eGeometry target) { hybrid::configure(target); } geometry = target; - - if(chaosmode && bounded) chaosmode = 0; - if(chaosmode == 1 && walls_not_implemented()) chaosmode = 0; - + #if CAP_IRR if(IRREGULAR) variation = eVariation::bitruncated; #endif @@ -1395,7 +1389,7 @@ EX void switch_game_mode(char switchWhat) { case rg::chaos: if(tactic::on) firstland = laIce; yendor::on = tactic::on = princess::challenge = false; - chaosmode = !chaosmode; + land_structure = ls::any_chaos() ? lsNiceWalls : lsChaos; if(bounded) set_geometry(gNormal); racing::on = false; break; @@ -1406,7 +1400,8 @@ EX void switch_game_mode(char switchWhat) { geometry = gNormal; yendor::on = tactic::on = princess::challenge = peace::on = inv::on = false; dual::disable(); - chaosmode = randomPatternsMode = false; + land_structure = lsNiceWalls; + randomPatternsMode = false; variation = eVariation::bitruncated; #if CAP_GP gp::param = gp::loc(1, 1); @@ -1424,7 +1419,7 @@ EX void switch_game_mode(char switchWhat) { inv::on = false; princess::challenge = false; randomPatternsMode = false; - chaosmode = false; + land_structure = lsNiceWalls; racing::on = false; if(!yendor::on) firstland = laIce; dual::disable(); @@ -1437,7 +1432,7 @@ EX void switch_game_mode(char switchWhat) { peace::on = false; tour::on = false; inv::on = false; - chaosmode = false; + land_structure = lsSingle; princess::challenge = false; dual::disable(); break; @@ -1451,7 +1446,7 @@ EX void switch_game_mode(char switchWhat) { randomPatternsMode = false; princess::challenge = false; racing::on = false; - chaosmode = false; + land_structure = tactic::on ? lsSingle : lsNiceWalls; if(!tactic::on) firstland = laIce; dual::disable(); break; @@ -1476,7 +1471,7 @@ EX void switch_game_mode(char switchWhat) { shmup::on = false; tactic::on = false; yendor::on = false; - chaosmode = false; + land_structure = princess::challenge ? lsSingle : lsNiceWalls; inv::on = false; racing::on = false; dual::disable(); diff --git a/yendor.cpp b/yendor.cpp index 012a3d9e..029206d0 100644 --- a/yendor.cpp +++ b/yendor.cpp @@ -541,6 +541,14 @@ EX namespace yendor { } } } + + EX eLandStructure get_land_structure() { + if(clev().flags & YF_CHAOS) + return lsChaos; + if(clev().l == laWhirlpool) + return lsSingle; + return lsNiceWalls; + } EX void init(int phase) { if(!on) return; @@ -548,7 +556,7 @@ EX namespace yendor { if(phase == 1) { won = false; if(!easy) items[itOrbYendor] = bestscore[modecode()][challenge]; - chaosmode = (clev().flags & YF_CHAOS) ? 1 : 0; + land_structure = get_land_structure(); specialland = clev().l; if(clev().flags & YF_START_AL) { specialland = laAlchemist; @@ -1064,7 +1072,7 @@ void save_mode_data(hstream& f) { if(yendor::on) f.write(0); else - f.write(chaosmode); + f.write(land_structure); f.write(shmup::on); f.write(inv::on); #if CAP_TOUR