1 // Hyperbolic Rogue -- land availability
2 // Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
3
4 /** \file landlock.cpp
5 * \brief unlocking lands, which lands could be found beyond the wall, validity of various lands depending on the settings
6 */
7
8 #include "hyper.h"
9 namespace hr {
10
in_full_game()11 EX bool in_full_game() {
12 if(ls::single()) return false;
13 return true;
14 }
15
nodisplay(eMonster m)16 EX bool nodisplay(eMonster m) {
17 return
18 m == moIvyDead ||
19 m == moDragonTail ||
20 m == moWolfMoved ||
21 m == moIvyNext ||
22 m == moIvyDead;
23 }
24
25 /** returns: 2 = treasure increaser, 1 = just appears, 0 = does not appear */
isNative(eLand l,eMonster m)26 EX int isNative(eLand l, eMonster m) {
27 switch(l) {
28 #define LAND(a,b,c,d,e,f,g) case c:
29 #define NATIVE(x) return x;
30 #include "content.cpp"
31
32 case landtypes: return 0;
33 }
34 return false;
35 }
36
treasureType(eLand l)37 EX eItem treasureType(eLand l) { return linf[l].treasure; }
38
treasureTypeUnlock(eLand l,eItem u)39 EX eItem treasureTypeUnlock(eLand l, eItem u) {
40 if(u != itOrbLove && l == laPrincessQuest)
41 return itPalace;
42 return treasureType(l);
43 }
44
landof(eItem it)45 EX eLand landof(eItem it) {
46 for(int i=0; i<landtypes; i++) if(treasureType(eLand(i)) == it) return eLand(i);
47 return laNone;
48 }
49
landMultiplier(eLand l)50 EX int landMultiplier(eLand l) {
51 if(l == laCamelot || l == laPrincessQuest) return 10;
52 return 1;
53 }
54
isCrossroads(eLand l)55 EX bool isCrossroads(eLand l) {
56 return l == laCrossroads || l == laCrossroads2 || l == laCrossroads3 ||
57 l == laCrossroads4 || l == laCrossroads5;
58 }
59
bearsCamelot(eLand l)60 EX bool bearsCamelot(eLand l) {
61 return isCrossroads(l) && l != laCrossroads2 && l != laCrossroads5;
62 }
63
inmirror(const cellwalker & cw)64 EX bool inmirror(const cellwalker& cw) {
65 return inmirror(cw.at->land);
66 }
67
oppositeElement(eLand l,eLand l2)68 EX eLand oppositeElement(eLand l, eLand l2) {
69 if(l == laEFire) return laEWater;
70 if(l == laEWater) return laEFire;
71 if(l == laEAir) return laEEarth;
72 if(l == laEEarth) return laEAir;
73 if(l == laMirror && l2 == laMirrored) return laMirrored2;
74 if(l == laMirrored2 && l2 == laMirrored) return laMirror;
75 return l;
76 }
77
78 // land unlocking
79
80 EX eLand firstland = laIce;
81 EX eLand specialland = laIce;
82
83 #if HDR
84 enum eLandStructure { lsNiceWalls, lsChaos, lsPatchedChaos, lsTotalChaos, lsChaosRW, lsWallChaos, lsSingle, lsNoWalls, lsGUARD };
85 #endif
86
87 EX eLandStructure land_structure;
88
89 EX namespace ls {
90
single()91 EX bool single() { return land_structure == lsSingle; }
92
any_chaos()93 EX bool any_chaos() { return among(land_structure, lsChaos, lsPatchedChaos, lsWallChaos, lsTotalChaos, lsChaosRW); }
std_chaos()94 EX bool std_chaos() { return land_structure == lsChaos; }
wall_chaos()95 EX bool wall_chaos() { return land_structure == lsWallChaos; }
patched_chaos()96 EX bool patched_chaos() { return land_structure == lsPatchedChaos; }
97
any_order()98 EX bool any_order() { return among(land_structure, lsNiceWalls, lsNoWalls); }
nice_walls()99 EX bool nice_walls() { return land_structure == lsNiceWalls; }
no_walls()100 EX bool no_walls() { return land_structure == lsNoWalls; }
101
any_nowall()102 EX bool any_nowall() { return no_walls() || std_chaos(); }
any_wall()103 EX bool any_wall() { return nice_walls() || wall_chaos(); }
104
chaoticity()105 EX int chaoticity() {
106 if(land_structure == lsTotalChaos) return 100;
107 if(land_structure == lsChaosRW) return 80;
108 if(land_structure == lsPatchedChaos) return 60;
109 if(land_structure == lsChaos) return 40;
110 if(land_structure == lsWallChaos) return 30;
111 if(land_structure == lsSingle) return 0;
112 return 10;
113 }
114
tame_chaos()115 EX bool tame_chaos() { return any_chaos() && chaoticity() < 35; }
116 EX }
117
land_structure_name(bool which)118 EX string land_structure_name(bool which) {
119 switch(land_structure) {
120 case lsNiceWalls:
121 return XLAT("standard");
122 case lsChaos:
123 return XLAT("Chaos mode");
124 case lsPatchedChaos:
125 return XLAT("patched Chaos");
126 case lsWallChaos:
127 return XLAT("excessive walls");
128 case lsTotalChaos:
129 return XLAT("total chaos");
130 case lsChaosRW:
131 return XLAT("random-walk chaos");
132 case lsSingle:
133 return which ? XLAT("single land: ") + XLATN(linf[specialland].name) : XLAT("single land");
134 case lsNoWalls:
135 return XLAT("wall-less");
136 default:
137 return "error structure";
138 }
139 }
140
fix_land_structure_choice()141 EX void fix_land_structure_choice() {
142 if(bounded) {
143 if(land_structure != lsTotalChaos && land_structure != lsChaosRW)
144 land_structure = lsSingle;
145 }
146 if(tactic::on || princess::challenge)
147 land_structure = lsSingle;
148 if(yendor::on)
149 land_structure = yendor::get_land_structure();
150 if(!nice_walls_available() && land_structure == lsNiceWalls)
151 land_structure = lsNoWalls;
152 if(!nice_walls_available() && land_structure == lsWallChaos)
153 land_structure = lsChaos;
154 if(walls_not_implemented() && among(land_structure, lsChaos, lsNoWalls))
155 land_structure = lsSingle;
156 if(land_structure == lsPatchedChaos && !(stdeuc || nil || cryst || (euclid && WDIM == 3)))
157 land_structure = lsSingle;
158 if(bounded && !among(land_structure, lsChaosRW, lsTotalChaos, lsSingle))
159 land_structure = lsSingle;
160 }
161
landUnlockedRPM(eLand n)162 EX bool landUnlockedRPM(eLand n) {
163 if(isRandland(n) == 2) return true;
164 if(isRandland(n) == 1)
165 return (autocheat || cheater || hiitemsMax(treasureType(n)) >= 10);
166 return false;
167 }
168
lands_for_hell()169 EX int lands_for_hell() {
170 return casual ? 40 : 9;
171 }
172
variant_unlock_value()173 EX int variant_unlock_value() {
174 return inv::on ? 75 : 30;
175 }
176
landUnlocked(eLand l)177 EX bool landUnlocked(eLand l) {
178 if(randomPatternsMode) {
179 return landUnlockedRPM(l);
180 }
181
182 if(all_unlocked) {
183 if(autocheat || hiitemsMax(treasureType(l)) >= 10) return true;
184 }
185
186 back:
187
188 if(princess::challenge) return among(l, laPalace, laPrincessQuest);
189
190 switch(l) {
191 #define LAND(a,b,c,d,e,f,g) case c:
192 #define REQ(x) x return true;
193 #define REQAS(x,y) l = x; goto back;
194 #define GOLD(x) if(gold() < x) return false;
195 #define ITEMS(kind, number) if(items[kind] < number) return false;
196 #define NEVER if(1) return false;
197 #define ALWAYS ;
198 #define KILLS(x) if(tkills() < x) return false;
199 #define KILL(x, where) if(!kills[x]) return false;
200 #define AKILL(x, where) if(kills[x]) return true;
201 #define ORD(a, b) a b
202 #define NUMBER(val, required, description) if(val < required) return false;
203 #define COND(x,y) if(!(x)) return false;
204 #define ITEMS_TOTAL(list, z) { int total = 0; for(eItem x: list) total += items[x]; if(total < z) return false; }
205 #define ACCONLY(x)
206 #define ACCONLY2(x,y)
207 #define ACCONLY3(x,y,z)
208 #define ACCONLYF(x)
209 #include "content.cpp"
210
211 case landtypes: return false;
212 }
213 return false;
214 }
215
required_for_hyperstones(eItem ttype)216 EX bool required_for_hyperstones(eItem ttype) {
217 if(ttype == itHyperstone)
218 return false;
219 if(among(ttype, itHolyGrail, itSavedPrincess))
220 return false;
221 if(euclid && among(ttype, itBabyTortoise, itHunting))
222 return false;
223 return true;
224 }
225
countHyperstoneQuest(int & i1,int & i2)226 EX void countHyperstoneQuest(int& i1, int& i2) {
227 i1 = 0; i2 = 0;
228 generateLandList(isLandIngame);
229 for(eLand l: landlist) {
230 eItem ttype = treasureType(l);
231 if(!required_for_hyperstones(ttype)) continue;
232 i2++; if(items[ttype] >= R10) i1++;
233 }
234 }
235
hyperstonesUnlocked()236 EX bool hyperstonesUnlocked() {
237 int i1, i2;
238 if(ls::single() && isCrossroads(specialland)) return true;
239 countHyperstoneQuest(i1, i2);
240 return i1 == i2;
241 }
242
243 // 2 = always available, 1 = highscore required, 0 = never available
isRandland(eLand l)244 EX int isRandland(eLand l) {
245 if(l == laIce || l == laDesert || l == laCaves || l == laWildWest || l == laDocks)
246 return 2;
247 for(eLand ll: randlands) if(l == ll) return 1;
248 return 0;
249 }
250
incompatible1(eLand l1,eLand l2)251 EX bool incompatible1(eLand l1, eLand l2) {
252 if(isCrossroads(l1) && isCrossroads(l2)) return true;
253 if(l1 == laJungle && l2 == laMotion) return true;
254 if(l1 == laMirrorOld && l2 == laMotion) return true;
255 if(l1 == laPower && l2 == laWineyard) return true;
256 if(l1 == laPower && l2 == laDryForest) return true;
257 if(l1 == laVolcano && l2 == laDryForest) return true;
258 if(l1 == laVolcano && l2 == laWineyard) return true;
259 if(l1 == laDragon && l2 == laDryForest) return true;
260 if(l1 == laEFire && l2 == laWineyard) return true;
261 if(l1 == laEFire && l2 == laDryForest) return true;
262 if(l1 == laGraveyard && l2 == laDryForest) return true;
263 if(l1 == laGraveyard && l2 == laDice) return true;
264 if(l1 == laGraveyard && l2 == laRuins) return true;
265 if(l1 == laGraveyard && l2 == laRedRock) return true;
266 if(l1 == laGraveyard && l2 == laEmerald) return true;
267 if(l1 == laDeadCaves && l2 == laEmerald) return true;
268 if(l1 == laDeadCaves && l2 == laCaves) return true;
269 if(l1 == laWarpSea && l2 == laKraken) return true;
270 if(l1 == laPrairie && l2 == laCrossroads3) return true;
271 if(l1 == laPrairie && l2 == laCrossroads4) return true;
272 if(l1 == laWet && l2 == laDesert) return true;
273 if(l1 == laFrog && l2 == laMotion) return true;
274 if(isElemental(l1) && isElemental(l2)) return true;
275 return false;
276 }
277
randomElementalLand()278 EX eLand randomElementalLand() {
279 int i = hrand(4);
280 eLand t[4] = { laEFire, laEWater, laEAir, laEEarth };
281 return t[i];
282 }
283
elementalKills()284 EX int elementalKills() {
285 return
286 kills[moAirElemental] + kills[moWaterElemental] + kills[moEarthElemental] + kills[moFireElemental];
287 }
288
randomElementalLandWeighted()289 EX eLand randomElementalLandWeighted() {
290 if(all_unlocked) return pick(laEAir, laEWater, laEEarth, laEFire);
291 int i = hrand(elementalKills());
292 i -= kills[moAirElemental]; if(i<0) return laEAir;
293 i -= kills[moWaterElemental]; if(i<0) return laEWater;
294 i -= kills[moEarthElemental]; if(i<0) return laEEarth;
295 i -= kills[moFireElemental]; if(i<0) return laEFire;
296 printf("elemental bug\n");
297 return laElementalWall;
298 }
299
incompatible(eLand nw,eLand old)300 EX bool incompatible(eLand nw, eLand old) {
301 return (nw == old) || incompatible1(nw, old) || incompatible1(old, nw);
302 }
303
rlyehComplete()304 EX bool rlyehComplete() {
305 if(ls::any_chaos()) return items[itStatue] >= 1;
306 return items[itStatue] >= 10 || items[itGrimoire] >= 10;
307 }
308
lchance(eLand l)309 bool lchance(eLand l) {
310 if(ls::single() || racing::on || ((geometry || GOLDBERG) && specialland == laElementalWall)) return true;
311 if(ls::any_chaos()) return hrand(100) < 25;
312 return hrand(100) >= 40 * kills[elementalOf(l)] / (elementalKills()+1);
313 }
314
pickLandRPM(eLand old)315 EX eLand pickLandRPM(eLand old) {
316 while(true) {
317 eLand n = randlands[hrand(isize(randlands))];
318 if(incompatible(n, old)) continue;
319 if(landUnlockedRPM(n)) return n;
320 }
321 }
322
pickluck(eLand l1,eLand l2)323 EX eLand pickluck(eLand l1, eLand l2) {
324 int t1 = items[treasureType(l1)];
325 int t2 = items[treasureType(l2)];
326 if(t1 < t2) return l1;
327 if(t2 < t1) return l2;
328 if(isCrossroads(l1)) return l1;
329 return l2;
330 }
331
332 #define LIKELY for(int u=0; u<5; u++)
333 #define LIKELY2 for(int u=0; u<2; u++)
334
335 /* bool noChaos(eLand l) {
336 if(l == laOcean || l == laTemple) return false;
337 return
338 isCrossroads(l) || isCyclic(l) || isHaunted(l) ||
339 l == laCaribbean || isGravityLand(l) || l == laPrincessQuest ||
340 l == laPrairie || l == laHalloween;
341 } */
342
getNewSealand(eLand old)343 EX eLand getNewSealand(eLand old) {
344 while(true) {
345 eLand p = pick(laOcean, pick(laCaribbean, laLivefjord, laWarpSea, laKraken, laDocks));
346 if(p == laKraken && !landUnlocked(p)) continue;
347 if(p == laKraken && peace::on) continue;
348 if(incompatible(old, p)) continue;
349 if(p == old) continue;
350 if(!isLandIngame(p)) continue;
351 return p;
352 }
353 }
354
createOnSea(eLand old)355 EX bool createOnSea(eLand old) {
356 return
357 old == laWarpSea || old == laCaribbean || old == laKraken ||
358 (old == laLivefjord && hrand(2)) ||
359 (old == laDocks && hrand(2)) ||
360 (old == laOcean && (ls::any_chaos() ? hrand(2) : !generatingEquidistant));
361 }
362
363 EX hookset<eLand(eLand)> hooks_nextland;
364
365 EX bool all_unlocked = false;
366
getNewLand(eLand old)367 EX eLand getNewLand(eLand old) {
368
369 eLand l = callhandlers(laNone, hooks_nextland, old);
370 if(l) return l;
371
372 if(cheatdest != old) if(!isCyclic(cheatdest) && !isTechnicalLand(cheatdest)) return cheatdest;
373
374 if(old == laTortoise) return laDragon;
375
376 if(yendor::on && ls::any_chaos()) {
377 while(true) {
378 eLand n = eLand(hrand(landtypes));
379 if(n == old) continue;
380 if(incompatible(n,old)) continue;
381 if(!isLandIngame(n)) continue;
382 if(n == laElementalWall || isTechnicalLand(n)) continue;
383 if(n == laWildWest) continue;
384 if(isElemental(n) && hrand(100) >= 25) continue;
385 return n;
386 }
387 }
388
389 if(markOrb(itOrbLuck)) {
390 int i = items[itOrbLuck];
391 items[itOrbLuck] = 0;
392 eLand l1 = getNewLand(old);
393 for(int i=1; i<3; i++)
394 l1 = pickluck(l1, getNewLand(old));
395 items[itOrbLuck] = i;
396 return l1;
397 }
398
399 if(randomPatternsMode) return pickLandRPM(old);
400
401 if(old == laEEarth && lchance(old)) return hrand(2) ? laEWater : laEFire;
402 if(old == laEAir && lchance(old)) return hrand(2) ? laEWater : laEFire;
403 if(old == laEWater && lchance(old)) return hrand(2) ? laEEarth : laEAir;
404 if(old == laEFire && lchance(old)) return hrand(2) ? laEEarth : laEAir;
405
406 #if CAP_RACING
407 if(racing::on && old != laElementalWall) {
408 eLand l = old;
409 using racing::race_lands;
410 while(l == old) l = race_lands[hrand(16)]; // fixed at 16
411 if(l == laElementalWall) l = randomElementalLand();
412 if(l == laMirror) l = laCrossroads;
413 return l;
414 }
415 #endif
416
417 if(tactic::on) return specialland;
418 if(specialland != old && easy_to_find_specialland) return specialland;
419
420 if(yendor::on && (yendor::clev().flags & YF_WALLS)) {
421 if(old != yendor::clev().l) return yendor::clev().l;
422 else if(old == laOcean) return pick(laLivefjord, laCaribbean);
423 }
424
425 if(yendor::on && yendor::nexttostart) {
426 eLand l = yendor::nexttostart;
427 if(!(yendor::clev().flags & YF_REPEAT))
428 yendor::nexttostart = laNone;
429 return l;
430 }
431
432 if(old == laDragon && tortoise::seek() && hrand(100) < 50)
433 return laTortoise;
434
435 if(isWarpedType(old) && (hrand(100) < 25) && ls::std_chaos()) return eLand(old ^ laWarpCoast ^ laWarpSea);
436
437 if(createOnSea(old))
438 return getNewSealand(old);
439
440 if(old == laGraveyard && generatingEquidistant)
441 return laHaunted;
442
443 if(old == laOcean && gold() >= R60 && hrand(100) < 75 && !rlyehComplete() && !all_unlocked)
444 return laRlyeh;
445
446 if(old == laRlyeh && !rlyehComplete() && !all_unlocked)
447 return laOcean;
448
449 eLand tab[16384];
450 int cnt = 0;
451
452 // return (hrand(2)) ? laMotion : laJungle;
453
454 for(eLand l: {
455 laCrossroads, laIce, laDesert, laJungle, laMotion, laHunting, laAlchemist, laCaves,
456 laMinefield, laPalace, laReptile, laSwitch, laBurial, laDungeon, laRuins, laZebra,
457 laStorms, laWhirlwind, laOvergrown, laBlizzard, laDryForest, laWineyard, laVolcano,
458 laDeadCaves, laRedRock, laVariant, laHell, laCocytus, laPower,
459 laBull, laTerracotta, laRose, laGraveyard, laHive, laDragon, laTrollheim,
460 laWet, laFrog, laEclectic, laCursed, laDice,
461 laCrossroads5,
462 })
463 if(landUnlocked(l)) tab[cnt++] = l;
464
465 struct clos {
466 eLand l1;
467 eLand l2;
468 int f1;
469 int f2;
470 };
471
472 for(clos c: {
473 clos{laZebra, laMotion, 2, 2}, {laZebra, laHunting, 2, 2},
474 {laDragon, laReptile, 5, 5},
475 {laVariant, laRuins, 5, 5}, {laVariant, laEmerald, 5, 5}, {laVariant, laGraveyard, 5, 5},
476 {laPalace, laDungeon, 5, 0},
477 {laJungle, laOvergrown, 5, 5},
478 {laIce, laBlizzard, 5, 5}, {laCocytus, laBlizzard, 5, 5}, {laHell, laCocytus, 5, 5}, {laIce, laCocytus, 5, 5},
479 {laWhirlwind, laBlizzard, 5, 5},
480 {laAlchemist, laVolcano, 5, 5},
481 {laDesert, laRedRock, 5, 5},
482 {laFrog, laReptile, 2, 2}, {laFrog, laSwitch, 2, 2}, {laFrog, laZebra, 2, 2},
483 {laEclectic, laStorms, 3, 3}, {laEclectic, laIce, 3, 3}, {laEclectic, laPalace, 3, 3}, {laEclectic, laDeadCaves, 3, 3},
484
485 {laEFire, laDragon, 5, 5}, {laEWater, laLivefjord, 5, 5}, {laEEarth, laDeadCaves, 5, 5}, {laEAir, laWhirlwind, 5, 5},
486 }) {
487 if(old == c.l1 && landUnlocked(c.l2)) for(int i=0; i<c.f1; i++) tab[cnt++] = c.l2;
488 if(old == c.l2 && landUnlocked(c.l1)) for(int i=0; i<c.f2; i++) tab[cnt++] = c.l1;
489 }
490
491 // these lands tend to crash while generating equidistant
492 for(eLand l: {laIvoryTower, laEndorian, laWestWall})
493 if(landUnlocked(l) && !generatingEquidistant)
494 tab[cnt++] = l;
495
496 // the intermediate lands
497 if(all_unlocked || gold() >= R30) {
498 tab[cnt++] = laCrossroads;
499 tab[cnt++] = geometry ? laMirrorOld : laMirror;
500 tab[cnt++] = laOcean;
501 tab[cnt++] = laLivefjord;
502 if(all_unlocked || kills[moVizier]) tab[cnt++] = laEmerald;
503 tab[cnt++] = laWarpCoast;
504 if(euclid) tab[cnt++] = laWarpSea;
505 tab[cnt++] = laDocks;
506 }
507
508 // the advanced lands
509 if(all_unlocked || gold() >= R60) {
510 tab[cnt++] = laCrossroads;
511 if(!generatingEquidistant) tab[cnt++] = laCrossroads2;
512 if(all_unlocked || rlyehComplete()) tab[cnt++] = laRlyeh;
513 else if(ls::std_chaos() && (old == laWarpCoast || old == laLivefjord || old == laOcean))
514 tab[cnt++] = laRlyeh;
515 if((all_unlocked || items[itStatue] >= U5) && ls::std_chaos())
516 tab[cnt++] = laTemple;
517 if(old == laCrossroads || old == laCrossroads2) tab[cnt++] = laOcean;
518 if(old == laOcean) tab[cnt++] = laCrossroads;
519 if(items[itGold] >= U5 && items[itFernFlower] >= U5 && !kills[moVizier] && !all_unlocked)
520 tab[cnt++] = laEmerald;
521 }
522
523 if(all_unlocked || gold() >= R90) {
524 if(!ls::std_chaos()) tab[cnt++] = laPrairie;
525 if(old == laPrairie) LIKELY tab[cnt++] = laBull;
526 if(old == laBull && !ls::any_chaos()) LIKELY tab[cnt++] = laPrairie;
527 if(ls::std_chaos() && geometry) tab[cnt++] = laDual;
528 if(ls::std_chaos() && geosupport_threecolor()) tab[cnt++] = laSnakeNest;
529 }
530
531 if(landUnlocked(laTrollheim)) {
532 if(isTrollLand(old)) LIKELY tab[cnt++] = laTrollheim;
533 if(old == laTrollheim) for(int i=0; i<landtypes; i++) {
534 eLand l2 = eLand(i);
535 if(isTrollLand(l2)) LIKELY tab[cnt++] = l2;
536 }
537 }
538
539 if(landUnlocked(laElementalWall)) {
540 tab[cnt++] = randomElementalLandWeighted();
541 }
542
543 if(landUnlocked(laHell)) {
544 if(!generatingEquidistant && old != laPrairie) tab[cnt++] = laCrossroads3;
545 }
546
547 if(items[itHell] >= U10) {
548 if(old == laCrossroads || old == laCrossroads2) tab[cnt++] = laOcean;
549 if(old == laOcean) tab[cnt++] = laCrossroads2;
550 }
551
552 eLand n = old;
553 while(incompatible(n, old) || !isLandIngame(n)) {
554 n = tab[hrand(cnt)];
555 if(weirdhyperbolic && specialland == laCrossroads4 && isCrossroads(n))
556 n = laCrossroads4;
557 }
558
559 return n;
560 }
561
562 EX vector<eLand> land_over = {
563 laIce, laCaves, laDesert, laHunting, laMotion, laJungle, laAlchemist,
564 laCrossroads,
565 laMirror, laMirrorOld, laMinefield, laPalace, laPrincessQuest, laZebra, laSwitch, laReptile, laWet,
566 laOcean, laDocks, laWarpCoast, laLivefjord, laKraken, laCaribbean, laBrownian, laWhirlpool, laRlyeh, laTemple,
567 laIvoryTower, laEndorian, laWestWall, laDungeon, laMountain,
568 laCrossroads2,
569 laDryForest, laWineyard, laDeadCaves, laGraveyard, laHaunted, laHive,
570 laRedRock, laVolcano,
571 laDragon, laTortoise, laDice,
572 laOvergrown, laClearing, laStorms, laBurial, laWhirlwind,
573 laBlizzard,
574 laFrog, laEclectic, laCursed,
575 laRuins, laEmerald, laVariant, laCamelot,
576 laPrairie, laBull, laTerracotta, laRose,
577 laElementalWall, laTrollheim,
578 laHell, laCrossroads3, laCocytus, laPower, laCrossroads4,
579 laCrossroads5,
580 // EXTRA
581 laWildWest, laHalloween, laDual, laSnakeNest, laMagnetic, laCA, laAsteroids
582 };
583
584 EX vector<eLand> landlist;
585
586 #if HDR
generateLandList(T t)587 template<class T> void generateLandList(T t) {
588 landlist.clear();
589 for(auto l: land_over) if(t(l)) landlist.push_back(l);
590 }
591 #endif
592
593 #if HDR
594 namespace lv {
595 static const flagtype appears_in_geom_exp = 1;
596 static const flagtype display_error_message = 2;
597 static const flagtype appears_in_full = 4;
598 static const flagtype appears_in_ptm = 8;
599 static const flagtype display_in_help = 16;
600 static const flagtype one_and_half = 32;
601 }
602
603 struct land_validity_t {
604 int quality_level; // 0 (dont show), 1 (1/2), 2 (ok), 3(1!)
605 flagtype flags;
606 string msg;
607 };
608 #endif
609
getLandForList(cell * c)610 EX eLand getLandForList(cell *c) {
611 eLand l = c->land;
612 if(isElemental(l)) return laElementalWall;
613 if(l == laWarpSea) return laWarpCoast;
614 if(l == laMercuryRiver) return laTerracotta;
615 if(l == laBarrier) return laCrossroads;
616 if(l == laOceanWall) return laOcean;
617 if(l == laPalace && princess::dist(cwt.at) < OUT_OF_PRISON)
618 l = laPrincessQuest;
619 // princess?
620 return l;
621 }
622
isLandIngame(eLand l)623 EX bool isLandIngame(eLand l) {
624 if(isElemental(l)) l = laElementalWall;
625 if(dual::state == 2 && !dual::check_side(l)) return false;
626 if((eubinary || sol) && isCyclic(l) && l != specialland) return false;
627 if(l == laCamelot && hyperbolic && WDIM == 3) return false;
628 return land_validity(l).flags & lv::appears_in_full;
629 }
630
631 namespace lv {
632
633 flagtype q0 = lv::display_error_message | lv::display_in_help | lv::appears_in_geom_exp;
634 flagtype q1 = lv::display_error_message | lv::appears_in_geom_exp | lv::appears_in_full | lv::display_in_help;
635 flagtype q2 = lv::appears_in_geom_exp | lv::appears_in_full | lv::display_in_help | lv::appears_in_ptm;
636 flagtype q3 = lv::appears_in_geom_exp | lv::appears_in_full | lv::display_in_help | lv::appears_in_ptm;
637 flagtype qm2= q2 | lv::display_error_message;
638 flagtype qm3= q3 | lv::display_error_message;
639
640 land_validity_t hedgehogs = { 1, qm2 &~ lv::appears_in_full, "Cannot kill Hedgehog Warriors in this geometry."};
641
642 land_validity_t no_randpattern_version = { 0, q0, "No random pattern version."};
643 land_validity_t no_great_walls = { 0, q0, "Great Walls not implemented."};
644 land_validity_t pattern_incompatibility = { 0, q0, "Pattern incompatible."};
645 land_validity_t pattern_not_implemented_random = { 1, q1 | one_and_half, "Pattern not implemented -- using random."};
646 land_validity_t pattern_not_implemented_weird = { 1, q1, "Pattern not implemented."};
647 land_validity_t pattern_not_implemented_exclude = { 1, q1 & ~ lv::appears_in_full, "Pattern not implemented."};
648 land_validity_t not_enough_space = { 0, q0, "Not enough space."};
649 land_validity_t dont_work = { 0, q0, "Does not work in this geometry."};
650 land_validity_t bounded_only = { 0, q0, "This land is designed for bounded worlds."};
651 land_validity_t unbounded_only = { 0, q0, "This land is designed for infinite worlds."};
652 land_validity_t unbounded_only_except_bigsphere = { 0, q0, "This land is designed for infinite worlds or big spheres."};
653 land_validity_t out_of_theme = { 3, qm2 &~ lv::appears_in_full, "Out of theme for the full game."};
654 land_validity_t no_game = { 2, q2 &~ lv::appears_in_full, "No game here."};
655 land_validity_t not_in_chaos = { 0, q0, "Does not work in chaos mode."};
656 land_validity_t not_in_full_game = {2, qm2 &~ lv::appears_in_full, "Not in the full game."};
657 land_validity_t not_in_full_game3 = {3, qm2 &~ lv::appears_in_full, "Not in the full game."};
658 land_validity_t special_chaos = { 2, qm2, "Special construction in the Chaos mode." };
659 land_validity_t special_euclidean = { 2, qm2, "Special construction in the Euclidean mode." };
660 land_validity_t special_geo = { 2, qm2, "Special construction in this geometry." };
661 land_validity_t special_geo3 = { 3, qm2, "Special construction in this geometry." };
662 land_validity_t not_implemented = {0, q0, "Not implemented."};
663 land_validity_t partially_implemented = {1, q1 | one_and_half, "Partially implemented."};
664 land_validity_t ok = {2, q2 &~ lv::display_in_help, "No comments."};
665 land_validity_t not_in_ptm = {0, q0, "Does not work in pure tactics mode."};
666 land_validity_t technical = {0, q0 &~ lv::appears_in_geom_exp, "Technical."};
667 land_validity_t full_game = {3, q3 &~ lv::display_in_help, "Full game."};
668 land_validity_t inaccurate = {1, q1, "Somewhat inaccurate."};
669 land_validity_t great_walls_missing = {1, q1 | one_and_half, "Mercury rivers not implemented (or could not work) in this geometry."};
670 land_validity_t pattern_compatibility = {3, qm3, "Patterns compatible."};
671 land_validity_t pattern_defined = {3, qm3, "Pattern defined."};
672 land_validity_t pattern_compatibility_notrec = {2, qm2, "Patterns compatible."};
673 land_validity_t specially_designed = {3, qm3, "This land is specially designed for this geometry."};
674 land_validity_t needs_threecolor = {0, q0, "Three-colorability required."};
675 land_validity_t land_not_implemented = {0, q0 &~ lv::appears_in_geom_exp, "Land not implemented."};
676 land_validity_t interesting = {3, q3, "Special interest."};
677 land_validity_t better_version_exists = {0, q0, "Better version exists."};
678 land_validity_t dont_work_but_ingame = {1, q0 | lv::appears_in_full, "Does not work in this geometry."};
679 land_validity_t ugly_version_infull = {1, q1 | lv::appears_in_full, "Grid does not work in this geometry."};
680 land_validity_t ugly_version_nofull = {1, q1, "Grid does not work in this geometry."};
681 land_validity_t bad_graphics = {1, q1, "Graphics not implemented in this geometry."};
682 land_validity_t some0 = {0, q0, "This land does not work in the current settings. Reason not available."};
683 land_validity_t some1 = {1, q1, "This land does not work well in the current settings. Reason not available."};
684 land_validity_t known_buggy = {1, q1, "This combination is known to be buggy at the moment."};
685 land_validity_t sloppy_pattern = {1, q1 | one_and_half, "Somewhat sloppy pattern."};
686 land_validity_t no_fractal_landscapes = {1, q1 | one_and_half, "Fractal landscapes not implemented in this geometry."};
687 land_validity_t simplified_walls = { 1, q1, "Only simplified walls implemented."};
688 land_validity_t no_walls = { 0, q0, "No walls implemented."};
689 land_validity_t disabled = {0, q0, "This land has been disabled with compilation flags."};
690 land_validity_t pattern_special = {3, qm3, "Special pattern implemented for this geometry."};
691 land_validity_t not_3d = {0, q0, "This land does not make much sense in 3D."};
692 land_validity_t not_binary = {0, q0, "This land does not make much sense in binary tiling."};
693 land_validity_t shmup_only = {0, q0, "This land works only in the shmup mode."};
694 land_validity_t not_in_shmup = {0, q0, "This land is not available in the shmup mode."};
695 land_validity_t not_in_multi = {0, q0, "This land is not available in multiplayer."};
696 }
697
698 // old Daily Challenges should keep their validity forever
699 // set this number for historical values of land_validity
700
701 EX int old_daily_id = 1000000;
702
703 const int landscapes_when = 177;
704
705 EX const int frog_when = 205;
706
707 EX const int cursed_when = 9999; /* don't do Dice and Curse for now in daily */
708
709 EX const int walls_when = 9999; /* don't do walls for now in daily */
710
711 // check if the given land should appear in lists
land_validity(eLand l)712 EX land_validity_t& land_validity(eLand l) {
713
714 bool stdeucx = stdeuc;
715 if(euclid && quotient) stdeucx = false;
716
717 using namespace lv;
718
719 if(l == laDice && geometry == gNormal && PURE)
720 return dont_work;
721
722 if(l == laDice && WDIM == 3)
723 return dont_work;
724
725 if(old_daily_id < frog_when && among(l, laFrog, laEclectic, laWet))
726 return not_implemented;
727
728 if(old_daily_id < cursed_when && among(l, laCursed, laDice))
729 return not_implemented;
730
731 if(arb::in() && among(l, laWarpCoast, laDual, laEclectic, laReptile, laKraken))
732 return not_implemented;
733
734 if(l == laEclectic && !(geometry == gNormal && BITRUNCATED))
735 return pattern_not_implemented_weird;
736
737 if(l == laFrog && shmup::on)
738 return not_in_shmup;
739
740 if(walls_not_implemented() && isCrossroads(l))
741 return no_walls;
742
743 if(hybri || hybrid::pmap) {
744 if(among(l, laPrincessQuest, laPrairie, laMirrorOld, laMirror, laDual, laWarpCoast, laKraken, laBrownian, laWhirlpool, laWestWall, laHive, laClearing, laWhirlwind, laBlizzard, laBull, laTerracotta, laCrossroads5,
745 laEndorian, laDungeon, laMountain))
746 return lv::not_implemented;
747 if(among(l, laReptile, laDragon, laTortoise))
748 return lv::bad_graphics;
749 if((hybrid::actual_geometry == gRotSpace || geometry == gRotSpace) && l == laDryForest)
750 return lv::hedgehogs;
751 if(hybri && hybrid::underlying && hybrid::underlying_cgip) {
752 return *PIU(&land_validity(l));
753 }
754 }
755
756 #if !CAP_FIELD
757 if(among(l, laPrairie, laBlizzard, laVolcano))
758 return disabled;
759 #endif
760
761 #if !CAP_COMPLEX2
762 if(among(l, laBrownian, laWestWall, laVariant))
763 return disabled;
764 #endif
765
766 if(l == laMinefield && bounded)
767 return special_geo3;
768
769 if(l == laAsteroids) {
770 if(!shmup::on) return shmup_only;
771 if(!bounded) return bounded_only;
772 return specially_designed;
773 }
774
775 if(nil) {
776 if(among(l, laCrossroads, laCrossroads2, laCrossroads3, laCrossroads4))
777 return lv::full_game;
778 if(among(l, laPalace, laGraveyard, laWineyard, laElementalWall))
779 return lv::pattern_special;
780 if(among(l, laEndorian, laCaribbean, laHaunted, laVolcano, laClearing, laStorms, laBlizzard))
781 return lv::not_implemented;
782 }
783
784 if(WDIM == 3) {
785 if(l == laWarpCoast) return ugly_version_nofull;
786 if(l == laWineyard && hyperbolic && !bt::in() && S7 == 6) return lv::pattern_special;
787 if(l == laEmerald && hyperbolic && !bt::in() && S7 == 12) return lv::pattern_special;
788 if(l == laZebra) return pattern_not_implemented_random;
789 if(among(l, laWhirlpool, laPrairie, laWestWall, laBull)) return lv::not_3d;
790 if(l == laEndorian && geometry == gKiteDart3) return not_implemented;
791 if(l == laEndorian && sol) return not_implemented;
792 if(l == laEndorian && hyperbolic && !quotient) return lv::pattern_special;
793 if(l == laIvoryTower && hyperbolic && bt::in()) return lv::pattern_special;
794 if(l == laDungeon || l == laBrownian) return not_implemented;
795 if(l == laKraken) return bt::in() ? not_binary : not_implemented;
796 if(l == laBurial && !shmup::on) return not_implemented;
797 if(l == laMirrorOld && !shmup::on) return not_implemented;
798 }
799
800 if(l == laBrownian) {
801 if(quotient || !hyperbolic || cryst) return dont_work;
802 }
803
804 if(bt::in()) {
805 if(among(l, laMountain, laTemple)) return lv::pattern_compatibility;
806 if(among(l, laDungeon, laIvoryTower, laOcean, laEndorian)) return lv::pattern_compatibility;
807 if(among(l, laCaribbean, laCamelot)) return lv::pattern_compatibility_notrec;
808 // Clearing -- does not generate
809 /* laCamelot, laCaribbean -> they are OK but not recommended */
810 }
811
812 #if CAP_ARCM
813 if(arcm::in()) {
814 if(among(l, laPower, laZebra, laFrog, laWineyard) && arcm::current.have_line) return lv::pattern_defined;
815 // horocycles not implemented
816 if(isCyclic(l)) return not_implemented;
817 }
818 #endif
819
820 #if CAP_CRYSTAL
821 if(cryst) {
822 if(l == laCamelot) return interesting;
823 if(isCrossroads(l)) return full_game;
824 }
825 #endif
826
827 // Random Pattern allowed only in some specific lands
828 if(randomPatternsMode && !isRandland(l))
829 return no_randpattern_version;
830
831 if(isElemental(l)) {
832 if(l != laElementalWall)
833 return technical;
834 // not good in Field quotient
835 if(geometry == gZebraQuotient)
836 return special_geo3;
837 if(quotient || sol)
838 return no_great_walls;
839 if(weirdhyperbolic)
840 return simplified_walls;
841 // works nice on a big non-tetrahedron-based sphere
842 if(sphere && S3 != 3 && GOLDBERG)
843 return special_geo3;
844 }
845
846 // not enough space
847 if(l == laStorms && (old_daily_id < 35 ? !BITRUNCATED : PURE) && elliptic)
848 return not_enough_space;
849
850 if(l == laStorms && WDIM == 3)
851 return not_in_full_game; /* uses too much memory */
852
853 if(l == laStorms && S7 == 3)
854 return not_enough_space;
855
856 // does not agree with the pattern
857 if(l == laStorms && quotient && geometry != gZebraQuotient)
858 return pattern_not_implemented_random;
859
860 // pattern not implemented
861 if(l == laStorms && S7 == 8)
862 return pattern_not_implemented_random;
863
864 // mirrors do not work in gp
865 if(among(l, laMirror, laMirrorOld) && (GOLDBERG && old_daily_id < 33))
866 return dont_work;
867
868 // mirrors do not work in kite and sol
869 if(among(l, laMirror, laMirrorOld) && (kite::in() || sol))
870 return dont_work;
871
872 if(isCrossroads(l) && geometry == gBinary4)
873 return not_implemented;
874
875 if(bt::in() && among(l, laMirror, laMirrorOld))
876 return dont_work;
877
878 if(l == laWhirlwind && hyperbolic_not37)
879 return pattern_incompatibility;
880
881 // available only in non-standard geometries
882 if(l == laMirrorOld && !geometry && STDVAR)
883 return better_version_exists;
884
885 // available only in standard geometry
886 if(l == laMirror && (geometry || NONSTDVAR))
887 return not_implemented;
888
889 // Halloween needs bounded world (can be big bounded)
890 if(l == laHalloween && !bounded)
891 return bounded_only;
892
893 // Crystal World is designed for nice_dual geometries
894 if(l == laDual && (!has_nice_dual() || nonisotropic))
895 return dont_work;
896
897 if(l == laHaunted && ls::std_chaos())
898 return not_in_chaos;
899
900 // standard, non-PTM specific
901 if(l == laCrossroads5 && old_daily_id < 999 && tactic::on)
902 return not_in_ptm;
903
904 // standard non-PTM non-chaos specific
905 if((l == laCrossroads5 || l == laCrossroads2) && (geometry || ls::any_chaos() || ls::no_walls()))
906 return some0;
907
908 // special construction in the Chaos mode
909 if(ls::any_chaos() && (l == laTemple || l == laHive || l == laOcean || l == laHaunted))
910 return special_chaos;
911
912 if(l == laWhirlpool && a4)
913 return dont_work;
914
915 if(isWarpedType(l) && a4 && GOLDBERG)
916 return dont_work;
917
918 #if CAP_IRR
919 if((isWarpedType(l) || l == laDual) && IRREGULAR && !irr::bitruncations_performed)
920 return dont_work;
921
922 if(IRREGULAR && among(l, laPrairie, laMirror, laMirrorOld))
923 return dont_work;
924 #endif
925
926 if(arcm::in() && l == laPrairie) return dont_work;
927
928 if((IRREGULAR || arcm::in()) && among(l, laBlizzard, laVolcano) && !sphere)
929 return dont_work;
930
931 if(arcm::in() && DUAL && l == laCrossroads4)
932 return not_implemented;
933
934 if(geometry == gKiteDart3 && l == laGraveyard)
935 return lv::pattern_special;
936
937 // equidistant-based lands
938 if(isEquidLand(l)) {
939 // no equidistants supported in chaos mode
940 if(ls::any_chaos())
941 return not_in_chaos;
942 // the algorithm fails in Archimedean DUAL
943 if(arcm::in() && DUAL)
944 return not_implemented;
945 // the algorithm fails in Binary4
946 if(geometry == gBinary4)
947 return not_implemented;
948 // no equidistants supported in these geometries (big sphere is OK though)
949 if(bounded && !bigsphere)
950 return unbounded_only_except_bigsphere;
951 // Yendorian only implemented in standard
952 if(l == laEndorian && geometry)
953 return not_implemented;
954 // special Euclidean implementations
955 if(euclid && (l == laIvoryTower || l == laMountain || l == laOcean || l == laMountain))
956 return special_geo;
957 // in other geometries, it works
958 if(geometry)
959 return ok;
960 }
961
962 if(l == laPrincessQuest && ls::any_chaos())
963 return not_in_chaos;
964
965 if(l == laPrincessQuest && tactic::on)
966 return not_in_ptm;
967
968 if(l == laPrincessQuest && (!stdeucx || NONSTDVAR))
969 return not_implemented;
970
971 if(l == laPrincessQuest && shmup::on)
972 return not_in_shmup;
973
974 if(l == laPrincessQuest && multi::players > 1)
975 return not_in_multi;
976
977 if(l == laMountain && ls::any_chaos())
978 return not_in_chaos;
979
980 if(l == laBrownian && ls::any_chaos())
981 return not_in_chaos;
982
983 // works correctly only in some geometries
984 if(l == laClearing && ls::any_chaos())
985 return not_in_chaos;
986
987 if(l == laClearing)
988 if(!(stdeucx || geometry == gBinaryTiling || a38 || (a45 && BITRUNCATED) || (a47 && BITRUNCATED)) || NONSTDVAR)
989 if(!bounded)
990 return not_implemented;
991
992 // does not work in non-bitrunc a4
993 if(l == laOvergrown && a4 && !BITRUNCATED)
994 return some0;
995
996 // does not work in bounded either
997 if(l == laOvergrown && bounded)
998 return some0;
999
1000 // horocycle-based lands, not available in bounded geometries nor in Chaos mode
1001 if(l == laWhirlpool || l == laCamelot || l == laCaribbean || l == laTemple || l == laHive) {
1002 if(ls::any_chaos()) {
1003 if(l == laTemple || l == laHive)
1004 return special_chaos;
1005 return not_in_chaos;
1006 }
1007 if(arcm::in() || kite::in()) return not_implemented;
1008 if(bounded) return unbounded_only;
1009 if(INVERSE) return not_implemented;
1010 }
1011
1012 if(ls::any_chaos() && isCrossroads(l))
1013 return not_in_chaos;
1014
1015 // this pattern does not work on elliptic and small spheres
1016 if((l == laBlizzard || l == laVolcano) && elliptic && S7 < 5 && !arcm::in())
1017 return not_enough_space;
1018
1019 // ... and it works in gp only partially
1020 if((l == laBlizzard || l == laVolcano) && GOLDBERG && (old_daily_id < 33 || !sphere))
1021 return partially_implemented;
1022
1023 // Kraken does not really work on odd-sided cells;
1024 // a nice football pattern will solve the problem by forbidding the Kraken to go there
1025 // (but we do have to allow it in non-bitrunc standard)
1026 if(l == laKraken && (S7&1) && !has_nice_dual()) {
1027 return dont_work_but_ingame;
1028 }
1029
1030 // works in most spheres, Zebra quotient, and stdeucx
1031 if(l == laWhirlwind) {
1032 if(geometry == gZebraQuotient)
1033 return pattern_compatibility;
1034 if(stdeucx) ;
1035 else if(S7 == 4 && BITRUNCATED) return special_geo;
1036 else if(bigsphere && !BITRUNCATED && !elliptic) return special_geo;
1037 else return dont_work;
1038 }
1039
1040 // needs standard/Euclidean (needs fractal landscape)
1041 if(among(l, laTortoise, laVariant) && !(old_daily_id < landscapes_when ? stdeucx : geometry_supports_cdata()))
1042 return not_implemented;
1043
1044 // technical lands do not count
1045 if(l != laCA && isTechnicalLand(l))
1046 return technical;
1047
1048 // only in bounded geometry, and not in PTM
1049 if(l == laCA && !bounded)
1050 return bounded_only;
1051
1052 if(l == laCA && tactic::on)
1053 return not_in_ptm;
1054
1055 if(l == laCA)
1056 return no_game;
1057
1058 // Dragon Chasm requires unbounded space [partial]
1059 if(l == laDragon && smallbounded)
1060 return unbounded_only;
1061
1062 // Graveyard pattern does not work on non-bitrunc weird geometries
1063 if((l == laGraveyard && !randomPatternsMode) || l == laRuins || l == laRedRock) switch(geosupport_football()) {
1064 case 0:
1065 return dont_work;
1066 case 1:
1067 return sloppy_pattern;
1068 default: ;
1069 }
1070
1071 // Warped Coast does not work on non-bitrunc S3s (except standard heptagonal where we have to keep it)
1072 if(l == laWarpCoast && (S3==3) && geosupport_football() != 2 && !(old_daily_id >= 33 && geosupport_chessboard())) {
1073 return ugly_version_infull;
1074 }
1075
1076 if(l == laWarpCoast && quotient && geometry != gZebraQuotient && !randomPatternsMode)
1077 return pattern_incompatibility;
1078
1079 if(among(l, laEmerald, laCamelot, laDryForest) && valence() != 3 && old_daily_id >= 65)
1080 return hedgehogs;
1081
1082 // laPower and laEmerald and laPalace -> [partial] in quotients and hyperbolic_non37
1083 if((l == laPower || l == laEmerald || l == laPalace || l == laWildWest) && !randomPatternsMode) {
1084 if(euclid || bigsphere) ;
1085 else if(old_daily_id <= 65 && a45) ;
1086 else if(!hyperbolic_37) return l == laWildWest ? some0 : pattern_not_implemented_random;
1087 else if(quotient) return pattern_incompatibility;
1088 }
1089
1090 if(among(l, laEmerald, laCamelot, laDryForest) && valence() != 3)
1091 return hedgehogs;
1092
1093 if(l == laWineyard && sol)
1094 return lv::pattern_special;
1095
1096 // ... wineyard pattern is GOOD only in the standard geometry or Euclidean
1097 if(l == laWineyard && (NONSTDVAR || sphere) && !randomPatternsMode)
1098 return pattern_not_implemented_random;
1099
1100 if(l == laTrollheim && quotient == qFIELD)
1101 return not_enough_space;
1102
1103 if(l == laStorms && hyperbolic_not37)
1104 return pattern_not_implemented_random;
1105
1106 if(l == laTrollheim && !stdeucx && !bounded)
1107 return some1;
1108
1109 if(l == laReptile && sol) return ugly_version_nofull;
1110
1111 if(l == laReptile) {
1112 if(old_daily_id <= 64) {
1113 if(l == laReptile && (a38 || a4 || sphere || !BITRUNCATED || (quotient && !euclid && geometry != gZebraQuotient)))
1114 return bad_graphics;
1115 }
1116 else {
1117 bool reptile_good = false;
1118 if(hyperbolic_37 && BITRUNCATED) reptile_good = true;
1119 if(euc::in(2,6)) reptile_good = true;
1120 if(quotient && geometry != gZebraQuotient && !euclid)
1121 reptile_good = false;
1122 if(!reptile_good)
1123 return bad_graphics;
1124 }
1125 }
1126
1127 if((l == laDragon || l == laReptile) && !stdeucx && !smallbounded && !randomPatternsMode)
1128 return no_fractal_landscapes;
1129
1130 if(l == laCrossroads && smallsphere)
1131 return not_enough_space;
1132
1133 if(l == laCrossroads3 && !stdeucx && !bigsphere)
1134 return not_enough_space;
1135
1136 if(among(l, laCrossroads, laCrossroads2, laCrossroads3, laCrossroads5) && weirdhyperbolic && old_daily_id < walls_when)
1137 return no_great_walls;
1138
1139 // Crossroads IV is great in weird hyperbolic
1140 if(l == laCrossroads4 && weirdhyperbolic && !quotient)
1141 return full_game;
1142
1143 // OK in small bounded worlds, and in Euclidean
1144 if(l == laCrossroads4 && quotient)
1145 return some0;
1146
1147 if(among(l, laZebra, laFrog) && quotient && geometry != gZebraQuotient && !randomPatternsMode)
1148 return pattern_incompatibility;
1149
1150 if(among(l, laZebra, laFrog) && !(stdeucx || (a4 && !BITRUNCATED) || a46 || (geometry == gZebraQuotient && old_daily_id > 106)) && !randomPatternsMode)
1151 return pattern_not_implemented_weird;
1152
1153 if(l == laCrossroads3 && euclid)
1154 return inaccurate; // because it is not accurate
1155
1156 if(l == laPrairie) {
1157 if(GOLDBERG) return not_implemented;
1158 else if(stdeucx || (bigsphere && BITRUNCATED && !elliptic) || (geometry == gFieldQuotient)) ;
1159 else if(!bounded) return not_implemented;
1160 else return unbounded_only;
1161 }
1162
1163 if(l == laTerracotta && !stdeucx && !(bigsphere))
1164 return great_walls_missing;
1165
1166 // highlight Crossroads on Euclidean
1167 if(euclid && !quotient && (l == laCrossroads || l == laCrossroads4) && !kite::in())
1168 return full_game;
1169
1170 if(sol && among(l, laCrossroads, laCrossroads4))
1171 return full_game;
1172
1173 if(sol && l == laCamelot)
1174 return not_implemented;
1175
1176 if(euclid && quotient && !bounded && l == laCrossroads && euc::sdxy().second == -2 * euc::sdxy().first)
1177 return full_game;
1178
1179 if(euclid && quotient && !bounded && l == laCrossroads4 && euc::sdxy().second == 0)
1180 return full_game;
1181
1182 // highlight Zebra-based lands on Zebra Quotient!
1183 if(among(l, laZebra, laWhirlwind, laStorms, laWarpCoast, laWarpSea, laFrog) && geometry == gZebraQuotient)
1184 return pattern_compatibility;
1185
1186 // highlight FP-based lands on Field Quotient!
1187 if((l == laPrairie || l == laVolcano || l == laBlizzard) && geometry == gFieldQuotient)
1188 return pattern_compatibility;
1189
1190 // highlight Docks-based lands on Bolza and Bolza x2!
1191 if(l == laDocks && among(geometry, gBolza, gBolza2))
1192 return pattern_compatibility;
1193
1194 // these are highlighted whenever allowed
1195 if(l == laHalloween)
1196 return specially_designed;
1197
1198 if(l == laDual && geosupport_threecolor() == 2)
1199 return specially_designed;
1200
1201 if(l == laDual && !geometry && !GOLDBERG)
1202 return hyperbolic_37 ? not_in_full_game3 : not_in_full_game;
1203
1204 if(l == laSnakeNest && WDIM == 2) {
1205 if(geosupport_threecolor() < 2)
1206 return needs_threecolor;
1207 else return specially_designed;
1208 }
1209
1210 if(l == laDocks && !randomPatternsMode) {
1211 if(a38 && !GOLDBERG && !nonisotropic) return specially_designed;
1212 if(a38 && !nonisotropic) return pattern_not_implemented_weird;
1213 return pattern_not_implemented_exclude;
1214 }
1215
1216 if(l == laStorms && euclid && bounded)
1217 return interesting;
1218
1219 if(l == laMagnetic)
1220 return land_not_implemented;
1221
1222 if(shmup::on && among(l, laMirror, laMirrorOld) && among(geometry, gElliptic, gZebraQuotient, gKleinQuartic, gBolza, gBolza2, gMinimal))
1223 return known_buggy;
1224
1225 // these don't appear in normal game, but do appear in special modes
1226 if(l == laWildWest && !randomPatternsMode)
1227 return out_of_theme;
1228
1229 if(l == laIce && STDVAR && hyperbolic_37 && !quotient && !arcm::in() && !bt::in())
1230 return full_game;
1231
1232 return ok;
1233 }
1234
1235 /*
1236 int checkLands() {
1237 for(int i=0; i<landtypes; i++) {
1238 eLand l = eLand(i);
1239 char inover = 'N';
1240 for(int i=0; i<LAND_OVERX; i++) if(land_over[i] == l) inover = 'X';
1241 for(int i=0; i<LAND_OVER; i++) if(land_over[i] == l) inover = 'Y';
1242 char ineuc = 'N';
1243 for(int i=0; i<LAND_EUC; i++) if(land_euc[i] == l) ineuc = 'Y';
1244 char insph = 'N';
1245 for(int i=0; i<LAND_SPH; i++) if(land_sph[i] == l) insph = 'Y';
1246 char inoct = 'N';
1247 for(int i=0; i<LAND_OCT; i++) if(land_oct[i] == l) inoct = 'Y';
1248 char intac = 'N';
1249 for(auto ti: land_tac) if(l == ti.l) intac = 'Y';
1250 printf("%c %c %c %c %c %c %c :: %s\n",
1251 isTechnicalLand(l) ? 'T' : 'R',
1252 inover, ineuc, insph, inoct, intac, noChaos(l) ? 'N' : 'Y', linf[i].name);
1253 }
1254 exit(0);
1255 }
1256
1257 auto hookcl = addHook(hooks_args, 100, checkLands); */
1258
1259 }
1260