#include "../hyper.h" #include #include #include namespace hr { namespace subquotient { eGeometry gSubquotient(eGeometry(-1)); vector 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; itype; i++) for(int m=0; m<2; m++) { vector visited; map 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; itype; 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 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; jtype; 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 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> 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 ids; int next_id = 0; vector by_id; set 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; itype; 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; }); } }