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