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