mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 14:02:59 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			179 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #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 swb: vmap) {
 | |
|       auto& s = swb.first;
 | |
|       auto& wb = swb.second;
 | |
|       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;
 | |
|   });
 | |
| 
 | |
| }
 | |
| 
 | |
| } | 
