mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 22:12:59 +00:00 
			
		
		
		
	3D:: 120-cell
This commit is contained in:
		
							
								
								
									
										1
									
								
								cell.cpp
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								cell.cpp
									
									
									
									
									
								
							| @@ -232,6 +232,7 @@ void initcells() { | |||||||
|   else if(fulltorus) currentmap = new hrmap_torus; |   else if(fulltorus) currentmap = new hrmap_torus; | ||||||
|   else if(euclid && DIM == 3) currentmap = euclid3::new_map(); |   else if(euclid && DIM == 3) currentmap = euclid3::new_map(); | ||||||
|   else if(euclid) currentmap = new hrmap_euclidean; |   else if(euclid) currentmap = new hrmap_euclidean; | ||||||
|  |   else if(sphere && DIM == 3) currentmap = new sphere3::hrmap_spherical3; | ||||||
|   else if(sphere) currentmap = new hrmap_spherical; |   else if(sphere) currentmap = new hrmap_spherical; | ||||||
|   else if(quotient) currentmap = new quotientspace::hrmap_quotient; |   else if(quotient) currentmap = new quotientspace::hrmap_quotient; | ||||||
|   else currentmap = new hrmap_hyperbolic; |   else currentmap = new hrmap_hyperbolic; | ||||||
|   | |||||||
| @@ -1767,6 +1767,7 @@ vector<geometryinfo> ginf = { | |||||||
|   {"{3,4}", "none",     "{3,4} (octahedron)",                         "4x3",      3, 4, qsSMALLB,  gcSphere,     0x28200, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, |   {"{3,4}", "none",     "{3,4} (octahedron)",                         "4x3",      3, 4, qsSMALLB,  gcSphere,     0x28200, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, | ||||||
|   {"bin3",  "none",     "3D binary tiling",                           "binary3",  9, 4, 0,         gcHyperbolic,       0, {{7, 3}}, eVariation::pure}, |   {"bin3",  "none",     "3D binary tiling",                           "binary3",  9, 4, 0,         gcHyperbolic,       0, {{7, 3}}, eVariation::pure}, | ||||||
|   {"cube",  "none",     "3D cube tiling",                             "cube",     6, 4, 0,         gcEuclid,           0, {{7, 5}}, eVariation::pure}, |   {"cube",  "none",     "3D cube tiling",                             "cube",     6, 4, 0,         gcEuclid,           0, {{7, 5}}, eVariation::pure}, | ||||||
|  |   {"120c",  "none",     "120-cell",                                   "120c",    12, 4, qsSMALLB,  gcSphere,           0, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| // remember to match the following mask when specifying codes for extra geometries: 0x78600 | // remember to match the following mask when specifying codes for extra geometries: 0x78600 | ||||||
|   | |||||||
| @@ -214,7 +214,7 @@ enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle | |||||||
| enum eGeometry { | enum eGeometry { | ||||||
|   gNormal, gEuclid, gSphere, gElliptic, gZebraQuotient, gFieldQuotient, gTorus, gOctagon, g45, g46, g47, gSmallSphere, gTinySphere, gEuclidSquare, gSmallElliptic,  |   gNormal, gEuclid, gSphere, gElliptic, gZebraQuotient, gFieldQuotient, gTorus, gOctagon, g45, g46, g47, gSmallSphere, gTinySphere, gEuclidSquare, gSmallElliptic,  | ||||||
|   gKleinQuartic, gBolza, gBolza2, gMinimal, gBinaryTiling, gArchimedean,  |   gKleinQuartic, gBolza, gBolza2, gMinimal, gBinaryTiling, gArchimedean,  | ||||||
|   gMacbeath, gBring, gSchmutzM2, gSchmutzM3, gCrystal, gOctahedron, gBinary3, gCubeTiling, |   gMacbeath, gBring, gSchmutzM2, gSchmutzM3, gCrystal, gOctahedron, gBinary3, gCubeTiling, gCell120, | ||||||
|   gGUARD}; |   gGUARD}; | ||||||
|  |  | ||||||
| enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere }; | enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere }; | ||||||
|   | |||||||
| @@ -94,6 +94,7 @@ transmatrix calc_relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hin | |||||||
|   #endif |   #endif | ||||||
|   #if MAXDIM == 4 |   #if MAXDIM == 4 | ||||||
|   if(euclid && DIM == 3) return euclid3::relative_matrix(c2->master, c1->master); |   if(euclid && DIM == 3) return euclid3::relative_matrix(c2->master, c1->master); | ||||||
|  |   if(sphere && DIM == 3) return sphere3::relative_matrix(c2->master, c1->master); | ||||||
|   #endif |   #endif | ||||||
|   #if CAP_ARCM |   #if CAP_ARCM | ||||||
|   if(archimedean) return arcm::relative_matrix(c2->master, c1->master); |   if(archimedean) return arcm::relative_matrix(c2->master, c1->master); | ||||||
|   | |||||||
| @@ -4595,9 +4595,12 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { | |||||||
|        |        | ||||||
|       if(DIM == 3) { |       if(DIM == 3) { | ||||||
|         if(isWall(c)) { |         if(isWall(c)) { | ||||||
|  |           const int darkval_h[9] = {0,2,2,0,6,6,8,8,0}; | ||||||
|  |           const int darkval_s[12] = {0,1,2,3,0,1,2,3,0,1,2,3}; | ||||||
|  |           const int darkval_e[6] = {0,0,4,4,6,6}; | ||||||
|  |           const int *darkval = sphere ? darkval_s : hyperbolic ? darkval_h : darkval_e; | ||||||
|  |           int d = (asciicol & 0xF0F0F0) >> 4; | ||||||
|  |  | ||||||
|           const int darkval[9] = {0,1,1,0,3,3,4,4,0}; |  | ||||||
|           int d = (asciicol & 0xF0F0F0) >> 3; |  | ||||||
|           for(int a=0; a<c->type; a++) |           for(int a=0; a<c->type; a++) | ||||||
|             if(c->move(a) && !isWall(c->move(a))) { |             if(c->move(a) && !isWall(c->move(a))) { | ||||||
|               if(a < 4 && hyperbolic) { |               if(a < 4 && hyperbolic) { | ||||||
| @@ -5712,6 +5715,8 @@ void drawthemap() { | |||||||
|   #if MAXDIM == 4 |   #if MAXDIM == 4 | ||||||
|   else if(euclid && DIM == 3) |   else if(euclid && DIM == 3) | ||||||
|     euclid3::draw(); |     euclid3::draw(); | ||||||
|  |   else if(sphere && DIM == 3) | ||||||
|  |     sphere3::draw(); | ||||||
|   #endif |   #endif | ||||||
|   else |   else | ||||||
|     drawStandard(); |     drawStandard(); | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								hyper.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								hyper.h
									
									
									
									
									
								
							| @@ -192,7 +192,7 @@ typedef complex<ld> cld; | |||||||
| #if MAXDIM == 3 | #if MAXDIM == 3 | ||||||
| #define DIM 2 | #define DIM 2 | ||||||
| #else | #else | ||||||
| #define DIM ((geometry == gBinary3 || geometry == gCubeTiling) ? 3 : 2) | #define DIM ((geometry == gBinary3 || geometry == gCubeTiling || geometry == gCell120) ? 3 : 2) | ||||||
| #endif | #endif | ||||||
| #define MDIM (DIM+1) | #define MDIM (DIM+1) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -731,6 +731,7 @@ transmatrix applyspin(const heptspin& hs, const transmatrix& V) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
| bool invis_point(const hyperpoint h) { | bool invis_point(const hyperpoint h) { | ||||||
|  |   if(DIM == 2 || sphere) return false; | ||||||
|   return h[2] < 0; |   return h[2] < 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								polygons.cpp
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								polygons.cpp
									
									
									
									
									
								
							| @@ -1615,7 +1615,7 @@ hpcshape | |||||||
|    |    | ||||||
|   shAsymmetric, |   shAsymmetric, | ||||||
|    |    | ||||||
|   shBinaryWall[9], |   shBinaryWall[12], | ||||||
|  |  | ||||||
|   shDodeca; |   shDodeca; | ||||||
| #endif | #endif | ||||||
| @@ -2464,6 +2464,14 @@ void buildpolys() { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|    |    | ||||||
|  |   if(DIM == 3 && sphere) { | ||||||
|  |     for(int w=0; w<12; w++) { | ||||||
|  |       bshape(shBinaryWall[w], PPR::WALL); | ||||||
|  |       for(int a=0; a<=5; a++)  | ||||||
|  |         hpcpush(sphere3::dodefaces[w*5+a%5]); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |    | ||||||
|   ld krsc = 1; |   ld krsc = 1; | ||||||
|   if(sphere) krsc *= 1.4; |   if(sphere) krsc *= 1.4; | ||||||
|   if(S7 ==8) krsc *= 1.3; |   if(S7 ==8) krsc *= 1.3; | ||||||
|   | |||||||
							
								
								
									
										192
									
								
								sphere.cpp
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								sphere.cpp
									
									
									
									
									
								
							| @@ -164,4 +164,196 @@ heptagon *getDodecahedron(int i) { | |||||||
|   return s->dodecahedron[i]; |   return s->dodecahedron[i]; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | namespace sphere3 { | ||||||
|  |  | ||||||
|  | vector<hyperpoint> vertices120; | ||||||
|  | array<transmatrix, 120> vmatrix120; | ||||||
|  | vector<int> adj0; | ||||||
|  | array<array<int, 4>, 120> js; | ||||||
|  | array<hyperpoint, 60> dodefaces; | ||||||
|  |  | ||||||
|  | hyperpoint zero4; | ||||||
|  |  | ||||||
|  | ld norm(hyperpoint a, hyperpoint b) { | ||||||
|  |   ld res = 0; | ||||||
|  |   for(int i=0; i<4; i++) res += pow(a[i]-b[i], 2); | ||||||
|  |   return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | void gen600() { | ||||||
|  |   vertices120.clear(); | ||||||
|  |    | ||||||
|  |   /// coordinates taken from Wikipedia | ||||||
|  |    | ||||||
|  |   for(int a=0; a<16; a++) { | ||||||
|  |     hyperpoint v = zero4; | ||||||
|  |     for(int i=0; i<4; i++) v[i] = ((a >> i) & 1) ? .5 : -.5; | ||||||
|  |     vertices120.push_back(v); | ||||||
|  |     } | ||||||
|  |    | ||||||
|  |   for(int i=0; i<4; i++) for(int q: {-1, 1}) { | ||||||
|  |     hyperpoint v = zero4; | ||||||
|  |     v[i]=q; | ||||||
|  |     vertices120.push_back(v); | ||||||
|  |     } | ||||||
|  |    | ||||||
|  |   ld phi = (1 + sqrt(5)) / 2; | ||||||
|  |    | ||||||
|  |   array<ld, 4> coo = {1, phi, 1/phi, 0}; | ||||||
|  |    | ||||||
|  |   // all permutations | ||||||
|  |   array<int, 4> tab; | ||||||
|  |   for(int i=0; i<4; i++) tab[i] = i; | ||||||
|  |    | ||||||
|  |   do { | ||||||
|  |  | ||||||
|  |     // check the permutation's sign | ||||||
|  |     auto tabs = tab; | ||||||
|  |     int inv = 0; | ||||||
|  |  | ||||||
|  |     for(int i=0; i<4; i++) while(tabs[i] != i) { | ||||||
|  |       swap(tabs[i], tabs[tabs[i]]); | ||||||
|  |       inv++; | ||||||
|  |       } | ||||||
|  |      | ||||||
|  |     if(inv&1) goto again; | ||||||
|  |      | ||||||
|  |     // 8 vertices for each permutation | ||||||
|  |      | ||||||
|  |     for(int sg=0; sg<8; sg++) { | ||||||
|  |       hyperpoint v; | ||||||
|  |       for(int i=0; i<4; i++)  | ||||||
|  |         v[i] = (((sg >> tab[i])&1) ? 1 : -1) * coo[tab[i]]/2; | ||||||
|  |       vertices120.push_back(v); | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |     again: ; | ||||||
|  |     } | ||||||
|  |   while(std::next_permutation(tab.begin(), tab.end())); | ||||||
|  |    | ||||||
|  |   if(isize(vertices120) != 120) { | ||||||
|  |     printf("error: wrong number of vertices\n"); | ||||||
|  |     exit(1); | ||||||
|  |     } | ||||||
|  |   // we add edges between vertices which are close to each other | ||||||
|  |   // ((specifically in distance 1/phi/phi) | ||||||
|  |    | ||||||
|  |   bool inedge[120][120]; | ||||||
|  |      | ||||||
|  |   for(int i=0; i<120; i++) | ||||||
|  |   for(int j=0; j<120; j++) { | ||||||
|  |     ld d = hdist(vertices120[i], vertices120[j]); | ||||||
|  |     inedge[i][j] = (i != j) && d < sqrt(.4); | ||||||
|  |     } | ||||||
|  |    | ||||||
|  |   vector<hyperpoint> cellvertices; | ||||||
|  |    | ||||||
|  |   for(int i=0; i<120; i++) | ||||||
|  |     for(int j=0; j<120; j++) if(inedge[i][j]) | ||||||
|  |     for(int k=0; k<120; k++) if(inedge[i][k] && inedge[k][j]) | ||||||
|  |     for(int l=0; l<120; l++) if(inedge[i][l] && inedge[j][l] && inedge[k][l]) { | ||||||
|  |       array<int, 4> ijkl = {i, j, k, l}; | ||||||
|  |       transmatrix T; | ||||||
|  |       for(int z=0; z<4; z++) set_column(T, z, vertices120[ijkl[z]]); | ||||||
|  |       if(det(T) > 0) js[i] = ijkl; | ||||||
|  |       } | ||||||
|  |      | ||||||
|  |   /* transmatrix src; | ||||||
|  |   for(int z=0; z<4; z++) set_column(src, z, vertices120[js[0][z]]); */ | ||||||
|  |  | ||||||
|  |   for(int i=0; i<120; i++) | ||||||
|  |     for(int z=0; z<4; z++) set_column(vmatrix120[i], z, vertices120[js[i][z]]); | ||||||
|  |  | ||||||
|  |   for(int i=0; i<120; i++) println(hlog, i, ": ", js[i], " -> ", vmatrix120[i]);   | ||||||
|  |    | ||||||
|  |   adj0.clear(); | ||||||
|  |   for(int i=0; i<120; i++) if(inedge[0][i]) adj0.push_back(i); | ||||||
|  |    | ||||||
|  |   using namespace hyperpoint_vec; | ||||||
|  |    | ||||||
|  |   int id = 0; | ||||||
|  |   for(int i=0; i<12; i++) { | ||||||
|  |     int ot = adj0[i]; | ||||||
|  |      | ||||||
|  |     vector<int> pentagon; | ||||||
|  |     for(int j: adj0) if(inedge[ot][j]) pentagon.push_back(j); | ||||||
|  |     println(hlog, i, ": ", pentagon); | ||||||
|  |      | ||||||
|  |     int illegal = -1; | ||||||
|  |     int at = pentagon[0]; | ||||||
|  |     for(int d=0; d<5; d++) { | ||||||
|  |       for(int s: pentagon) if(inedge[at][s] && s != illegal) { | ||||||
|  |         hyperpoint m = vertices120[0] + vertices120[ot] + vertices120[at] + vertices120[s]; | ||||||
|  |         m = mid(m, m); | ||||||
|  |         println(hlog, id, ": ", m); | ||||||
|  |         dodefaces[id++] = m; | ||||||
|  |         illegal = at; | ||||||
|  |         at = s; | ||||||
|  |         break; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |    | ||||||
|  |   printf("id = %d\n", id); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | struct hrmap_spherical3 : hrmap { | ||||||
|  |   heptagon* cells[120]; | ||||||
|  |  | ||||||
|  |   hrmap_spherical3() { | ||||||
|  |     gen600(); | ||||||
|  |     for(int i=0; i<120; i++) { | ||||||
|  |       cells[i] = tailored_alloc<heptagon> (12); | ||||||
|  |       heptagon& h = *(cells[i]); | ||||||
|  |       h.s = hsOrigin; | ||||||
|  |       h.emeraldval = i; | ||||||
|  |       h.zebraval = i; | ||||||
|  |       h.fiftyval = i; | ||||||
|  |       h.rval0 = h.rval1 = 0; | ||||||
|  |       h.alt = NULL; | ||||||
|  |       h.cdata = NULL; | ||||||
|  |       h.c.fullclear(); | ||||||
|  |       h.fieldval = i; | ||||||
|  |       h.c7 = newCell(12, &h);       | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     for(int i=0; i<120; i++) { | ||||||
|  |       for(int k=0; k<12; k++) { | ||||||
|  |         hyperpoint which = vmatrix120[i] * inverse(vmatrix120[0]) * vertices120[adj0[k]]; | ||||||
|  |         for(int s=0; s<120; s++) if(hdist(which, vertices120[s]) < 1e-6) { | ||||||
|  |           cells[i]->move(k) = cells[s]; | ||||||
|  |           println(hlog, i,".",k, " -> ", s, " ; ", js[i]); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     for(int i=0; i<120; i++) | ||||||
|  |       for(int k=0; k<12; k++)  | ||||||
|  |         for(int l=0; l<12; l++) | ||||||
|  |           if(cells[i]->move(k)->move(l) == cells[i]) | ||||||
|  |             cells[i]->c.setspin(k, l, false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   heptagon *getOrigin() { return cells[0]; } | ||||||
|  |  | ||||||
|  |   ~hrmap_spherical3() { | ||||||
|  |     for(int i=0; i<120; i++) tailored_delete(cells[i]); | ||||||
|  |     }     | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  | void draw() { | ||||||
|  |   auto m = (hrmap_spherical3*) currentmap; | ||||||
|  |  | ||||||
|  |   int old = viewctr.at->zebraval; | ||||||
|  |  | ||||||
|  |   for(int i=0; i<120; i++) | ||||||
|  |     drawcell(m->cells[i]->c7, View * vmatrix120[0] * inverse(vmatrix120[old]) * vmatrix120[i] * inverse(vmatrix120[0]), 0, false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | transmatrix relative_matrix(heptagon *h2, heptagon *h1) { | ||||||
|  |   return vmatrix120[0] * inverse(vmatrix120[h1->zebraval]) * vmatrix120[h2->zebraval] * inverse(vmatrix120[0]); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1194,7 +1194,7 @@ void set_geometry(eGeometry target) { | |||||||
|     if(DUAL && geometry != gArchimedean)  |     if(DUAL && geometry != gArchimedean)  | ||||||
|       variation = ginf[geometry].default_variation; |       variation = ginf[geometry].default_variation; | ||||||
|     #if CAP_BT |     #if CAP_BT | ||||||
|     if(among(geometry, gBinaryTiling, gBinary3, gCubeTiling)) variation = eVariation::pure; |     if(among(geometry, gBinaryTiling, gBinary3, gCubeTiling, gCell120)) variation = eVariation::pure; | ||||||
|     #endif |     #endif | ||||||
|     |     | ||||||
|     need_reset_geometry = true;  |     need_reset_geometry = true;  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ?
					?