mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-29 21:13:00 +00:00 
			
		
		
		
	rogueviz:: added subquotient space generator
This commit is contained in:
		
							
								
								
									
										177
									
								
								rogueviz/subquotient.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								rogueviz/subquotient.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | ||||
| #include "../hyper.h" | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <thread> | ||||
|  | ||||
| namespace hr { | ||||
|  | ||||
| namespace subquotient { | ||||
|  | ||||
| eGeometry gSubquotient(eGeometry(-1)); | ||||
|  | ||||
| vector<int> connections; | ||||
|  | ||||
| void create_subquotient(int qty = -1, int id = 0) { | ||||
|   start_game(); | ||||
|   auto ac = currentmap->allcells(); | ||||
|   auto ca = currentmap->gamestart(); | ||||
|    | ||||
|   for(auto cb: ac) for(int i=0; i<cb->type; i++) for(int m=0; m<2; m++) { | ||||
|     vector<cell*> visited; | ||||
|     map<cell*, cellwalker> vmap; | ||||
|      | ||||
|     auto visit = [&] (cell *da, cellwalker db) {  | ||||
|       if(vmap.count(da)) { | ||||
|         // println(hlog, da, " -> ", db, " [old]"); | ||||
|         return; | ||||
|         } | ||||
|       // println(hlog, da, " -> ", db, " [new]"); | ||||
|       vmap[da] = db; | ||||
|       visited.emplace_back(da);  | ||||
|       }; | ||||
|      | ||||
|     visit(ca, cellwalker(cb, i, m)); | ||||
|      | ||||
|     for(int i=0; i<isize(visited); i++) { | ||||
|       for(int j=0; j<visited[i]->type; j++) { | ||||
|         cellwalker wa(visited[i], 0); | ||||
|         cellwalker wb(vmap[visited[i]]); | ||||
|         wa += j; | ||||
|         wb += j; | ||||
|         wa += wstep; | ||||
|         wb += wstep; | ||||
|         int r = wa.spin; | ||||
|         wa -= r; | ||||
|         wb -= r; | ||||
|         // println(hlog, wa, " -> ", wb); | ||||
|         setdist(wa.at, 7, nullptr); | ||||
|         wa.at->item = itGold; | ||||
|         visit(wa.at, wb); | ||||
|         } | ||||
|       } | ||||
|      | ||||
|     int vertex = 0, edge = 0, badcycle = 0; | ||||
|  | ||||
|     map<int, int> by_cycle; | ||||
|      | ||||
|     for(auto [s, wb]: vmap) { | ||||
|       if(s == wb.at) { vertex++; continue; } | ||||
|       bool is_edge = false; | ||||
|       for(int j=0; j<s->type; j++) if(s->move(j) == wb.at && (wb+j).peek() == s) | ||||
|         is_edge = true; | ||||
|       if(is_edge) { edge++; continue; } | ||||
|       int cs = 0; | ||||
|       cell *sx = s; | ||||
|       auto cw = cellwalker(s, 0); | ||||
|       vector<cell*> lst; | ||||
|       do { | ||||
|         int sp = cw.spin; | ||||
|         bool mirr = cw.mirrored; | ||||
|         if(cw.mirrored) sp = -sp; | ||||
|         cw -= sp; | ||||
|         lst.push_back(sx); | ||||
|         cw = vmap[sx]; | ||||
|         if(mirr) cw += wmirror; | ||||
|         sx = cw.at; | ||||
|         cw += sp; | ||||
|         cs++; | ||||
|         if(cs >= 100) break; | ||||
|         } | ||||
|       while(sx != s); | ||||
|       if(cw.spin) badcycle++; | ||||
|       by_cycle[cs]++;       | ||||
|       } | ||||
|      | ||||
|     if(vertex || edge || badcycle || m == 0) continue; | ||||
|      | ||||
|     vector<pair<int, int>> bcp; | ||||
|     for(auto b: by_cycle) bcp.push_back(b); | ||||
|      | ||||
|     if(qty == -1) | ||||
|       println(hlog, "m=", m, " vertex/edge = ", tie(vertex, edge), " badcycle = ", badcycle, " by_cycle = ", bcp); | ||||
|      | ||||
|     if(by_cycle[qty] == isize(vmap)) { | ||||
|       if(id > 0) {id--; continue; } | ||||
|        | ||||
|       map<cell*, int> ids; | ||||
|       int next_id = 0; | ||||
|       vector<cell*> by_id; | ||||
|        | ||||
|       set<cell*> visited; | ||||
|        | ||||
|       for(auto s: ac) if(!visited.count(s)) { | ||||
|         by_id.push_back(s); | ||||
|         ids[s] = next_id; | ||||
|         auto sx = s; | ||||
|         do { | ||||
|           visited.insert(sx); | ||||
|           sx = vmap[sx].at; | ||||
|           } | ||||
|         while(sx != s); | ||||
|         next_id++; | ||||
|         } | ||||
|  | ||||
|       println(hlog, "ids = ", next_id); | ||||
|       connections.clear(); | ||||
|       if(int(gSubquotient) == -1) { | ||||
|         ginf.push_back(ginf[geometry]); | ||||
|         gSubquotient = eGeometry(isize(ginf) - 1);         | ||||
|         } | ||||
|        | ||||
|       ginf[gSubquotient] = ginf[geometry]; | ||||
|       /* we need to be 'pure', unrectified may not work */ | ||||
|       if(UNRECTIFIED) swap(ginf[gSubquotient].sides, ginf[gSubquotient].vertex); | ||||
|        | ||||
|       for(int i=0; i<next_id; i++) { | ||||
|         cell *s = by_id[i]; | ||||
|         for(int j=0; j<s->type; j++) { | ||||
|           cellwalker cw(s, j); | ||||
|           cw += wstep; | ||||
|           int res; | ||||
|           while(!ids.count(cw.at)) { | ||||
|             int sp = cw.spin; | ||||
|             bool flip = cw.mirrored; | ||||
|             if(flip) sp = -sp; | ||||
|             cw -= sp; | ||||
|             if(cw.spin) println(hlog, "bad spin"); | ||||
|             cw = vmap[cw.at]; | ||||
|             if(flip) cw += wmirror; | ||||
|             cw += sp;             | ||||
|             } | ||||
|           res = ids[cw.at] * s->type + cw.spin; | ||||
|           if(cw.mirrored)  res |= quotientspace::symmask; | ||||
|           connections.push_back(res); | ||||
|           } | ||||
|         } | ||||
|        | ||||
|       stop_game(); | ||||
|       set_geometry(gSubquotient); | ||||
|       variation = eVariation::pure; | ||||
|       println(hlog, "variation = ", int(variation)); | ||||
|       start_game(); | ||||
|       println(hlog, "started"); | ||||
|       return; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| int readArgs() { | ||||
|   using namespace arg; | ||||
|             | ||||
|   if(0) ; | ||||
|   else if(argis("-subquotient")) { start_game(); shift(); create_subquotient(argi()); } | ||||
|  | ||||
|   else return 1; | ||||
|   return 0; | ||||
|   } | ||||
|  | ||||
| auto fundamentalhook = addHook(hooks_args, 100, readArgs) | ||||
|   + addHook(hooks_newmap, 0, [] { | ||||
|     if(geometry == gSubquotient)  | ||||
|       return (hrmap*) new quotientspace::hrmap_quotient(connections); | ||||
|     return (hrmap*) nullptr; | ||||
|   }); | ||||
|  | ||||
| } | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue