diff --git a/achievement.cpp b/achievement.cpp index 1770fc56..8699ca02 100644 --- a/achievement.cpp +++ b/achievement.cpp @@ -112,6 +112,7 @@ EX bool wrongMode(char flags) { if(flags != rg::special_geometry && flags != rg::special_geometry_nicewalls) { if(!BITRUNCATED) return true; if(geometry != gNormal) return true; + if(disksize) return true; } if(shmup::on != (flags == rg::shmup || flags == rg::racing)) return true; @@ -225,10 +226,10 @@ EX void achievement_collection2(eItem it, int q) { if(randomPatternsMode) return; LATE( achievement_collection2(it, q); ) - if(it == itTreat && q == 50 && (geometry == gSphere || geometry == gElliptic) && BITRUNCATED) + if(it == itTreat && q == 50 && (geometry == gSphere || geometry == gElliptic) && BITRUNCATED && !disksize) achievement_gain("HALLOWEEN1", rg::special_geometry); - if(it == itTreat && q == 100 && (geometry == gSphere || geometry == gElliptic) && BITRUNCATED) + if(it == itTreat && q == 100 && (geometry == gSphere || geometry == gElliptic) && BITRUNCATED && !disksize) achievement_gain("HALLOWEEN2", rg::special_geometry); if(q == 1) { @@ -309,12 +310,12 @@ EX void achievement_collection2(eItem it, int q) { // 32 if(it == itHolyGrail) { if(q == 1) achievement_gain("GRAIL2"); - if(PURE && geometry == gNormal) + if(PURE && geometry == gNormal && !disksize) achievement_gain("GRAILH", rg::special_geometry_nicewalls); #if CAP_CRYSTAL - if(PURE && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 4 && !crystal::used_compass_inside) + if(PURE && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 4 && !crystal::used_compass_inside && !disksize) achievement_gain("GRAIL4D", rg::special_geometry); - if(BITRUNCATED && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 3 && !crystal::used_compass_inside) + if(BITRUNCATED && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 3 && !crystal::used_compass_inside && !disksize) achievement_gain("GRAIL4D2", rg::special_geometry); #endif if(q == 3) achievement_gain("GRAIL3"); @@ -599,7 +600,7 @@ EX void achievement_count(const string& s, int current, int prev) { achievement_gain("LIGHTNING2"); if(s == "LIGHTNING" && current-prev >= 10) achievement_gain("LIGHTNING3"); - if(s == "MIRAGE" && current >= 35 && geometry == gEuclid) + if(s == "MIRAGE" && current >= 35 && geometry == gEuclid && !disksize) achievement_gain("MIRAGE", rg::special_geometry); if(s == "ORB" && current >= 10) achievement_gain("ORB3"); @@ -633,6 +634,7 @@ EX void achievement_score(int cat, int number) { if(cheater) return; if(casual) return; LATE( achievement_score(cat, number); ) + if(disksize) return; if(cat == LB_HALLOWEEN) { if(geometry != gSphere && geometry != gElliptic) return; @@ -943,7 +945,7 @@ EX string get_rich_presence_text() { return "Guided Tour"; string res; - if(geometry != gNormal || !BITRUNCATED) + if(geometry != gNormal || !BITRUNCATED || disksize) res = res + full_geometry_name() + " "; if(land_structure != default_land_structure()) res += land_structure_name(false) + " "; diff --git a/arbitrile.cpp b/arbitrile.cpp index 43bb0b40..8b4356cb 100644 --- a/arbitrile.cpp +++ b/arbitrile.cpp @@ -659,21 +659,21 @@ EX void load(const string& fname, bool load_as_slided IS(false), bool keep_slide ep.force_eat(")"); ginf[gArbitrary].g = curv > 0 ? giSphere2 : curv < 0 ? giHyperb2 : giEuclid2; ginf[gArbitrary].sides = 7; - set_flag(ginf[gArbitrary].flags, qBOUNDED, curv > 0); + set_flag(ginf[gArbitrary].flags, qCLOSED, curv > 0); set_flag(ginf[gArbitrary].flags, qAFFINE, false); geom3::apply_always3(); } else if(ep.eat("e2.")) { ginf[gArbitrary].g = giEuclid2; ginf[gArbitrary].sides = 7; - set_flag(ginf[gArbitrary].flags, qBOUNDED, false); + set_flag(ginf[gArbitrary].flags, qCLOSED, false); set_flag(ginf[gArbitrary].flags, qAFFINE, false); geom3::apply_always3(); } else if(ep.eat("a2.")) { ginf[gArbitrary].g = giEuclid2; ginf[gArbitrary].sides = 7; - set_flag(ginf[gArbitrary].flags, qBOUNDED, false); + set_flag(ginf[gArbitrary].flags, qCLOSED, false); set_flag(ginf[gArbitrary].flags, qAFFINE, true); affine_limit = 200; geom3::apply_always3(); @@ -681,14 +681,14 @@ EX void load(const string& fname, bool load_as_slided IS(false), bool keep_slide else if(ep.eat("h2.")) { ginf[gArbitrary].g = giHyperb2; ginf[gArbitrary].sides = 7; - set_flag(ginf[gArbitrary].flags, qBOUNDED, false); + set_flag(ginf[gArbitrary].flags, qCLOSED, false); set_flag(ginf[gArbitrary].flags, qAFFINE, false); geom3::apply_always3(); } else if(ep.eat("s2.")) { ginf[gArbitrary].g = giSphere2; ginf[gArbitrary].sides = 5; - set_flag(ginf[gArbitrary].flags, qBOUNDED, true); + set_flag(ginf[gArbitrary].flags, qCLOSED, true); set_flag(ginf[gArbitrary].flags, qAFFINE, false); geom3::apply_always3(); } @@ -1504,7 +1504,7 @@ EX void convert() { ac.shapes.resize(N); ginf[gArbitrary].g = cginf.g; - ginf[gArbitrary].flags = cgflags & qBOUNDED; + ginf[gArbitrary].flags = cgflags & qCLOSED; for(int i=0; i 16384); } diff --git a/bigstuff.cpp b/bigstuff.cpp index 4f0db017..1d26a052 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -2008,7 +2008,7 @@ EX void moreBigStuff(cell *c) { EX void generate_mines() { vector candidates; - if(bounded) + if(closed_or_bounded) for(cell *c: currentmap->allcells()) setdist(c, 7, nullptr); diff --git a/cell.cpp b/cell.cpp index 536e598b..1d720429 100644 --- a/cell.cpp +++ b/cell.cpp @@ -183,7 +183,8 @@ transmatrix hrmap::adj(heptagon *h, int i) { return relative_matrix(h->cmove(i), vector& hrmap::allcells() { static vector default_allcells; - if(bounded && !(cgflags & qHUGE_BOUNDED) && !(hybri && hybrid::csteps == 0)) { + if(disksize) return all_disk_cells; + if(closed_manifold && !(cgflags & qHUGE_BOUNDED) && !(hybri && hybrid::csteps == 0)) { celllister cl(gamestart(), 1000000, 1000000, NULL); default_allcells = cl.lst; return default_allcells; @@ -330,6 +331,24 @@ EX void eumerge(cell* c1, int s1, cell *c2, int s2, bool mirror) { EX hookset hooks_newmap; +EX int req_disksize, disksize; +EX vector all_disk_cells; + +EX void init_disk_cells() { + disksize = req_disksize; + all_disk_cells.clear(); + if(!disksize) return; + celllister cl(currentmap->gamestart(), 1000000, disksize, NULL); + all_disk_cells = cl.lst; + sort(all_disk_cells.begin(), all_disk_cells.end()); + } + +EX bool is_in_disk(cell *c) { + auto it = lower_bound(all_disk_cells.begin(), all_disk_cells.end(), c); + if(it == all_disk_cells.end()) return false; + return *it == c; + } + /** create a map in the current geometry */ EX void initcells() { DEBB(DF_INIT, ("initcells")); @@ -520,7 +539,7 @@ EX int celldist(cell *c) { return hybrid::celldistance(c, currentmap->gamestart()); if(nil && !quotient) return DISTANCE_UNKNOWN; if(euc::in()) return celldistance(currentmap->gamestart(), c); - if(sphere || bt::in() || WDIM == 3 || cryst || sn::in() || kite::in() || bounded) return celldistance(currentmap->gamestart(), c); + if(sphere || bt::in() || WDIM == 3 || cryst || sn::in() || kite::in() || closed_manifold) return celldistance(currentmap->gamestart(), c); #if CAP_IRR if(IRREGULAR) return irr::celldist(c, false); #endif @@ -1204,7 +1223,7 @@ EX int celldistance(cell *c1, cell *c2) { } #endif - if(bounded) return bounded_celldistance(c1, c2); + if(closed_manifold) return bounded_celldistance(c1, c2); #if CAP_CRYSTAL if(cryst) return crystal::precise_distance(c1, c2); diff --git a/classes.cpp b/classes.cpp index 3941b1db..0484d4d7 100644 --- a/classes.cpp +++ b/classes.cpp @@ -785,7 +785,7 @@ struct geometryinfo { eVariation default_variation; }; -static const flagtype qBOUNDED = 1; +static const flagtype qCLOSED = 1; static const flagtype qANYQ = 2; static const flagtype qNONORIENTABLE = 4; static const flagtype qSMALL = 8; @@ -835,20 +835,20 @@ extern eVariation variation; #endif #if HDR -static const flagtype qsNONOR = qANYQ | qSMALL | qBOUNDED | qNONORIENTABLE; +static const flagtype qsNONOR = qANYQ | qSMALL | qCLOSED | qNONORIENTABLE; static const flagtype qsNONORE = qsNONOR | qELLIPTIC; -static const flagtype qsBQ = qANYQ | qSMALL | qBOUNDED; -static const flagtype qsSMALL = qANYQ | qSMALL | qBOUNDED; -static const flagtype qsSMALLN = qANYQ | qSMALL | qBOUNDED | qNONORIENTABLE; -static const flagtype qsZEBRA = qANYQ | qSMALL | qBOUNDED | qZEBRA; -static const flagtype qsFIELD = qANYQ | qFIELD | qBOUNDED; -static const flagtype qsDOCKS = qANYQ | qSMALL | qBOUNDED | qDOCKS; -static const flagtype qsSMALLB = qSMALL | qBOUNDED; +static const flagtype qsBQ = qANYQ | qSMALL | qCLOSED; +static const flagtype qsSMALL = qANYQ | qSMALL | qCLOSED; +static const flagtype qsSMALLN = qANYQ | qSMALL | qCLOSED | qNONORIENTABLE; +static const flagtype qsZEBRA = qANYQ | qSMALL | qCLOSED | qZEBRA; +static const flagtype qsFIELD = qANYQ | qFIELD | qCLOSED; +static const flagtype qsDOCKS = qANYQ | qSMALL | qCLOSED | qDOCKS; +static const flagtype qsSMALLB = qSMALL | qCLOSED; static const flagtype qsSMALLBF = qsSMALLB | qsFIELD | qANYQ; static const flagtype qsSMALLBE = qsSMALLB | qELLIPTIC | qANYQ; static const flagtype qsBP = qBINARY | qKITE; -static const flagtype qsSINGLE = qANYQ | qSMALL | qBOUNDED | qSINGLE; +static const flagtype qsSINGLE = qANYQ | qSMALL | qCLOSED | qSINGLE; #endif EX geometryinfo1 giEuclid2 = { gcEuclid, 2, 2, 3, {1,1, 0,0 } }; diff --git a/complex.cpp b/complex.cpp index 44d2a2bd..6758c0fd 100644 --- a/complex.cpp +++ b/complex.cpp @@ -15,7 +15,7 @@ EX namespace whirlwind { EX int fzebra3(cell *c) { if(arcm::in()) return 0; if(euclid) { - if(bounded) return 0; + if(closed_manifold) return 0; auto co = euc2_coordinates(c); int y = co.second; return 1+((((signed short)(y)+int(50000))/3)%3); @@ -1011,7 +1011,7 @@ EX namespace clearing { } EX void imput(cell *c) { - if(bounded) return; + if(closed_manifold) return; if(score.count(c)) return; changes.map_value(score, c); auto& is = score[c]; @@ -1216,7 +1216,7 @@ EX namespace mirror { #endif bool noMirrorOn(cell *c) { - return c->monst || (!shmup::on && isPlayerOn(c)) || (!bounded && c->cpdist > gamerange()); + return c->monst || (!shmup::on && isPlayerOn(c)) || (!closed_or_bounded && c->cpdist > gamerange()); } bool cellMirrorable(cell *c) { @@ -3671,6 +3671,53 @@ EX namespace halloween { EX cell *dragoncells[4]; vector srch; + EX void generate() { + auto lst = currentmap->allcells(); + for(cell *c: lst) + setdist(c, 7, nullptr); + + halloween::dragoncells[0] = NULL; + + if(sphere && geometry == gNormal) { + for(cell *c: lst) { + if(GOLDBERG) { + int fv = c->master->fiftyval; + if(fv == 1 || fv == 4 || fv == 10) + c->wall = waChasm; + if(c == c->master->c7 && fv == 3) + c->item = itTreat; + } + else if(!BITRUNCATED) { + int fv = c->master->fiftyval; + if(fv == 1 || fv == 4 || fv == 2) + c->wall = waChasm; + if(fv == 3) c->item = itTreat; + } + else { + if(c->type == 5) { + int fv = c->master->fiftyval; + if(fv == 3 || fv == 4 || fv == 2 || fv == 5) + c->wall = waChasm; + if(fv == 2) halloween::dragoncells[0] = c; + if(fv == 5) halloween::dragoncells[3] = c; + if(fv == 1) c->item = itTreat; + } + if(c->type == 6) { + int fvset = 0; + for(int i=0; i<6; i+=2) fvset |= 1 << createMov(c, i)->master->fiftyval; + if(fvset == 35 || fvset == 7) c->wall = waChasm; + if(fvset == 7) halloween::dragoncells[1] = c; + if(fvset == 35) halloween::dragoncells[2] = c; + } + } + } + } + else { + for(int i=1; iitem = itTreat; + for(int i=2; iwall = waChasm; + } + } + cell *farempty(bool lastresort = false) { int maxdist = 0; vector validcells; diff --git a/complex2.cpp b/complex2.cpp index ce2637f9..de922d0e 100644 --- a/complex2.cpp +++ b/complex2.cpp @@ -531,7 +531,7 @@ EX void count_status() { } EX bool in_minesweeper() { - return bounded && specialland == laMinefield; + return closed_or_bounded && specialland == laMinefield; } EX bool uncoverMines(cell *c, int lev, int dist, bool just_checking) { @@ -620,7 +620,7 @@ EX bool safe() { EX void uncover_full(cell *c2) { int mineradius = - bounded ? 3 : + closed_or_bounded ? 3 : (items[itBombEgg] < 1 && !tactic::on) ? 0 : items[itBombEgg] < 20 ? 1 : items[itBombEgg] < 30 ? 2 : diff --git a/config.cpp b/config.cpp index 3f47ee76..df934093 100644 --- a/config.cpp +++ b/config.cpp @@ -934,6 +934,11 @@ EX void initConfig() { param_b(vid.smart_area_based, "smart-area-based", false); param_i(vid.cells_drawn_limit, "limit on cells drawn", 10000); param_i(vid.cells_generated_limit, "limit on cells generated", 250); + + param_i(req_disksize, "disk_size") + ->editable(10, 100000, 10, "disk size", "Play on a disk. Enables the special game rules for small bounded spaces (especially relevant for e.g. Minefield and Halloween). The number given is the number of tiles to use; it is not used exactly, actually the smallest disk above this size is used. Set to 0 to disable.", 'd') + ->set_sets([] { dialog::bound_low(0); }) + ->set_reaction([] { if(game_active) { stop_game(); start_game(); } }); #if CAP_SOLV addsaver(sn::solrange_xy, "solrange-xy"); diff --git a/crystal.cpp b/crystal.cpp index 732a506b..7c164751 100644 --- a/crystal.cpp +++ b/crystal.cpp @@ -1358,7 +1358,7 @@ EX void set_crystal_period_flags() { for(auto& g: ginf) if(g.flags & qCRYSTAL) { set_flag(ginf[gNil].flags, qSMALL, crystal_period && crystal_period <= 8); - set_flag(ginf[gNil].flags, qBOUNDED, crystal_period); + set_flag(ginf[gNil].flags, qCLOSED, crystal_period); } } diff --git a/euclid.cpp b/euclid.cpp index ec779512..4db630b0 100644 --- a/euclid.cpp +++ b/euclid.cpp @@ -149,7 +149,7 @@ EX namespace euc { vector toruscells; vector& allcells() override { - if(bounded) { + if(closed_manifold && !disksize) { if(isize(toruscells) == 0) { celllister cl(getOrigin()->c7, 1000, 1000000, NULL); toruscells = cl.lst; @@ -634,7 +634,7 @@ EX namespace euc { } set_flag(ginf[g].flags, qANYQ, eu.infinite_dims < dim); - set_flag(ginf[g].flags, qBOUNDED, eu.infinite_dims == 0); + set_flag(ginf[g].flags, qCLOSED, eu.infinite_dims == 0); set_flag(ginf[g].flags, qSMALL, eu.infinite_dims == 0 && eu.det <= 4096); bool nonori = false; if(eu.twisted&1) nonori = !nonori; diff --git a/expansion.cpp b/expansion.cpp index c16f914b..1df410a6 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -392,7 +392,7 @@ int type_in_quick(expansion_analyzer& ea, cell *c, const cellfunction& f) { EX bool sizes_known() { if(reg3::in_rule()) return true; - if(bounded) return false; + if(closed_manifold) return false; // Castle Anthrax is infinite if(bt::in()) return false; // not implemented @@ -717,7 +717,7 @@ string produce_coef_formula(vector coef) { void expansion_analyzer::view_distances_dialog() { static int lastticks; - if(scrolling_distances && !bounded) { + if(scrolling_distances && !closed_manifold) { scrolltime += SDL_GetTicks() - lastticks; first_distance += scrolltime / scrollspeed; scrolltime %= scrollspeed; @@ -729,7 +729,7 @@ void expansion_analyzer::view_distances_dialog() { dialog::init(""); cmode |= sm::DIALOG_STRICT_X | sm::EXPANSION; - int maxlen = bounded ? 128 : 16 + first_distance; + int maxlen = closed_manifold ? 128 : 16 + first_distance; vector qty(maxlen); auto& expansion = get_expansion(); @@ -748,12 +748,12 @@ void expansion_analyzer::view_distances_dialog() { } else { if(distance_from == dfPlayer) { - celllister cl(cwt.at, bounded ? maxlen-1 : gamerange(), 100000, NULL); + celllister cl(cwt.at, closed_manifold ? maxlen-1 : gamerange(), 100000, NULL); for(int d: cl.dists) if(d >= 0 && d < maxlen) qty[d]++; } else { - celllister cl(cwt.at, bounded ? maxlen-1 : gamerange(), 100000, NULL); + celllister cl(cwt.at, closed_manifold ? maxlen-1 : gamerange(), 100000, NULL); for(cell *c: cl.lst) if((not_only_descendants || is_descendant(c)) && curr_dist(c) < maxlen) qty[curr_dist(c)]++; } #if !CAP_GMP diff --git a/fieldpattern.cpp b/fieldpattern.cpp index 0e304ae2..2902578b 100644 --- a/fieldpattern.cpp +++ b/fieldpattern.cpp @@ -1458,7 +1458,7 @@ EX void enableFieldChange() { ginf[geometry].distlimit = ginf[gxcur.base].distlimit; ginf[geometry].tiling_name = ginf[gxcur.base].tiling_name; ginf[geometry].default_variation = ginf[gxcur.base].default_variation; - ginf[geometry].flags = qFIELD | qANYQ | qBOUNDED; + ginf[geometry].flags = qFIELD | qANYQ | qCLOSED; fieldpattern::current_quotient_field.init(gxcur.primes[gxcur.current_prime_id].p); } @@ -1473,7 +1473,7 @@ EX void field_from_current() { gg.vertex = go.vertex; gg.distlimit = go.distlimit; gg.tiling_name = go.tiling_name; - gg.flags = go.flags | qANYQ | qFIELD | qBOUNDED; + gg.flags = go.flags | qANYQ | qFIELD | qCLOSED; gg.g = go.g; gg.default_variation = go.default_variation; fieldpattern::quotient_field_changed = true; diff --git a/geom-exp.cpp b/geom-exp.cpp index 8093adcb..0c6399ee 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -760,7 +760,7 @@ EX geometry_data compute_geometry_data() { if(euclid) gd.euler = 0; else if(sphere && nonorientable) gd.euler = 1; else if(sphere) gd.euler = 2; - else if(!bounded) gd.euler = -2; + else if(!closed_manifold) gd.euler = -2; else if(WDIM == 3) gd.euler = 0; else switch(geometry) { case gFieldQuotient: @@ -810,7 +810,7 @@ EX geometry_data compute_geometry_data() { gd.denom /= g; } - if(euclid && bounded) { + if(euclid && closed_manifold) { gd.worldsize = euc::eu.det; if(BITRUNCATED) gd.worldsize *= (a4 ? 2 : 3); if(GOLDBERG) gd.worldsize *= cgi.gpdata->area; @@ -821,7 +821,7 @@ EX geometry_data compute_geometry_data() { else gd.worldsize = gd.denom ? gd.nom / gd.denom : 0; - if(gd.euler < 0 && !bounded) + if(gd.euler < 0 && !closed_manifold) gd.worldsize = -gd.worldsize; string spf = its(ts); @@ -895,6 +895,7 @@ EX geometry_data compute_geometry_data() { } gd.size_str = + disksize ? its(isize(currentmap->allcells())) : #if CAP_BT bt::in() ? fts(8 * M_PI * sqrt(2) * log(2) / pow(vid.binary_width, WDIM-1), 4) + " exp(∞)" : #endif @@ -905,10 +906,10 @@ EX geometry_data compute_geometry_data() { #if CAP_CRYSTAL cryst ? "∞^" + its(ts/2) : #endif - WDIM == 3 && bounded ? its(isize(currentmap->allcells())) : + WDIM == 3 && closed_manifold ? its(isize(currentmap->allcells())) : WDIM == 3 && euclid ? "∞" : gd.worldsize < 0 ? (gd.nom%gd.denom ? its(gd.nom)+"/"+its(gd.denom) : its(-gd.worldsize)) + " exp(∞)": - (euclid && quotient && !bounded) ? "∞" : + (euclid && quotient && !closed_manifold) ? "∞" : gd.worldsize == 0 ? "∞²" : its(gd.worldsize); @@ -1057,8 +1058,9 @@ EX void showEuclideanMenu() { dialog::addBreak(100); menuitem_land_structure('l'); + add_edit(req_disksize); - if(specialland == laMinefield && bounded) { + if(specialland == laMinefield && closed_or_bounded) { dialog::addSelItem(XLAT("number of mines"), its(bounded_mine_quantity), 'm'); dialog::add_action([] { dialog::editNumber(bounded_mine_quantity, 0, bounded_mine_max, 1, (bounded_mine_max+5)/10, @@ -1129,7 +1131,7 @@ EX void showEuclideanMenu() { else if(viewdists) viewdists = false; }); - if(bounded) { + if(closed_manifold) { dialog::addSelItem(XLAT("Euler characteristics"), its(gd.euler), 0); if(WDIM == 3) ; else if(nonorientable) diff --git a/geometry2.cpp b/geometry2.cpp index 0fd07762..4f5cf930 100644 --- a/geometry2.cpp +++ b/geometry2.cpp @@ -139,7 +139,7 @@ transmatrix hrmap_standard::relative_matrixh(heptagon *h2, heptagon *h1, const h steps++; if(steps > 10000) { println(hlog, "not found"); return Id; } - if(bounded) { + if(closed_manifold) { transmatrix T; ld bestdist = 1e9; for(int d=0; dwall = RANDPAT3(0) ? waCavewall : waCavefloor; - else if(euclid && bounded) { + else if(euclid && closed_or_bounded) { c->wall = waCavefloor; } else if(nil) { @@ -685,7 +685,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { #endif else if(arb::in() && arb::current.have_line) v = arb::linespattern(c) ? 24 : 16; - else if((euclid&&bounded) || hyperbolic_not37 || quotient || arcm::in()) { + else if((euclid&&closed_or_bounded) || hyperbolic_not37 || quotient || arcm::in()) { v = hrand(100) < 25 ? 24 : 16; } else if(euclid) { @@ -760,7 +760,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { if(d==8) { if(randomPatternsMode) c->wall = RANDPAT ? waVinePlant : waNone; - else if(euclid && bounded) ; + else if(euclid && closed_or_bounded) ; #if CAP_ARCM else if(arcm::in() && arcm::current.have_line) c->wall = arcm::linespattern(c) ? waVinePlant : waNone; @@ -1269,50 +1269,6 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { break; case laHalloween: - if(fargen) { - if(GOLDBERG) { - int fv = c->master->fiftyval; - if(fv == 1 || fv == 4 || fv == 10) - c->wall = waChasm; - if(c == c->master->c7 && fv == 3) - c->item = itTreat; - } - else if(!BITRUNCATED && !euclid) { - int fv = c->master->fiftyval; - if(fv == 1 || fv == 4 || fv == 2) - c->wall = waChasm; - if(fv == 3) c->item = itTreat; - } - else { - if(c->type == 5) { - int fv = c->master->fiftyval; - if(fv == 3 || fv == 4 || fv == 2 || fv == 5) - c->wall = waChasm; - if(fv == 2) halloween::dragoncells[0] = c; - if(fv == 5) halloween::dragoncells[3] = c; - if(fv == 1) c->item = itTreat; - } - if(c->type == 6 && !euclid) { - int fvset = 0; - for(int i=0; i<6; i+=2) fvset |= 1 << createMov(c, i)->master->fiftyval; - if(fvset == 35 || fvset == 7) c->wall = waChasm; - if(fvset == 7) halloween::dragoncells[1] = c; - if(fvset == 35) halloween::dragoncells[2] = c; - } - } - if(quotient && zebra40(c) == 7) { - c->item = itTreat; - halloween::dragoncells[0] = NULL; - } - if(quotient && zebra40(c) == 5) { - c->wall = waChasm; - } - if(euclid && bounded) { - int i = hrand(100); - if(i == 0) c->item = itTreat; - else if(i < 5) c->wall = waChasm; - } - } break; case laWildWest: @@ -2158,7 +2114,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { break; case laMinefield: - if(d == 7 && bounded) c->wall = waMineUnknown; + if(d == 7 && closed_or_bounded) c->wall = waMineUnknown; else if(d == 7) { c->wall = waMineUnknown; // 250: rare mines @@ -2191,7 +2147,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { c->monst = moBomberbird; else placeLocalSpecial(c, 500); } - if(d == 3 && safety && (c->wall == waMineMine || c->wall == waMineUnknown) && !bounded) + if(d == 3 && safety && (c->wall == waMineMine || c->wall == waMineUnknown) && !closed_or_bounded) c->wall = waMineOpen; break; @@ -2879,7 +2835,7 @@ EX void set_land_for_geometry(cell *c) { else if(euc::in(3)) euc::set_land(c); #endif else if(hybri) setLandHybrid(c); - else if(sphere || (euclid && bounded)) setLandSphere(c); + else if(sphere || (euclid && closed_or_bounded)) setLandSphere(c); else if(euclid) setLandEuclid(c); else if(quotient) { setland(c, specialland); setLandQuotient(c); } else if(sol) setLandSol(c); @@ -3058,6 +3014,13 @@ EX void setdist(cell *c, int d, cell *from) { } } + if(disksize && !is_in_disk(c)) { + setland(c, laMemory); + if(!isMultitile(c)) c->monst = moNone; + c->item = itNone; + c->wall = waChasm; + } + ONEMPTY if(!c->item) { if(isCrossroads(c->land)) placeCrossroadOrbs(c); diff --git a/landlock.cpp b/landlock.cpp index c0b6fbd0..31131918 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -139,7 +139,7 @@ EX string land_structure_name(bool which) { } EX void fix_land_structure_choice() { - if(bounded) { + if(closed_or_bounded) { if(land_structure != lsTotalChaos && land_structure != lsChaosRW) land_structure = lsSingle; } @@ -155,7 +155,7 @@ EX void fix_land_structure_choice() { land_structure = lsSingle; if(land_structure == lsPatchedChaos && !(stdeuc || nil || cryst || (euclid && WDIM == 3))) land_structure = lsSingle; - if(bounded && !among(land_structure, lsChaosRW, lsTotalChaos, lsSingle)) + if(closed_or_bounded && !among(land_structure, lsChaosRW, lsTotalChaos, lsSingle)) land_structure = lsSingle; } @@ -777,12 +777,12 @@ EX land_validity_t& land_validity(eLand l) { return disabled; #endif - if(l == laMinefield && bounded) + if(l == laMinefield && closed_or_bounded) return special_geo3; if(l == laAsteroids) { if(!shmup::on) return shmup_only; - if(!bounded) return bounded_only; + if(!closed_manifold) return bounded_only; return specially_designed; } @@ -901,7 +901,7 @@ EX land_validity_t& land_validity(eLand l) { return not_implemented; // Halloween needs bounded world (can be big bounded) - if(l == laHalloween && !bounded) + if(l == laHalloween && !closed_or_bounded) return bounded_only; // Crystal World is designed for nice_dual geometries @@ -960,7 +960,7 @@ EX land_validity_t& land_validity(eLand l) { if(geometry == gBinary4) return not_implemented; // no equidistants supported in these geometries (big sphere is OK though) - if(bounded && !bigsphere) + if(closed_or_bounded && !bigsphere) return unbounded_only_except_bigsphere; // Yendorian only implemented in standard if(l == laEndorian && geometry) @@ -1004,7 +1004,7 @@ EX land_validity_t& land_validity(eLand l) { if(l == laClearing) if(!(stdeucx || geometry == gBinaryTiling || a38 || (a45 && BITRUNCATED) || (a47 && BITRUNCATED)) || NONSTDVAR) - if(!bounded) + if(!closed_or_bounded) return not_implemented; // does not work in non-bitrunc a4 @@ -1012,7 +1012,7 @@ EX land_validity_t& land_validity(eLand l) { return some0; // does not work in bounded either - if(l == laOvergrown && bounded) + if(l == laOvergrown && closed_or_bounded) return some0; // horocycle-based lands, not available in bounded geometries nor in Chaos mode @@ -1023,7 +1023,7 @@ EX land_validity_t& land_validity(eLand l) { return not_in_chaos; } if(arcm::in() || kite::in()) return not_implemented; - if(bounded) return unbounded_only; + if(closed_or_bounded) return unbounded_only; if(INVERSE) return not_implemented; } @@ -1064,7 +1064,7 @@ EX land_validity_t& land_validity(eLand l) { return technical; // only in bounded geometry, and not in PTM - if(l == laCA && !bounded) + if(l == laCA && !closed_or_bounded) return bounded_only; if(l == laCA && tactic::on) @@ -1121,7 +1121,7 @@ EX land_validity_t& land_validity(eLand l) { if(l == laStorms && hyperbolic_not37) return pattern_not_implemented_random; - if(l == laTrollheim && !stdeucx && !bounded) + if(l == laTrollheim && !stdeucx && !closed_or_bounded) return some1; if(l == laReptile && sol) return ugly_version_nofull; @@ -1174,7 +1174,7 @@ EX land_validity_t& land_validity(eLand l) { if(l == laPrairie) { if(GOLDBERG) return not_implemented; else if(stdeucx || (bigsphere && BITRUNCATED && !elliptic) || (geometry == gFieldQuotient)) ; - else if(!bounded) return not_implemented; + else if(!closed_or_bounded) return not_implemented; else return unbounded_only; } @@ -1191,10 +1191,10 @@ EX land_validity_t& land_validity(eLand l) { if(sol && l == laCamelot) return not_implemented; - if(euclid && quotient && !bounded && l == laCrossroads && euc::sdxy().second == -2 * euc::sdxy().first) + if(euclid && quotient && !closed_or_bounded && l == laCrossroads && euc::sdxy().second == -2 * euc::sdxy().first) return full_game; - if(euclid && quotient && !bounded && l == laCrossroads4 && euc::sdxy().second == 0) + if(euclid && quotient && !closed_or_bounded && l == laCrossroads4 && euc::sdxy().second == 0) return full_game; // highlight Zebra-based lands on Zebra Quotient! @@ -1231,7 +1231,7 @@ EX land_validity_t& land_validity(eLand l) { return pattern_not_implemented_exclude; } - if(l == laStorms && euclid && bounded) + if(l == laStorms && euclid && closed_manifold) return interesting; if(l == laMagnetic) diff --git a/mapeditor.cpp b/mapeditor.cpp index 59e21ea7..d6320d3a 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -684,7 +684,7 @@ EX namespace mapstream { EX hookset hooks_loadmap; EX cell *save_start() { - return (bounded || euclid || prod || arcm::in() || sol || INVERSE) ? currentmap->gamestart() : cwt.at->master->c7; + return (closed_manifold || euclid || prod || arcm::in() || sol || INVERSE) ? currentmap->gamestart() : cwt.at->master->c7; } #if CAP_EDIT diff --git a/mapeffects.cpp b/mapeffects.cpp index 176532de..539f2be8 100644 --- a/mapeffects.cpp +++ b/mapeffects.cpp @@ -770,9 +770,9 @@ EX bool makeEmpty(cell *c) { c->wall = waBoat; // , c->item = itOrbYendor; else if(c->land == laMinefield) c->wall = waMineOpen; - else if(c->wall == waFan && bounded) + else if(c->wall == waFan && closed_manifold) ; - else if(c->wall == waOpenPlate && bounded) + else if(c->wall == waOpenPlate && closed_manifold) ; else if(c->wall == waTrunk || c->wall == waSolidBranch || c->wall == waWeakBranch) ; @@ -786,13 +786,13 @@ EX bool makeEmpty(cell *c) { ; else if(c->land == laDocks) c->wall = waBoat; - else if(c->wall == waFreshGrave && bounded) + else if(c->wall == waFreshGrave && closed_manifold) ; else if(c->wall == waBarrier && sphere && WDIM == 3) ; else if(isReptile(c->wall)) c->wparam = reptilemax(); - else if(c->wall == waAncientGrave && bounded) + else if(c->wall == waAncientGrave && closed_manifold) ; else if(c->wall != waRoundTable) c->wall = waNone; diff --git a/menus.cpp b/menus.cpp index 71343a83..96d922dd 100644 --- a/menus.cpp +++ b/menus.cpp @@ -704,7 +704,7 @@ EX void mode_higlights() { } EX eLandStructure default_land_structure() { - if(bounded) return lsSingle; + if(closed_or_bounded) return lsSingle; if(tactic::on || princess::challenge) return lsSingle; if(yendor::on) return yendor::get_land_structure(); if(specialland == laCanvas) return lsSingle; @@ -1171,7 +1171,7 @@ EX named_functionality get_o_key() { dialog::infix = ""; - if((geometry != gNormal || NONSTDVAR) && !daily::on) + if((geometry != gNormal || NONSTDVAR || disksize) && !daily::on) res.push_back(named_functionality(XLAT("experiment with geometry"), runGeometryExperiments)); if(res.empty()) return named_dialog(XLAT("world overview"), showOverview); diff --git a/monstergen.cpp b/monstergen.cpp index a92b8ca9..f69dc222 100644 --- a/monstergen.cpp +++ b/monstergen.cpp @@ -335,18 +335,20 @@ EX void wandering() { if(cwt.at->land == laCA) ghostcount = 0; bool genturn = hrand(100) < 30; - if(bounded && specialland == laClearing) + if(closed_or_bounded && specialland == laClearing) clearing::new_root(); if(cwt.at->land == laZebra && cwt.at->wall == waNone && wchance(items[itZebra], 20)) wanderingZebra(cwt.at); - - bool smallbounded_generation = smallbounded || (bounded && specialland == laClearing); - + + bool smallbounded_generation = smallbounded || (closed_manifold && specialland == laClearing); + + auto valid = [] (cell *c) { if(disksize && !is_in_disk(c)) return false; if(inmirror(c)) return false; return true; }; + if(smallbounded_generation) { int maxdist = 0; - for(int i=0; icpdist > maxdist) maxdist = dcal[i]->cpdist; - for(int i=0; icpdist >= maxdist-1) { first7 = i; break; } + for(int i=0; icpdist > maxdist) maxdist = dcal[i]->cpdist; + for(int i=0; icpdist >= maxdist-1) { first7 = i; break; } if(hrand(5) == 0) { // spawn treasure @@ -362,10 +364,12 @@ EX void wandering() { } } + int iter = 0; while(first7 < isize(dcal)) { + iter++; if(iter > 1000) break; int i = first7 + hrand(isize(dcal) - first7); cell *c = dcal[i]; - if(inmirror(c)) continue; + if(!valid(c)) continue; if(isPlayerOn(c)) break; if(specialland == laStorms) { diff --git a/monstermove.cpp b/monstermove.cpp index 9ca128b2..7ae8df9a 100644 --- a/monstermove.cpp +++ b/monstermove.cpp @@ -1393,7 +1393,7 @@ EX void movehex_rest(bool mounted) { EX void movemutant() { manual_celllister mcells; for(cell *c: currentmap->allcells()) mcells.add(c); - if(!bounded) + if(!closed_or_bounded) for(int i=0; iland == laClearing && c->monst != moMutant && !pseudohept(c)) @@ -1427,7 +1427,7 @@ EX void movemutant() { if(isPlayerOn(c2)) continue; if((c2->land == laOvergrown || !pseudohept(c2)) && passable(c2, c, 0)) { - if(c2->land == laClearing && !bounded && c2->mpdist > 7) continue; + if(c2->land == laClearing && !closed_or_bounded && c2->mpdist > 7) continue; c2->monst = moMutant; c2->mondir = c->c.spin(j); c2->stuntime = mutantphase; @@ -2096,7 +2096,7 @@ EX void movemonsters() { DEBB(DF_TURN, ("leader")); if(havewhat & HF_LEADER) groupmove(moPirate, 0); DEBB(DF_TURN, ("mutant")); - if((havewhat & HF_MUTANT) || (bounded && among(specialland, laOvergrown, laClearing))) movemutant(); + if((havewhat & HF_MUTANT) || (closed_or_bounded && among(specialland, laOvergrown, laClearing))) movemutant(); DEBB(DF_TURN, ("bugs")); if(havewhat & HF_BUG) hive::movebugs(); DEBB(DF_TURN, ("whirlpool")); diff --git a/nonisotropic.cpp b/nonisotropic.cpp index 27afcf37..0ff8fa0c 100644 --- a/nonisotropic.cpp +++ b/nonisotropic.cpp @@ -962,7 +962,7 @@ EX namespace nilv { int coords = 0; for(int a=0; a<3; a++) if(nilperiod[a]) coords++; set_flag(ginf[gNil].flags, qANYQ, coords); - set_flag(ginf[gNil].flags, qBOUNDED, coords == 3); + set_flag(ginf[gNil].flags, qCLOSED, coords == 3); set_flag(ginf[gNil].flags, qSMALL, coords == 3 && nilperiod[0] * nilperiod[1] * nilperiod[2] <= 4096); } @@ -1229,7 +1229,7 @@ EX namespace hybrid { EX void fix_bounded_cycles() { if(!rotspace) return; - if(!bounded) return; + if(!closed_manifold) return; in_underlying([&] { cellwalker final(currentmap->gamestart(), 0); auto& ac = currentmap->allcells(); @@ -1505,7 +1505,7 @@ EX namespace hybrid { dialog::extra_options = [=] () { if(rotspace) { int e_steps = cgi.psl_steps / gcd(cgi.single_step, cgi.psl_steps); - bool ubounded = PIU(bounded); + bool ubounded = PIU(closed_manifold); dialog::addSelItem( sphere ? XLAT("elliptic") : XLAT("PSL(2,R)"), its(e_steps), 'P'); dialog::add_action(set_s(e_steps, true)); dialog::addSelItem( sphere ? XLAT("sphere") : XLAT("SL(2,R)"), its(2*e_steps), 'P'); diff --git a/pattern2.cpp b/pattern2.cpp index 9fe0a78f..006bd576 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -441,12 +441,12 @@ EX int fieldval_uniq(cell *c) { } else if(euc::in(2)) { auto p = euc2_coordinates(c); - if(bounded) return p.first + p.second * (1 << 16); + if(closed_manifold) return p.first + p.second * (1 << 16); return gmod(p.first - 22 * p.second, 3*127); } else if(euc::in(3)) { auto co = euc::get_ispacemap()[c->master]; - if(bounded) return co[0] + (co[1] << 10) + (co[2] << 20); + if(closed_manifold) return co[0] + (co[1] << 10) + (co[2] << 20); return gmod(co[0] + 3 * co[1] + 9 * co[2], 3*127); } else if(bt::in() || arcm::in() || nil || S3 >= OINF || (cgflags & qIDEAL)) return 0; @@ -1604,7 +1604,7 @@ EX namespace patterns { color_t nearer_map(cell *c) { if(computed_nearer_map.count(c)) return computed_nearer_map[c]; - if(!bounded) return 0; + if(!closed_manifold) return 0; cell *sc = currentmap->gamestart(); auto ac = currentmap->allcells(); @@ -1645,7 +1645,7 @@ EX namespace patterns { color_t furthest_map(cell *c, int reduce) { auto& cfm = computed_furthest_map; if(cfm.count(c)) return cfm[c]; - if(!bounded) return 0; + if(!closed_manifold) return 0; cell *sc = currentmap->gamestart(); auto ac = currentmap->allcells(); @@ -2031,7 +2031,7 @@ EX namespace patterns { dialog::addSelItem(XLAT("Penrose staircase"), "Nil", '/'); } - if(bounded) { + if(closed_manifold) { dialog::addSelItem(XLAT("nearer end"), "bounded", 'Z'); dialog::addSelItem(XLAT("furthest from start"), "bounded", 'Y'); } diff --git a/quit.cpp b/quit.cpp index 5b8564f8..d6712d9d 100644 --- a/quit.cpp +++ b/quit.cpp @@ -371,7 +371,7 @@ EX void showMission() { } dialog::addInfo(XLAT("Dropped floors: %1/%2", its(score), its(all))); if(score == all) dialog::addInfo(XLAT("CONGRATULATIONS!"), iinf[itOrbYendor].color); - if(score == all && geometry == gKleinQuartic && variation == eVariation::untruncated && gp::param == gp::loc(1,1)) + if(score == all && geometry == gKleinQuartic && variation == eVariation::untruncated && gp::param == gp::loc(1,1) && !disksize) achievement_gain_once("LOVASZ", rg::special_geometry); } else { diff --git a/racing.cpp b/racing.cpp index 5338b298..5166dbe2 100644 --- a/racing.cpp +++ b/racing.cpp @@ -475,7 +475,7 @@ EX void generate_track() { } try { - if(bounded && !prod && !(cgflags & qHUGE_BOUNDED)) { + if(closed_or_bounded && !prod && !(cgflags & qHUGE_BOUNDED)) { bounded_track = true; make_bounded_track(s); } @@ -754,7 +754,7 @@ bool inrec = false; EX ld race_angle = 90; EX bool force_standard_centering() { - return nonisotropic || hybri || quotient || bounded; + return nonisotropic || hybri || quotient || closed_or_bounded; } EX bool use_standard_centering() { diff --git a/rogueviz/balloonsim.cpp b/rogueviz/balloonsim.cpp index 5494bd1e..e2848f41 100644 --- a/rogueviz/balloonsim.cpp +++ b/rogueviz/balloonsim.cpp @@ -490,7 +490,7 @@ void explore() { ginf[gArbitrary].g = giEuclid2; ginf[gArbitrary].sides = 7; - set_flag(ginf[gArbitrary].flags, qBOUNDED, true); + set_flag(ginf[gArbitrary].flags, qCLOSED, true); set_flag(ginf[gArbitrary].flags, qAFFINE, false); geom3::apply_always3(); diff --git a/rogueviz/flocking.cpp b/rogueviz/flocking.cpp index b49bf592..afa0efb5 100644 --- a/rogueviz/flocking.cpp +++ b/rogueviz/flocking.cpp @@ -503,8 +503,8 @@ bool drawVertex(const shiftmatrix &V, cell *c, shmup::monster *m) { } void init() { - if(!bounded) { - addMessage("Flocking simulation needs a bounded space."); + if(!closed_manifold) { + addMessage("Flocking simulation needs a closed manifold."); return; } stop_game(); diff --git a/rogueviz/janko.cpp b/rogueviz/janko.cpp index 38364db2..bbde8881 100644 --- a/rogueviz/janko.cpp +++ b/rogueviz/janko.cpp @@ -126,7 +126,7 @@ void create_janko() { gJanko1 = eGeometry(isize(ginf) - 1); // variation = eVariation::pure; auto& gi = ginf.back(); - gi.flags = qANYQ | qBOUNDED | qEXPERIMENTAL; + gi.flags = qANYQ | qCLOSED | qEXPERIMENTAL; gi.quotient_name = "Janko"; gi.shortname = "Janko"; gi.menu_displayed_name = "Janko group J1"; diff --git a/rogueviz/notknot.cpp b/rogueviz/notknot.cpp index 427149b5..f5f158e9 100644 --- a/rogueviz/notknot.cpp +++ b/rogueviz/notknot.cpp @@ -1148,7 +1148,7 @@ void create_notknot() { } else ginf[gNotKnot] = ginf[base]; auto& gi = ginf.back(); - gi.flags |= qANYQ | qBOUNDED | qEXPERIMENTAL | qPORTALSPACE; + gi.flags |= qANYQ | qCLOSED | qEXPERIMENTAL | qPORTALSPACE; gi.quotient_name = "notknot"; gi.shortname = "notknot"; gi.menu_displayed_name = "notknot"; diff --git a/rogueviz/rogueviz.cpp b/rogueviz/rogueviz.cpp index b37cc7a1..f6f9dccb 100644 --- a/rogueviz/rogueviz.cpp +++ b/rogueviz/rogueviz.cpp @@ -602,7 +602,7 @@ bool drawVertex(const shiftmatrix &V, cell *c, shmup::monster *m) { bool multidraw = quotient; - bool use_brm = bounded && isize(currentmap->allcells()) <= brm_limit; + bool use_brm = closed_or_bounded && isize(currentmap->allcells()) <= brm_limit; if(!lshiftclick) for(int j=0; jallcells()); + if(closed_or_bounded) n = isize(currentmap->allcells()); numsnake = n; snakecells.resize(numsnake); snakefirst.resize(numsnake); @@ -85,7 +85,7 @@ namespace sag { snakenode.resize(numsnake); lpbak.resize(numsnake); wpbak.resize(numsnake); - if(bounded) { + if(closed_or_bounded) { for(int i=0; iallcells()[i], 0); setsnake(cw, i); diff --git a/rug.cpp b/rug.cpp index bfbe4800..af8cc4cc 100644 --- a/rug.cpp +++ b/rug.cpp @@ -183,7 +183,7 @@ EX rugpoint *addRugpoint(shiftpoint h, double dist) { m->y1 = (1 - onscreen[1] * pconf.scale) / 2; m->valid = false; - if(euclid && quotient && !bounded) { + if(euclid && quotient && !closed_manifold) { hyperpoint h1 = iso_inverse(models::euclidean_spin) * eumove(euc::eu.user_axes[1]) * C0; h1 /= sqhypot_d(2, h1); if(nonorientable) h1 /= 2; @@ -557,7 +557,7 @@ EX void buildRug() { need_mouseh = true; good_shape = false; #if MAXMDIM >= 4 - if(euclid && bounded) { + if(euclid && closed_manifold) { good_shape = true; buildTorusRug(); return; @@ -785,7 +785,7 @@ EX int precision_increases; bool stop = false; EX bool subdivide_further() { - if(euclid && bounded) return false; + if(euclid && closed_manifold) return false; if(GDIM == 3) return false; return isize(points) * 4 < vertex_limit; } @@ -794,7 +794,7 @@ EX void subdivide() { int N = isize(points); // if(euclid && gwhere == gEuclid) return; if(!subdivide_further()) { - if(euclid && !bounded && gwhere == gEuclid) { + if(euclid && !closed_manifold && gwhere == gEuclid) { println(hlog, "Euclidean -- full precision"); stop = true; } diff --git a/system.cpp b/system.cpp index a968cca2..c7c34f4e 100644 --- a/system.cpp +++ b/system.cpp @@ -346,11 +346,14 @@ EX void initgame() { makeEmpty(cwt.at); } - if(specialland == laMinefield && bounded) { + if(specialland == laMinefield && closed_or_bounded) { bfs(); generate_mines(); } - + + if(specialland == laHalloween) + halloween::generate(); + if(in_lovasz()) { cwt.at->item = itOrbInvis; } @@ -1455,7 +1458,7 @@ EX void switch_game_mode(char switchWhat) { if(tactic::on) firstland = laIce; yendor::on = tactic::on = princess::challenge = false; land_structure = ls::any_chaos() ? lsNiceWalls : lsChaos; - if(bounded) set_geometry(gNormal); + if(closed_or_bounded) set_geometry(gNormal); racing::on = false; break; @@ -1570,6 +1573,7 @@ EX void start_game() { #endif initcells(); get_expansion().reset(); + init_disk_cells(); if(randomPatternsMode) { for(int i=0; i