1 // Hyperbolic Rogue -- items, monsters, walls, lands, descriptions, etc.
2 // Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details
3 
4 /** \file classes.cpp
5  *  \brief items, monsters, walls, lands, descriptions, etc.
6  *
7  *  See content.cpp for actual items, monsters, walls and lands.
8  */
9 
10 #include "hyper.h"
11 namespace hr {
12 
13 // --- help ---
14 
15 const char *wormdes =
16   "These huge monsters normally live below the sand, but your movements have "
17   "disturbed them. They are too big to be slain with your "
18   "weapons, but you can defeat them by making them unable to move. "
19   "This also produces some Spice. They move two times slower than you.";
20 
21 const char *cocytushelp =
22    "This frozen lake is a hellish version of the Icy Land. Now, your body heat melts the floor, not the walls.";
23 
24 const char *tentdes =
25   "The tentacles of Cthulhu are like sandworms, but longer. "
26   "They also withdraw one cell at a time, instead of exploding instantly.";
27 
28 const char *gameboardhelp =
29   "Ever wondered how some boardgame would look on the hyperbolic plane? "
30   "I wondered about Go, so I have created this feature. Now you can try yourself!\n"
31   "Enter = pick up an item (and score), space = clear an item\n"
32   "Other keys place orbs and terrain features of various kinds\n"
33   "In the periodic editor, press 0-4 to switch walls in different ways\n"
34   ;
35 
36 const char *ivydes =
37   "A huge plant growing in the Jungle. Each Ivy has many branches, "
38   "and one branch grows per each of your moves. Branches grow in a clockwise "
39   "order. The root itself is vulnerable.";
40 
41 const char *slimehelp =
42   "The Alchemists produce magical potions from pools of blue and red slime. You "
43   "can go through these pools, but you cannot move from a blue pool to a red "
44   "pool, or vice versa. Pools containing items count as colorless, and "
45   "they change color to the PC's previous color when the item is picked up. "
46   "Slime beasts also have to keep to their own color, "
47   "but when they are killed, they explode, destroying items and changing "
48   "the color of the slime and slime beasts around them.";
49 
50 const char *gdemonhelp =
51     "These creatures are slow, but very powerful... more powerful than you. "
52     "You need some more experience in demon fighting before you will be able to defeat them. "
53     "Even then, you will be able to slay this one, but more powerful demons will come...\n\n"
54     "Each 10 lesser demons you kill, you become powerful enough to kill all the greater "
55     "demons on the screen, effectively turning them into lesser demons.";
56 
57 const char *ldemonhelp =
58     "These creatures are slow, but they often appear in large numbers.";
59 
60 const char *trollhelp =
61   "A big monster from the Living Caves. A dead Troll will be reunited "
62   "with the rocks, causing some walls to grow around its body.";
63 
64 EX const char *trollhelp2 =
65   " Additionally, all items around the killed Troll will be destroyed.";
66 
67 const char *trollhelpX =
68   "There are several species of trolls living in the hyperbolic world. "
69   "Some of them leave this wall behind them when they die.";
70 
71 const char *camelothelp =
72   "The Knights of the Round Table are the greatest warriors of these lands. "
73   "They are not very inventive with names though, as they call each of their "
74   "castles Camelot. "
75   "You are probably worthy of joining them, but they will surely give you "
76   "some quest to prove yourself...\n\n"
77   "Each castle contains a single treasure, the Holy Grail, in the center. "
78   "The radius of the Round Table is usually 28, but after you find a Holy Grail "
79   "successfully, each new castle (and each Round Table) you find will be bigger.";
80 
81 const char *templehelp =
82   "The temple of Cthulhu consists of many concentric circles of columns. "
83   "You will surely encounter many Cultists there, who believe that a pilgrimage "
84   "to the inner circles will bring them closer to Cthulhu himself, and Grimoires "
85   "which surely contain many interesting secrets.\n\n"
86   "The circles in the temple of Cthulhu are actually horocycles. They are "
87   "infinite, and there is an infinite number of them.";
88 
89 const char *barrierhelp =
90   "Huge, impassable walls which separate various lands.";
91 
92 const char *cavehelp =
93   "This cave contains walls which are somehow living. After each turn, each cell "
94   "counts the number of living wall and living floor cells around it, and if it is "
95   "currently of a different type than the majority of cells around it, it switches. "
96   "Items count as three floor cells, and dead Trolls count as five wall cells. "
97   "Some foreign monsters also count as floor or wall cells.\n";
98 
99 const char *vinehelp =
100   "The Vineyard is filled with vines. A very dense pattern of straight lines here...\n\n"
101   "Vine Beasts and Vine Spirits change vine cells to grass, and vice versa.";
102 
103 const char *hvinehelp =
104   "A vine is growing here... but only on a half of the cell. How is that even possible?!"
105   "Most monsters cannot move from this cell to the cell containing the other half. "
106   "Vine spirits can move only to the adjacent cells which are also adjacent to the "
107   "other half.";
108 
109 const char *deadcavehelp =
110   "Somehow, this cave has not received the spark of Life yet.";
111 
112 const char *foresthelp =
113   "This forest is quite dry. Beware the bushfires!\n"
114   "Trees catch fire on the next turn. The temperature of the grass cells "
115   "rises once per turn for each fire nearby, and becomes fire itself "
116   "when its temperature has risen 10 times.\n"
117   "You can also chop down the trees. Big trees take two turns to chop down.";
118 
119 const char *hivehelp =
120   "The Hive is filled with Hyperbugs. They are huge insects which look a bit like "
121   "ants, a bit like bees, and a bit like roaches. "
122   "They live in circular nests, and an army of Hyperbugs will attack any intruder, "
123   "including you and enemy Hyperbugs. Will you manage to get to the "
124   "heart of such a nest, and get the precious Royal Jelly?";
125 
126 const char *redrockhelp =
127   "This land contains high rock formations. Most of the valley is at level 0, "
128   "while items are found at level 3. It is impossible to gain two or more levels, "
129   "or to lose three levels, in a single move, (attacks are possible at any "
130   "difference, though). Kill Red Trolls and Rock Snakes to make a cell higher.";
131 
132 const char *caribbeanhelp =
133   "This dangerous sea contains nasty sharks and pirates. ";
134 
135 const char *cislandhelp =
136   "The islands of Caribbean are infinite and circular, and "
137   "the pirates probably have hidden their treasures somewhere far from the coast.";
138 
139 const char *redsnakedes =
140   "Rock snakes are similar to Sandworms, but they move each turn. However, they "
141   "only move on the hexagonal cells. They are also somewhat longer than the Sandworms.";
142 
143 const char *minedesc =
144   "This minefield has been created by the Bomberbirds to protect their valuable eggs. "
145   "Mines explode when they are stepped on, creating fire all around them "
146   "(this fire never expires in the Minefield). If you don't step on a mine, you "
147   "know the number of mines in cells around you. These numbers are marked with "
148   "color codes on the cells you have visited.";
149 
150 const char *palacedesc =
151   "So better just to concentrate on collecting treasure. "
152   "Beware the traps, and the guards, who are hard to kill!";
153 
154 const char *gatedesc =
155   "Green pressure plates open all gates in radius 3 around them. "
156   "Similarly, red pressure plates close all gates in this radius.";
157 
158 const char *princessdesc =
159   "A mouse squeaks at you. It seems that it wants you to go somewhere. "
160   "That's interesting, what could you find here?\n\n"
161   "Note: in the part of the Palace that you are exploring during this "
162   "quest, the distribution of monsters, pressure plates, and items has been "
163   "changed somewhat, to make it a bit more suitable for less "
164   "experienced players. The number of monsters does not depend on the "
165   "number of Hypersian Rugs you have collected, and there are more "
166   "opening plates.\n\n"
167   "However, even with the normal distribution, it appears that it should be "
168   "always possible to reach your goal. If you want this challenge, "
169   "select it from the special game modes menu.";
170 
171 const char *elemdesc =
172   "The Elemental Planes are divided into four subzones: Planes of Fire, Water, Air, and Earth. "
173   "You need to collect a Shard from each Plane to construct an Elemental Gem. "
174   "It is dangerous to collect too many Shards of the same type without constructing a Gem.";
175 
176 const char *wildwestdesc =
177   "Take a revolver, kill outlaws, collect bounties.\n\n"
178   "Note: since this land is anachronistic, it is not available in normal game. "
179   "It is only available in special modes.";
180 
181 const char *elecdesc =
182   "Whenever after your move there is a connection between a charged and a "
183   "grounded cell, there is a short circuit. All cells on any "
184   "path connecting a charged and a grounded cell (without repeated cells, "
185   "or two consecutive grounded/charged cells) become damaged.\n\n"
186 
187   "Sandstone walls and most creatures are conductive. Great Walls are "
188   "isolators, but lands beyond them count as grounded.\n\n"
189 
190   "Fulgurite, the treasure, is created when you manage to short circuit "
191   "a sandstone wall, or a Rich Metal Beast.\n\n"
192 
193   "Trolls leave conductive rocks when killed, and Metal Beasts can only "
194   "be killed by electricity -- your attacks only stun them, or push "
195   "them away if already stunned.";
196 
197 const char *overdesc =
198   "The Overgrown Woods are filled with mutant ivies! These plants "
199   "grow very fast. Each leaf, after being grown, can grow itself "
200   "on the next turn. However, each part is only able to grow "
201   "once in 16 turns. Outside of the Overgrown Woods, the Mutant Ivy "
202   "may grow only on hexagonal cells.\n\n"
203   "Maybe such fast growing plants could help you solve the problem "
204   "of hunger in your world? Kill the Mutant Ivies to collect Mutant Saplings.";
205 
206 const char *cleardesc =
207   "A clearing in the Overgrown Woods. Obviously, this gives "
208   "the Mutant Ivies an infinite space to grow...\n\n"
209   "Mutant Fruits rot if they are not adjacent to a Mutant Ivy.";
210 
211 const char *winddesc =
212   "Someone has put air fans in these plains, causing strong winds everywhere. "
213   "You think that the purpose is to harness the magical power of Air Elementals, but "
214   "you are not sure.\n\n"
215   "All cells except fans are grouped into three colors according to a pattern. "
216   "Wind blows counterclockwise around each group of cells of a single color. "
217   "Cells which are blocked by walls, or at distance at most 2 from an Air Elemental, "
218   "do not count for this.\n\n"
219   "It is illegal to move in a direction which is closer to incoming wind than to "
220   "outgoing wind. However, you can move two cells with the wind in a single turn, "
221   "and so can the birds.";
222 
223 const char *warningdesc =
224   "Warnings are issued when you try to do something that appears dangerous, "
225   "like stepping on a known mine, or getting your boat destroyed by "
226   "a Kraken without having Orb of the Fish. In some cases the action "
227   "might actually be safe -- so you can ignore the warning and do it anyway, "
228   "simply by repeating the action.";
229 
230 const char *hauntdesc =
231   "A dark forest filled with ghosts and graves. But there is also treasure hidden "
232   "deep within... But don't let greed make you stray from your path, as "
233   "you can get lost!\n\n"
234   "The Haunted Woods are bounded by a single equidistant curve. It is not a circle or horocycle.\n\n";
235 
236 const char *bulldashdesc =
237   "Butterflies don't pursue you -- unless you get next to them, they just spin around the obstacles. "
238   "They cannot be killed conventionally, but you get treasure when a Raging Bull crashes into a Butterfly. ";
239 
240 const char *prairiedesc =
241   "You can find safety in some places in the Prairie, but if you want treasures, "
242   "they can be found only on the other side of a giant herd of bulls.";
243 
244 const char *cadesc =
245   "A land for people wanting to experiment with cellular automata in the HyperRogue grid. "
246   "Rules can be given on the command line; the default rules are:\n"
247   "-c07 00100000 -c06 0010000 -c17 00011000 -c16 0001100 -caprob 0.3\n"
248   "(-c0 or -c1 can be given if the same rule is to be used for hexagonal "
249   "and heptagonal cells).";
250 
251 const char *huntingdesc =
252   "The Happy Hunting Ground is the place where hunting is easy; "
253   "the spirits of hunters go here after their death, if their life was deemed worthy. "
254   "You did not qualify though, so you will not ever be able to find your way to the places "
255   "where the hunter spirits and game are... "
256   "and their hunting dogs will hunt you instead!\n\n"
257   "You hope to use this to learn some "
258   "skills in fighting in open hyperbolic space, though.";
259 
260 const char *terradesc =
261   "Spending 3-5 turns next to the Terracotta Warriors will cause them to awaken. "
262   "They have 7 HP, and get stunned for longer and longer time with each attack.";
263 
264 const char *terraldesc =
265   "The Emperor's mausoleum. The army "
266   "of Terracotta Warriors is supposed to protect him in his "
267   "afterlife, while the traps are to protect the treasures "
268   "in the mausoleum from thieves.";
269 
270 const char *arrowtrapdesc =
271   "The arrow traps will automatically launch a deadly arrow when stepped on. They are quite old though, so the arrow will "
272   "actually fly at the end of the next turn.";
273 
274 const char *lavadesc =
275   "The volcanic activity in this land is extremely unstable. "
276   "Lava is too hot to walk on. It cools quickly, but another "
277   "flow will come soon...";
278 
279 const char *blizzarddesc =
280   "Once in the past there lived a tribe whose prophets warned about the great blizzard that was to come and freeze the world. "
281   "They thought it was the wrath of the gods, so they put some altars, so that the gods could hear their pleas. "
282   "The mighty golems guarded those altars, making sure nobody steals the jewels, because a robbed god is a angry god. "
283   "Unfortunately winter has come (maybe because only the monks knew how to stop the golems, and they were said to had escaped earlier with some of the jewels). "
284   "The tribe has frozen to death, altars got covered with snow and ice. Only ice golems still guard them waiting for the spring.";
285 
286 const char *crystaldesc =
287   "Yes, this is definitely a crystal. A very regular crystalline structure.\n\n"
288   "This land has been designed as a tool to play with various geometries, and it does not appear during a normal gameplay.";
289 
290 const char *NODESC = "No description yet.";
291 const char *NODESCYET = "No description yet.";
292 const char *GENDERSWITCH = NODESC;
293 
294 // --- monsters ---
295 
296 EX const char *rosedesc =
297   "Each eight turns, each rosebush at distance at most 5 from you will "
298   "release a wave of alluring scent. Creatures on the frontwave "
299   "will move towards where the scent came from. Even if it causes them "
300   "to attack their friends or beautiful creatures, or move into water, fire, chasm, or thorns of the rosebush. "
301   "Ivies, Ghosts, Rock Snakes, Rose Ladies and Lords, and monsters restricted to a specific "
302   "terrain are immune to scents.";
303 
304 EX const char *warpdesc =
305   "This part of the world is warped, restricting the movement somewhat. "
306   "\"Diagonal\" movement and attacking between triangular cells is not allowed. "
307   "Flash, Storms, and Freedom spells ignore this, and Ghosts can move, attack, and "
308   "be attacked diagonally.";
309 
310 const char *warplanddesc =
311   "This land is warped. Ironically, the coast is completely straight...";
312 
313 const char *roselanddesc =
314   "This land is filled with beautiful, but dangerous, creatures and plants.";
315 
316 const char *dragondesc =
317   "Dragons are powerful monsters. They are slow, but evil, "
318   "and love to pick on creatures who are even slower than "
319   "them. They must be stopped!\n\n"
320 
321   "A Dragon moves each two turns. It may attack with all its segments, "
322   "or move its whole body forwards or "
323   "backwards, it may also move a frontal part backwards. To kill a Dragon, "
324   "you need to hit each of its segments. "
325   "The head will regenerate on the "
326   "turns the Dragon is not moving, so you will usually have to hit it with "
327   "your last attack; otherwise, if the head is healthy, it may breathe "
328   "fire (at range 3), losing the hitpoint. Killing the Dragon "
329   "while still in the Dragon Chasms gives you treasure.";
330 
331 const char *tortoisedesc =
332   "Galápagos is the land of Tortoises. "
333   "They are very slow, which allows the Dragons to pick on them by "
334   "stealing and eating their young. Bring the Baby Tortoises back, "
335   "but, there is a catch: the Tortoises come in many varieties, depending "
336   "on the part of Galápagos they live in -- there are 21 binary environmental "
337   "factors, and thus "
338   "2097152 varieties. You'll have to find a "
339   "Tortoise which matches the baby exactly!\n\n"
340   "Tortoises move each 3 turns, and attacks only stun them.\n\n"
341   "Bringing back a Baby Tortoise counts as 5 $$$. The more factors agree in "
342   "the given location of Galápagos, the brighter it is shown on your screen.";
343 
344 const char *krakendesc =
345   "There are Krakens in your homeland, too... huge sea monsters which "
346   "could easily destroy ships. The geometry of this strange world "
347   "prevents quick movement of huge objects, "
348   "so there are no large ships, only small boats, and "
349   "hyperbolic Krakens are relatively small too. Still, you suppose they might be "
350   "the widest creatures which could still move at considerable speed...\n\n"
351 
352   "Kraken heads can move only on hexagons. You need to attack all the tentacles to "
353   "kill the Kraken. A tentacle cannot attack if it has been attacked on the "
354   "same turn. When a Kraken attacks you while you are in a boat, it "
355   "destroys the boat, but does not kill you.";
356 
357 const char *halloweendesc =
358   "Halloween is a special land, that is available only in the spherical "
359   "or elliptic geometry (press 'o' to switch). You play on the surface of "
360   "a jack-o'-lantern, "
361   "and have to collect as many Treats as possible. Each Treat you collect "
362   "brings new monsters to fight, and new magical powers for you. You "
363   "have to fight the monsters while effectively managing your limited "
364   "resources.";
365 
366 const char *reptiledesc =
367   "These reptiles are quite strange creatures. They "
368   "spend most of their lives sleeping as floors "
369   "that other creatures can walk on. "
370   "Sometimes they wake up to hunt their prey, "
371   "but they will happily go back to sleep if they "
372   "happen to move into a hole on their way. "
373   "Your attacks do not kill the Reptiles, but "
374   "you can push and stun them.";
375 
376 const char *naturedesc =
377   "This Orb allows you to grow like an Ivy. "
378   "The Ivy is always rooted in your current location; "
379   "moving among the Ivy cells will move the root. "
380   "Moving to a new location will cause the Ivy to grow "
381   ", if an Ivy could make that movement "
382   "(otherwise it breaks). "
383   "You can also target one of the cells adjacent to your ivy "
384   "(not to you) to grow or attack there.";
385 
386 const char *mirroreddesc =
387   "A perfect mirror wall. It is unbreakable "
388   "and impassable "
389   "even for aethereal beings, and everything "
390   "you see inside is just an image of "
391   "the real world; you can swing your sword "
392   "at them, but that will not destroy them "
393   "in the real world. "
394   "Mirror walls reflect Mimics, lightning bolts, and "
395   "missiles perfectly.";
396 
397 const char* tamebomberdesc =
398   "This bomberbird will follow you at some distance, and attack your enemies. "
399   "You can kill it to place a mine.";
400 
401 const char *gargdesc =
402     "A being made of stone, who likes high buildings. It becomes normal stone when "
403     "killed, but only if next to something stable -- otherwise it falls.";
404 
405 const char *lakeDesc = "Hell has these lakes everywhere... They are shaped like evil stars, and filled with burning sulphur.";
406 
407 const char *thumpdesc = "A device that attracts sandworms and other enemies. You need to activate it.";
408 
409 const char *twdesc = "This structure will disappear after some time.";
410 
411 const char *jellydesc =
412   "Some of the Slime Beasts have decided to revolt against the color rules in the "
413   "Alchemist Lab. They have changed their shape and consistency, declared independence, and established their own Kingdom.\n\n"
414   "Jellies switch between being a wall and being a monster after every treasure you collect.";
415 
416 const char *ruindesc =
417   "Once a beautiful city... but now overrun by the mighty Raiders of unknown origin.\n\n"
418   "Raiders cannot be harmed with mundane weapons, but each color has its movement restrictions.";
419 
420 const char *rock_description =
421   "Shoot the Space Rocks for score. Large Rocks will split into two smaller rocks.";
422 
423 #if HDR
424 enum eSlimegroup { sgNone, sgCave, sgWater, sgFloorA, sgFloorB, sgVine, sgTree };
425 #endif
426 
427 #if HDR
428 // we use CF not MF to avoid confusion with MF_ movement flags
429 static const flagtype CF_NOGHOST = Flag(0);
430 static const flagtype CF_RAIDER = Flag(1);
431 static const flagtype CF_PRINCESS = Flag(2);
432 static const flagtype CF_MIMIC = Flag(3);
433 static const flagtype CF_GOK = Flag(4);
434 static const flagtype CF_NONLIVING = Flag(5);
435 static const flagtype CF_METAL = Flag(6);
436 static const flagtype CF_STUNNABLE = Flag(7);
437 static const flagtype CF_HP = Flag(8);
438 static const flagtype CF_MOUNTABLE = Flag(9);
439 static const flagtype CF_FRIENDLY = Flag(10);
440 static const flagtype CF_PLAYER = Flag(11);
441 static const flagtype CF_BUG = Flag(12);
442 static const flagtype CF_IVY = Flag(13);
443 static const flagtype CF_PART = Flag(14);
444 static const flagtype CF_MUTANTIVY = Flag(15);
445 static const flagtype CF_ANYIVY = Flag(16);
446 static const flagtype CF_BULLET = Flag(17);
447 static const flagtype CF_DEMON = Flag(18);
448 static const flagtype CF_WORM = Flag(19);
449 static const flagtype CF_WITCH = Flag(20);
450 static const flagtype CF_BIRD = Flag(21);
451 static const flagtype CF_SLOWMOVER = Flag(22);
452 static const flagtype CF_MAGNETIC = Flag(23);
453 static const flagtype CF_SWITCH = Flag(24);
454 static const flagtype CF_GHOST = Flag(25);
455 static const flagtype CF_SHARK = Flag(26);
456 static const flagtype CF_SLIME = Flag(27);
457 static const flagtype CF_DRAGON = Flag(28);
458 static const flagtype CF_KRAKEN = Flag(29);
459 static const flagtype CF_NOBLOW = Flag(30);
460 static const flagtype CF_MULTITILE = Flag(31);
461 static const flagtype CF_LEADER = Flag(32);
462 static const flagtype CF_FLYING = Flag(33);
463 static const flagtype CF_ATTACK_THRU_VINE = Flag(34);
464 static const flagtype CF_ATTACK_NONADJACENT = Flag(35);
465 static const flagtype CF_NOHIGHLIGHT = Flag(36);
466 static const flagtype CF_INACTIVE = Flag(37);
467 static const flagtype CF_UNARMED = Flag(38);
468 static const flagtype CF_IGNORE_PLATE = Flag(39);
469 static const flagtype CF_BULL = Flag(40);
470 static const flagtype CF_TROLL = Flag(41);
471 static const flagtype CF_IGNORE_SMELL = Flag(42);
472 static const flagtype CF_RATLING = Flag(43);
473 static const flagtype CF_POWER = Flag(44);
474 static const flagtype CF_GHOSTMOVER = Flag(45);
475 static const flagtype CF_TECHNICAL = Flag(46);
476 static const flagtype CF_MOVED = Flag(47);
477 static const flagtype CF_FACING = Flag(48);
478 static const flagtype CF_FACE_UP = Flag(49);
479 static const flagtype CF_FACE_SIDE = Flag(50);
480 static const flagtype CF_HIGH_THREAT = Flag(51);
481 static const flagtype CF_SPAM = Flag(52);
482 
483 enum eMonster {
484   #define MONSTER(a,b,c,d,e,f,g,h) d,
485   #include "content.cpp"
486   motypes
487   };
488 
489 struct monstertype {
490   char  glyph;
491   color_t color;
492   const char *name;
493   flagtype flags;
494   enum eMonster mgroup;
495   const char *help;
496   };
497 #endif
498 
499 EX monstertype minf[motypes] = {
500   #define MONSTER(a,b,c,d,e,f,g,h) {a,b,c,e,g,h},
501   #include "content.cpp"
502   };
503 
504 #if HDR
505 #define NUM_GS 8
506 struct genderswitch_t {
507   int gender;
508   eMonster m;
509   const char *name;
510   const char *desc;
511   };
512 #endif
513 
514 EX genderswitch_t genderswitch[NUM_GS] = {
515   { GEN_F, moFalsePrincess, "False Princess",
516      "Don't be fooled by this red-haired girl, or you will be stabbed if you come too close!"},
517   { GEN_M, moFalsePrincess, "False Prince",
518     "Don't be fooled by this red-haired boy, or you will be stabbed if you come too close!"},
519   { GEN_F, moRoseLady,      "Rose Lady",
520     "This false princess is immune to the alluring scent of roses."},
521   { GEN_M, moRoseLady,      "Rose Lord",
522     "This false prince is immune to the alluring scent of roses."},
523   { GEN_F, moRoseBeauty,    "Rose Beauty",
524     "She has flowers in her long fair hair. You could not bring yourself to attack such a beautiful woman."},
525   { GEN_M, moRoseBeauty,    "Handsome Gardener",
526     "Tall, strong, and holding a flower in his hand. You could "
527     "not bring yourself to attack such a handsome man."},
528   { GEN_F, moRusalka,       "Rusałka",
529     "A malicious water being. When you kill her, she changes the tile you are standing on, from land to shallow water, or from shallow water to deep water."},
530   { GEN_M, moRusalka,       "Topielec",
531     "A malicious water being. When you kill him, he changes the tile you are standing on, from land to shallow water, or from shallow water to deep water."},
532   };
533 
534 // --- items ---
535 
536 #if HDR
537 enum eOrbshape { osNone, osLove, osRanged, osOffensive, osFriend, osUtility, osDirectional, osWarping, osFrog, osPowerUtility, osProtective, osMovement, osTerraform };
538 
539 static const flagtype ZERO = 0;
540 
541 static const flagtype IF_SHARD = Flag(0);
542 static const flagtype IF_FIREPROOF = Flag(1);
543 static const flagtype IF_PROTECTION = Flag(2);
544 static const flagtype IF_EMPATHY = Flag(3);
545 static const flagtype IF_RANGED = Flag(4);
546 static const flagtype IF_SHMUPLIFE = Flag(5);
547 static const flagtype IF_REVIVAL = Flag(6);
548 static const flagtype IF_CURSE = Flag(7);
549 
550 // 0 = basic treasure, 1 = other item, 2 = power orb, 3 = not an item
551 #define IC_TREASURE 0
552 #define IC_OTHER 1
553 #define IC_ORB 2
554 #define IC_NAI 3
555 
556 struct itemtype {
557   char  glyph;
558   color_t color;
559   const char *name;
560   int itemclass;
561   flagtype flags;
562   eOrbshape orbshape;
563   const char *help;
564   };
565 
566 enum eItem {
567   #define ITEM(a,b,c,d,e,f,g,h,i) d,
568   #include "content.cpp"
569   ittypes
570   };
571 #endif
572 
573 EX itemtype iinf[ittypes] = {
574   #define ITEM(a,b,c,d,e,f,g,h,i) {a,b,c,e,f,h,i},
575   #include "content.cpp"
576   };
577 
578 // --- wall types ---
579 
580 #if HDR
581 static const flagtype WF_WATER = Flag(0);
582 static const flagtype WF_BOAT = Flag(1);
583 static const flagtype WF_CHASM = Flag(2);
584 static const flagtype WF_NOFLIGHT = Flag(3);
585 static const flagtype WF_FIRE = Flag(4);
586 static const flagtype WF_THUMPER = Flag(5);
587 static const flagtype WF_ACTIVABLE = Flag(6);
588 static const flagtype WF_ALCHEMY = Flag(7);
589 static const flagtype WF_RED = Flag(8);
590 static const flagtype WF_WALL = Flag(9);
591 static const flagtype WF_PUSHABLE = Flag(10);
592 static const flagtype WF_CONE = Flag(11);
593 static const flagtype WF_STDTREE = Flag(12);
594 static const flagtype WF_GRAVE = Flag(13);
595 static const flagtype WF_REPTILE = Flag(14);
596 static const flagtype WF_HEATCOLOR = Flag(15);
597 static const flagtype WF_HIGHWALL = Flag(16);
598 static const flagtype WF_THORNY = Flag(17);
599 static const flagtype WF_TIMEOUT = Flag(18);
600 static const flagtype WF_CISLAND = Flag(19);
601 static const flagtype WF_SULPHURIC = Flag(20);
602 static const flagtype WF_HALFVINE = Flag(21);
603 
604 struct walltype {
605   char  glyph;
606   color_t color;
607   const char *name;
608   flagtype flags;
609   int snakelevel;
610   eSlimegroup sg;
611   const char *help;
612   };
613 
614 enum eWall {
615   #define WALL(a,b,c,d,e,f,g,h,i) d,
616   #include "content.cpp"
617   walltypes
618   };
619 #endif
620 
621 EX walltype winf[walltypes] = {
622   #define WALL(a,b,c,d,e,f,g,h,i) {a,b,c,e,g,h,i},
623   #include "content.cpp"
624   };
625 
626 // -- land types ---
627 
628 #if HDR
629 static const flagtype LF_GENERATE_ALL = Flag(0);
630 static const flagtype LF_ICY = Flag(1);
631 static const flagtype LF_GRAVITY = Flag(2);
632 static const flagtype LF_EQUI = Flag(3);
633 static const flagtype LF_WARPED = Flag(4);
634 static const flagtype LF_CYCLIC = Flag(5);
635 static const flagtype LF_TECHNICAL = Flag(6);
636 static const flagtype LF_MIRROR = Flag(7);
637 static const flagtype LF_SEA = Flag(8);
638 static const flagtype LF_COASTAL = Flag(9);
639 static const flagtype LF_PURESEA = Flag(10);
640 static const flagtype LF_ELEMENTAL = Flag(11);
641 static const flagtype LF_HAUNTED = Flag(12);
642 static const flagtype LF_TROLL = Flag(13);
643 static const flagtype LF_INMIRROR = Flag(14);
644 static const flagtype LF_INMIRRORORWALL = Flag(15);
645 static const flagtype LF_ELECTRIC = Flag(17);
646 
647 struct landtype {
648   color_t color;
649   const char *name;
650   flagtype flags;
651   eItem treasure;
652   const char *help;
653   };
654 
655 enum eLand {
656   #define LAND(a,b,c,d,e,f,g) c,
657   #include "content.cpp"
658   landtypes
659   };
660 
661 extern color_t floorcolors[landtypes];
662 #endif
663 
664 EX const landtype linf[landtypes] = {
665   #define LAND(a,b,c,d,e,f,g) {a,b,d,e,g},
666   #include "content.cpp"
667   };
668 
669 #if HDR
670 struct landtacinfo { eLand l; int tries, multiplier; };
671 #endif
672 
673 EX vector<landtacinfo> land_tac = {
674   {laIce, 10, 1}, {laDesert, 10, 1},
675   {laHunting, 5, 2},
676   {laMotion, 10, 1}, {laCaves, 10, 1}, {laAlchemist, 10, 1},
677   {laJungle, 10, 1}, {laMirror, 10, 1}, {laZebra, 10, 1}, {laPalace, 10, 1},
678   {laOcean, 10, 1}, {laLivefjord, 10, 1}, {laWarpCoast, 10, 1}, {laRlyeh, 10, 1}, {laHell, 10, 1},
679   {laDryForest, 10, 1}, {laWineyard, 10, 1}, {laSwitch, 10, 1}, {laReptile, 10, 1},
680   {laDeadCaves, 10, 1}, {laGraveyard, 10, 1},
681   {laHaunted, 10, 1},
682   {laIvoryTower, 10, 1}, {laEndorian, 10, 1}, {laMountain, 5, 2}, {laDungeon, 5, 2},
683   {laRuins, 10, 1}, {laEmerald, 10, 1},
684   {laCocytus, 10, 1},
685 
686   {laCaribbean, 5, 2}, {laWhirlpool, 5, 2}, {laKraken, 5, 2},
687   {laTemple, 5, 2}, {laMinefield, 5, 2},
688   {laPower, 5, 2}, {laHive, 5, 2}, {laRedRock, 5, 2}, {laStorms, 5, 2}, {laOvergrown, 5, 2},
689   {laClearing, 5, 2},
690   {laWhirlwind, 5, 2},
691   {laBlizzard, 10, 1},
692   {laRose, 5, 2}, {laVolcano, 10, 1}, {laDragon, 2, 5}, {laTortoise, 1, 10},
693   {laBurial, 5, 2},
694   {laElementalWall, 10, 1}, {laTrollheim, 5, 2},
695   {laPrairie, 5, 2}, {laBull, 5, 2}, {laTerracotta, 10, 1},
696   {laDice, 5, 2}, {laCursed, 5, 2},
697 
698   {laCrossroads, 10, 1}, {laCrossroads2, 10, 1}, {laCrossroads3, 10, 1}, {laCrossroads4, 10, 1}, {laCrossroads5, 5, 2},
699 
700   {laCamelot, 1, 100},
701   {laWildWest, 10, 1},
702   {laDual, 10, 1},
703   {laSnakeNest, 10, 1},
704   {laDocks, 10, 1},
705 
706   {laBrownian, 10, 1},
707   {laVariant, 10, 1},
708   {laWestWall, 10, 1},
709   {laWet, 10, 1}, {laFrog, 10, 1}, {laEclectic, 10, 1},
710   };
711 
712 EX vector<eLand> randlands = {
713   laIce, laDesert, laCaves, laAlchemist, laGraveyard, laPower, laLivefjord, laZebra,
714   laRlyeh, laDryForest, laEmerald, laWineyard, laDeadCaves, laRedRock,
715   laOvergrown, laWildWest, laWarpCoast, laRuins, laBull, laDragon, laReptile, laDocks,
716   laFrog, laWet, laZebra
717   };
718 
719 #if HDR
720 enum eGeometry {
721   gNormal, gEuclid, gSphere, gElliptic, gZebraQuotient, gFieldQuotient, gTorus, gOctagon, g45, g46, g47, gSmallSphere, gTinySphere, gEuclidSquare, gSmallElliptic,
722   gKleinQuartic, gBolza, gBolza2, gMinimal, gBinaryTiling, gArchimedean,
723   gMacbeath, gBring, gSchmutzM2, gSchmutzM3, gCrystal, gOctahedron,
724   gBinary3, gCubeTiling, gCell120, gECell120, gRhombic3, gBitrunc3,
725   gSpace534, gSpace435,
726   gCell5,
727   gCell16, gECell16,
728   gCell8, gECell8,
729   gCell24, gECell24,
730   gCell600, gECell600,
731   gHoroTris, gHoroRec, gHoroHex,
732   gField435, gField534,
733   gBinary4, gSol,
734   gKiteDart2, gKiteDart3, gNil, gProduct, gRotSpace,
735   gTernary, gNIH, gSolN, gInfOrder, gSpace336, gSpace344, gCrystal344,
736   gArnoldCat, gArbitrary, gInfOrder4, gCrystal534,
737   gSpace535, gSpace536, gSeifertCover, gSeifertWeber, gHomologySphere,
738   gInfOrderMixed, gSpace436, gFake,
739   gSpace345, gSpace353, gSpace354, gSpace355,
740   gGUARD};
741 
742 enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSolNIH, gcNil, gcProduct, gcSL2 };
743 
744 enum class eVariation { bitruncated, pure, goldberg, irregular, dual, untruncated, warped, unrectified, subcubes, coxeter, dual_subcubes, bch, bch_oct };
745 
746 typedef int modecode_t;
747 
748 /** only the actual geometry */
749 struct geometryinfo1 {
750   /** geometry class */
751   eGeometryClass kind;
752   /** dimension of the gameplay (2 for crystal) */
753   int gameplay_dimension;
754   /** dimension of the graphics, may be greater than gameplay_dimension with vid.always3 on */
755   int graphical_dimension;
756   /** dimension of the homogeneous vector space used, usually graphical_dimension+1, but 3 in product */
757   int homogeneous_dimension;
758   /** signature of the scalar product used */
759   int sig[4];
760   };
761 
762 struct geometryinfo {
763   std::string tiling_name;
764   std::string quotient_name;
765   const char* menu_displayed_name;
766   const char* shortname;
767   int sides;
768   int vertex;
769   flagtype flags;
770   geometryinfo1 g;
771   std::array<int,2> distlimit; // bitrunc, non-bitrunc
772   eVariation default_variation;
773   };
774 
775 static const flagtype qBOUNDED         = 1;
776 static const flagtype qANYQ            = 2;
777 static const flagtype qNONORIENTABLE   = 4;
778 static const flagtype qSMALL           = 8;
779 
780 static const flagtype qFIELD           = 16;
781 static const flagtype qDOCKS           = 32;
782 static const flagtype qZEBRA           = 64;
783 
784 static const flagtype qELLIPTIC        = 128;
785 
786 static const flagtype qBINARY          = 256;
787 static const flagtype qKITE            = 512;
788 
789 static const flagtype qREGULAR         = 1024; /* not set! */
790 static const flagtype qARCHI           = 2048;
791 static const flagtype qHYBRID          = 4096;
792 static const flagtype qCRYSTAL         = 8192;
793 static const flagtype qSOL             = 16384;
794 static const flagtype qEXPERIMENTAL    = 32768;
795 static const flagtype qNIH             = 65536;
796 
797 static const flagtype qIDEAL           = 131072;
798 static const flagtype qHUGE_BOUNDED    = 262144;
799 static const flagtype qOPTQ            = Flag(19);
800 static const flagtype qSINGLE          = Flag(20);
801 
802 static const flagtype qDEPRECATED      = Flag(21);
803 static const flagtype qINFMIXED        = Flag(22);
804 
805 static const flagtype qRAYONLY         = Flag(23);
806 static const flagtype qAFFINE          = Flag(24);
807 
808 static const flagtype qULTRA           = Flag(25);
809 
810 static const flagtype qPORTALSPACE     = Flag(26);
811 
812 static const flagtype qSTRETCHABLE     = Flag(27);
813 
814 static const flagtype qCAT             = Flag(28);
815 
816 // note: dnext assumes that x&7 equals 7
817 static const int SEE_ALL = 50;
818 static const int OINF = 100;
819 
820 extern eGeometry geometry;
821 extern eVariation variation;
822 #endif
823 
824 static const flagtype qsNONOR           = qANYQ | qSMALL | qBOUNDED | qNONORIENTABLE;
825 static const flagtype qsNONORE          = qsNONOR | qELLIPTIC;
826 static const flagtype qsBQ              = qANYQ | qSMALL | qBOUNDED;
827 static const flagtype qsSMALL           = qANYQ | qSMALL | qBOUNDED;
828 static const flagtype qsSMALLN          = qANYQ | qSMALL | qBOUNDED | qNONORIENTABLE;
829 static const flagtype qsZEBRA           = qANYQ | qSMALL | qBOUNDED | qZEBRA;
830 static const flagtype qsFIELD           = qANYQ | qFIELD | qBOUNDED;
831 static const flagtype qsDOCKS           = qANYQ | qSMALL | qBOUNDED | qDOCKS;
832 static const flagtype qsSMALLB          = qSMALL | qBOUNDED;
833 static const flagtype qsSMALLBF         = qsSMALLB | qsFIELD | qANYQ;
834 static const flagtype qsSMALLBE         = qsSMALLB | qELLIPTIC | qANYQ;
835 static const flagtype qsBP              = qBINARY | qKITE;
836 
837 static const flagtype qsSINGLE          = qANYQ | qSMALL | qBOUNDED | qSINGLE;
838 
839 EX geometryinfo1 giEuclid2 = { gcEuclid,     2, 2, 3, {1,1, 0,0 } };
840 EX geometryinfo1 giHyperb2 = { gcHyperbolic, 2, 2, 3, {1,1,-1,0 } };
841 EX geometryinfo1 giSphere2 = { gcSphere,     2, 2, 3, {1,1,+1,0 } };
842 
843 EX geometryinfo1 giEuclid3 = { gcEuclid,     3, 3, 4, {1,1, 1,0 } };
844 EX geometryinfo1 giHyperb3 = { gcHyperbolic, 3, 3, 4, {1,1, 1,-1} };
845 EX geometryinfo1 giSphere3 = { gcSphere,     3, 3, 4, {1,1, 1,+1} };
846 
847 EX geometryinfo1 giSolNIH  = { gcSolNIH,     3, 3, 4, {1,1, 1,0 } };
848 EX geometryinfo1 giNil     = { gcNil,        3, 3, 4, {1,1, 1,0 } };
849 EX geometryinfo1 giProduct = { gcSL2,        3, 3, 4, {1,1, 1,0 } /* will be filled in product::configure() */ };
850 EX geometryinfo1 giSL2     = { gcSL2,        3, 3, 4, {1,1,-1,-1} };
851 
852 EX modecode_t no_code = 0x1;
853 
854 /** list of available geometries */
855 EX vector<geometryinfo> ginf = {
856   {"{7,3}", "none",     "{7,3} (standard HyperRogue map)",            "HR",       7, 3, 0,         giHyperb2, {{7, 5}}, eVariation::bitruncated},
857   {"{6,3}", "none",     "{6,3} (euclidean Hex grid)",                 "euclid",   6, 3, qOPTQ,     giEuclid2, {{7, 7}}, eVariation::bitruncated},
858   {"{5,3}", "none",     "{5,3} (dodecahedron)",                       "sphere",   5, 3, qsSMALLB,  giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated},
859   {"{5,3}", "elliptic", "elliptic geometry in {5,3}",                 "elliptic", 5, 3, qsNONORE,  giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated},
860   {"{7,3}", "Zebra",    "Zebra quotient",                             "Zebra",    7, 3, qsZEBRA,   giHyperb2, {{7, 5}}, eVariation::bitruncated},
861   {"{7,3}", "field",    "field quotient",                             "field",    7, 3, qsFIELD,   giHyperb2, {{7, 5}}, eVariation::bitruncated},
862   {"{6,3}", "torus",    "torus/Klein bottle/...",                     "torus",    6, 3, qsBQ|qDEPRECATED,      giEuclid2, {{7, 7}}, eVariation::bitruncated},
863   {"{8,3}", "none",     "{8,3} (like standard but with octagons)",    "oct",      8, 3, 0,         giHyperb2, {{6, 4}}, eVariation::bitruncated},
864   {"{5,4}", "none",     "{5,4} (four pentagons)",                     "4x5",      5, 4, 0,         giHyperb2, {{6, 4}}, eVariation::bitruncated},
865   {"{6,4}", "none",     "{6,4} (four hexagons)",                      "4x6",      6, 4, 0,         giHyperb2, {{5, 3}}, eVariation::bitruncated},
866   {"{7,4}", "none",     "{7,4} (four heptagons)",                     "4x7",      7, 4, 0,         giHyperb2, {{4, 3}}, eVariation::bitruncated},
867   {"{4,3}", "none",     "{4,3} (cube)",                               "3x4",      4, 3, qsSMALLB,  giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated},
868   {"{3,3}", "none",     "{3,3} (tetrahedron)",                        "3x3",      3, 3, qsSMALLB,  giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated},
869   {"{4,4}", "none",     "{4,4} (Euclidean square grid)",              "4x4",      4, 4, qOPTQ,     giEuclid2, {{7, 7}}, eVariation::bitruncated},
870   {"{4,3}", "elliptic", "elliptic geometry in {4,3}",                 "e3x4",     4, 3, qsNONORE,  giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated},
871   {"{7,3}", "Klein",    "Klein Quartic",                              "Klein",    7, 3, qsSMALL,   giHyperb2, {{7, 5}}, eVariation::bitruncated},
872   {"{8,3}", "Bolza",    "Bolza Surface",                              "Bolza",    8, 3, qsDOCKS,   giHyperb2, {{6, 4}}, eVariation::bitruncated},
873   {"{8,3}", "Bolza2",   "Bolza Surface x2",                           "Bolza2",   8, 3, qsDOCKS,   giHyperb2, {{6, 4}}, eVariation::bitruncated},
874   {"{7,3}", "minimal",  "minimal quotient",                           "minimal",  7, 3, qsSMALLN,  giHyperb2, {{7, 5}}, eVariation::bitruncated},
875   {"binary","none",     "variant of the binary tiling",               "binary",   7, 3, qBINARY,   giHyperb2, {{7, 5}}, eVariation::pure},
876   {"Arch",  "none",     "Archimedean",                                "A",        7, 3, qARCHI,    giHyperb2, {{7, 5}}, eVariation::pure},
877   {"{7,3}", "Macbeath", "Macbeath Surface",                           "Macbeath", 7, 3, qsSMALL,   giHyperb2, {{7, 5}}, eVariation::bitruncated},
878   {"{5,4}", "Bring",    "Bring's Surface",                            "Bring",    5, 4, qsSMALL,   giHyperb2, {{6, 4}}, eVariation::bitruncated},
879   {"{12,3}","M3",       "Schmutz's M(3)",                             "M3",      12, 3, qsSMALL,   giHyperb2, {{4, 2}}, eVariation::bitruncated},
880   {"{12,3}","M4",       "Schmutz's M(4)",                             "M4",      12, 3, qsSMALL,   giHyperb2, {{4, 2}}, eVariation::bitruncated},
881   {"{6,4}", "Crystal",  "dimensional crystal",                        "Crystal",  6, 4, qANYQ|qCRYSTAL, giHyperb2, {{5, 3}}, eVariation::pure},
882   {"{3,4}", "none",     "{3,4} (octahedron)",                         "4x3",      3, 4, qsSMALLB,  giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated},
883   {"bin{4,4}",  "none", "{4,4} on horospheres",                       "bin44",    9, 3, qBINARY,   giHyperb3, {{7, 3}}, eVariation::pure},
884   {"{4,3,4}","none",    "{4,3,4} cube tiling",                        "434",      6, 4, qOPTQ,     giEuclid3, {{7, 5}}, eVariation::pure},
885   {"{5,3,3}","none",    "{5,3,3} 120-cell",                           "533",     12, 3, qsSMALLB | qSTRETCHABLE,  giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
886   {"{5,3,3}", "elliptic","{5,3,3} 120-cell (elliptic space)",         "e533",    12, 3, qsSMALLBE | qSTRETCHABLE, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
887   {"rh{4,3,4}","none",  "rhombic dodecahedral honeycomb",             "rh434",   12, 3, qOPTQ,     giEuclid3, {{7, 5}}, eVariation::pure},
888   {"2t{4,3,4}","none",  "bitruncated cubic honeycomb",                "2t434",   14, 3, qOPTQ,     giEuclid3, {{7, 5}}, eVariation::pure},
889   {"{5,3,4}","none",    "{5,3,4} hyperbolic honeycomb",               "534",     12, 4, 0,         giHyperb3, {{7, 2}}, eVariation::pure},
890   {"{4,3,5}","none",    "{4,3,5} hyperbolic honeycomb",               "435",      6, 5, 0,         giHyperb3, {{7, 2}}, eVariation::pure},
891   {"{3,3,3}","none",    "{3,3,3} 5-cell",                             "333",      4, 3, qsSMALLB,  giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
892   {"{3,3,4}","none",    "{3,3,4} 16-cell",                            "334",      4, 4, qsSMALLB,  giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
893   {"{3,3,4}","elliptic","{3,3,4} 16-cell (elliptic space)",           "e334",     4, 4, qsSMALLBE, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
894   {"{4,3,3}","none",    "{4,3,3} 8-cell",                             "433",      6, 4, qsSMALLB | qSTRETCHABLE,  giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
895   {"{4,3,3}","elliptic","{4,3,3} 8-cell (elliptic space)",            "e433",     6, 4, qsSMALLBE | qSTRETCHABLE, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
896   {"{3,4,3}","none",    "{3,4,3} 24-cell",                            "343",      8, 3, qsSMALLB | qSTRETCHABLE,  giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
897   {"{3,4,3}","elliptic","{3,4,3} 24-cell (elliptic space)",           "e343",     8, 3, qsSMALLBE | qSTRETCHABLE, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
898   {"{3,3,5}","none",    "{3,3,5} 600-cell",                           "335",      4, 3, qsSMALLB,  giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
899   {"{3,3,5}","elliptic","{3,3,5} 600-cell (elliptic space)",          "e335",     4, 3, qsSMALLBE, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
900   {"bin{3,6}", "none",  "{3,6} on horospheres",                       "bin36",    8, 3, qBINARY,   giHyperb3, {{7, 3}}, eVariation::pure},
901   {"bin-rect", "none",  "rectangles on horospheres",                  "bin44/2",  7, 3, qBINARY,   giHyperb3, {{7, 3}}, eVariation::pure},
902   {"bin{6,3}", "none",  "{6,3} on horospheres",                       "bin63",   14, 3, qBINARY,   giHyperb3, {{7, 3}}, eVariation::pure},
903   {"{4,3,5}","field",   "{4,3,5} field quotient space",               "f435",     6, 5, qsSMALLBF | qDEPRECATED, giHyperb3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
904   {"{5,3,4}","field",   "{5,3,4} field quotient space",               "f435",    12, 4, qsSMALLBF | qDEPRECATED, giHyperb3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
905   {"binary4","none",    "standard binary tiling",                     "binary4",  5, 3, qBINARY,   giHyperb2, {{7, 5}}, eVariation::pure},
906   {"sol",    "none",    "Solv geometry",                              "sol",      8, 3, qBINARY|qSOL,   giSolNIH, {{7, 5}}, eVariation::pure},
907   {"kd2",    "none",    "kite-and-dart",                              "kd2",      4, 3, qKITE,     giEuclid2, {{7, 7}}, eVariation::pure},
908   {"kd3",    "none",    "kite-and-dart on horospheres",               "kd3",     12, 3, qsBP,      giHyperb3, {{7, 3}}, eVariation::pure},
909   {"nil",    "none",    "Nil geometry",                               "nil",      6, 3, qOPTQ,     giNil,     {{7, 5}}, eVariation::pure},
910   {"product","none",    "product space",                              "product",  7, 3, qHYBRID,   giProduct, {{7, 3}}, eVariation::pure},
911   {"twisted","none",    "rotation space",                             "twisted",  7, 3, qHYBRID,   giSL2,     {{6, 4}}, eVariation::pure},
912   {"ternary","none",    "standard ternary tiling",                    "ternary",  6, 3, qBINARY,   giHyperb2, {{6, 4}}, eVariation::pure},
913   {"3x2",    "none",    "stretched hyperbolic",                       "3:2",     11, 3, qBINARY|qNIH,   giSolNIH,  {{6, 3}}, eVariation::pure},
914   {"3x1/2",  "none",    "stretched Solv",                             "3:1/2",    9, 3, (qBINARY|qSOL|qNIH),   giSolNIH,  {{7, 3}}, eVariation::pure},
915   {"{3,oo}", "none",    "{3,∞} (infinite triangles)",                 "oox3",     3, OINF, qIDEAL,  giHyperb2, {{7, 7}}, eVariation::pure},
916   {"{3,3,6}","none",    "{3,3,6} hyperbolic honeycomb",               "336",      4, 6, qIDEAL,    giHyperb3, {{7, 2}}, eVariation::pure},
917   {"{3,4,4}","none",    "{3,4,4} hyperbolic honeycomb",               "344",      8, 4, qIDEAL,    giHyperb3, {{7, 2}}, eVariation::pure},
918   {"{3,4,4}","Crystal", "4D crystal in H3",                           "Cryst3" ,  8, 4, qIDEAL | qANYQ | qCRYSTAL, giHyperb3, {{7, 3}}, eVariation::pure},
919   {"cat",    "cat",     "Arnold's cat mapping torus",                 "cat",     12, 3, qBINARY | qSOL | qsBQ | qOPTQ | qCAT, giSolNIH, {{6, 4}}, eVariation::pure},
920   {"file",   "none",    "load from file",                             "file",     7, 3, 0,  giEuclid2, {{7, 5}}, eVariation::pure},
921   {"{4,oo}", "none",    "{4,∞} (infinite squares)",                   "oox4",     4, OINF, qIDEAL,  giHyperb2, {{5, 5}}, eVariation::pure},
922   {"{5,3,4}","Crystal", "6D crystal in H3",                           "Cryst6" , 12, 4, qANYQ | qCRYSTAL, giHyperb3, {{7, 3}}, eVariation::pure},
923   {"{5,3,5}","none",    "{5,3,5} hyperbolic honeycomb",               "535",     12, 5, 0,         giHyperb3, {{7, 2}}, eVariation::pure},
924   {"{5,3,6}","none",    "{5,3,6} hyperbolic honeycomb",               "536",     12, 6, qIDEAL,    giHyperb3, {{7, 2}}, eVariation::pure},
925   {"{5,3,5}","SWh",     "{5,3,5} quotient",                           "535c",    12, 5, qsSMALLB | qANYQ, giHyperb3, {{7, 2}}, eVariation::pure},
926   {"{5,3,5}","SW",      "Seifert-Weber space",                        "535s",    12, 5, qsSINGLE,  giHyperb3, {{7, 2}}, eVariation::pure},
927   {"{5,3,3}","SW",      "Poincaré homology sphere",                   "533s",    12, 3, qsSINGLE,  giSphere3, {{7, 2}}, eVariation::pure},
928   {"{?,oo}", "none",    "{3/4,∞} (infinite triangles and squares)",   "ooxm",     3, OINF, qIDEAL | qINFMIXED,  giHyperb2, {{6, 6}}, eVariation::pure},
929   {"{4,3,6}","none",    "{4,3,6} hyperbolic honeycomb",               "436",      6, 6, qIDEAL,    giHyperb3, {{7, 2}}, eVariation::pure},
930   {"?",      "none",    "fake",                                       "",         0, 0, qRAYONLY,  giHyperb3, {{7, 2}}, eVariation::pure},
931   {"{3,4,5}","none",    "{3,4,5} hyperbolic honeycomb",               "345",      8, 5, qIDEAL | qULTRA,    giHyperb3, {{7, 2}}, eVariation::pure},
932   {"{3,5,3}","none",    "{3,5,3} hyperbolic honeycomb",               "353",     20, 5, 0,         giHyperb3, {{7, 2}}, eVariation::pure},
933   {"{3,5,4}","none",    "{3,5,4} hyperbolic honeycomb",               "354",     20, 5, qIDEAL | qULTRA,    giHyperb3, {{7, 2}}, eVariation::pure},
934   {"{3,5,5}","none",    "{3,5,5} hyperbolic honeycomb",               "355",     20, 5, qIDEAL | qULTRA,    giHyperb3, {{7, 2}}, eVariation::pure},
935   };
936   // bits: 9, 10, 15, 16, (reserved for later) 17, 18
937 
938 #if HDR
939 namespace mf {
940   static const flagtype azimuthal = 1;
941   static const flagtype cylindrical = 2;
942   static const flagtype equiarea = 4;
943   static const flagtype equidistant = 8;
944   static const flagtype conformal = 16;
945   static const flagtype euc_boring = 32;
946   static const flagtype space = 64;
947   static const flagtype hyper_only = 128;
948   static const flagtype hyper_or_torus = 256;
949   static const flagtype pseudocylindrical = 512; /* includes cylindrical */
950   static const flagtype equivolume = 1024;
951   static const flagtype twopoint = 2048;
952   static const flagtype uses_bandshift = 4096;
953   static const flagtype broken = 8192; /* in spherical case, these are broken along the meridian 180 deg */
954 
955   static const flagtype band = (cylindrical | pseudocylindrical | uses_bandshift);
956   static const flagtype pseudoband = (pseudocylindrical | uses_bandshift);
957   }
958 
959 struct modelinfo {
960   const char *name_hyperbolic;
961   const char *name_euclidean;
962   const char *name_spherical;
963 
964   flagtype flags;
965 
966   int is_azimuthal;
967   int is_band;
968   int is_equiarea;
969   int is_equidistant;
970   int is_conformal;
971   const char* name;
972   };
973 
974 enum eModel : int {
975   mdDisk, mdHalfplane, mdBand, mdPolygonal, mdFormula,
976   // 5..8.
977   mdEquidistant, mdEquiarea, mdBall, mdHyperboloid,
978   // 9..13
979   mdHemisphere, mdBandEquidistant, mdBandEquiarea, mdSinusoidal, mdTwoPoint,
980   // 14..16
981   mdFisheye, mdJoukowsky, mdJoukowskyInverted,
982   // 17..19
983   mdRotatedHyperboles, mdSpiral, mdPerspective,
984   // 20..24
985   mdEquivolume, mdCentralInversion, mdSimulatedPerspective, mdTwoHybrid, mdGeodesic,
986   // 25..27
987   mdMollweide, mdCentralCyl, mdCollignon,
988   // 28..31
989   mdHorocyclic, mdQuadrant, mdAxial, mdAntiAxial,
990   // 32..38
991   mdWerner, mdAitoff, mdHammer, mdLoximuthal, mdMiller, mdGallStereographic, mdWinkelTripel,
992   // 39..
993   mdPoorMan, mdPanini, mdRetroCraig, mdRetroLittrow, mdRetroHammer, mdThreePoint,
994   // 45..
995   mdGUARD, mdPixel, mdHyperboloidFlat, mdPolynomial, mdManual
996   };
997 #endif
998 
999 // remember to match the following mask when specifying codes for extra geometries: 0x78600
1000 // (other bits are used for other information)
1001 
1002 #define X3(x) x, x, x
1003 #define DEFAULTS 0, 0, 0, 0, 0, nullptr
1004 
1005 /** list of available models (i.e., projections) */
1006 EX vector<modelinfo> mdinf = {
1007   {"disk/Gans", "general perspective", "general perspective", mf::azimuthal | mf::conformal, DEFAULTS},
1008   {"half-plane", "inversion", "stereographic projection [VR]", mf::conformal, DEFAULTS},
1009   {"band", "band", "Mercator", mf::band | mf::conformal, DEFAULTS},
1010   {X3("polygonal"), mf::conformal, DEFAULTS},
1011   {X3("formula"), 0, DEFAULTS},
1012   {X3("azimuthal equidistant"), mf::azimuthal | mf::equidistant | mf::euc_boring, DEFAULTS},
1013   {X3("azimuthal equi-area"), mf::azimuthal | mf::equiarea | mf::euc_boring, DEFAULTS},
1014   {X3("ball model"), mf::conformal | mf::azimuthal | mf::space, DEFAULTS},
1015   {"Minkowski hyperboloid", "plane", "sphere", mf::conformal | mf::space | mf::euc_boring, DEFAULTS},
1016   {"hemisphere", "sphere", "sphere", mf::conformal | mf::space, DEFAULTS},
1017   {X3("band equidistant"), mf::band | mf::equidistant | mf::euc_boring, DEFAULTS},
1018   {X3("band equi-area"), mf::band | mf::equiarea | mf::euc_boring, DEFAULTS},
1019   {X3("sinusoidal"), mf::pseudoband | mf::equiarea | mf::euc_boring, DEFAULTS},
1020   {X3("two-point equidistant"), mf::equidistant | mf::euc_boring | mf::twopoint, DEFAULTS},
1021   {X3("fisheye"), 0, DEFAULTS},
1022   {X3("Joukowsky transform"), mf::hyper_only | mf::conformal, DEFAULTS},
1023   {X3("Joukowsky+inversion"), mf::hyper_only | mf::conformal, DEFAULTS},
1024   {X3("rotated hyperboles"), mf::hyper_only, DEFAULTS},
1025   {X3("spiral/ring"), mf::hyper_or_torus | mf::uses_bandshift, DEFAULTS},
1026   {X3("native perspective"), 0, DEFAULTS},
1027   {X3("azimuthal equi-volume"), mf::azimuthal | mf::equivolume | mf::euc_boring, DEFAULTS},
1028   {X3("central inversion"), mf::azimuthal | mf::conformal, DEFAULTS},
1029   {X3("two-point azimuthal"), mf::euc_boring | mf::twopoint, DEFAULTS},
1030   {X3("two-point hybrid"), mf::euc_boring | mf::twopoint, DEFAULTS},
1031   {X3("geodesic"), 0, DEFAULTS},
1032   {X3("Mollweide"), mf::euc_boring | mf::pseudoband | mf::equiarea, DEFAULTS},
1033   {X3("central cylindrical"), mf::euc_boring | mf::band, DEFAULTS},
1034   {X3("Collignon"), mf::pseudoband | mf::equiarea, DEFAULTS},
1035   {X3("horocyclic coordinates"), mf::euc_boring, DEFAULTS},
1036   {X3("quadrant coordinates"), mf::euc_boring, DEFAULTS},
1037   {X3("axial coordinates"), mf::euc_boring, DEFAULTS},
1038   {X3("anti-axial coordinates"), mf::euc_boring, DEFAULTS},
1039   {X3("Werner projection"), mf::euc_boring | mf::broken, DEFAULTS}, // keep distances from pole, and distances along parallels
1040   {X3("Aitoff projection"), mf::euc_boring | mf::broken, DEFAULTS}, // halve longitudes, do azequid, double x
1041   {X3("Hammer projection"), mf::euc_boring | mf::broken, DEFAULTS}, // halve longitudes, do azequia, double x
1042   {X3("loximuthal projection"), mf::euc_boring | mf::broken, DEFAULTS}, // map loxodromes azimuthally and equidistantly
1043   {X3("Miller projection"), mf::euc_boring | mf::band, DEFAULTS}, // scale latitude 4/5 -> Mercator -> 5/4
1044   {X3("Gall stereographic"), mf::euc_boring | mf::band, DEFAULTS}, // like central cylindrical but stereographic
1045   {X3("Winkel tripel"), mf::euc_boring | mf::broken, DEFAULTS}, // mean of equirec and Aitoff
1046   {X3("Poor man's square"), mf::euc_boring, DEFAULTS}, //
1047   {X3("Panini projection"), mf::euc_boring, DEFAULTS}, //
1048   {X3("Craig retroazimuthal"), mf::euc_boring | mf::broken, DEFAULTS}, // retroazimuthal cylindrical
1049   {X3("Littrow retroazimuthal"), mf::euc_boring | mf::broken, DEFAULTS}, // retroazimuthal conformal
1050   {X3("Hammer retroazimuthal"), mf::euc_boring, DEFAULTS}, // retroazimuthal equidistant
1051   {X3("three-point equidistant"), mf::euc_boring, DEFAULTS},
1052   {X3("guard"), 0, DEFAULTS},
1053   {X3("polynomial"), mf::conformal, DEFAULTS},
1054   };
1055 
1056 #undef X3
1057 #undef DEFAULTS
1058 
1059 #if HDR
orbProtection(eItem it)1060 static inline bool orbProtection(eItem it) { return false; } // not implemented
1061 
1062 // these markers use lands which never appear on barrier sides
1063 
1064 const eLand NOWALLSEP = laNone;
1065 const eLand NOWALLSEP_SWAP = laMountain;
1066 const eLand NOWALLSEP_WALL = laHauntedWall;
1067 const eLand NOWALLSEP_USED = laWhirlpool;
1068 const eLand NOWALLSEP_WALL_CPOS = laBarrier;
1069 const eLand NOWALLSEP_WALL_CNEG = laOceanWall;
1070 const eLand NOWALLSEP_WALL_EPOS = laClearing;
1071 const eLand NOWALLSEP_WALL_ENEG = laPrincessQuest;
1072 
1073 #endif
1074 
1075 }
1076