hyperrogue/rogueviz/subquotient.cpp

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;
});
}
}