1 // Hyperbolic Rogue -- quotient spaces
2 // Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
3 
4 /** \file quotient.cpp
5  *  \brief quotient spaces
6  */
7 
8 #include "hyper.h"
9 namespace hr {
10 
11 /** \brief quotient spaces */
12 
13 EX namespace quotientspace {
14 
cod(heptagon * h)15   int cod(heptagon *h) {
16     return zebra40(h->c7);
17     }
18 
get(heptspin hs)19   code get(heptspin hs) {
20     code res;
21     res.connections.resize(S7+1);
22     res.connections[0] = cod(hs.at);
23     for(int i=1; i<=S7; i++) {
24       res.connections[i] = cod((hs + wstep).at);
25       hs += 1;
26       }
27     return res;
28     }
29 
30   EX int rvadd = 0;
31   EX int rvdir = 1;
32 
rv(int x)33   int rv(int x) { return (rvadd+x*rvdir) % S7; }
34 
35 #if HDR
36 constexpr int symmask = (1<<30);
37 
38 struct code {
39   vector<int> connections;
40 
operator ==hr::quotientspace::code41   bool operator == (const code &c2) const { return connections == c2.connections; }
operator <hr::quotientspace::code42   bool operator < (const code &c2) const { return connections < c2.connections; }
43 
44   };
45 
46 struct hrmap_quotient : hrmap_standard {
47 
48   hrmap_hyperbolic base;
49 
50   vector<cell*> celllist;
51 
52   cell *origin;
53 
54   map<quotientspace::code, int> reachable;
55   vector<heptspin> bfsq;
56 
57   vector<int> connections;
58 
59   void add(const heptspin& hs);
60 
61   vector<heptagon*> allh;
62 
63   void generate_connections();
64 
65   void build();
66 
hrmap_quotienthr::quotientspace::hrmap_quotient67   explicit hrmap_quotient() {
68     generate_connections();
69     build();
70     }
71 
hrmap_quotienthr::quotientspace::hrmap_quotient72   explicit hrmap_quotient(const vector<int>& con) : connections(con) {
73     build();
74     }
75 
getOriginhr::quotientspace::hrmap_quotient76   heptagon *getOrigin() override { return allh[0]; }
77 
~hrmap_quotienthr::quotientspace::hrmap_quotient78   ~hrmap_quotient() {
79     for(int i=0; i<isize(allh); i++) {
80       clearHexes(allh[i]);
81       tailored_delete(allh[i]);
82       }
83     }
84 
allcellshr::quotientspace::hrmap_quotient85   vector<cell*>& allcells() override { return celllist; }
86   };
87 #endif
88 
add(const heptspin & hs)89   void hrmap_quotient::add(const heptspin& hs) {
90     code g = get(hs);
91     if(!reachable.count(g)) {
92       reachable[g] = bfsq.size();
93       bfsq.push_back(hs);
94       add(hs + 1);
95       }
96     }
97 
generate_connections()98   void hrmap_quotient::generate_connections() {
99 
100     dynamicval<hrmap*> cmap(currentmap, this);
101     connections.clear();
102     switch(geometry) {
103       #if CAP_FIELD
104       case gFieldQuotient: {
105         connections = currfp.connections;
106         break;
107         }
108       #endif
109 
110       case gZebraQuotient: {
111         heptspin hs(base.origin);
112         reachable.clear();
113         bfsq.clear();
114         add(hs);
115 
116         for(int i=0; i<(int)bfsq.size(); i++) {
117           hs = bfsq[i] + wstep;
118           add(hs);
119           connections.push_back(reachable[get(hs)]);
120           }
121         break;
122         }
123 
124       case gMinimal: {
125         int altzebra[6][7] = {
126           { 16,125,111, 45, 32, 56, 20 },
127           { 26,102,146,152, 35,124, 00 },
128           { 06, 55,143,134,115,101, 10 },
129           { 41, 50, 04, 44,123, 14,153 },
130           { 51, 30,154,122, 33, 03,112 },
131           { 31, 40,113,136,142, 21, 05 }
132           };
133 
134         // int ok = 0;
135         for(int a=0; a<6; a++) {
136         for(int b=0; b<7; b++) {
137           int s = altzebra[a][b];
138           int mirr = s/100; s %= 100;
139           int which = s/10; s %= 10;
140 
141           int shouldbe = a*10+b+mirr*100;
142 
143           if(altzebra[which][s] != shouldbe) {
144             printf("error at %d:%d (is=%d shouldbe=%d)\n", a, b, altzebra[which][s], shouldbe);
145             }
146 
147           connections.push_back(which * 7 + s + (mirr ? symmask : 0) );
148           }
149           }
150         break;
151         }
152 
153       case gKleinQuartic: {
154         connections = {
155           /* 000 */ 7, 14, 21, 28, 35, 42, 49,
156           /* 001 */ 0, 55, 56, 63, 70, 77, 15,
157           /* 002 */ 1, 13, 83, 84, 91, 98, 22,
158           /* 003 */ 2, 20, 104, 105, 112, 119, 29,
159           /* 004 */ 3, 27, 125, 74, 126, 133, 36,
160           /* 005 */ 4, 34, 139, 95, 66, 140, 43,
161           /* 006 */ 5, 41, 146, 116, 87, 147, 50,
162           /* 007 */ 6, 48, 153, 130, 108, 57, 8,
163           /* 008 */ 9, 54, 107, 102, 154, 142, 64,
164           /* 009 */ 10, 62, 141, 39, 94, 161, 71,
165           /* 010 */ 11, 69, 167, 127, 31, 124, 78,
166           /* 011 */ 12, 76, 123, 158, 149, 85, 16,
167           /* 012 */ 17, 82, 148, 46, 115, 163, 92,
168           /* 013 */ 18, 90, 162, 67, 38, 138, 99,
169           /* 014 */ 19, 97, 137, 155, 59, 106, 23,
170           /* 015 */ 24, 103, 58, 53, 129, 165, 113,
171           /* 016 */ 25, 111, 164, 88, 45, 145, 120,
172           /* 017 */ 26, 118, 144, 159, 79, 75, 30,
173           /* 018 */ 32, 73, 166, 109, 52, 152, 134,
174           /* 019 */ 33, 132, 151, 156, 100, 96, 37,
175           /* 020 */ 40, 65, 61, 160, 121, 117, 44,
176           /* 021 */ 47, 86, 81, 157, 135, 131, 51,
177           /* 022 */ 60, 101, 136, 150, 80, 122, 143,
178           /* 023 */ 68, 93, 89, 114, 110, 128, 72,
179           };
180         break;
181         }
182 
183       case gBolza: {
184         connections = {
185           /* 000 */ 8, 16, 24, 32, 12, 20, 28, 36,
186           /* 001 */ 0, 35, 47, 21, 4, 39, 43, 17,
187           /* 002 */ 1, 15, 42, 29, 5, 11, 46, 25,
188           /* 003 */ 2, 23, 45, 37, 6, 19, 41, 33,
189           /* 004 */ 3, 31, 40, 9, 7, 27, 44, 13,
190           /* 005 */ 34, 30, 18, 14, 38, 26, 22, 10,
191           };
192         break;
193         }
194 
195       case gBolza2: {
196         connections = {
197 /* 000 */ 16, 32, 48, 64, 24, 40, 56, 72,
198 /* 001 */ 20, 44, 52, 76, 28, 36, 60, 68,
199 /* 002 */ 0, 79, 83, 45, 8, 67, 95, 33,
200 /* 003 */ 4, 71, 87, 37, 12, 75, 91, 41,
201 /* 004 */ 1, 23, 94, 61, 13, 27, 86, 49,
202 /* 005 */ 5, 31, 90, 53, 9, 19, 82, 57,
203 /* 006 */ 2, 39, 85, 77, 10, 43, 89, 65,
204 /* 007 */ 6, 47, 81, 69, 14, 35, 93, 73,
205 /* 008 */ 3, 55, 88, 21, 15, 59, 80, 25,
206 /* 009 */ 7, 63, 92, 29, 11, 51, 84, 17,
207 /* 010 */ 70, 58, 46, 18, 78, 50, 38, 26,
208 /* 011 */ 66, 54, 42, 30, 74, 62, 34, 22,
209           };
210         break;
211         }
212 
213       case gMacbeath: {
214         connections = {
215 /* 000 */ 359, 498, 189, 215, 424, 381, 20,
216 /* 001 */ 366, 491, 217, 187, 431, 346, 27,
217 /* 002 */ 380, 484, 168, 208, 438, 360, 6,
218 /* 003 */ 345, 477, 196, 180, 445, 367, 13,
219 /* 004 */ 352, 470, 203, 173, 396, 388, 48,
220 /* 005 */ 373, 463, 175, 201, 403, 339, 55,
221 /* 006 */ 387, 456, 210, 194, 410, 353, 34,
222 /* 007 */ 338, 449, 182, 222, 417, 374, 41,
223 /* 008 */ 254, 459, 140, 138, 414, 248, 69,
224 /* 009 */ 247, 480, 112, 166, 435, 255, 62,
225 /* 010 */ 233, 452, 161, 117, 407, 269, 83,
226 /* 011 */ 268, 487, 133, 145, 442, 234, 76,
227 /* 012 */ 261, 473, 126, 152, 400, 241, 97,
228 /* 013 */ 240, 494, 154, 124, 421, 262, 90,
229 /* 014 */ 226, 466, 119, 159, 393, 276, 111,
230 /* 015 */ 275, 501, 147, 131, 428, 227, 104,
231 /* 016 */ 65, 479, 343, 355, 408, 73, 167,
232 /* 017 */ 100, 465, 371, 383, 422, 94, 160,
233 /* 018 */ 86, 472, 350, 348, 429, 108, 153,
234 /* 019 */ 79, 486, 378, 376, 415, 59, 146,
235 /* 020 */ 58, 458, 385, 369, 443, 80, 139,
236 /* 021 */ 107, 500, 357, 341, 401, 87, 132,
237 /* 022 */ 93, 493, 364, 390, 394, 101, 125,
238 /* 023 */ 72, 451, 336, 362, 436, 66, 118,
239 /* 024 */ 16, 483, 294, 313, 397, 31, 209,
240 /* 025 */ 37, 462, 322, 285, 446, 24, 202,
241 /* 026 */ 51, 448, 287, 334, 432, 10, 223,
242 /* 027 */ 2, 497, 315, 306, 411, 45, 216,
243 /* 028 */ 23, 476, 308, 299, 404, 38, 181,
244 /* 029 */ 30, 469, 280, 327, 439, 17, 174,
245 /* 030 */ 44, 455, 329, 292, 425, 3, 195,
246 /* 031 */ 9, 490, 301, 320, 418, 52, 188,
247 /* 032 */ 324, 467, 98, 110, 427, 332, 258,
248 /* 033 */ 289, 453, 70, 82, 441, 283, 265,
249 /* 034 */ 303, 495, 91, 89, 399, 297, 272,
250 /* 035 */ 310, 481, 63, 61, 413, 318, 279,
251 /* 036 */ 331, 460, 56, 68, 434, 325, 230,
252 /* 037 */ 282, 474, 84, 96, 420, 290, 237,
253 /* 038 */ 296, 488, 77, 75, 406, 304, 244,
254 /* 039 */ 317, 502, 105, 103, 392, 311, 251,
255 /* 040 */ 205, 475, 259, 236, 447, 178, 328,
256 /* 041 */ 184, 454, 231, 264, 426, 213, 335,
257 /* 042 */ 170, 489, 266, 243, 405, 199, 314,
258 /* 043 */ 219, 496, 238, 271, 412, 192, 321,
259 /* 044 */ 198, 482, 245, 278, 398, 171, 300,
260 /* 045 */ 191, 503, 273, 250, 419, 220, 307,
261 /* 046 */ 177, 468, 224, 257, 440, 206, 286,
262 /* 047 */ 212, 461, 252, 229, 433, 185, 293,
263 /* 048 */ 163, 450, 49, 40, 402, 150, 363,
264 /* 049 */ 114, 478, 21, 12, 430, 129, 356,
265 /* 050 */ 128, 471, 28, 47, 409, 115, 349,
266 /* 051 */ 149, 499, 0, 19, 437, 164, 342,
267 /* 052 */ 156, 492, 7, 26, 444, 143, 391,
268 /* 053 */ 121, 464, 35, 54, 416, 136, 384,
269 /* 054 */ 135, 485, 14, 5, 423, 122, 377,
270 /* 055 */ 142, 457, 42, 33, 395, 157, 370,
271 /* 056 */ 277, 102, 158, 389, 32, 172, 312,
272 /* 057 */ 242, 88, 151, 340, 39, 200, 298,
273 /* 058 */ 270, 74, 116, 354, 46, 193, 305,
274 /* 059 */ 249, 60, 137, 375, 53, 221, 319,
275 /* 060 */ 263, 95, 123, 382, 4, 214, 291,
276 /* 061 */ 228, 109, 130, 347, 11, 186, 333,
277 /* 062 */ 256, 67, 165, 361, 18, 207, 326,
278 /* 063 */ 235, 81, 144, 368, 25, 179, 284,
279 /* 064 */ 183, 50, 337, 162, 71, 232, 288,
280 /* 065 */ 211, 43, 386, 141, 57, 253, 330,
281 /* 066 */ 176, 36, 372, 120, 99, 225, 323,
282 /* 067 */ 204, 29, 351, 127, 85, 260, 281,
283 /* 068 */ 197, 22, 344, 113, 64, 246, 309,
284 /* 069 */ 169, 15, 379, 134, 78, 267, 295,
285 /* 070 */ 218, 8, 365, 155, 92, 239, 302,
286 /* 071 */ 190, 1, 358, 148, 106, 274, 316,
287           };
288         break;
289         }
290 
291       case gBring: {
292         connections = {
293 /* 000 */ 5, 92, 46, 33, 14,
294 /* 001 */ 0, 62, 56, 38, 24,
295 /* 002 */ 15, 97, 76, 63, 4,
296 /* 003 */ 10, 32, 86, 68, 29,
297 /* 004 */ 25, 67, 106, 93, 9,
298 /* 005 */ 20, 37, 116, 98, 19,
299 /* 006 */ 35, 102, 16, 3, 44,
300 /* 007 */ 30, 72, 26, 8, 54,
301 /* 008 */ 45, 107, 66, 73, 34,
302 /* 009 */ 40, 2, 81, 78, 59,
303 /* 010 */ 55, 77, 96, 103, 39,
304 /* 011 */ 50, 7, 111, 108, 49,
305 /* 012 */ 65, 112, 6, 13, 74,
306 /* 013 */ 60, 42, 21, 18, 84,
307 /* 014 */ 75, 117, 36, 43, 64,
308 /* 015 */ 70, 12, 51, 48, 89,
309 /* 016 */ 85, 47, 91, 113, 69,
310 /* 017 */ 80, 17, 101, 118, 79,
311 /* 018 */ 95, 82, 1, 23, 104,
312 /* 019 */ 90, 52, 11, 28, 114,
313 /* 020 */ 105, 87, 31, 53, 94,
314 /* 021 */ 100, 22, 41, 58, 119,
315 /* 022 */ 115, 57, 61, 83, 99,
316 /* 023 */ 110, 27, 71, 88, 109,
317           };
318         break;
319         }
320 
321       case gSchmutzM2: {
322         connections = {
323           23,  47,  27,  14,  38,  30,  17,  41,  33,  20,  44,  24,
324           35,  39,   3,  26,  42,   6,  29,  45,   9,  32,  36,   0,
325           11,  43,  15,   2,  46,  18,   5,  37,  21,   8,  40,  12,
326           22,  31,   4,  13,  34,   7,  16,  25,  10,  19,  28,   1,
327           };
328         break;
329         }
330 
331       case gSchmutzM3: {
332         connections = {
333           23,  47,  64,  28,  15,  39,  68,  32,  19,  43,  60,  24,
334           35,  52,  40,   4,  27,  56,  44,   8,  31,  48,  36,   0,
335           11,  71,  57,  16,   3,  63,  49,  20,   7,  67,  53,  12,
336           22,  59,  69,   5,  14,  51,  61,   9,  18,  55,  65,   1,
337           21,  30,  62,  41,  13,  34,  66,  45,  17,  26,  70,  37,
338           10,  42,  50,  29,   2,  46,  54,  33,   6,  38,  58,  25,
339           };
340         break;
341         }
342 
343       default: break;
344       }
345     }
346 
build()347   void hrmap_quotient::build() {
348 
349     dynamicval<hrmap*> cmap(currentmap, this);
350 
351     int TOT = connections.size() / S7;
352     // printf("heptagons = %d\n", TOT);
353     // printf("all cells = %d\n", TOT*(S7+S3)/S3);
354     if(!TOT) exit(1);
355     allh.resize(TOT);
356     for(int i=0; i<TOT; i++) allh[i] = init_heptagon(S7);
357     // heptagon *oldorigin = origin;
358     allh[0]->alt = base.origin;
359 
360     for(int i=0; i<TOT; i++) {
361       heptagon *h = allh[i];
362       if(true) {
363         h->s = hsOrigin;
364         h->fieldval = S7*i;
365         if(!IRREGULAR) h->c7 = newCell(S7, h);
366         }
367       for(int j=0; j<S7; j++) {
368         int co = connections[i*S7+j];
369         bool swapped = co & symmask;
370         co &= ~symmask;
371         h->move(rv(j)) = allh[co/S7];
372         h->c.setspin(rv(j), rv(co%S7), swapped);
373         }
374       }
375 
376     vector<heptagon*> by_dist;
377     by_dist.push_back(allh[0]);
378     for(int i=0; i<TOT; i++) {
379       if(i >= isize(by_dist)) { printf("too fast\n"); exit(1); }
380       for(int a=0; a<S7; a++) if(by_dist[i]->move(a)->alt == NULL) by_dist.push_back(by_dist[i]->move(a));
381       currentmap->extend_altmap(by_dist[i], 0, false);
382       }
383 
384     for(int i=0; i<TOT; i++) {
385       allh[i]->emeraldval = allh[i]->alt->emeraldval;
386       allh[i]->zebraval = allh[i]->alt->zebraval;
387       allh[i]->fiftyval = allh[i]->alt->fiftyval;
388       allh[i]->distance = allh[i]->alt->distance;
389       /* for(int j=0; j<7; j++)
390         allh[i]->move[j]->alt = createStep(allh[i]->alt, j); */
391       }
392 
393     #if CAP_IRR
394     if(IRREGULAR) {
395       irr::link_start(allh[0]);
396       for(int i=0; i<TOT; i++)
397         for(int j=0; j<S7; j++)
398           irr::may_link_next(allh[i], j);
399       }
400     #endif
401 
402     celllister cl(gamestart(), 100, 100000000, NULL);
403     celllist = cl.lst;
404     }
405 
406 
new_map()407 EX struct hrmap_quotient* new_map() { return new hrmap_quotient; }
408 
409 EX }
410 
411 
412 }
413