An option to play on a disk (and use bounded space rules). Also renamed 'bounded' flag to 'closed' or similar, and improved Halloween

This commit is contained in:
Zeno Rogue 2022-05-21 13:08:42 +02:00
parent 9bc0623022
commit 793148729b
40 changed files with 218 additions and 171 deletions

View File

@ -112,6 +112,7 @@ EX bool wrongMode(char flags) {
if(flags != rg::special_geometry && flags != rg::special_geometry_nicewalls) { if(flags != rg::special_geometry && flags != rg::special_geometry_nicewalls) {
if(!BITRUNCATED) return true; if(!BITRUNCATED) return true;
if(geometry != gNormal) return true; if(geometry != gNormal) return true;
if(disksize) return true;
} }
if(shmup::on != (flags == rg::shmup || flags == rg::racing)) 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; if(randomPatternsMode) return;
LATE( achievement_collection2(it, q); ) 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); 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); achievement_gain("HALLOWEEN2", rg::special_geometry);
if(q == 1) { if(q == 1) {
@ -309,12 +310,12 @@ EX void achievement_collection2(eItem it, int q) {
// 32 // 32
if(it == itHolyGrail) { if(it == itHolyGrail) {
if(q == 1) achievement_gain("GRAIL2"); if(q == 1) achievement_gain("GRAIL2");
if(PURE && geometry == gNormal) if(PURE && geometry == gNormal && !disksize)
achievement_gain("GRAILH", rg::special_geometry_nicewalls); achievement_gain("GRAILH", rg::special_geometry_nicewalls);
#if CAP_CRYSTAL #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); 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); achievement_gain("GRAIL4D2", rg::special_geometry);
#endif #endif
if(q == 3) achievement_gain("GRAIL3"); if(q == 3) achievement_gain("GRAIL3");
@ -599,7 +600,7 @@ EX void achievement_count(const string& s, int current, int prev) {
achievement_gain("LIGHTNING2"); achievement_gain("LIGHTNING2");
if(s == "LIGHTNING" && current-prev >= 10) if(s == "LIGHTNING" && current-prev >= 10)
achievement_gain("LIGHTNING3"); achievement_gain("LIGHTNING3");
if(s == "MIRAGE" && current >= 35 && geometry == gEuclid) if(s == "MIRAGE" && current >= 35 && geometry == gEuclid && !disksize)
achievement_gain("MIRAGE", rg::special_geometry); achievement_gain("MIRAGE", rg::special_geometry);
if(s == "ORB" && current >= 10) if(s == "ORB" && current >= 10)
achievement_gain("ORB3"); achievement_gain("ORB3");
@ -633,6 +634,7 @@ EX void achievement_score(int cat, int number) {
if(cheater) return; if(cheater) return;
if(casual) return; if(casual) return;
LATE( achievement_score(cat, number); ) LATE( achievement_score(cat, number); )
if(disksize) return;
if(cat == LB_HALLOWEEN) { if(cat == LB_HALLOWEEN) {
if(geometry != gSphere && geometry != gElliptic) if(geometry != gSphere && geometry != gElliptic)
return; return;
@ -943,7 +945,7 @@ EX string get_rich_presence_text() {
return "Guided Tour"; return "Guided Tour";
string res; string res;
if(geometry != gNormal || !BITRUNCATED) if(geometry != gNormal || !BITRUNCATED || disksize)
res = res + full_geometry_name() + " "; res = res + full_geometry_name() + " ";
if(land_structure != default_land_structure()) res += land_structure_name(false) + " "; if(land_structure != default_land_structure()) res += land_structure_name(false) + " ";

View File

@ -659,21 +659,21 @@ EX void load(const string& fname, bool load_as_slided IS(false), bool keep_slide
ep.force_eat(")"); ep.force_eat(")");
ginf[gArbitrary].g = curv > 0 ? giSphere2 : curv < 0 ? giHyperb2 : giEuclid2; ginf[gArbitrary].g = curv > 0 ? giSphere2 : curv < 0 ? giHyperb2 : giEuclid2;
ginf[gArbitrary].sides = 7; 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); set_flag(ginf[gArbitrary].flags, qAFFINE, false);
geom3::apply_always3(); geom3::apply_always3();
} }
else if(ep.eat("e2.")) { else if(ep.eat("e2.")) {
ginf[gArbitrary].g = giEuclid2; ginf[gArbitrary].g = giEuclid2;
ginf[gArbitrary].sides = 7; 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); set_flag(ginf[gArbitrary].flags, qAFFINE, false);
geom3::apply_always3(); geom3::apply_always3();
} }
else if(ep.eat("a2.")) { else if(ep.eat("a2.")) {
ginf[gArbitrary].g = giEuclid2; ginf[gArbitrary].g = giEuclid2;
ginf[gArbitrary].sides = 7; 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); set_flag(ginf[gArbitrary].flags, qAFFINE, true);
affine_limit = 200; affine_limit = 200;
geom3::apply_always3(); 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.")) { else if(ep.eat("h2.")) {
ginf[gArbitrary].g = giHyperb2; ginf[gArbitrary].g = giHyperb2;
ginf[gArbitrary].sides = 7; 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); set_flag(ginf[gArbitrary].flags, qAFFINE, false);
geom3::apply_always3(); geom3::apply_always3();
} }
else if(ep.eat("s2.")) { else if(ep.eat("s2.")) {
ginf[gArbitrary].g = giSphere2; ginf[gArbitrary].g = giSphere2;
ginf[gArbitrary].sides = 5; 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); set_flag(ginf[gArbitrary].flags, qAFFINE, false);
geom3::apply_always3(); geom3::apply_always3();
} }
@ -1504,7 +1504,7 @@ EX void convert() {
ac.shapes.resize(N); ac.shapes.resize(N);
ginf[gArbitrary].g = cginf.g; ginf[gArbitrary].g = cginf.g;
ginf[gArbitrary].flags = cgflags & qBOUNDED; ginf[gArbitrary].flags = cgflags & qCLOSED;
for(int i=0; i<N; i++) { for(int i=0; i<N; i++) {
auto id = identification[old_shvids[i]]; auto id = identification[old_shvids[i]];

View File

@ -419,7 +419,7 @@ geometryinfo1& archimedean_tiling::get_geometry(ld mul) {
void archimedean_tiling::compute_geometry() { void archimedean_tiling::compute_geometry() {
ginf[gArchimedean].g = get_geometry(); ginf[gArchimedean].g = get_geometry();
set_flag(ginf[gArchimedean].flags, qBOUNDED, get_class() == gcSphere); set_flag(ginf[gArchimedean].flags, qCLOSED, get_class() == gcSphere);
DEBB(DF_GEOM, (format("euclidean_angle_sum = %f\n", float(euclidean_angle_sum)))); DEBB(DF_GEOM, (format("euclidean_angle_sum = %f\n", float(euclidean_angle_sum))));

View File

@ -214,7 +214,7 @@ EX int period_xy_edit, period_z_edit;
EX void set_flags() { EX void set_flags() {
auto& flag = ginf[gArnoldCat].flags; auto& flag = ginf[gArnoldCat].flags;
set_flag(flag, qANYQ, period_xy || period_z); set_flag(flag, qANYQ, period_xy || period_z);
set_flag(flag, qBOUNDED, period_xy && period_z); set_flag(flag, qCLOSED, period_xy && period_z);
set_flag(flag, qSMALL, period_xy && period_z && (period_xy * period_xy * period_z <= 4096)); set_flag(flag, qSMALL, period_xy && period_z && (period_xy * period_xy * period_z <= 4096));
set_flag(flag, qHUGE_BOUNDED, period_xy * period_xy * period_z > 16384); set_flag(flag, qHUGE_BOUNDED, period_xy * period_xy * period_z > 16384);
} }

View File

@ -2008,7 +2008,7 @@ EX void moreBigStuff(cell *c) {
EX void generate_mines() { EX void generate_mines() {
vector<cell*> candidates; vector<cell*> candidates;
if(bounded) if(closed_or_bounded)
for(cell *c: currentmap->allcells()) for(cell *c: currentmap->allcells())
setdist(c, 7, nullptr); setdist(c, 7, nullptr);

View File

@ -183,7 +183,8 @@ transmatrix hrmap::adj(heptagon *h, int i) { return relative_matrix(h->cmove(i),
vector<cell*>& hrmap::allcells() { vector<cell*>& hrmap::allcells() {
static vector<cell*> default_allcells; static vector<cell*> 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); celllister cl(gamestart(), 1000000, 1000000, NULL);
default_allcells = cl.lst; default_allcells = cl.lst;
return default_allcells; return default_allcells;
@ -330,6 +331,24 @@ EX void eumerge(cell* c1, int s1, cell *c2, int s2, bool mirror) {
EX hookset<hrmap*()> hooks_newmap; EX hookset<hrmap*()> hooks_newmap;
EX int req_disksize, disksize;
EX vector<cell*> 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 */ /** create a map in the current geometry */
EX void initcells() { EX void initcells() {
DEBB(DF_INIT, ("initcells")); DEBB(DF_INIT, ("initcells"));
@ -520,7 +539,7 @@ EX int celldist(cell *c) {
return hybrid::celldistance(c, currentmap->gamestart()); return hybrid::celldistance(c, currentmap->gamestart());
if(nil && !quotient) return DISTANCE_UNKNOWN; if(nil && !quotient) return DISTANCE_UNKNOWN;
if(euc::in()) return celldistance(currentmap->gamestart(), c); 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 CAP_IRR
if(IRREGULAR) return irr::celldist(c, false); if(IRREGULAR) return irr::celldist(c, false);
#endif #endif
@ -1204,7 +1223,7 @@ EX int celldistance(cell *c1, cell *c2) {
} }
#endif #endif
if(bounded) return bounded_celldistance(c1, c2); if(closed_manifold) return bounded_celldistance(c1, c2);
#if CAP_CRYSTAL #if CAP_CRYSTAL
if(cryst) return crystal::precise_distance(c1, c2); if(cryst) return crystal::precise_distance(c1, c2);

View File

@ -785,7 +785,7 @@ struct geometryinfo {
eVariation default_variation; eVariation default_variation;
}; };
static const flagtype qBOUNDED = 1; static const flagtype qCLOSED = 1;
static const flagtype qANYQ = 2; static const flagtype qANYQ = 2;
static const flagtype qNONORIENTABLE = 4; static const flagtype qNONORIENTABLE = 4;
static const flagtype qSMALL = 8; static const flagtype qSMALL = 8;
@ -835,20 +835,20 @@ extern eVariation variation;
#endif #endif
#if HDR #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 qsNONORE = qsNONOR | qELLIPTIC;
static const flagtype qsBQ = qANYQ | qSMALL | qBOUNDED; static const flagtype qsBQ = qANYQ | qSMALL | qCLOSED;
static const flagtype qsSMALL = qANYQ | qSMALL | qBOUNDED; static const flagtype qsSMALL = qANYQ | qSMALL | qCLOSED;
static const flagtype qsSMALLN = qANYQ | qSMALL | qBOUNDED | qNONORIENTABLE; static const flagtype qsSMALLN = qANYQ | qSMALL | qCLOSED | qNONORIENTABLE;
static const flagtype qsZEBRA = qANYQ | qSMALL | qBOUNDED | qZEBRA; static const flagtype qsZEBRA = qANYQ | qSMALL | qCLOSED | qZEBRA;
static const flagtype qsFIELD = qANYQ | qFIELD | qBOUNDED; static const flagtype qsFIELD = qANYQ | qFIELD | qCLOSED;
static const flagtype qsDOCKS = qANYQ | qSMALL | qBOUNDED | qDOCKS; static const flagtype qsDOCKS = qANYQ | qSMALL | qCLOSED | qDOCKS;
static const flagtype qsSMALLB = qSMALL | qBOUNDED; static const flagtype qsSMALLB = qSMALL | qCLOSED;
static const flagtype qsSMALLBF = qsSMALLB | qsFIELD | qANYQ; static const flagtype qsSMALLBF = qsSMALLB | qsFIELD | qANYQ;
static const flagtype qsSMALLBE = qsSMALLB | qELLIPTIC | qANYQ; static const flagtype qsSMALLBE = qsSMALLB | qELLIPTIC | qANYQ;
static const flagtype qsBP = qBINARY | qKITE; static const flagtype qsBP = qBINARY | qKITE;
static const flagtype qsSINGLE = qANYQ | qSMALL | qBOUNDED | qSINGLE; static const flagtype qsSINGLE = qANYQ | qSMALL | qCLOSED | qSINGLE;
#endif #endif
EX geometryinfo1 giEuclid2 = { gcEuclid, 2, 2, 3, {1,1, 0,0 } }; EX geometryinfo1 giEuclid2 = { gcEuclid, 2, 2, 3, {1,1, 0,0 } };

View File

@ -15,7 +15,7 @@ EX namespace whirlwind {
EX int fzebra3(cell *c) { EX int fzebra3(cell *c) {
if(arcm::in()) return 0; if(arcm::in()) return 0;
if(euclid) { if(euclid) {
if(bounded) return 0; if(closed_manifold) return 0;
auto co = euc2_coordinates(c); auto co = euc2_coordinates(c);
int y = co.second; int y = co.second;
return 1+((((signed short)(y)+int(50000))/3)%3); return 1+((((signed short)(y)+int(50000))/3)%3);
@ -1011,7 +1011,7 @@ EX namespace clearing {
} }
EX void imput(cell *c) { EX void imput(cell *c) {
if(bounded) return; if(closed_manifold) return;
if(score.count(c)) return; if(score.count(c)) return;
changes.map_value(score, c); changes.map_value(score, c);
auto& is = score[c]; auto& is = score[c];
@ -1216,7 +1216,7 @@ EX namespace mirror {
#endif #endif
bool noMirrorOn(cell *c) { 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) { bool cellMirrorable(cell *c) {
@ -3671,6 +3671,53 @@ EX namespace halloween {
EX cell *dragoncells[4]; EX cell *dragoncells[4];
vector<cell*> srch; vector<cell*> 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; i<isize(lst); i+=60) lst[i]->item = itTreat;
for(int i=2; i<isize(lst); i+=6) lst[i]->wall = waChasm;
}
}
cell *farempty(bool lastresort = false) { cell *farempty(bool lastresort = false) {
int maxdist = 0; int maxdist = 0;
vector<cell*> validcells; vector<cell*> validcells;

View File

@ -531,7 +531,7 @@ EX void count_status() {
} }
EX bool in_minesweeper() { 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) { 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) { EX void uncover_full(cell *c2) {
int mineradius = int mineradius =
bounded ? 3 : closed_or_bounded ? 3 :
(items[itBombEgg] < 1 && !tactic::on) ? 0 : (items[itBombEgg] < 1 && !tactic::on) ? 0 :
items[itBombEgg] < 20 ? 1 : items[itBombEgg] < 20 ? 1 :
items[itBombEgg] < 30 ? 2 : items[itBombEgg] < 30 ? 2 :

View File

@ -934,6 +934,11 @@ EX void initConfig() {
param_b(vid.smart_area_based, "smart-area-based", false); 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_drawn_limit, "limit on cells drawn", 10000);
param_i(vid.cells_generated_limit, "limit on cells generated", 250); 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 #if CAP_SOLV
addsaver(sn::solrange_xy, "solrange-xy"); addsaver(sn::solrange_xy, "solrange-xy");

View File

@ -1358,7 +1358,7 @@ EX void set_crystal_period_flags() {
for(auto& g: ginf) for(auto& g: ginf)
if(g.flags & qCRYSTAL) { if(g.flags & qCRYSTAL) {
set_flag(ginf[gNil].flags, qSMALL, crystal_period && crystal_period <= 8); 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);
} }
} }

View File

@ -149,7 +149,7 @@ EX namespace euc {
vector<cell*> toruscells; vector<cell*> toruscells;
vector<cell*>& allcells() override { vector<cell*>& allcells() override {
if(bounded) { if(closed_manifold && !disksize) {
if(isize(toruscells) == 0) { if(isize(toruscells) == 0) {
celllister cl(getOrigin()->c7, 1000, 1000000, NULL); celllister cl(getOrigin()->c7, 1000, 1000000, NULL);
toruscells = cl.lst; 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, 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); set_flag(ginf[g].flags, qSMALL, eu.infinite_dims == 0 && eu.det <= 4096);
bool nonori = false; bool nonori = false;
if(eu.twisted&1) nonori = !nonori; if(eu.twisted&1) nonori = !nonori;

View File

@ -392,7 +392,7 @@ int type_in_quick(expansion_analyzer& ea, cell *c, const cellfunction& f) {
EX bool sizes_known() { EX bool sizes_known() {
if(reg3::in_rule()) return true; if(reg3::in_rule()) return true;
if(bounded) return false; if(closed_manifold) return false;
// Castle Anthrax is infinite // Castle Anthrax is infinite
if(bt::in()) return false; if(bt::in()) return false;
// not implemented // not implemented
@ -717,7 +717,7 @@ string produce_coef_formula(vector<int> coef) {
void expansion_analyzer::view_distances_dialog() { void expansion_analyzer::view_distances_dialog() {
static int lastticks; static int lastticks;
if(scrolling_distances && !bounded) { if(scrolling_distances && !closed_manifold) {
scrolltime += SDL_GetTicks() - lastticks; scrolltime += SDL_GetTicks() - lastticks;
first_distance += scrolltime / scrollspeed; first_distance += scrolltime / scrollspeed;
scrolltime %= scrollspeed; scrolltime %= scrollspeed;
@ -729,7 +729,7 @@ void expansion_analyzer::view_distances_dialog() {
dialog::init(""); dialog::init("");
cmode |= sm::DIALOG_STRICT_X | sm::EXPANSION; cmode |= sm::DIALOG_STRICT_X | sm::EXPANSION;
int maxlen = bounded ? 128 : 16 + first_distance; int maxlen = closed_manifold ? 128 : 16 + first_distance;
vector<bignum> qty(maxlen); vector<bignum> qty(maxlen);
auto& expansion = get_expansion(); auto& expansion = get_expansion();
@ -748,12 +748,12 @@ void expansion_analyzer::view_distances_dialog() {
} }
else { else {
if(distance_from == dfPlayer) { 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) for(int d: cl.dists)
if(d >= 0 && d < maxlen) qty[d]++; if(d >= 0 && d < maxlen) qty[d]++;
} }
else { 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)]++; for(cell *c: cl.lst) if((not_only_descendants || is_descendant(c)) && curr_dist(c) < maxlen) qty[curr_dist(c)]++;
} }
#if !CAP_GMP #if !CAP_GMP

View File

@ -1458,7 +1458,7 @@ EX void enableFieldChange() {
ginf[geometry].distlimit = ginf[gxcur.base].distlimit; ginf[geometry].distlimit = ginf[gxcur.base].distlimit;
ginf[geometry].tiling_name = ginf[gxcur.base].tiling_name; ginf[geometry].tiling_name = ginf[gxcur.base].tiling_name;
ginf[geometry].default_variation = ginf[gxcur.base].default_variation; 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); 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.vertex = go.vertex;
gg.distlimit = go.distlimit; gg.distlimit = go.distlimit;
gg.tiling_name = go.tiling_name; 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.g = go.g;
gg.default_variation = go.default_variation; gg.default_variation = go.default_variation;
fieldpattern::quotient_field_changed = true; fieldpattern::quotient_field_changed = true;

View File

@ -760,7 +760,7 @@ EX geometry_data compute_geometry_data() {
if(euclid) gd.euler = 0; if(euclid) gd.euler = 0;
else if(sphere && nonorientable) gd.euler = 1; else if(sphere && nonorientable) gd.euler = 1;
else if(sphere) gd.euler = 2; 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 if(WDIM == 3) gd.euler = 0;
else switch(geometry) { else switch(geometry) {
case gFieldQuotient: case gFieldQuotient:
@ -810,7 +810,7 @@ EX geometry_data compute_geometry_data() {
gd.denom /= g; gd.denom /= g;
} }
if(euclid && bounded) { if(euclid && closed_manifold) {
gd.worldsize = euc::eu.det; gd.worldsize = euc::eu.det;
if(BITRUNCATED) gd.worldsize *= (a4 ? 2 : 3); if(BITRUNCATED) gd.worldsize *= (a4 ? 2 : 3);
if(GOLDBERG) gd.worldsize *= cgi.gpdata->area; if(GOLDBERG) gd.worldsize *= cgi.gpdata->area;
@ -821,7 +821,7 @@ EX geometry_data compute_geometry_data() {
else else
gd.worldsize = gd.denom ? gd.nom / gd.denom : 0; gd.worldsize = gd.denom ? gd.nom / gd.denom : 0;
if(gd.euler < 0 && !bounded) if(gd.euler < 0 && !closed_manifold)
gd.worldsize = -gd.worldsize; gd.worldsize = -gd.worldsize;
string spf = its(ts); string spf = its(ts);
@ -895,6 +895,7 @@ EX geometry_data compute_geometry_data() {
} }
gd.size_str = gd.size_str =
disksize ? its(isize(currentmap->allcells())) :
#if CAP_BT #if CAP_BT
bt::in() ? fts(8 * M_PI * sqrt(2) * log(2) / pow(vid.binary_width, WDIM-1), 4) + " exp(∞)" : bt::in() ? fts(8 * M_PI * sqrt(2) * log(2) / pow(vid.binary_width, WDIM-1), 4) + " exp(∞)" :
#endif #endif
@ -905,10 +906,10 @@ EX geometry_data compute_geometry_data() {
#if CAP_CRYSTAL #if CAP_CRYSTAL
cryst ? "∞^" + its(ts/2) : cryst ? "∞^" + its(ts/2) :
#endif #endif
WDIM == 3 && bounded ? its(isize(currentmap->allcells())) : WDIM == 3 && closed_manifold ? its(isize(currentmap->allcells())) :
WDIM == 3 && euclid ? "" : WDIM == 3 && euclid ? "" :
gd.worldsize < 0 ? (gd.nom%gd.denom ? its(gd.nom)+"/"+its(gd.denom) : its(-gd.worldsize)) + " exp(∞)": 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 ? "∞²" : gd.worldsize == 0 ? "∞²" :
its(gd.worldsize); its(gd.worldsize);
@ -1057,8 +1058,9 @@ EX void showEuclideanMenu() {
dialog::addBreak(100); dialog::addBreak(100);
menuitem_land_structure('l'); 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::addSelItem(XLAT("number of mines"), its(bounded_mine_quantity), 'm');
dialog::add_action([] { dialog::add_action([] {
dialog::editNumber(bounded_mine_quantity, 0, bounded_mine_max, 1, (bounded_mine_max+5)/10, 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; else if(viewdists) viewdists = false;
}); });
if(bounded) { if(closed_manifold) {
dialog::addSelItem(XLAT("Euler characteristics"), its(gd.euler), 0); dialog::addSelItem(XLAT("Euler characteristics"), its(gd.euler), 0);
if(WDIM == 3) ; if(WDIM == 3) ;
else if(nonorientable) else if(nonorientable)

View File

@ -139,7 +139,7 @@ transmatrix hrmap_standard::relative_matrixh(heptagon *h2, heptagon *h1, const h
steps++; if(steps > 10000) { steps++; if(steps > 10000) {
println(hlog, "not found"); return Id; println(hlog, "not found"); return Id;
} }
if(bounded) { if(closed_manifold) {
transmatrix T; transmatrix T;
ld bestdist = 1e9; ld bestdist = 1e9;
for(int d=0; d<S7; d++) { for(int d=0; d<S7; d++) {
@ -817,7 +817,7 @@ EX bool exhaustive_distance_appropriate() {
if(asonov::in() && asonov::period_xy && asonov::period_xy <= 256) return true; if(asonov::in() && asonov::period_xy && asonov::period_xy <= 256) return true;
#endif #endif
if(bounded) return true; if(closed_manifold) return true;
return false; return false;
} }

View File

@ -895,7 +895,7 @@ EX namespace gp {
dialog::addBoolItem(XLAT("irregular"), IRREGULAR, 'i'); dialog::addBoolItem(XLAT("irregular"), IRREGULAR, 'i');
dialog::add_action(dialog::add_confirmation([=] () { dialog::add_action(dialog::add_confirmation([=] () {
if(min_quality && !irr::bitruncations_requested) irr::bitruncations_requested++; if(min_quality && !irr::bitruncations_requested) irr::bitruncations_requested++;
if(euclid && (!bounded || nonorientable)) { if(euclid && (!closed_manifold || nonorientable)) {
println(hlog, XLAT("To create Euclidean irregular tesselations, first enable a torus")); println(hlog, XLAT("To create Euclidean irregular tesselations, first enable a torus"));
return; return;
} }

View File

@ -152,11 +152,12 @@ void addMessage(string s, char spamtype = 0);
#define nonorientable (cgflags & qNONORIENTABLE) #define nonorientable (cgflags & qNONORIENTABLE)
#define elliptic (cgflags & qELLIPTIC) #define elliptic (cgflags & qELLIPTIC)
#define quotient (cgflags & qANYQ) #define quotient (cgflags & qANYQ)
#define smallbounded (cgflags & qSMALL) #define smallbounded ((cgflags & qSMALL) || disksize)
#define bounded (cgflags & qBOUNDED) #define closed_manifold (cgflags & qCLOSED)
#define closed_or_bounded (closed_manifold || disksize)
// Dry Forest burning, heat transfer, etc. are performed on the whole universe // Dry Forest burning, heat transfer, etc. are performed on the whole universe
#define doall (bounded) #define doall (closed_or_bounded)
#define sphere_narcm (sphere && !arcm::in()) #define sphere_narcm (sphere && !arcm::in())

View File

@ -1045,7 +1045,7 @@ EX bool ctof(cell* c) {
} }
EX bool supports(eGeometry g) { EX bool supports(eGeometry g) {
if(g == gEuclid || g == gEuclidSquare) return ginf[g].flags & qBOUNDED; if(g == gEuclid || g == gEuclidSquare) return ginf[g].flags & qCLOSED;
return among(g, gNormal, gKleinQuartic, gOctagon, gBolza2, gFieldQuotient, gSphere, gSmallSphere, gTinySphere); return among(g, gNormal, gKleinQuartic, gOctagon, gBolza2, gFieldQuotient, gSphere, gSmallSphere, gTinySphere);
} }

View File

@ -79,7 +79,7 @@ EX void pickupMovedItems(cell *c, cell *from) {
} }
EX bool in_lovasz() { EX bool in_lovasz() {
return specialland == laMotion && bounded && ls::single() && !daily::on; return specialland == laMotion && closed_or_bounded && ls::single() && !daily::on;
} }
EX int threshold_met(int i) { EX int threshold_met(int i) {

View File

@ -184,7 +184,7 @@ EX int hrand_monster(int x) {
} }
EX bool is_zebra_trapdoor(cell *c) { EX bool is_zebra_trapdoor(cell *c) {
if(euclid && bounded) return false; if(euclid && closed_or_bounded) return false;
#if CAP_ARCM #if CAP_ARCM
else if(arcm::in() && arcm::current.have_line) else if(arcm::in() && arcm::current.have_line)
return arcm::linespattern(c); return arcm::linespattern(c);
@ -359,7 +359,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
} }
} }
} }
else if(PIU(hyperbolic_not37 || (euclid&&bounded) || S7 < 5 || arcm::in() || WDIM == 3)) { else if(PIU(hyperbolic_not37 || (euclid&&closed_or_bounded) || S7 < 5 || arcm::in() || WDIM == 3)) {
if(fargen) { if(fargen) {
int i = hrand(100); int i = hrand(100);
if(i < 10) if(i < 10)
@ -579,7 +579,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
if(d==8) { if(d==8) {
if(randomPatternsMode) if(randomPatternsMode)
c->wall = RANDPAT3(0) ? waCavewall : waCavefloor; c->wall = RANDPAT3(0) ? waCavewall : waCavefloor;
else if(euclid && bounded) { else if(euclid && closed_or_bounded) {
c->wall = waCavefloor; c->wall = waCavefloor;
} }
else if(nil) { else if(nil) {
@ -685,7 +685,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
#endif #endif
else if(arb::in() && arb::current.have_line) else if(arb::in() && arb::current.have_line)
v = arb::linespattern(c) ? 24 : 16; 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; v = hrand(100) < 25 ? 24 : 16;
} }
else if(euclid) { else if(euclid) {
@ -760,7 +760,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
if(d==8) { if(d==8) {
if(randomPatternsMode) if(randomPatternsMode)
c->wall = RANDPAT ? waVinePlant : waNone; c->wall = RANDPAT ? waVinePlant : waNone;
else if(euclid && bounded) ; else if(euclid && closed_or_bounded) ;
#if CAP_ARCM #if CAP_ARCM
else if(arcm::in() && arcm::current.have_line) else if(arcm::in() && arcm::current.have_line)
c->wall = arcm::linespattern(c) ? waVinePlant : waNone; c->wall = arcm::linespattern(c) ? waVinePlant : waNone;
@ -1269,50 +1269,6 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
break; break;
case laHalloween: 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; break;
case laWildWest: case laWildWest:
@ -2158,7 +2114,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
break; break;
case laMinefield: case laMinefield:
if(d == 7 && bounded) c->wall = waMineUnknown; if(d == 7 && closed_or_bounded) c->wall = waMineUnknown;
else if(d == 7) { else if(d == 7) {
c->wall = waMineUnknown; c->wall = waMineUnknown;
// 250: rare mines // 250: rare mines
@ -2191,7 +2147,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
c->monst = moBomberbird; c->monst = moBomberbird;
else placeLocalSpecial(c, 500); 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; c->wall = waMineOpen;
break; break;
@ -2879,7 +2835,7 @@ EX void set_land_for_geometry(cell *c) {
else if(euc::in(3)) euc::set_land(c); else if(euc::in(3)) euc::set_land(c);
#endif #endif
else if(hybri) setLandHybrid(c); 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(euclid) setLandEuclid(c);
else if(quotient) { setland(c, specialland); setLandQuotient(c); } else if(quotient) { setland(c, specialland); setLandQuotient(c); }
else if(sol) setLandSol(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) { ONEMPTY if(!c->item) {
if(isCrossroads(c->land)) if(isCrossroads(c->land))
placeCrossroadOrbs(c); placeCrossroadOrbs(c);

View File

@ -139,7 +139,7 @@ EX string land_structure_name(bool which) {
} }
EX void fix_land_structure_choice() { EX void fix_land_structure_choice() {
if(bounded) { if(closed_or_bounded) {
if(land_structure != lsTotalChaos && land_structure != lsChaosRW) if(land_structure != lsTotalChaos && land_structure != lsChaosRW)
land_structure = lsSingle; land_structure = lsSingle;
} }
@ -155,7 +155,7 @@ EX void fix_land_structure_choice() {
land_structure = lsSingle; land_structure = lsSingle;
if(land_structure == lsPatchedChaos && !(stdeuc || nil || cryst || (euclid && WDIM == 3))) if(land_structure == lsPatchedChaos && !(stdeuc || nil || cryst || (euclid && WDIM == 3)))
land_structure = lsSingle; land_structure = lsSingle;
if(bounded && !among(land_structure, lsChaosRW, lsTotalChaos, lsSingle)) if(closed_or_bounded && !among(land_structure, lsChaosRW, lsTotalChaos, lsSingle))
land_structure = lsSingle; land_structure = lsSingle;
} }
@ -777,12 +777,12 @@ EX land_validity_t& land_validity(eLand l) {
return disabled; return disabled;
#endif #endif
if(l == laMinefield && bounded) if(l == laMinefield && closed_or_bounded)
return special_geo3; return special_geo3;
if(l == laAsteroids) { if(l == laAsteroids) {
if(!shmup::on) return shmup_only; if(!shmup::on) return shmup_only;
if(!bounded) return bounded_only; if(!closed_manifold) return bounded_only;
return specially_designed; return specially_designed;
} }
@ -901,7 +901,7 @@ EX land_validity_t& land_validity(eLand l) {
return not_implemented; return not_implemented;
// Halloween needs bounded world (can be big bounded) // Halloween needs bounded world (can be big bounded)
if(l == laHalloween && !bounded) if(l == laHalloween && !closed_or_bounded)
return bounded_only; return bounded_only;
// Crystal World is designed for nice_dual geometries // Crystal World is designed for nice_dual geometries
@ -960,7 +960,7 @@ EX land_validity_t& land_validity(eLand l) {
if(geometry == gBinary4) if(geometry == gBinary4)
return not_implemented; return not_implemented;
// no equidistants supported in these geometries (big sphere is OK though) // no equidistants supported in these geometries (big sphere is OK though)
if(bounded && !bigsphere) if(closed_or_bounded && !bigsphere)
return unbounded_only_except_bigsphere; return unbounded_only_except_bigsphere;
// Yendorian only implemented in standard // Yendorian only implemented in standard
if(l == laEndorian && geometry) if(l == laEndorian && geometry)
@ -1004,7 +1004,7 @@ EX land_validity_t& land_validity(eLand l) {
if(l == laClearing) if(l == laClearing)
if(!(stdeucx || geometry == gBinaryTiling || a38 || (a45 && BITRUNCATED) || (a47 && BITRUNCATED)) || NONSTDVAR) if(!(stdeucx || geometry == gBinaryTiling || a38 || (a45 && BITRUNCATED) || (a47 && BITRUNCATED)) || NONSTDVAR)
if(!bounded) if(!closed_or_bounded)
return not_implemented; return not_implemented;
// does not work in non-bitrunc a4 // does not work in non-bitrunc a4
@ -1012,7 +1012,7 @@ EX land_validity_t& land_validity(eLand l) {
return some0; return some0;
// does not work in bounded either // does not work in bounded either
if(l == laOvergrown && bounded) if(l == laOvergrown && closed_or_bounded)
return some0; return some0;
// horocycle-based lands, not available in bounded geometries nor in Chaos mode // 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; return not_in_chaos;
} }
if(arcm::in() || kite::in()) return not_implemented; 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; if(INVERSE) return not_implemented;
} }
@ -1064,7 +1064,7 @@ EX land_validity_t& land_validity(eLand l) {
return technical; return technical;
// only in bounded geometry, and not in PTM // only in bounded geometry, and not in PTM
if(l == laCA && !bounded) if(l == laCA && !closed_or_bounded)
return bounded_only; return bounded_only;
if(l == laCA && tactic::on) if(l == laCA && tactic::on)
@ -1121,7 +1121,7 @@ EX land_validity_t& land_validity(eLand l) {
if(l == laStorms && hyperbolic_not37) if(l == laStorms && hyperbolic_not37)
return pattern_not_implemented_random; return pattern_not_implemented_random;
if(l == laTrollheim && !stdeucx && !bounded) if(l == laTrollheim && !stdeucx && !closed_or_bounded)
return some1; return some1;
if(l == laReptile && sol) return ugly_version_nofull; if(l == laReptile && sol) return ugly_version_nofull;
@ -1174,7 +1174,7 @@ EX land_validity_t& land_validity(eLand l) {
if(l == laPrairie) { if(l == laPrairie) {
if(GOLDBERG) return not_implemented; if(GOLDBERG) return not_implemented;
else if(stdeucx || (bigsphere && BITRUNCATED && !elliptic) || (geometry == gFieldQuotient)) ; 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; else return unbounded_only;
} }
@ -1191,10 +1191,10 @@ EX land_validity_t& land_validity(eLand l) {
if(sol && l == laCamelot) if(sol && l == laCamelot)
return not_implemented; 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; 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; return full_game;
// highlight Zebra-based lands on Zebra Quotient! // highlight Zebra-based lands on Zebra Quotient!
@ -1231,7 +1231,7 @@ EX land_validity_t& land_validity(eLand l) {
return pattern_not_implemented_exclude; return pattern_not_implemented_exclude;
} }
if(l == laStorms && euclid && bounded) if(l == laStorms && euclid && closed_manifold)
return interesting; return interesting;
if(l == laMagnetic) if(l == laMagnetic)

View File

@ -684,7 +684,7 @@ EX namespace mapstream {
EX hookset<void(fhstream&, int)> hooks_loadmap; EX hookset<void(fhstream&, int)> hooks_loadmap;
EX cell *save_start() { 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 #if CAP_EDIT

View File

@ -770,9 +770,9 @@ EX bool makeEmpty(cell *c) {
c->wall = waBoat; // , c->item = itOrbYendor; c->wall = waBoat; // , c->item = itOrbYendor;
else if(c->land == laMinefield) else if(c->land == laMinefield)
c->wall = waMineOpen; 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) 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) else if(c->land == laDocks)
c->wall = waBoat; 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(c->wall == waBarrier && sphere && WDIM == 3)
; ;
else if(isReptile(c->wall)) else if(isReptile(c->wall))
c->wparam = reptilemax(); c->wparam = reptilemax();
else if(c->wall == waAncientGrave && bounded) else if(c->wall == waAncientGrave && closed_manifold)
; ;
else if(c->wall != waRoundTable) else if(c->wall != waRoundTable)
c->wall = waNone; c->wall = waNone;

View File

@ -704,7 +704,7 @@ EX void mode_higlights() {
} }
EX eLandStructure default_land_structure() { EX eLandStructure default_land_structure() {
if(bounded) return lsSingle; if(closed_or_bounded) return lsSingle;
if(tactic::on || princess::challenge) return lsSingle; if(tactic::on || princess::challenge) return lsSingle;
if(yendor::on) return yendor::get_land_structure(); if(yendor::on) return yendor::get_land_structure();
if(specialland == laCanvas) return lsSingle; if(specialland == laCanvas) return lsSingle;
@ -1171,7 +1171,7 @@ EX named_functionality get_o_key() {
dialog::infix = ""; 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)); res.push_back(named_functionality(XLAT("experiment with geometry"), runGeometryExperiments));
if(res.empty()) return named_dialog(XLAT("world overview"), showOverview); if(res.empty()) return named_dialog(XLAT("world overview"), showOverview);

View File

@ -335,18 +335,20 @@ EX void wandering() {
if(cwt.at->land == laCA) ghostcount = 0; if(cwt.at->land == laCA) ghostcount = 0;
bool genturn = hrand(100) < 30; bool genturn = hrand(100) < 30;
if(bounded && specialland == laClearing) if(closed_or_bounded && specialland == laClearing)
clearing::new_root(); clearing::new_root();
if(cwt.at->land == laZebra && cwt.at->wall == waNone && wchance(items[itZebra], 20)) if(cwt.at->land == laZebra && cwt.at->wall == waNone && wchance(items[itZebra], 20))
wanderingZebra(cwt.at); 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) { if(smallbounded_generation) {
int maxdist = 0; int maxdist = 0;
for(int i=0; i<isize(dcal); i++) if(dcal[i]->cpdist > maxdist) maxdist = dcal[i]->cpdist; for(int i=0; i<isize(dcal); i++) if(valid(dcal[i])) if(dcal[i]->cpdist > maxdist) maxdist = dcal[i]->cpdist;
for(int i=0; i<isize(dcal); i++) if(dcal[i]->cpdist >= maxdist-1) { first7 = i; break; } for(int i=0; i<isize(dcal); i++) if(valid(dcal[i])) if(dcal[i]->cpdist >= maxdist-1) { first7 = i; break; }
if(hrand(5) == 0) { if(hrand(5) == 0) {
// spawn treasure // spawn treasure
@ -362,10 +364,12 @@ EX void wandering() {
} }
} }
int iter = 0;
while(first7 < isize(dcal)) { while(first7 < isize(dcal)) {
iter++; if(iter > 1000) break;
int i = first7 + hrand(isize(dcal) - first7); int i = first7 + hrand(isize(dcal) - first7);
cell *c = dcal[i]; cell *c = dcal[i];
if(inmirror(c)) continue; if(!valid(c)) continue;
if(isPlayerOn(c)) break; if(isPlayerOn(c)) break;
if(specialland == laStorms) { if(specialland == laStorms) {

View File

@ -1393,7 +1393,7 @@ EX void movehex_rest(bool mounted) {
EX void movemutant() { EX void movemutant() {
manual_celllister mcells; manual_celllister mcells;
for(cell *c: currentmap->allcells()) mcells.add(c); for(cell *c: currentmap->allcells()) mcells.add(c);
if(!bounded) if(!closed_or_bounded)
for(int i=0; i<isize(mcells.lst); i++) { for(int i=0; i<isize(mcells.lst); i++) {
cell *c = mcells.lst[i]; cell *c = mcells.lst[i];
if(c->land == laClearing && c->monst != moMutant && !pseudohept(c)) if(c->land == laClearing && c->monst != moMutant && !pseudohept(c))
@ -1427,7 +1427,7 @@ EX void movemutant() {
if(isPlayerOn(c2)) continue; if(isPlayerOn(c2)) continue;
if((c2->land == laOvergrown || !pseudohept(c2)) && passable(c2, c, 0)) { 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->monst = moMutant;
c2->mondir = c->c.spin(j); c2->mondir = c->c.spin(j);
c2->stuntime = mutantphase; c2->stuntime = mutantphase;
@ -2096,7 +2096,7 @@ EX void movemonsters() {
DEBB(DF_TURN, ("leader")); DEBB(DF_TURN, ("leader"));
if(havewhat & HF_LEADER) groupmove(moPirate, 0); if(havewhat & HF_LEADER) groupmove(moPirate, 0);
DEBB(DF_TURN, ("mutant")); 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")); DEBB(DF_TURN, ("bugs"));
if(havewhat & HF_BUG) hive::movebugs(); if(havewhat & HF_BUG) hive::movebugs();
DEBB(DF_TURN, ("whirlpool")); DEBB(DF_TURN, ("whirlpool"));

View File

@ -962,7 +962,7 @@ EX namespace nilv {
int coords = 0; int coords = 0;
for(int a=0; a<3; a++) if(nilperiod[a]) coords++; for(int a=0; a<3; a++) if(nilperiod[a]) coords++;
set_flag(ginf[gNil].flags, qANYQ, 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); 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() { EX void fix_bounded_cycles() {
if(!rotspace) return; if(!rotspace) return;
if(!bounded) return; if(!closed_manifold) return;
in_underlying([&] { in_underlying([&] {
cellwalker final(currentmap->gamestart(), 0); cellwalker final(currentmap->gamestart(), 0);
auto& ac = currentmap->allcells(); auto& ac = currentmap->allcells();
@ -1505,7 +1505,7 @@ EX namespace hybrid {
dialog::extra_options = [=] () { dialog::extra_options = [=] () {
if(rotspace) { if(rotspace) {
int e_steps = cgi.psl_steps / gcd(cgi.single_step, cgi.psl_steps); 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::addSelItem( sphere ? XLAT("elliptic") : XLAT("PSL(2,R)"), its(e_steps), 'P');
dialog::add_action(set_s(e_steps, true)); dialog::add_action(set_s(e_steps, true));
dialog::addSelItem( sphere ? XLAT("sphere") : XLAT("SL(2,R)"), its(2*e_steps), 'P'); dialog::addSelItem( sphere ? XLAT("sphere") : XLAT("SL(2,R)"), its(2*e_steps), 'P');

View File

@ -441,12 +441,12 @@ EX int fieldval_uniq(cell *c) {
} }
else if(euc::in(2)) { else if(euc::in(2)) {
auto p = euc2_coordinates(c); 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); return gmod(p.first - 22 * p.second, 3*127);
} }
else if(euc::in(3)) { else if(euc::in(3)) {
auto co = euc::get_ispacemap()[c->master]; 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); 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; 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) { color_t nearer_map(cell *c) {
if(computed_nearer_map.count(c)) return computed_nearer_map[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(); cell *sc = currentmap->gamestart();
auto ac = currentmap->allcells(); auto ac = currentmap->allcells();
@ -1645,7 +1645,7 @@ EX namespace patterns {
color_t furthest_map(cell *c, int reduce) { color_t furthest_map(cell *c, int reduce) {
auto& cfm = computed_furthest_map; auto& cfm = computed_furthest_map;
if(cfm.count(c)) return cfm[c]; if(cfm.count(c)) return cfm[c];
if(!bounded) return 0; if(!closed_manifold) return 0;
cell *sc = currentmap->gamestart(); cell *sc = currentmap->gamestart();
auto ac = currentmap->allcells(); auto ac = currentmap->allcells();
@ -2031,7 +2031,7 @@ EX namespace patterns {
dialog::addSelItem(XLAT("Penrose staircase"), "Nil", '/'); dialog::addSelItem(XLAT("Penrose staircase"), "Nil", '/');
} }
if(bounded) { if(closed_manifold) {
dialog::addSelItem(XLAT("nearer end"), "bounded", 'Z'); dialog::addSelItem(XLAT("nearer end"), "bounded", 'Z');
dialog::addSelItem(XLAT("furthest from start"), "bounded", 'Y'); dialog::addSelItem(XLAT("furthest from start"), "bounded", 'Y');
} }

View File

@ -371,7 +371,7 @@ EX void showMission() {
} }
dialog::addInfo(XLAT("Dropped floors: %1/%2", its(score), its(all))); dialog::addInfo(XLAT("Dropped floors: %1/%2", its(score), its(all)));
if(score == all) dialog::addInfo(XLAT("CONGRATULATIONS!"), iinf[itOrbYendor].color); 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); achievement_gain_once("LOVASZ", rg::special_geometry);
} }
else { else {

View File

@ -475,7 +475,7 @@ EX void generate_track() {
} }
try { try {
if(bounded && !prod && !(cgflags & qHUGE_BOUNDED)) { if(closed_or_bounded && !prod && !(cgflags & qHUGE_BOUNDED)) {
bounded_track = true; bounded_track = true;
make_bounded_track(s); make_bounded_track(s);
} }
@ -754,7 +754,7 @@ bool inrec = false;
EX ld race_angle = 90; EX ld race_angle = 90;
EX bool force_standard_centering() { EX bool force_standard_centering() {
return nonisotropic || hybri || quotient || bounded; return nonisotropic || hybri || quotient || closed_or_bounded;
} }
EX bool use_standard_centering() { EX bool use_standard_centering() {

View File

@ -490,7 +490,7 @@ void explore() {
ginf[gArbitrary].g = giEuclid2; ginf[gArbitrary].g = giEuclid2;
ginf[gArbitrary].sides = 7; 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); set_flag(ginf[gArbitrary].flags, qAFFINE, false);
geom3::apply_always3(); geom3::apply_always3();

View File

@ -503,8 +503,8 @@ bool drawVertex(const shiftmatrix &V, cell *c, shmup::monster *m) {
} }
void init() { void init() {
if(!bounded) { if(!closed_manifold) {
addMessage("Flocking simulation needs a bounded space."); addMessage("Flocking simulation needs a closed manifold.");
return; return;
} }
stop_game(); stop_game();

View File

@ -126,7 +126,7 @@ void create_janko() {
gJanko1 = eGeometry(isize(ginf) - 1); gJanko1 = eGeometry(isize(ginf) - 1);
// variation = eVariation::pure; // variation = eVariation::pure;
auto& gi = ginf.back(); auto& gi = ginf.back();
gi.flags = qANYQ | qBOUNDED | qEXPERIMENTAL; gi.flags = qANYQ | qCLOSED | qEXPERIMENTAL;
gi.quotient_name = "Janko"; gi.quotient_name = "Janko";
gi.shortname = "Janko"; gi.shortname = "Janko";
gi.menu_displayed_name = "Janko group J1"; gi.menu_displayed_name = "Janko group J1";

View File

@ -1148,7 +1148,7 @@ void create_notknot() {
} }
else ginf[gNotKnot] = ginf[base]; else ginf[gNotKnot] = ginf[base];
auto& gi = ginf.back(); auto& gi = ginf.back();
gi.flags |= qANYQ | qBOUNDED | qEXPERIMENTAL | qPORTALSPACE; gi.flags |= qANYQ | qCLOSED | qEXPERIMENTAL | qPORTALSPACE;
gi.quotient_name = "notknot"; gi.quotient_name = "notknot";
gi.shortname = "notknot"; gi.shortname = "notknot";
gi.menu_displayed_name = "notknot"; gi.menu_displayed_name = "notknot";

View File

@ -602,7 +602,7 @@ bool drawVertex(const shiftmatrix &V, cell *c, shmup::monster *m) {
bool multidraw = quotient; 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; j<isize(vd.edges); j++) { if(!lshiftclick) for(int j=0; j<isize(vd.edges); j++) {
edgeinfo *ei = vd.edges[j].second; edgeinfo *ei = vd.edges[j].second;

View File

@ -63,7 +63,7 @@ namespace sag {
int snakedist(int i, int j) { int snakedist(int i, int j) {
if(i < insnaketab && j < insnaketab) return sdist[i][j]; if(i < insnaketab && j < insnaketab) return sdist[i][j];
if(bounded) return celldistance(snakecells[i], snakecells[j]); if(closed_manifold) return celldistance(snakecells[i], snakecells[j]);
int i0 = i, i1 = i, j0 = j, j1 = j; int i0 = i, i1 = i, j0 = j, j1 = j;
int cost = 0; int cost = 0;
// intersect // intersect
@ -77,7 +77,7 @@ namespace sag {
} }
void initSnake(int n) { void initSnake(int n) {
if(bounded) n = isize(currentmap->allcells()); if(closed_or_bounded) n = isize(currentmap->allcells());
numsnake = n; numsnake = n;
snakecells.resize(numsnake); snakecells.resize(numsnake);
snakefirst.resize(numsnake); snakefirst.resize(numsnake);
@ -85,7 +85,7 @@ namespace sag {
snakenode.resize(numsnake); snakenode.resize(numsnake);
lpbak.resize(numsnake); lpbak.resize(numsnake);
wpbak.resize(numsnake); wpbak.resize(numsnake);
if(bounded) { if(closed_or_bounded) {
for(int i=0; i<n; i++) { for(int i=0; i<n; i++) {
cellwalker cw(currentmap->allcells()[i], 0); cellwalker cw(currentmap->allcells()[i], 0);
setsnake(cw, i); setsnake(cw, i);

View File

@ -183,7 +183,7 @@ EX rugpoint *addRugpoint(shiftpoint h, double dist) {
m->y1 = (1 - onscreen[1] * pconf.scale) / 2; m->y1 = (1 - onscreen[1] * pconf.scale) / 2;
m->valid = false; 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; hyperpoint h1 = iso_inverse(models::euclidean_spin) * eumove(euc::eu.user_axes[1]) * C0;
h1 /= sqhypot_d(2, h1); h1 /= sqhypot_d(2, h1);
if(nonorientable) h1 /= 2; if(nonorientable) h1 /= 2;
@ -557,7 +557,7 @@ EX void buildRug() {
need_mouseh = true; need_mouseh = true;
good_shape = false; good_shape = false;
#if MAXMDIM >= 4 #if MAXMDIM >= 4
if(euclid && bounded) { if(euclid && closed_manifold) {
good_shape = true; good_shape = true;
buildTorusRug(); buildTorusRug();
return; return;
@ -785,7 +785,7 @@ EX int precision_increases;
bool stop = false; bool stop = false;
EX bool subdivide_further() { EX bool subdivide_further() {
if(euclid && bounded) return false; if(euclid && closed_manifold) return false;
if(GDIM == 3) return false; if(GDIM == 3) return false;
return isize(points) * 4 < vertex_limit; return isize(points) * 4 < vertex_limit;
} }
@ -794,7 +794,7 @@ EX void subdivide() {
int N = isize(points); int N = isize(points);
// if(euclid && gwhere == gEuclid) return; // if(euclid && gwhere == gEuclid) return;
if(!subdivide_further()) { if(!subdivide_further()) {
if(euclid && !bounded && gwhere == gEuclid) { if(euclid && !closed_manifold && gwhere == gEuclid) {
println(hlog, "Euclidean -- full precision"); println(hlog, "Euclidean -- full precision");
stop = true; stop = true;
} }

View File

@ -346,11 +346,14 @@ EX void initgame() {
makeEmpty(cwt.at); makeEmpty(cwt.at);
} }
if(specialland == laMinefield && bounded) { if(specialland == laMinefield && closed_or_bounded) {
bfs(); bfs();
generate_mines(); generate_mines();
} }
if(specialland == laHalloween)
halloween::generate();
if(in_lovasz()) { if(in_lovasz()) {
cwt.at->item = itOrbInvis; cwt.at->item = itOrbInvis;
} }
@ -1455,7 +1458,7 @@ EX void switch_game_mode(char switchWhat) {
if(tactic::on) firstland = laIce; if(tactic::on) firstland = laIce;
yendor::on = tactic::on = princess::challenge = false; yendor::on = tactic::on = princess::challenge = false;
land_structure = ls::any_chaos() ? lsNiceWalls : lsChaos; land_structure = ls::any_chaos() ? lsNiceWalls : lsChaos;
if(bounded) set_geometry(gNormal); if(closed_or_bounded) set_geometry(gNormal);
racing::on = false; racing::on = false;
break; break;
@ -1570,6 +1573,7 @@ EX void start_game() {
#endif #endif
initcells(); initcells();
get_expansion().reset(); get_expansion().reset();
init_disk_cells();
if(randomPatternsMode) { if(randomPatternsMode) {
for(int i=0; i<landtypes; i++) { for(int i=0; i<landtypes; i++) {

View File

@ -1234,7 +1234,7 @@ EX namespace peace {
reset_modes(); reset_modes();
if(peace::on) stop_game_and_switch_mode(rg::peace); if(peace::on) stop_game_and_switch_mode(rg::peace);
specialland = firstland = laMinefield; specialland = firstland = laMinefield;
if(!bounded) { if(!closed_or_bounded) {
geometry = gBring; geometry = gBring;
variation = eVariation::goldberg; variation = eVariation::goldberg;
gp::param = gp::loc(2, 1); gp::param = gp::loc(2, 1);