mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 14:02:59 +00:00 
			
		
		
		
	irregular grids
This commit is contained in:
		| @@ -105,8 +105,10 @@ bool grailWasFound(cell *c) { | ||||
|  | ||||
| void generateAlts(heptagon *h, int levs, bool link_cdata) { | ||||
|   if(!h->alt) return; | ||||
|   preventbarriers(h->c7); | ||||
|   for(int i=0; i<S7; i++) preventbarriers(h->c7->mov[i]); | ||||
|   if(!irr::on) { | ||||
|     preventbarriers(h->c7); | ||||
|     for(int i=0; i<S7; i++) preventbarriers(h->c7->mov[i]); | ||||
|     } | ||||
|   if(gp::on) | ||||
|     for(int i=0; i<S7; i++) preventbarriers(createStep(h, i)->c7); | ||||
|   for(int i=0; i<S7; i++)  | ||||
| @@ -973,7 +975,7 @@ int wallchance(cell *c, bool deepOcean) { | ||||
| bool horo_ok() { | ||||
|   // do the horocycles work in the current geometry? | ||||
|   // (they work in ALL hyperbolic geometries currently!) | ||||
|   return hyperbolic; | ||||
|   return hyperbolic && !irr::on; | ||||
|   } | ||||
|  | ||||
| bool gp_wall_test() { | ||||
|   | ||||
| @@ -6,7 +6,7 @@ namespace hr { | ||||
| double randd() { return (rand() + .5) / (RAND_MAX + 1.); } | ||||
|  | ||||
| double cellgfxdist(cell *c, int i) { | ||||
|   if(gp::on) return hdist0(tC0(shmup::calc_relative_matrix(c->mov[i], c, i))); | ||||
|   if(gp::on || irr::on) return hdist0(tC0(shmup::calc_relative_matrix(c->mov[i], c, i))); | ||||
|   return nonbitrunc ? tessf * gp::scale : (c->type == 6 && (i&1)) ? hexhexdist : crossf; | ||||
|   } | ||||
|  | ||||
|   | ||||
							
								
								
									
										42
									
								
								cell.cpp
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								cell.cpp
									
									
									
									
									
								
							| @@ -73,7 +73,10 @@ hrmap_hyperbolic::hrmap_hyperbolic() { | ||||
|   h.alt = NULL; | ||||
|   h.distance = 0; | ||||
|   isnonbitrunc = nonbitrunc; | ||||
|   h.c7 = newCell(S7, origin); | ||||
|   if(irr::on) | ||||
|     irr::link_start(origin); | ||||
|   else | ||||
|     h.c7 = newCell(S7, origin); | ||||
|   } | ||||
|  | ||||
| // --- spherical geometry --- | ||||
| @@ -107,7 +110,7 @@ struct hrmap_spherical : hrmap { | ||||
|       h.spintable = 0; | ||||
|       h.fieldval = i; | ||||
|       for(int i=0; i<S7; i++) h.move[i] = NULL; | ||||
|       h.c7 = newCell(S7, &h); | ||||
|       if(!irr::on) h.c7 = newCell(S7, &h); | ||||
|       } | ||||
|     if(S7 == 5) | ||||
|       siblings = {1, 0, 10, 4, 3, 8, 9, 11, 5, 6, 2, 7}; | ||||
| @@ -174,6 +177,13 @@ struct hrmap_spherical : hrmap { | ||||
|         dodecahedron[i+1]->setspin(2, 3-i); | ||||
|         } | ||||
|       } | ||||
|  | ||||
|     if(irr::on) { | ||||
|       irr::link_start(dodecahedron[0]); | ||||
|       for(int i=0; i<spherecells(); i++) | ||||
|         for(int j=0; j<S7; j++) | ||||
|           irr::may_link_next(dodecahedron[i], j); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   heptagon *getOrigin() { return dodecahedron[0]; } | ||||
| @@ -717,7 +727,7 @@ struct hrmap_quotient : hrmap { | ||||
|         h->fieldval = S7*i; | ||||
|         h->rval0 = h->rval1 = 0; h->cdata = NULL; | ||||
|         h->distance = 0; | ||||
|         h->c7 = newCell(S7, h); | ||||
|         if(!irr::on) h->c7 = newCell(S7, h); | ||||
|         } | ||||
|       for(int j=0; j<S7; j++) { | ||||
|         int co = connections[i*S7+j]; | ||||
| @@ -738,6 +748,13 @@ struct hrmap_quotient : hrmap { | ||||
|         allh[i]->move[j]->alt = createStep(allh[i]->alt, j); */ | ||||
|       }     | ||||
|      | ||||
|     if(irr::on) { | ||||
|       irr::link_start(allh[0]); | ||||
|       for(int i=0; i<TOT; i++) | ||||
|         for(int j=0; j<S7; j++) | ||||
|           irr::may_link_next(allh[i], j); | ||||
|       } | ||||
|  | ||||
|     celllister cl(gamestart(), 100, 100000000, NULL); | ||||
|     celllist = cl.lst; | ||||
|     } | ||||
| @@ -827,6 +844,9 @@ cell *createMov(cell *c, int d) { | ||||
|     } | ||||
|    | ||||
|   if(c->mov[d]) return c->mov[d]; | ||||
|   else if(irr::on) { | ||||
|     irr::link_cell(c, d); | ||||
|     } | ||||
|   else if(nonbitrunc && gp::on) { | ||||
|     gp::extend_map(c, d); | ||||
|     if(!c->mov[d]) { | ||||
| @@ -951,7 +971,8 @@ void clearHexes(heptagon *at) { | ||||
|     delete at->cdata; | ||||
|     at->cdata = NULL; | ||||
|     } | ||||
|   if(at->c7) subcell(at->c7, clearcell); | ||||
|   if(irr::on) irr::clear_links(at); | ||||
|   else if(at->c7) subcell(at->c7, clearcell); | ||||
|   } | ||||
|  | ||||
| void unlink_cdata(heptagon *h) { | ||||
| @@ -1017,7 +1038,7 @@ void verifycell(cell *c) { | ||||
|   } | ||||
|  | ||||
| void verifycells(heptagon *at) { | ||||
|   if(gp::on) return; | ||||
|   if(gp::on || irr::on) return; | ||||
|   for(int i=0; i<S7; i++) if(at->move[i] && at->move[i]->move[at->spin(i)] && at->move[i]->move[at->spin(i)] != at) { | ||||
|     printf("hexmix error %p [%d s=%d] %p %p\n", at, i, at->spin(i), at->move[i], at->move[i]->move[at->spin(i)]); | ||||
|     } | ||||
| @@ -1066,6 +1087,7 @@ int celldist(cell *c) { | ||||
|   if(sphere) return celldistance(c, currentmap->gamestart()); | ||||
|   if(ctof(c)) return c->master->distance; | ||||
|   if(gp::on) return gp::compute_dist(c, celldist); | ||||
|   if(irr::on)  return c->master->distance; | ||||
|   int dx[MAX_S3]; | ||||
|   for(int u=0; u<S3; u++) | ||||
|     dx[u] = createMov(c, u+u)->master->distance; | ||||
| @@ -1400,7 +1422,7 @@ int getCdata(cell *c, int j) { | ||||
|     int jj = 0; | ||||
|     auto ar = gp::get_masters(c); | ||||
|     for(int k=0; k<3; k++) | ||||
|       jj += getHeptagonCdata(ar[k]->master)->val[j]; | ||||
|       jj += getHeptagonCdata(ar[k])->val[j]; | ||||
|     return jj; | ||||
|     } | ||||
|   } | ||||
| @@ -1411,9 +1433,9 @@ int getBits(cell *c) { | ||||
|   else if(c->type != 6) return getHeptagonCdata(c->master)->bits; | ||||
|   else { | ||||
|     auto ar = gp::get_masters(c); | ||||
|     int b0 = getHeptagonCdata(ar[0]->master)->bits; | ||||
|     int b1 = getHeptagonCdata(ar[1]->master)->bits; | ||||
|     int b2 = getHeptagonCdata(ar[2]->master)->bits; | ||||
|     int b0 = getHeptagonCdata(ar[0])->bits; | ||||
|     int b1 = getHeptagonCdata(ar[1])->bits; | ||||
|     int b2 = getHeptagonCdata(ar[2])->bits; | ||||
|     return (b0 & b1) | (b1 & b2) | (b2 & b0); | ||||
|     } | ||||
|   } | ||||
| @@ -1475,7 +1497,7 @@ int celldistance(cell *c1, cell *c2) { | ||||
|     return 64; | ||||
|     } | ||||
|    | ||||
|   if(gp::on || euclid) { | ||||
|   if(gp::on || euclid || irr::on) { | ||||
|      | ||||
|     if(saved_distances.count(make_pair(c1,c2))) | ||||
|       return saved_distances[make_pair(c1,c2)]; | ||||
|   | ||||
| @@ -32,6 +32,7 @@ | ||||
| #include "language.cpp" | ||||
| #include "cell.cpp" | ||||
| #include "goldberg.cpp" | ||||
| #include "irregular.cpp" | ||||
| #include "pattern2.cpp" | ||||
| #include "flags.cpp" | ||||
| #include "yendor.cpp" | ||||
|   | ||||
| @@ -3094,7 +3094,7 @@ namespace windmap { | ||||
|       // cw.spin = 0; | ||||
|       neighbors.emplace_back(); | ||||
|       auto &v = neighbors.back(); | ||||
|       if(gp::on) | ||||
|       if(gp::on || irr::on) | ||||
|         for(int l=0; l<S7; l++) { | ||||
|           heptspin hs(cw.c->master, cw.spin); | ||||
|           hs = hs + l + wstep; | ||||
|   | ||||
							
								
								
									
										119
									
								
								floorshapes.cpp
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								floorshapes.cpp
									
									
									
									
									
								
							| @@ -218,9 +218,17 @@ void bshape_regular(floorshape &fsh, int id, int sides, int shift, ld size) { | ||||
|     } | ||||
|   } | ||||
|  | ||||
| namespace irr { void generate_floorshapes(); } | ||||
|  | ||||
| void generate_floorshapes() { | ||||
|  | ||||
|   if(irr::on) { | ||||
|     printf("generating irregular floorshapes...\n"); | ||||
|     irr::generate_floorshapes(); | ||||
|     printf("done\n"); | ||||
|     return; | ||||
|     } | ||||
|      | ||||
|   if(gp::on) { | ||||
|     return; | ||||
|     } | ||||
| @@ -489,6 +497,103 @@ namespace gp { | ||||
|     } | ||||
|   } | ||||
|  | ||||
| namespace irr { | ||||
|  | ||||
|   map<int, matrixlist> usedml; | ||||
|  | ||||
|   void generate_floorshapes() { | ||||
|    | ||||
|     if(irr::cells.empty()) return; | ||||
|  | ||||
|     for(auto pfsh: all_escher_floorshapes) { | ||||
|       auto& fsh = *pfsh; | ||||
|       generate_matrices_scale(1, fsh.noftype); | ||||
|       auto& m = hept_matrices; | ||||
|        | ||||
|       /* if(siid == 0) | ||||
|         for(auto& ma: m.v) ma.first = ma.first * pispin; */ | ||||
|    | ||||
|       fsh.b.resize(irr::sc); | ||||
|  | ||||
|       for(int id=0; id<irr::sc; id++) {       | ||||
|         auto& vs = irr::cells[id]; | ||||
|  | ||||
|         int cor = isize(vs.vertices); | ||||
|         m.n.sym = cor;       | ||||
|          | ||||
|         int i = 0; | ||||
|    | ||||
|         for(int d=0; d<m.o.sym; d++) { | ||||
|           hyperpoint center = hpxy(0,0); | ||||
|      | ||||
|           for(int c=0; c<cor; c++) { | ||||
|             hyperpoint nlcorner = vs.vertices[(d+c+1) % cor]; | ||||
|             hyperpoint nrcorner = vs.vertices[(d+c+2) % cor]; | ||||
|              | ||||
|             hyperpoint nfar = vs.jpoints[vs.neid[(d+c+1) % cor]]; | ||||
|             hyperpoint nlfar = nfar; | ||||
|             hyperpoint nrfar = nfar; | ||||
|             m.v[i].second[c] = build_matrix(center, nlcorner, nrcorner); | ||||
|             m.v[i+1].second[c] = build_matrix(nfar, nlcorner, nrcorner); | ||||
|             m.v[i+2].second[c] = build_matrix(nfar, nlcorner, nlfar); | ||||
|             m.v[i+3].second[c] = build_matrix(nfar, nrcorner, nrfar); | ||||
|             } | ||||
|            | ||||
|           i += 4; | ||||
|           } | ||||
|            | ||||
|         usedml[id] = m; | ||||
|        | ||||
|         m.n.sym = cor; | ||||
|         bshape2(fsh.b[id], fsh.prio, fsh.shapeid2 ? fsh.shapeid2 : fsh.shapeid1, m); | ||||
|         } | ||||
|       } | ||||
|      | ||||
|     for(auto pfsh: all_plain_floorshapes) { | ||||
|       auto& fsh = *pfsh; | ||||
|  | ||||
|       ld sca = fsh.rad0 / shFullFloor.rad0; | ||||
|        | ||||
|       fsh.b.resize(irr::sc); | ||||
|       fsh.shadow.resize(irr::sc);         | ||||
|        | ||||
|       for(int i=0; i<irr::sc; i++) {       | ||||
|         auto& vs = irr::cells[i]; | ||||
|         vector<hyperpoint> cornerlist; | ||||
|          | ||||
|         int cor = isize(vs.vertices); | ||||
|         for(int j=0; j<cor; j++) | ||||
|           cornerlist.push_back(rspintox(vs.vertices[j]) * xpush(hdist0(vs.vertices[j]) * sca) * C0); | ||||
|        | ||||
|         bshape(fsh.b[i], fsh.prio); | ||||
|         for(int i=0; i<=cor; i++) hpcpush(cornerlist[i%cor]); | ||||
|          | ||||
|         bshape(fsh.shadow[i], fsh.prio); | ||||
|         for(int i=0; i<=cor; i++) | ||||
|           hpcpush(mid_at(hpxy(0,0), cornerlist[i%cor], SHADMUL)); | ||||
|          | ||||
|         cell fc; | ||||
|         fc.type = cor; | ||||
|         irr::cellindex[&fc] = i; | ||||
|          | ||||
|         // printf("at = %d,%d cor = %d sca = %lf\n", li.relative.first, li.relative.second, cor, sca); | ||||
|    | ||||
|         for(int k=0; k<SIDEPARS; k++)  | ||||
|           for(int c=0; c<cor; c++) { | ||||
|             fsh.gpside[k][c].resize(irr::sc); | ||||
|             bshape(fsh.gpside[k][c][i], fsh.prio); | ||||
|             hpcpush(iddspin(&fc, c) * cornerlist[c]); | ||||
|             hpcpush(iddspin(&fc, c) * cornerlist[(c+1)%cor]); | ||||
|             chasmifyPoly(dlow_table[k], dhi_table[k], k); | ||||
|             } | ||||
|         } | ||||
|       } | ||||
|      | ||||
|     finishshape(); last = NULL; | ||||
|     extra_vertices(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| qfloorinfo qfi; | ||||
| qfloorinfo qfi_dc; | ||||
|  | ||||
| @@ -521,6 +626,13 @@ void draw_shapevec(cell *c, const transmatrix& V, const vector<hpcshape> &shv, i | ||||
|     int id = gp::get_plainshape_id(c); | ||||
|     queuepolyat(V, shv[id], col, prio); | ||||
|     } | ||||
|   else if(irr::on) { | ||||
|     int id = irr::cellindex[c]; | ||||
|     if(id < 0 || id >= isize(shv)) { | ||||
|       return; | ||||
|       } | ||||
|     queuepolyat(V, shv[id], col, prio); | ||||
|     } | ||||
|   else if((euclid || gp::on) && ishex1(c))  | ||||
|     queuepolyat(V * pispin, shv[0], col, prio); | ||||
|   else if(!(S7&1) && nonbitrunc) { | ||||
| @@ -566,8 +678,13 @@ void viewmat() { | ||||
|     gp::just_matrices = false; | ||||
|     } | ||||
|   // if(gp::on && !gp::usedml.count(cwt.c)) return; | ||||
|   for(auto& v: (pseudohept(cwt.c) ? hept_matrices : hex_matrices).v) { | ||||
| //  for(auto& v: (pseudohept(cwt.c) ? hept_matrices : hex_matrices).v) { | ||||
| //  for(auto& v: (gp::on ? gp::usedml[cwt.c] : pseudohept(cwt.c) ? hept_matrices : hex_matrices).v) { | ||||
| //    hyperpoint h1 = gmatrix[cwt.c] * v.second[0] * hpxyz(1,0,0); | ||||
|   id = irr::cellindex[cwt.c]; | ||||
|   for(auto& v: irr::usedml[id].v) {  | ||||
| //  for(auto& v: (gp::on ? gp::usedml[cwt.c] : pseudohept(cwt.c) ? hept_matrices : hex_matrices).v) { | ||||
|      | ||||
|     hyperpoint h1 = gmatrix[cwt.c] * v.second[0] * hpxyz(1,0,0); | ||||
|     hyperpoint h2 = gmatrix[cwt.c] * v.second[0] * hpxyz(0,1,0); | ||||
|     hyperpoint h3 = gmatrix[cwt.c] * v.second[0] * hpxyz(0,0,1); | ||||
|   | ||||
| @@ -170,6 +170,7 @@ void precalc() { | ||||
|   base_distlimit = ginf[geometry].distlimit[nonbitrunc]; | ||||
|    | ||||
|   gp::compute_geometry();   | ||||
|   irr::compute_geometry(); | ||||
|   } | ||||
|  | ||||
| transmatrix ddi(ld dir, ld dist) { | ||||
|   | ||||
							
								
								
									
										10
									
								
								goldberg.cpp
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								goldberg.cpp
									
									
									
									
									
								
							| @@ -857,16 +857,18 @@ namespace hr { namespace gp { | ||||
|     return dmain + length(centerloc-at) - length(centerloc); | ||||
|     } | ||||
|    | ||||
|   array<cell*, 3> get_masters(cell *c) { | ||||
|   array<heptagon*, 3> get_masters(cell *c) { | ||||
|     if(gp::on) { | ||||
|       auto li = get_local_info(c); | ||||
|       be_in_triangle(li);       | ||||
|       auto cm = c->master; | ||||
|       int i = li.last_dir; | ||||
|       return make_array(cm->c7, createStep(cm, i)->c7, createStep(cm, fix7(i+1))->c7); | ||||
|       return make_array(cm, createStep(cm, i), createStep(cm, fix7(i+1))); | ||||
|       } | ||||
|     else  | ||||
|       return make_array(c->mov[0], c->mov[2], c->mov[4]);     | ||||
|     else if(irr::on) | ||||
|       return irr::get_masters(c); | ||||
|     else | ||||
|       return make_array(c->mov[0]->master, c->mov[2]->master, c->mov[4]->master); | ||||
|     } | ||||
|    | ||||
|   int compute_dist(cell *c, int master_function(cell*)) { | ||||
|   | ||||
							
								
								
									
										28
									
								
								graph.cpp
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								graph.cpp
									
									
									
									
									
								
							| @@ -158,6 +158,7 @@ void drawSpeed(const transmatrix& V) { | ||||
|   } | ||||
|  | ||||
| int ctof(cell *c) { | ||||
|   if(irr::on) return irr::ctof(c); | ||||
|   if(nonbitrunc && !gp::on) return 1; | ||||
|   // if(euclid) return 0; | ||||
|   return ishept(c) ? 1 : 0; | ||||
| @@ -232,7 +233,14 @@ void drawLightning(const transmatrix& V) { | ||||
|   } | ||||
|  | ||||
| int displaydir(cell *c, int d) { | ||||
|   if(euclid) | ||||
|   if(irr::on) { | ||||
|     auto id = irr::cellindex[c]; | ||||
|     auto& vs = irr::cells[id]; | ||||
|     if(d < 0 || d >= c->type) return 0; | ||||
|     auto& p = vs.jpoints[vs.neid[d]]; | ||||
|     return -int(atan2(p[1], p[0]) * S84 / 2 / M_PI + MODFIXER + .5); | ||||
|     } | ||||
|   else if(euclid) | ||||
|     return - d * S84 / c->type; | ||||
|   else | ||||
|     return S42 - d * S84 / c->type; | ||||
| @@ -2092,7 +2100,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) { | ||||
|       Vb = Vb * pispin; | ||||
|       Vb = Vb * xpush(tentacle_length - cellgfxdist(c, c->mondir)); | ||||
|       } | ||||
|     else if(gp::on) { | ||||
|     else if(gp::on || irr::on) { | ||||
|       transmatrix T = shmup::calc_relative_matrix(c->mov[c->mondir], c, c->mondir); | ||||
|       Vb = Vb * T * rspintox(tC0(inverse(T))) * xpush(tentacle_length); | ||||
|       } | ||||
| @@ -3076,6 +3084,7 @@ bool noAdjacentChasms(cell *c) { | ||||
|  | ||||
| // does the current geometry allow nice duals | ||||
| bool has_nice_dual() { | ||||
|   if(irr::on) return false; | ||||
|   if(!nonbitrunc) return true; | ||||
|   if((S7 & 1) == 0) return true; | ||||
|   if(!gp::on) return false; | ||||
| @@ -3171,8 +3180,8 @@ bool placeSidewall(cell *c, int i, int sidepar, const transmatrix& V, int col) { | ||||
|   else prio = PPR_REDWALL-2+4*(sidepar-SIDE_SLEV); | ||||
|    | ||||
|   transmatrix V2 = V * ddspin(c, i); | ||||
|    | ||||
|   if(gp::on) { | ||||
|   | ||||
|   if(gp::on || irr::on) { | ||||
|     draw_shapevec(c, V2, qfi.fshape->gpside[sidepar][i], col, prio); | ||||
|     return false; | ||||
|     } | ||||
| @@ -4024,7 +4033,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { | ||||
|          | ||||
|         case laSwitch: | ||||
|           set_floor(shSwitchFloor); | ||||
|           if(ctof(c)) for(int i=0; i<c->type; i++) | ||||
|           if(ctof(c) && !gp::on && !irr::on) for(int i=0; i<c->type; i++) | ||||
|             queuepoly(Vf * ddspin(c, i, S6) * xpush(rhexf), shSwitchDisk, darkena(minf[active_switch()].color, fd, 0xFF)); | ||||
|           break; | ||||
|  | ||||
| @@ -4709,7 +4718,14 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { | ||||
|        | ||||
|       int prec = sphere ? 3 : 1; | ||||
|        | ||||
|       if(gp::on) { | ||||
|       if(irr::on) { | ||||
|         int id = irr::cellindex[c]; | ||||
|         auto &vs = irr::cells[id]; | ||||
|         for(int t=0; t<c->type; t++) | ||||
|           if(c->mov[t] && c->mov[t] < c) | ||||
|             queueline(V * vs.vertices[t], V * vs.vertices[(1+t)%c->type], gridcolor(c, c->mov[t]), prec); | ||||
|         } | ||||
|       else if(gp::on) { | ||||
|         vid.linewidth *= gp::scale * 2; | ||||
|         if(isWarped(c) && has_nice_dual()) { | ||||
|           if(pseudohept(c)) for(int t=0; t<c->type; t++) | ||||
|   | ||||
| @@ -75,7 +75,10 @@ heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0, int fix | ||||
|   h->move[pard] = parent; tsetspin(h->spintable, pard, d); | ||||
|   parent->move[d] = h; tsetspin(parent->spintable, d, pard); | ||||
|   if(parent->c7) { | ||||
|     h->c7 = newCell(S7, h); | ||||
|     if(irr::on) | ||||
|       irr::link_next(parent, d); | ||||
|     else | ||||
|       h->c7 = newCell(S7, h); | ||||
|     h->rval0 = h->rval1 = 0; h->cdata = NULL; | ||||
|     h->emeraldval = emerald_heptagon(parent->emeraldval, d); | ||||
|     h->zebraval = zebra_heptagon(parent->zebraval, d); | ||||
|   | ||||
							
								
								
									
										18
									
								
								hyper.h
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								hyper.h
									
									
									
									
									
								
							| @@ -78,7 +78,7 @@ void addMessage(string s, char spamtype = 0); | ||||
| #define S3 ginf[geometry].vertex | ||||
| #define hyperbolic_37 (S7 == 7 && S3 == 3) | ||||
| #define hyperbolic_not37 ((S7 > 7 || S3 > 3) && hyperbolic) | ||||
| #define weirdhyperbolic ((S7 > 7 || S3 > 3 || gp::on) && hyperbolic) | ||||
| #define weirdhyperbolic ((S7 > 7 || S3 > 3 || gp::on || irr::on) && hyperbolic) | ||||
| #define stdhyperbolic (S7 == 7 && S3 == 3 && !gp::on) | ||||
|  | ||||
| #define cgclass (ginf[geometry].cclass) | ||||
| @@ -2549,6 +2549,20 @@ struct hrmap_hyperbolic : hrmap { | ||||
|   void verify() { verifycells(origin); } | ||||
|   }; | ||||
|  | ||||
| namespace quotientspace { hrmap *new_map(); } | ||||
| namespace irr {  | ||||
|   extern bool on; | ||||
|   void link_to_base(heptagon *h, heptspin base); | ||||
|   void link_start(heptagon *h); | ||||
|   void link_next(heptagon *h, int d); | ||||
|   void may_link_next(heptagon *h, int d); | ||||
|   void link_cell(cell *c, int d); | ||||
|   void clear_links(heptagon *h); | ||||
|   bool pseudohept(cell*); | ||||
|   array<heptagon*, 3> get_masters(cell *c); | ||||
|   bool ctof(cell* c); | ||||
|   } | ||||
|  | ||||
| extern hrmap *currentmap; | ||||
| extern vector<hrmap*> allmaps; | ||||
|  | ||||
| @@ -3149,7 +3163,7 @@ namespace gp { | ||||
|  | ||||
|   int solve_triangle(int dmain, int d0, int d1, loc at); | ||||
|  | ||||
|   array<cell*, 3> get_masters(cell *c); | ||||
|   array<heptagon*, 3> get_masters(cell *c); | ||||
|   } | ||||
|  | ||||
| int get_sightrange(); | ||||
|   | ||||
							
								
								
									
										16
									
								
								hypgraph.cpp
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								hypgraph.cpp
									
									
									
									
									
								
							| @@ -486,6 +486,8 @@ ld master_to_c7_angle() { | ||||
|   } | ||||
|  | ||||
| transmatrix actualV(const heptspin& hs, const transmatrix& V) { | ||||
|   if(irr::on) | ||||
|     return V * spin(M_PI + 2 * M_PI / S7 * (hs.spin + irr::periodmap[hs.h].base.spin)); | ||||
|   return (hs.spin || nonbitrunc) ? V * spin(hs.spin*2*M_PI/S7 + master_to_c7_angle()) : V; | ||||
|   } | ||||
|  | ||||
| @@ -564,10 +566,22 @@ void drawrec(const heptspin& hs, hstate s, const transmatrix& V) { | ||||
|   transmatrix V10; | ||||
|   const transmatrix& V1 = hs.mirrored ? (V10 = V * Mirror) : V; | ||||
|    | ||||
|   bool draw = c->pathdist < PINFD; | ||||
|    | ||||
|   if(gp::on) { | ||||
|     gp::drawrec(c, actualV(hs, V1)); | ||||
|     } | ||||
|    | ||||
|   else if(irr::on) { | ||||
|     auto& hi = irr::periodmap[hs.h]; | ||||
|     transmatrix V0 = actualV(hs, V1); | ||||
|     auto& vc = irr::cells_of_heptagon[hi.base.h]; | ||||
|     for(int i=0; i<isize(vc); i++) | ||||
|       if(dodrawcell(hi.subcells[i]) && in_qrange(V0 * irr::cells[vc[i]].pusher)) | ||||
|         draw = true, | ||||
|         drawcell(hi.subcells[i], V0 * irr::cells[vc[i]].pusher, 0, false); | ||||
|     } | ||||
|    | ||||
|   else { | ||||
|     if(dodrawcell(c)) { | ||||
|       transmatrix V2 = actualV(hs, V1); | ||||
| @@ -585,7 +599,7 @@ void drawrec(const heptspin& hs, hstate s, const transmatrix& V) { | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   if(c->pathdist < PINFD && in_qrange(V)) for(int d=0; d<S7; d++) { | ||||
|   if(draw && in_qrange(V)) for(int d=0; d<S7; d++) { | ||||
|     hstate s2 = transition(s, d); | ||||
|     if(s2 == hsError) continue; | ||||
|     heptspin hs2 = hs + d + wstep; | ||||
|   | ||||
							
								
								
									
										530
									
								
								irregular.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										530
									
								
								irregular.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,530 @@ | ||||
| namespace hr { namespace irr { | ||||
|  | ||||
| bool on; | ||||
|  | ||||
| int sc = 100; | ||||
|  | ||||
| struct cellinfo { | ||||
|   cell *owner; | ||||
|   vector<hyperpoint> jpoints; | ||||
|   hyperpoint p; | ||||
|   transmatrix pusher, rpusher; | ||||
|   vector<int> neid; | ||||
|   vector<int> spin; | ||||
|   vector<hyperpoint> vertices; | ||||
|   int localindex; | ||||
|   bool is_pseudohept; | ||||
|   int patterndir; | ||||
|   }; | ||||
|  | ||||
| map<cell*, int> cellindex; | ||||
|  | ||||
| vector<cellinfo> cells; | ||||
|  | ||||
| ld inner(hyperpoint h1, hyperpoint h2) { | ||||
|   return  | ||||
|     hyperbolic ? h1[2] * h2[2] - h1[0] * h2[0] - h1[1] * h2[1] : | ||||
|     h1[2] * h2[2] + h1[0] * h2[0] + h1[1] * h2[1]; | ||||
|   } | ||||
|  | ||||
| hyperpoint circumscribe(hyperpoint a, hyperpoint b, hyperpoint c) { | ||||
|   using namespace hyperpoint_vec; | ||||
|   hyperpoint h = C0; | ||||
|  | ||||
|   b = b - a; | ||||
|   c = c - a; | ||||
|    | ||||
|   if(inner(b,b) < 0) { | ||||
|     b = b / sqrt(-inner(b, b)); | ||||
|     c = c + b * inner(c, b); | ||||
|     h = h + b * inner(h, b); | ||||
|     } | ||||
|   else { | ||||
|     b = b / sqrt(inner(b, b)); | ||||
|     c = c - b * inner(c, b); | ||||
|     h = h - b * inner(h, b); | ||||
|     } | ||||
|    | ||||
|   if(inner(c,c) < 0) { | ||||
|     c = c / sqrt(-inner(c, c)); | ||||
|     h = h + c * inner(h, c); | ||||
|     } | ||||
|   else { | ||||
|     c = c / sqrt(inner(c, c)); | ||||
|     h = h - c * inner(h, c); | ||||
|     } | ||||
|    | ||||
|   if(h[2] < 0) h[0] = -h[0], h[1] = -h[1], h[2] = -h[2]; | ||||
|  | ||||
|   ld i = inner(h, h); | ||||
|   if(i > 0) h /= sqrt(i); | ||||
|   else h /= -sqrt(-i); | ||||
|  | ||||
|   return h; | ||||
|   } | ||||
|  | ||||
| bool clockwise(hyperpoint h1, hyperpoint h2) { | ||||
|   return h1[0] * h2[1] > h1[1] * h2[0]; | ||||
|   } | ||||
|  | ||||
| map<heptagon*, vector<int> > cells_of_heptagon; | ||||
|  | ||||
| int runlevel; | ||||
| vector<ld> edgelens, distlens; | ||||
|  | ||||
| void make_cells_of_heptagon() { | ||||
|   cells_of_heptagon.clear(); | ||||
|   for(int i=0; i<isize(cells); i++) { | ||||
|     auto &p1 = cells[i]; | ||||
|     auto &vc = cells_of_heptagon[p1.owner->master]; | ||||
|     p1.localindex = isize(vc); | ||||
|     vc.push_back(i); | ||||
|     } | ||||
|   } | ||||
|    | ||||
| hrmap *base; | ||||
|  | ||||
| bool gridmaking; | ||||
|  | ||||
| bool step(int delta) { | ||||
|  | ||||
|   if(!gridmaking) return false; | ||||
|   timetowait = 0; | ||||
|  | ||||
|   auto& all = base->allcells(); | ||||
|  | ||||
|   auto t = SDL_GetTicks(); | ||||
|   while(SDL_GetTicks() < t + 250) | ||||
|   switch(runlevel) { | ||||
|     case 0: { | ||||
|  | ||||
|      cells.clear(); | ||||
|      cells_of_heptagon.clear(); | ||||
|       | ||||
|      if(sc <= isize(all) * 2) { | ||||
|        for(auto h: all) { | ||||
|          cellinfo s; s.patterndir = -1; | ||||
|          s.owner = h, s.p = spin(hrand(1000)) * xpush(.01) * C0; | ||||
|          cells.emplace_back(s); | ||||
|          } | ||||
|        } | ||||
|       runlevel++; | ||||
|       break; | ||||
|       } | ||||
|       | ||||
|     case 1: { | ||||
|       while(isize(cells) < sc) { | ||||
|         if(SDL_GetTicks() > t + 250) { make_cells_of_heptagon(); return false; } | ||||
|         cellinfo s; s.patterndir = -1; | ||||
|         ld bestval = 0; | ||||
|         for(int j=0; j<10; j++) { | ||||
|           int k = hrand(isize(all)); | ||||
|           cell *c = all[k]; | ||||
|           hyperpoint h = randomPointIn(c->type); | ||||
|           ld mindist = 1e6; | ||||
|           for(auto p: cells) { | ||||
|             ld val = hdist(h, shmup::calc_relative_matrix(p.owner, c, h) * p.p); | ||||
|             if(val < mindist) mindist = val; | ||||
|             } | ||||
|           if(mindist > bestval) bestval = mindist, s.owner = c, s.p = h; | ||||
|           } | ||||
|         // printf("%lf %p %s\n", bestval, s.owner, display(s.p)); | ||||
|         cells.emplace_back(s); | ||||
|         } | ||||
|       make_cells_of_heptagon(); | ||||
|       runlevel++; | ||||
|       break; | ||||
|       } | ||||
|      | ||||
|     case 2: { | ||||
|  | ||||
|       sort(cells.begin(), cells.end(), [] (cellinfo &s1, cellinfo &s2) { return hdist0(s1.p) < hdist0(s2.p); }); | ||||
|       make_cells_of_heptagon(); | ||||
|  | ||||
|       edgelens.clear(); | ||||
|       distlens.clear(); | ||||
|    | ||||
|       int stats[16]; | ||||
|       for(int k=0; k<16; k++) stats[k] = 0; | ||||
|        | ||||
|       for(int i=0; i<sc; i++) { | ||||
|         auto &p1 = cells[i]; | ||||
|         p1.vertices.clear(); | ||||
|         p1.neid.clear(); | ||||
|      | ||||
|         p1.pusher = rgpushxto0(p1.p); | ||||
|         p1.rpusher = gpushxto0(p1.p); | ||||
|          | ||||
|         p1.jpoints.clear(); | ||||
|      | ||||
|         for(int j=0; j<sc; j++) { | ||||
|           auto &p2 = cells[j]; | ||||
|           p1.jpoints.push_back(p1.rpusher * shmup::calc_relative_matrix(p2.owner, p1.owner, p1.p) * p2.p); | ||||
|           } | ||||
|      | ||||
|         int j = 0; | ||||
|         if(j == i) j = 1; | ||||
|      | ||||
|         for(int k=0; k<sc; k++) if(k != i) { | ||||
|           if(hdist(p1.jpoints[k], C0) < hdist(p1.jpoints[j], C0)) | ||||
|             j = k; | ||||
|           } | ||||
|            | ||||
|         hyperpoint t = mid(p1.jpoints[j], C0); | ||||
|               // p1.vertices.push_back(p1.pusher * t); | ||||
|         int j0 = j; | ||||
|         int oldj = j; | ||||
|         do { | ||||
|           int best_k = -1; | ||||
|           hyperpoint best_h; | ||||
|           for(int k=0; k<sc; k++) if(k != i && k != j && k != oldj) { | ||||
|             hyperpoint h = circumscribe(C0, p1.jpoints[j], p1.jpoints[k]); | ||||
|             if(h[2] < 0) continue; | ||||
|             if(!clockwise(t, h)) continue; | ||||
|             if(best_k == -1) | ||||
|               best_k = k, best_h = h; | ||||
|             else if(clockwise(h, best_h)) | ||||
|               best_k = k, best_h = h; | ||||
|             } | ||||
|           p1.vertices.push_back(best_h); | ||||
|           p1.neid.push_back(best_k); | ||||
|           distlens.push_back(hdist0(best_h)); | ||||
|           oldj = j, j = best_k, t = best_h; | ||||
|           if(j == -1) break; | ||||
|           if(isize(p1.vertices) == 15) break; | ||||
|           } | ||||
|         while(j != j0); | ||||
|          | ||||
|         for(int j=0; j<isize(p1.vertices); j++) | ||||
|           edgelens.push_back(hdist(p1.vertices[j], p1.vertices[(j+1) % isize(p1.vertices)])); | ||||
|      | ||||
|         stats[isize(p1.vertices)]++; | ||||
|         } | ||||
|      | ||||
|       for(int a=0; a<16; a++) printf("%3d ", stats[a]); | ||||
|       if(isize(edgelens)) { | ||||
|         printf("|"); | ||||
|         printf("%4d ", isize(edgelens)); | ||||
|         sort(edgelens.begin(), edgelens.end()); | ||||
|         for(int a=0; a<=8; a++) printf("%6.3lf", double(edgelens[(a * isize(edgelens) - 1) / 8])); | ||||
|         printf(" | "); | ||||
|         sort(distlens.begin(), distlens.end()); | ||||
|         for(int a=0; a<=8; a++) printf("%5.2lf", double(distlens[(a * isize(edgelens) - 1) / 8])); | ||||
|         } | ||||
|       printf("\n"); | ||||
|        | ||||
|       runlevel++; | ||||
|       break; | ||||
|       } | ||||
|      | ||||
|     case 3: { | ||||
|    | ||||
|       for(int i=0; i<isize(cells); i++) if(isize(cells[i].vertices) > 8 || isize(cells[i].vertices) < 3) { | ||||
|         cells[i] = cells.back(); | ||||
|         i--; cells.pop_back(); | ||||
|         } | ||||
|       if(isize(cells) < sc*3/4) runlevel = 0; | ||||
|       else if(isize(cells) < sc) runlevel = 1; | ||||
|       else runlevel++; | ||||
|       break; | ||||
|       } | ||||
|      | ||||
|     case 4: { | ||||
|    | ||||
|       ld minedge = edgelens[isize(edgelens) / 2] / 5; | ||||
|       if(edgelens[0] < minedge) { | ||||
|         printf("rearranging\n"); | ||||
|         for(int i=0; i<isize(cells); i++) { | ||||
|           auto& p1 = cells[i]; | ||||
|           using namespace hyperpoint_vec; | ||||
|           hyperpoint h = hpxyz(0, 0, 0); | ||||
|           for(auto v: p1.vertices) h = h + v; | ||||
|      | ||||
|           for(int j=0; j<isize(p1.vertices); j++) | ||||
|             if(hdist(p1.vertices[j], p1.vertices[(j+1) % isize(p1.vertices)]) < minedge) | ||||
|               h = h + p1.vertices[j] + p1.vertices[(j+1) % isize(p1.vertices)]; | ||||
|           cells[i].p = p1.pusher * normalize(h); | ||||
|           } | ||||
|         runlevel = 2; | ||||
|         break; | ||||
|         } | ||||
|       runlevel++; | ||||
|       break; | ||||
|       } | ||||
|      | ||||
|     case 5: { | ||||
|        | ||||
|       int notfound = 0; | ||||
|      | ||||
|       for(int i=0; i<sc; i++) { | ||||
|         auto &p1 = cells[i]; | ||||
|         int N = isize(p1.vertices); | ||||
|         p1.spin.resize(N); | ||||
|         for(int j=0; j<N; j++) { | ||||
|           auto i1 = p1.neid[j]; | ||||
|           bool found = false; | ||||
|           for(int k=0; k < isize(cells[i1].vertices); k++) | ||||
|             if(cells[i1].neid[k] == i) | ||||
|               found = true, p1.spin[j] = k; | ||||
|           if(!found) notfound++; | ||||
|           } | ||||
|         } | ||||
|        | ||||
|       printf("notfound = %d\n", notfound); | ||||
|       if(notfound) { runlevel = 0; break; } | ||||
|        | ||||
|       int heptas = 0; | ||||
|       for(auto p: cells_of_heptagon) { | ||||
|         printf("%p: %d\n", p.first, isize(p.second)); | ||||
|         heptas++; | ||||
|         } | ||||
|        | ||||
|       if(heptas != isize(all)) { | ||||
|         printf("heptas = %d\n", heptas); | ||||
|         runlevel = 0; break; | ||||
|         } | ||||
|      | ||||
|       for(int i=0; i<sc; i++) { | ||||
|         auto &p1 = cells[i]; | ||||
|         for(int j: p1.neid) { | ||||
|           auto &p2 = cells[j]; | ||||
|           bool ok = p1.owner == p2.owner || isNeighbor(p1.owner, p2.owner); | ||||
|           if(!ok) { printf("far edge\n"); runlevel = 0; return false; } | ||||
|           } | ||||
|         } | ||||
|       runlevel = 10; | ||||
|        | ||||
|       for(auto& s: cells) s.is_pseudohept = false; | ||||
|       for(auto& s: cells) { | ||||
|         s.is_pseudohept = true; | ||||
|         for(int i: s.neid) if(cells[i].is_pseudohept) s.is_pseudohept = false; | ||||
|         } | ||||
|  | ||||
|       for(auto& s: cells) { | ||||
|         int d = -1; | ||||
|         ld dist = hcrossf / 2; | ||||
|         ld dists[8]; | ||||
|         for(int i=0; i<S7; i++) { | ||||
|           dists[i] = hdist(s.p, spin(hexshift - i * ALPHA) * xpush(-hcrossf) * C0); | ||||
|           // shmup::calc_relative_matrix(s.owner->mov[i], s.owner, s.p) * C0); | ||||
|           // spin(2 * M_PI * i / S7) * xpush(hcrossf) * C0); | ||||
|           if(dists[i] < dist) | ||||
|             d = i, dist = dists[i];             | ||||
|           } | ||||
|         if(d != -1 && dists[(d+1) % S7] > dists[(d+S7-1) % S7]) | ||||
|           d = (d + S7 - 1) % S7; | ||||
|         s.patterndir = d; | ||||
|         } | ||||
|  | ||||
|       break; | ||||
|       } | ||||
|      | ||||
|     case 10: | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|   return false; | ||||
|   } | ||||
|  | ||||
| void compute_geometry() { | ||||
|   if(irr::on) { | ||||
|     ld scal = sqrt(isize(cells_of_heptagon) * 1. / sc); | ||||
|     crossf *= scal; | ||||
|     hepvdist *= scal; | ||||
|     rhexf *= scal; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| bool draw_cell_schematics(cell *c, transmatrix V) { | ||||
|   if(gridmaking) { | ||||
|     heptagon *h = c->master; | ||||
|     for(int i: cells_of_heptagon[h]) { | ||||
|       auto& p = cells[i]; | ||||
|       if(p.owner == c) { | ||||
|         queuestr(V * rgpushxto0(p.p), .1, its(i), isize(p.vertices) > 8 ? 0xFF0000 : 0xFFFFFF); | ||||
|         int N = isize(p.vertices); | ||||
|         for(int j=0; j<N; j++) | ||||
|           queueline(V * p.pusher * p.vertices[j], V * p.pusher * p.vertices[(1+j)%N], 0xFFFFFFFF); | ||||
|  | ||||
|         queueline(V * p.p, V * C0, 0xFF0000FF); | ||||
|         if(p.patterndir != -1) | ||||
|           queueline(V * p.p, V * shmup::calc_relative_matrix(c->master->move[p.patterndir]->c7, c, p.p) * C0, 0x00FF00FF); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   return false; | ||||
|   } | ||||
|  | ||||
| struct heptinfo { | ||||
|   heptspin base; | ||||
|   vector<cell*> subcells; | ||||
|   }; | ||||
|  | ||||
| map<heptagon*, heptinfo> periodmap; | ||||
|  | ||||
| void link_to_base(heptagon *h, heptspin base) { | ||||
|   // printf("linking %p to %p/%d\n", h, base.h, base.spin); | ||||
|   auto &hi = periodmap[h]; | ||||
|   hi.base = base; | ||||
|   for(int k: cells_of_heptagon[base.h]) { | ||||
|     cell *c = newCell(isize(cells[k].vertices), h); | ||||
|     hi.subcells.push_back(c); | ||||
|     cellindex[c] = k; | ||||
|     } | ||||
|   h->c7 = hi.subcells[0]; | ||||
|   } | ||||
|  | ||||
| void clear_links(heptagon *h) { | ||||
|   auto& hi = periodmap[h]; | ||||
|   for(cell *c: hi.subcells) { | ||||
|     for(int i=0; i<c->type; i++) if(c->mov[i]) c->mov[i]->mov[c->spin(i)] = NULL; | ||||
|     cellindex.erase(c); | ||||
|     delete c; | ||||
|     } | ||||
|   h->c7 = NULL; | ||||
|   periodmap.erase(h); | ||||
|   } | ||||
|  | ||||
| void link_start(heptagon *h) { | ||||
|   link_to_base(h, heptspin(cells[0].owner->master, 0)); | ||||
|   } | ||||
|  | ||||
| void link_next(heptagon *parent, int d) { | ||||
|   if(!periodmap.count(parent)) | ||||
|     link_to_base(parent, heptspin(cells[0].owner->master, 0)); | ||||
|   // printf("linking next: %p direction %d [s%d]\n", parent, d, parent->spin(d)); | ||||
|   auto *h = parent->move[d]; | ||||
|   heptspin hs = periodmap[parent].base + d + wstep - parent->spin(d); | ||||
|   link_to_base(h, hs); | ||||
|   } | ||||
|  | ||||
| void may_link_next(heptagon *parent, int d) { | ||||
|   if(!periodmap.count(parent->move[d])) | ||||
|     link_next(parent, d); | ||||
|   } | ||||
|  | ||||
|  | ||||
| void link_cell(cell *c, int d) { | ||||
|   // printf("linking cell: %p direction %d\n", c, d); | ||||
|   int ci = cellindex[c]; | ||||
|   auto& sc = cells[ci]; | ||||
|   int ci2 = sc.neid[d]; | ||||
|   auto& sc2 = cells[ci2]; | ||||
|    | ||||
|   heptagon *master2 = NULL; | ||||
|  | ||||
|   if(sc2.owner == sc.owner) { | ||||
|     master2 = c->master; | ||||
|     // printf("local\n"); | ||||
|     } | ||||
|   else { | ||||
|     int dirs = 0; | ||||
|     int os = periodmap[c->master].base.spin; | ||||
|     for(int d=0; d<S7; d++) if(sc2.owner->master == sc.owner->master->move[(os+d)%S7]) { | ||||
|       heptspin hss(c->master, d); | ||||
|       hss += wstep; | ||||
|       master2 = hss.h; | ||||
|       // printf("master2 is %p; base = %p; should be = %p\n", master2, periodmap[master2].base.h, sc2.owner->master); | ||||
|       dirs++; | ||||
|       } | ||||
|     if(dirs != 1) { printf("dirs error\n"); exit(1); } | ||||
|     } | ||||
|    | ||||
|   cell *c2 = periodmap[master2].subcells[sc2.localindex]; | ||||
|   c->mov[d] = c2; | ||||
|   tsetspin(c->spintable, d, sc.spin[d]); | ||||
|   c2->mov[sc.spin[d]] = c; | ||||
|   tsetspin(c2->spintable, sc.spin[d], d); | ||||
|   } | ||||
|  | ||||
| void show_gridmaker() { | ||||
|   cmode = sm::SIDE; | ||||
|   gamescreen(0);   | ||||
|   dialog::init(XLAT("Irregular grid")); | ||||
|   dialog::addSelItem(XLAT("activate"), its(runlevel), 'f'); | ||||
|   dialog::display(); | ||||
|   if(runlevel == 10) dialog::add_action([] { | ||||
|     popScreen(); | ||||
|     pop_game(); | ||||
|     for(hrmap *& hm : allmaps) if(hm == base) hm = NULL; | ||||
|     stop_game(); | ||||
|     irr::on = true; | ||||
|     nonbitrunc = true; | ||||
|     need_reset_geometry = true; | ||||
|     gridmaking = false; | ||||
|     start_game(); | ||||
|     }); | ||||
|   keyhandler = [] (int sym, int uni) { | ||||
|     dialog::handleNavigation(sym, uni); | ||||
|     // no exit | ||||
|     }; | ||||
|   } | ||||
|  | ||||
| void create_map() { | ||||
|   push_game(); | ||||
|   switch(geometry) { | ||||
|     case gNormal: | ||||
|       geometry = gKleinQuartic; | ||||
|       break; | ||||
|      | ||||
|     case gOctagon: | ||||
|       geometry = gBolza2; | ||||
|       break; | ||||
|      | ||||
|     default: ; | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   nonbitrunc = true; | ||||
|   need_reset_geometry = true; | ||||
|   start_game(); | ||||
|   base = currentmap;  | ||||
|   drawthemap(); | ||||
|   pushScreen(show_gridmaker); | ||||
|   runlevel = 0; | ||||
|   gridmaking = true; | ||||
|   } | ||||
|    | ||||
| int readArgs() { | ||||
|   using namespace arg; | ||||
|             | ||||
|   if(0) ; | ||||
|   else if(argis("-irr")) { | ||||
|     PHASE(3); | ||||
|     shift(); sc = argi(); | ||||
|     restart_game(); | ||||
|     create_map(); | ||||
|     } | ||||
|   else return 1; | ||||
|   return 0; | ||||
|   } | ||||
|  | ||||
| bool pseudohept(cell* c) { | ||||
|   return cells[cellindex[c]].is_pseudohept; | ||||
|   } | ||||
|  | ||||
| bool ctof(cell* c) { | ||||
|   return cells[cellindex[c]].patterndir == -1; | ||||
|   } | ||||
|  | ||||
| array<heptagon*, 3> get_masters(cell *c) { | ||||
|   int d = cells[cellindex[c]].patterndir; | ||||
|   heptspin s = periodmap[c->master].base; | ||||
|   heptspin s0 = heptspin(c->master, 0) + (d - s.spin); | ||||
|   return make_array(s0.h, (s0 + wstep).h, (s0 + 1 + wstep).h); | ||||
|   } | ||||
|  | ||||
| auto hook =  | ||||
|   addHook(hooks_args, 100, readArgs) +  | ||||
|   addHook(hooks_drawcell, 100, draw_cell_schematics) + | ||||
|   addHook(shmup::hooks_turn, 100, step); | ||||
|  | ||||
|   }} | ||||
|  | ||||
| /* | ||||
|   if(mouseover && !ctof(mouseover)) { | ||||
|     for(auto h: gp::get_masters(mouseover))  | ||||
|       queueline(shmup::ggmatrix(h->c7)*C0, shmup::ggmatrix(mouseover)*C0, 0xFFFFFFFF); | ||||
|     } | ||||
|      | ||||
| */ | ||||
| @@ -210,14 +210,14 @@ void giantLandSwitch(cell *c, int d, cell *from) { | ||||
|       else { | ||||
|  | ||||
|         if(d == 9) { | ||||
|           cell *c2 = gp::on ? c->master->c7 : c; | ||||
|           cell *c2 = (gp::on || irr::on) ? c->master->c7 : c; | ||||
|           if(cdist50(c2) == 3 && polarb50(c2) == 1) | ||||
|             c->wall = waPalace; | ||||
|           } | ||||
|        | ||||
|         if(d == 8 && sphere) { | ||||
|           int gs = getHemisphere(c,0); | ||||
|           if(gp::on) { | ||||
|           if(gp::on || irr::on) { | ||||
|             int v = 1; | ||||
|             forCellEx(c2, c) if(getHemisphere(c2, 0) != gs) | ||||
|               v = 2; | ||||
| @@ -583,7 +583,7 @@ void giantLandSwitch(cell *c, int d, cell *from) { | ||||
|             else if(v == 25 || v == 59 || v == 27 || v == 57) | ||||
|               c->wall = waVineHalfB; | ||||
|             else c->wall = waNone; | ||||
|             if(gp::on && cellHalfvine(c)) { | ||||
|             if((gp::on || irr::on) && cellHalfvine(c)) { | ||||
|               c->wall = waNone; | ||||
|               forCellCM(c2, c) if(emeraldval(c2) == (v^1)) | ||||
|                 c->wall = waVinePlant; | ||||
|   | ||||
| @@ -1159,6 +1159,15 @@ land_validity_t& land_validity(eLand l) { | ||||
|   if(isWarped(l) && a4 && gp::on) | ||||
|     return dont_work; | ||||
|    | ||||
|   if((isWarped(l) || l == laDual) && irr::on) | ||||
|     return dont_work; | ||||
|    | ||||
|   if(irr::on && among(l, laStorms, laPrairie, laBlizzard, laVolcano)) | ||||
|     return dont_work; | ||||
|  | ||||
|   if(irr::on && among(l, laWhirlpool, laCamelot, laCaribbean, laClearing, laTemple, laHive, laMirror, laMirrorOld, laReptile, laKraken, laBurial)) | ||||
|     return dont_work; | ||||
|    | ||||
|   // equidistant-based lands | ||||
|   if(isEquidLand(l)) { | ||||
|     // no equidistants supported in chaos mode | ||||
|   | ||||
| @@ -826,7 +826,7 @@ void setAppropriateOverview() { | ||||
|     pushScreen(yendor::showMenu); | ||||
|   else if(peace::on) | ||||
|     pushScreen(peace::showMenu); | ||||
|   else if((geometry != gNormal || gp::on) && !chaosmode && !(geometry == gEuclid && isCrossroads(specialland)) && !(weirdhyperbolic && specialland == laCrossroads4)) { | ||||
|   else if((geometry != gNormal || gp::on || irr::on) && !chaosmode && !(geometry == gEuclid && isCrossroads(specialland)) && !(weirdhyperbolic && specialland == laCrossroads4)) { | ||||
|     runGeometryExperiments(); | ||||
|     } | ||||
|   else { | ||||
|   | ||||
							
								
								
									
										103
									
								
								pattern2.cpp
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								pattern2.cpp
									
									
									
									
									
								
							| @@ -49,11 +49,13 @@ bool ishex2(cell *c) { | ||||
|   else return c->type != S6; | ||||
|   } | ||||
|  | ||||
| int emeraldval(heptagon *h) { return h->emeraldval >> 3; } | ||||
|  | ||||
| int emeraldval(cell *c) { | ||||
|   if(euclid) return eupattern(c); | ||||
|   if(sphere) return 0; | ||||
|   if(ctof(c)) | ||||
|     return c->master->emeraldval >> 3; | ||||
|     return emeraldval(c->master); | ||||
|   else { | ||||
|     auto ar = gp::get_masters(c); | ||||
|     return emerald_hexagon( | ||||
| @@ -96,9 +98,9 @@ int fiftyval(cell *c) { | ||||
|   else { | ||||
|     auto ar = gp::get_masters(c); | ||||
|     return bitmajority( | ||||
|       fiftyval(ar[0]),  | ||||
|       fiftyval(ar[1]),  | ||||
|       fiftyval(ar[2])) + 512; | ||||
|       ar[0]->fiftyval,  | ||||
|       ar[1]->fiftyval,  | ||||
|       ar[2]->fiftyval) + 512; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -109,47 +111,47 @@ int cdist50(cell *c) { | ||||
|       return "0123333332112332223322233211233333322"[eufifty(c)] - '0'; | ||||
|     else return "012333321112322232222321123"[eufifty(c)] - '0'; | ||||
|     } | ||||
|   if(c->type != 6) return cdist50(fiftyval(c)); | ||||
|   if(ctof(c)) return cdist50(c->master->fiftyval); | ||||
|   auto ar = gp::get_masters(c); | ||||
|   int a0 = cdist50(ar[0]); | ||||
|   int a1 = cdist50(ar[1]); | ||||
|   int a2 = cdist50(ar[2]); | ||||
|   int a0 = cdist50(ar[0]->fiftyval); | ||||
|   int a1 = cdist50(ar[1]->fiftyval); | ||||
|   int a2 = cdist50(ar[2]->fiftyval); | ||||
|   if(a0 == 0 || a1 == 0 || a2 == 0) return 1; | ||||
|   return a0+a1+a2-5; | ||||
|   } | ||||
|  | ||||
| int land50(cell *c) { | ||||
|   if(c->type != 6) return land50(fiftyval(c)); | ||||
|   else if(sphere || euclid) return 0; | ||||
|   if(sphere || euclid) return 0; | ||||
|   else if(ctof(c)) return land50(fiftyval(c)); | ||||
|   else { | ||||
|     auto ar = gp::get_masters(c); | ||||
|     for(int i=0; i<3; i++) | ||||
|       if(cdist50(ar[i]) < 3) return land50(ar[i]); | ||||
|       if(cdist50(ar[i]->fiftyval) < 3) return land50(ar[i]->fiftyval); | ||||
|     return 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| int polara50(cell *c) { | ||||
|   if(c->type != 6) return polara50(fiftyval(c)); | ||||
|   else if(sphere || euclid || S7>7 || S6>6) return 0; | ||||
|   else if(gp::on) return polara50(fiftyval(c->master->c7)); | ||||
|   if(sphere || euclid || S7>7 || S6>6) return 0; | ||||
|   else if(gp::on || irr::on) return polara50(fiftyval(c->master->c7)); | ||||
|   else if(ctof(c)) return polara50(fiftyval(c)); | ||||
|   else { | ||||
|     auto ar = gp::get_masters(c); | ||||
|     for(int i=0; i<3; i++) | ||||
|       if(cdist50(ar[i]) < 3) return polara50(ar[i]); | ||||
|       if(cdist50(ar[i]->fiftyval) < 3) return polara50(ar[i]->fiftyval); | ||||
|     return 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| int polarb50(cell *c) { | ||||
|   if(euclid) return true; | ||||
|   if(c->type != 6) return polarb50(fiftyval(c)); | ||||
|   else if(sphere || euclid || S7>7 || S6>6) return true; | ||||
|   else if(gp::on) return polarb50(fiftyval(c->master->c7)); | ||||
|   if(sphere || euclid || S7>7 || S6>6) return true; | ||||
|   else if(gp::on || irr::on) return polarb50(fiftyval(c->master->c7)); | ||||
|   else if(ctof(c)) return polarb50(fiftyval(c)); | ||||
|   else { | ||||
|     auto ar = gp::get_masters(c); | ||||
|     for(int i=0; i<3; i++) | ||||
|       if(cdist50(ar[i]) < 3) return polarb50(ar[i]); | ||||
|       if(cdist50(ar[i]->fiftyval) < 3) return polarb50(ar[i]->fiftyval); | ||||
|     return 0; | ||||
|     } | ||||
|   } | ||||
| @@ -158,30 +160,32 @@ int elhextable[28][3] = { | ||||
|   {0,1,2}, {1,2,9}, {1,9,-1}, {1,8,-1}, {1,-1,-1} | ||||
|   }; | ||||
|  | ||||
| int fiftyval049(heptagon *h) { | ||||
|   int i = h->fiftyval / 32; | ||||
|   if(i <= 7) return i; | ||||
|   if(quotient) return 0; | ||||
|   vector<int> allcodes; | ||||
|   for(int k=0; k<7; k++) { | ||||
|     heptagon *h2 = createStep(h, k); | ||||
|     if(polara50(h2->fiftyval) == polara50(h->fiftyval) && polarb50(h2->fiftyval) == polarb50(h->fiftyval)) | ||||
|       allcodes.push_back(fiftyval049(h2)); | ||||
|     } | ||||
|   int d = allcodes[1] - allcodes[0]; | ||||
|   if(d == -1 || d == 6) swap(allcodes[0], allcodes[1]); | ||||
|   // printf("%d,%d: %d\n", allcodes[0], allcodes[1], allcodes[0] + 7); | ||||
|   return allcodes[0] + 7; | ||||
|   } | ||||
|  | ||||
| int fiftyval049(cell *c) { | ||||
|   if(euclid) return fiftyval(c) / 32; | ||||
|   else if(ctof(c)) { | ||||
|     int i = fiftyval(c) / 32; | ||||
|     if(i <= 7) return i; | ||||
|     if(quotient) return 0; | ||||
|     vector<int> allcodes; | ||||
|     for(int k=0; k<7; k++) { | ||||
|       cell *c2 = createStep(c->master, k)->c7; | ||||
|       if(polara50(c2) == polara50(c) && polarb50(c2) == polarb50(c))         | ||||
|         allcodes.push_back(fiftyval049(c2)); | ||||
|       } | ||||
|     int d = allcodes[1] - allcodes[0]; | ||||
|     if(d == -1 || d == 6) swap(allcodes[0], allcodes[1]); | ||||
|     // printf("%d,%d: %d\n", allcodes[0], allcodes[1], allcodes[0] + 7); | ||||
|     return allcodes[0] + 7; | ||||
|     } | ||||
|   else if(ctof(c)) return fiftyval049(c->master); | ||||
|   else if(sphere) return 0; | ||||
|   else { | ||||
|     int a[3], qa=0; | ||||
|     int pa = polara50(c), pb = polarb50(c); | ||||
|     auto ar = gp::get_masters(c); | ||||
|     for(int i=0; i<3; i++) | ||||
|       if(polara50(ar[i]) == pa && polarb50(ar[i]) == pb) | ||||
|       if(polara50(ar[i]->fiftyval) == pa && polarb50(ar[i]->fiftyval) == pb) | ||||
|         a[qa++] = fiftyval049(ar[i]); | ||||
|     // 0-1-2 | ||||
|     sort(a, a+qa); | ||||
| @@ -248,6 +252,7 @@ int val46(cell *c); | ||||
|  | ||||
| int zebra40(cell *c) { | ||||
|   if(euclid) return eupattern(c); | ||||
|   else if(irr::on) return c->master->zebraval/10; | ||||
|   else if(a46) { | ||||
|     int v = val46(c); | ||||
|     if(v<4) return v; | ||||
| @@ -285,9 +290,9 @@ int zebra40(cell *c) { | ||||
|   else { | ||||
|     int ii[3], z; | ||||
|     auto ar = gp::get_masters(c); | ||||
|     ii[0] = (ar[0]->master->zebraval/10); | ||||
|     ii[1] = (ar[1]->master->zebraval/10); | ||||
|     ii[2] = (ar[2]->master->zebraval/10); | ||||
|     ii[0] = (ar[0]->zebraval/10); | ||||
|     ii[1] = (ar[1]->zebraval/10); | ||||
|     ii[2] = (ar[2]->zebraval/10); | ||||
|     for(int r=0; r<2; r++)  | ||||
|       if(ii[1] < ii[0] || ii[2] < ii[0])  | ||||
|         z = ii[0], ii[0] = ii[1], ii[1] = ii[2], ii[2] = z; | ||||
| @@ -304,14 +309,14 @@ int zebra40(cell *c) { | ||||
|   } | ||||
|  | ||||
| int zebra3(cell *c) { | ||||
|   if(c->type != 6) return (c->master->zebraval/10)/4; | ||||
|   else if(sphere || S7>7 || S6>6) return 0; | ||||
|   if(ctof(c)) return (c->master->zebraval/10)/4; | ||||
|   else if(euclid || sphere || S7>7 || S6>6) return 0; | ||||
|   else {  | ||||
|     int ii[3]; | ||||
|     auto ar = gp::get_masters(c); | ||||
|     ii[0] = (ar[0]->master->zebraval/10)/4; | ||||
|     ii[1] = (ar[1]->master->zebraval/10)/4; | ||||
|     ii[2] = (ar[2]->master->zebraval/10)/4; | ||||
|     ii[0] = (ar[0]->zebraval/10)/4; | ||||
|     ii[1] = (ar[1]->zebraval/10)/4; | ||||
|     ii[2] = (ar[2]->zebraval/10)/4; | ||||
|     if(ii[0] == ii[1]) return ii[0]; | ||||
|     if(ii[1] == ii[2]) return ii[1]; | ||||
|     if(ii[2] == ii[0]) return ii[2]; | ||||
| @@ -328,7 +333,7 @@ pair<int, bool> fieldval(cell *c) { | ||||
|  | ||||
| int fieldval_uniq(cell *c) { | ||||
|   if(sphere) { | ||||
|     if(ctof(c)) return c->master->fieldval; | ||||
|     if(ctof(c) || gp::on || irr::on) return c->master->fieldval; | ||||
|     else return createMov(c, 0)->master->fieldval + 256 * createMov(c,2)->master->fieldval + (1<<16) * createMov(c,4)->master->fieldval; | ||||
|     } | ||||
|   else if(torus) { | ||||
| @@ -338,7 +343,7 @@ int fieldval_uniq(cell *c) { | ||||
|     auto p = cell_to_pair(c); | ||||
|     return gmod(p.first * torusconfig::dx + p.second * torusconfig::dy, torusconfig::qty); | ||||
|     } | ||||
|   if(ctof(c) || gp::on) return c->master->fieldval/S7; | ||||
|   if(ctof(c) || gp::on || irr::on) return c->master->fieldval/S7; | ||||
|   else { | ||||
|     int z = 0; | ||||
|     for(int u=0; u<S6; u+=2)  | ||||
| @@ -348,7 +353,7 @@ int fieldval_uniq(cell *c) { | ||||
|   } | ||||
|  | ||||
| int fieldval_uniq_rand(cell *c, int randval) { | ||||
|   if(sphere || torus || euclid)  | ||||
|   if(sphere || torus || euclid || gp::on || irr::on)  | ||||
|     // we do not care in these cases | ||||
|     return fieldval_uniq(c); | ||||
|   if(ctof(c)) return currfp.gmul(c->master->fieldval, randval)/7; | ||||
| @@ -708,7 +713,8 @@ namespace patterns { | ||||
|     } | ||||
|  | ||||
|   void val_all(cell *c, patterninfo &si, int sub, int pat) { | ||||
|     if(a46) val46(c, si, sub, pat); | ||||
|     if(irr::on) si.symmetries = 1; | ||||
|     else if(a46) val46(c, si, sub, pat); | ||||
|     else if(a38) val38(c, si, sub, pat); | ||||
|     else if(sphere) valSibling(c, si, sub, pat); | ||||
|     else if(euclid4) valEuclid4(c, si, sub); | ||||
| @@ -1005,6 +1011,7 @@ namespace patterns { | ||||
|   } | ||||
|  | ||||
| int geosupport_threecolor() { | ||||
|   if(irr::on) return 0; | ||||
|   if(!nonbitrunc && S3 == 3) { | ||||
|     if(S7 % 2) return 1; | ||||
|     return 2; | ||||
| @@ -1019,6 +1026,7 @@ int geosupport_threecolor() { | ||||
| int geosupport_graveyard() { | ||||
|   // always works in bitrunc geometries | ||||
|   if(!nonbitrunc) return 2; | ||||
|   if(irr::on) return 0; | ||||
|    | ||||
|   // always works in patterns supporting three-color | ||||
|   int tc = max(geosupport_threecolor(), gp_threecolor()); | ||||
| @@ -1130,6 +1138,7 @@ int pattern_threecolor(cell *c) { | ||||
| // in the 'pure heptagonal' tiling, returns true for a set of cells | ||||
| // which roughly corresponds to the heptagons in the normal tiling | ||||
| bool pseudohept(cell *c) { | ||||
|   if(irr::on) return irr::pseudohept(c); | ||||
|   if(gp::on && gp_threecolor() == 2) | ||||
|     return gp::pseudohept_val(c) == 0; | ||||
|   if(gp::on && gp_threecolor() == 1 && (S7&1) && (S3 == 3)) | ||||
|   | ||||
| @@ -3313,7 +3313,12 @@ void destroyBoats(cell *c) { | ||||
|   } | ||||
|  | ||||
| transmatrix master_relative(cell *c, bool get_inverse) { | ||||
|   if(gp::on) { | ||||
|   if(irr::on) { | ||||
|     int id = irr::cellindex[c]; | ||||
|     ld alpha = 2 * M_PI / S7 * irr::periodmap[c->master].base.spin; | ||||
|     return get_inverse ? irr::cells[id].rpusher * spin(-alpha-master_to_c7_angle()): spin(alpha + master_to_c7_angle()) * irr::cells[id].pusher; | ||||
|     } | ||||
|   else if(gp::on) { | ||||
|     if(c == c->master->c7) { | ||||
|       return spin((get_inverse?-1:1) * master_to_c7_angle()); | ||||
|       } | ||||
|   | ||||
| @@ -1029,10 +1029,10 @@ namespace gamestack { | ||||
|   bool pushed() { return isize(gd); } | ||||
|    | ||||
|   void push() { | ||||
|     if(geometry) { | ||||
|     /* if(geometry) { | ||||
|       printf("ERROR: push implemented only in non-hyperbolic geometry\n"); | ||||
|       exit(1); | ||||
|       } | ||||
|       } */ | ||||
|     gamedata gdn; | ||||
|     gdn.hmap = currentmap; | ||||
|     gdn.cwt = cwt; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue