1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-10-31 19:36:16 +00:00

rulegen:: base the functions on twalkers to avoid unification errors

This commit is contained in:
Zeno Rogue 2021-12-24 23:08:14 +01:00
parent a373bad6c7
commit a065fc4d86
2 changed files with 92 additions and 83 deletions

View File

@ -45,7 +45,7 @@ struct hrmap_testproto : hrmap {
}
heptagon *getOrigin() override {
return clone(t_origin[0]);
return clone(t_origin[0].at);
}
heptagon *create_step(heptagon *h, int d) override {
@ -179,9 +179,9 @@ void move_to(twalker dw) {
move_to(cellwalker(m->clone(dw.at)->c7, dw.spin, dw.mirrored));
}
void sprawl(tcell *c) {
void sprawl(twalker c) {
auto [d, id] = get_code(c);
twalker cw(c, d);
twalker cw(c.at, d);
cur_sprawl = spread(get_analyzer(cw), cw);
println(hlog, "sprawl result = ", cur_sprawl);
println(hlog, "code = ", treestates[id].code);
@ -211,7 +211,7 @@ void debug_menu() {
dialog::addItem("sprawl", 's');
dialog::add_action([m] {
sprawl(m->counterpart[centerover->master]);
sprawl(twalker(m->counterpart[centerover->master], 0));
});
dialog::addItem("parent_dir", 'p');
@ -228,7 +228,8 @@ void debug_menu() {
c->parent_dir = MYSTERY;
parent_debug = true;
try {
get_parent_dir(c);
twalker cw(c, 0);
get_parent_dir(cw);
}
catch(rulegen_failure& f) {
println(hlog, "catched: ", f.what());
@ -984,9 +985,10 @@ void label_all(int i, int mode) {
if(cdist == i) break;
}
try {
twalker cw(c, 0);
if(mode & 4) index_pointer(c);
if(mode & 1) get_parent_dir(c);
if(mode & 2) get_code(c);
if(mode & 1) get_parent_dir(cw);
if(mode & 2) get_code(cw);
}
catch(hr_exception& ex) {
}

View File

@ -389,7 +389,7 @@ EX void unify(twalker pw1, twalker pw2) {
fix_distances(pw1.at);
}
EX vector<tcell*> t_origin;
EX vector<twalker> t_origin;
EX void delete_tmap() {
while(first_tcell) {
@ -430,16 +430,21 @@ struct shortcut {
EX map<int, vector<unique_ptr<shortcut>> > shortcuts;
vector<int> root_path(twalker cw) {
vector<int> root_path(twalker& cw) {
cw += wstep;
vector<int> res;
while(true) {
int i = cw.at->dist == 0 ? 0 : get_parent_dir(cw.at);
int j = cw.to_spin(i);
if(cw.at->dist == 0) {
int j = cw.to_spin(0);
res.push_back(j);
if(cw.at->dist == 0) return res;
cw += j;
cw += wstep;
return res;
}
else {
auto cwd = get_parent_dir(cw);
int j = cw.to_spin(cwd.spin);
res.push_back(j);
cw = cwd + wstep;
}
}
}
@ -752,13 +757,10 @@ void trace_root_path(vector<int>& rp, twalker cw) {
if(d > 0) {
ufind(cw);
handle_distance_errors();
int di = side ? -1 : get_parent_dir(cw.at);
auto cw1 = cw;
ufind(cw);
if(cw != cw1) goto next;
auto cwd = get_parent_dir(cw);
for(int i=0; i<cw.at->type; i++) {
if((!side) && (cw+i).spin != di) continue;
tcell *c1 = (cw+i).peek();
if((!side) && (cw+i) != cwd) continue;
tcell *c1 = cwd.peek();
if(!c1) continue;
be_solid(c1);
handle_distance_errors();
@ -781,13 +783,16 @@ void trace_root_path(vector<int>& rp, twalker cw) {
/** which neighbor will become the parent of c */
EX int get_parent_dir(tcell *c) {
if(c->parent_dir != MYSTERY) return c->parent_dir;
EX twalker get_parent_dir(twalker& cw) {
tcell*& c = cw.at;
if(c->parent_dir != MYSTERY) return twalker(c, c->parent_dir);
int bestd = -1;
vector<int> bestrootpath;
be_solid(c);
auto oc = c;
if(c->dist > 0) {
auto& sh = arb::current.shapes[c->id];
int n = sh.size();
@ -805,20 +810,16 @@ EX int get_parent_dir(tcell *c) {
int d = c->dist;
for(int i=0; i<n; i++) {
ensure_shorter(twalker(c, i));
ensure_shorter(cw+i);
tcell *c1 = c->cmove(i);
be_solid(c1);
if(parent_debug) println(hlog, "direction = ", i, " is ", c1, " distance = ", c1->dist);
if(c1->dist < d) nearer.push_back(i);
ufind(cw); if(d != cw.at->dist || oc != cw.at) return get_parent_dir(cw);
}
if(parent_debug) println(hlog, "nearer = ", nearer, " n=", n, " k=", k);
auto oc = c;
ufindc(c); if(d != c->dist || oc != c) {
return get_parent_dir(c);
}
bool failed = false;
if(flags & w_parent_always) {failed = true; goto resolve; }
@ -864,7 +865,7 @@ EX int get_parent_dir(tcell *c) {
if(parent_debug) println(hlog, "set parent_dir to ", bestd);
c->parent_dir = bestd;
return bestd;
return twalker(c, bestd);
}
/** determine states for tcells */
@ -974,7 +975,7 @@ struct treestate {
twalker giver;
int sid;
int parent_dir;
tcell* where_seen;
twalker where_seen;
code_t code;
bool is_live;
bool is_possible_parent;
@ -997,13 +998,12 @@ EX set<tcell*> single_live_branch_close_to_root;
/** is what on the left side, or the right side, of to_what? */
void treewalk(twalker& cw, int delta) {
int d = get_parent_dir(cw.at);
if(cw.spin == d) cw = addstep(cw);
auto cwd = get_parent_dir(cw);
if(cw == cwd) cw = addstep(cw);
else {
auto cw1 = addstep(cw);
get_parent_dir(cw1.at);
ufind(cw1);
if(get_parent_dir(cw1.at) == cw1.spin) cw = cw1;
auto cwd = get_parent_dir(cw1);
if(cwd == cw1) cw = cw1;
}
cw+=delta;
}
@ -1027,15 +1027,13 @@ int get_side(twalker what) {
twalker w = what;
twalker tw = what + wstep;
auto adv = [] (twalker& cw) {
int d = get_parent_dir(cw.at);
ufind(cw);
if(cw.at->move(d)->dist >= cw.at->dist) {
cw = get_parent_dir(cw);
if(cw.peek()->dist >= cw.at->dist) {
handle_distance_errors();
if(debugflags & DF_GEOM)
println(hlog, "get_parent_dir error at ", cw, " and ", cw.at->move(d), ": ", cw.at->dist, "::", cw.at->move(d)->dist);
println(hlog, "get_parent_dir error at ", cw, " and ", cw.at->move(cw.spin), ": ", cw.at->dist, "::", cw.at->move(cw.spin)->dist);
throw rulegen_failure("get_parent_dir error");
}
cw.spin = d;
cw += wstep;
};
while(w.at != tw.at) {
@ -1052,11 +1050,11 @@ int get_side(twalker what) {
adv(w); adv(tw);
}
}
int d = get_parent_dir(w.at);
if(d >= 0 && !single_live_branch_close_to_root.count(w.at)) {
twalker last(w.at, d);
res = last.to_spin(w.spin) - last.to_spin(tw.spin);
if(w.at->dist && !single_live_branch_close_to_root.count(w.at)) {
twalker wd = get_parent_dir(w);
ufind(tw);
res = wd.to_spin(w.spin) - wd.to_spin(tw.spin);
}
}
@ -1107,8 +1105,12 @@ code_t id_at_spin(twalker cw) {
}
else if(id == 0) x = C_CHILD;
else {
int p = get_parent_dir(cs.at);
if(p >= 0 && get_parent_dir(cs.at) == cs.spin)
bool child = false;
if(cs.at->dist) {
auto csd = get_parent_dir(cs);
child = cs == csd;
}
if(child)
x = C_CHILD;
else {
auto cs2 = cs + wstep;
@ -1134,7 +1136,8 @@ code_t id_at_spin(twalker cw) {
map<code_t, int> code_to_id;
EX pair<int, int> get_code(tcell *c) {
EX pair<int, int> get_code(twalker& cw) {
tcell *c = cw.at;
if(c->code != MYSTERY && c->parent_dir != MYSTERY) {
int bestd = c->parent_dir;
if(bestd == -1) bestd = 0;
@ -1143,34 +1146,35 @@ EX pair<int, int> get_code(tcell *c) {
be_solid(c);
int bestd = get_parent_dir(c);
if(bestd == -1) bestd = 0;
twalker cd = c->dist == 0 ? twalker(c, 0) : get_parent_dir(cw);
if(cd.at != c) ufind(cw);
indenter ind(2);
code_t v = id_at_spin(twalker(c, bestd));
code_t v = id_at_spin(cd);
if(code_to_id.count(v)) {
c->code = code_to_id[v];
return {bestd, code_to_id[v]};
cd.at->code = code_to_id[v];
return {cd.spin, code_to_id[v]};
}
int id = isize(treestates);
code_to_id[v] = id;
if(c->code != MYSTERY && (c->code != id || c->parent_dir != bestd)) {
if(cd.at->code != MYSTERY && (cd.at->code != id || cd.at->parent_dir != cd.spin)) {
throw rulegen_retry("exit from get_code");
}
c->code = id;
cd.at->code = id;
treestates.emplace_back();
auto& nts = treestates.back();
nts.id = id;
nts.code = v;
nts.where_seen = c;
nts.where_seen = cw;
nts.known = false;
nts.is_live = true;
return {bestd, id};
return {cd.spin, id};
}
/* == rule generation == */
@ -1180,9 +1184,9 @@ EX int rule_root;
vector<int> gen_rule(twalker cwmain);
EX int try_count;
EX vector<tcell*> important;
EX vector<twalker> important;
vector<tcell*> cq;
vector<twalker> cq;
#if HDR
/* special codes */
@ -1196,14 +1200,14 @@ vector<int> gen_rule(twalker cwmain, int id) {
vector<int> cids;
for(int a=0; a<cwmain.at->type; a++) {
auto front = cwmain+a;
tcell *c1 = front.cpeek();
be_solid(c1);
twalker c1 = front + wstep;
be_solid(c1.at);
if(a == 0 && cwmain.at->dist) { cids.push_back(DIR_PARENT); continue; }
if(c1->dist <= cwmain.at->dist) { cids.push_back(DIR_UNKNOWN); continue; }
if(c1.at->dist <= cwmain.at->dist) { cids.push_back(DIR_UNKNOWN); continue; }
auto co = get_code(c1);
auto& d1 = co.first;
auto& id1 = co.second;
if(c1->cmove(d1) != cwmain.at || c1->c.spin(d1) != front.spin) {
if(c1.at->cmove(d1) != cwmain.at || c1.at->c.spin(d1) != front.spin) {
cids.push_back(DIR_UNKNOWN); continue;
}
cids.push_back(id1);
@ -1223,13 +1227,13 @@ vector<int> gen_rule(twalker cwmain, int id) {
return cids;
}
void rules_iteration_for(tcell *c) {
void rules_iteration_for(twalker& cw) {
indenter ri(2);
ufindc(c);
auto co = get_code(c);
ufind(cw);
auto co = get_code(cw);
auto& d = co.first;
auto& id = co.second;
twalker cwmain(c,d);
twalker cwmain(cw.at, d);
ufind(cwmain);
vector<int> cids = gen_rule(cwmain, id);
@ -1241,7 +1245,7 @@ void rules_iteration_for(tcell *c) {
ts.giver = cwmain;
ts.sid = cwmain.at->id;
ts.parent_dir = cwmain.spin;
ts.is_root = c->dist == 0;
ts.is_root = cw.at->dist == 0;
}
else if(ts.rules != cids) {
handle_distance_errors();
@ -1275,7 +1279,7 @@ void rules_iteration_for(tcell *c) {
if(debugflags & DF_GEOM) {
println(hlog, "code mismatch (", c1[k], " vs ", c2[k], " at position ", k, " out of ", isize(c1), ")");
println(hlog, "rulegiver = ", treestates[id].giver, " c = ", cwmain);
println(hlog, "gshvid = ", c->id);
println(hlog, "gshvid = ", cw.at->id);
println(hlog, "cellcount = ", tcellcount, "-", tunified, " codes discovered = ", isize(treestates));
}
@ -1400,8 +1404,8 @@ void find_possible_parents() {
using tsinfo = pair<int, int>;
tsinfo get_tsinfo(twalker tw) {
auto co = get_code(tw.at);
tsinfo get_tsinfo(twalker& tw) {
auto co = get_code(tw);
int spin;
if(co.first == -1) spin = tw.spin;
else spin = gmod(tw.spin - co.first, tw.at->type);
@ -1452,8 +1456,9 @@ set<conflict_id_type> branch_conflicts_seen;
void verified_treewalk(twalker& tw, int id, int dir) {
if(id >= 0) {
auto co = get_code(tw.cpeek());
if(co.second != id || co.first != (tw+wstep).spin) {
auto tw1 = tw + wstep;
auto co = get_code(tw1);
if(co.second != id || co.first != tw1.spin) {
handle_distance_errors();
conflict_id_type conflict_id = make_pair(make_pair((tw+wstep).spin,id), co);
@ -1571,10 +1576,10 @@ void clear_codes() {
}
}
void find_single_live_branch(twalker at) {
void find_single_live_branch(twalker& at) {
handle_distance_errors();
rules_iteration_for(at.at);
int id = get_code(at.at).second;
rules_iteration_for(at);
int id = get_code(at).second;
int t = at.at->type;
auto r = treestates[id].rules; /* no & because may move */
int q = 0;
@ -1584,8 +1589,10 @@ void find_single_live_branch(twalker at) {
}
for(int i=0; i<t; i++) if(r[i] >= 0) {
single_live_branch_close_to_root.insert(at.at);
if(!treestates[r[i]].is_live || q == 1)
find_single_live_branch(at + i + wstep);
if(!treestates[r[i]].is_live || q == 1) {
auto at1 = at + i + wstep;
find_single_live_branch(at1);
}
}
}
@ -1806,7 +1813,7 @@ EX void generate_rules() {
cell_to_tcell[s] = c;
tcell_to_cell[c] = s;
c->dist = 0;
t_origin.push_back(c);
t_origin.push_back(twalker(c, 0));
if((flags & w_known_structure) && !(flags & w_single_origin))
add_other_origins(currentmap);
@ -1816,16 +1823,16 @@ EX void generate_rules() {
else if(flags & w_single_origin) {
tcell *c = gen_tcell(origin_id);
c->dist = 0;
t_origin.push_back(c);
t_origin.push_back(twalker(c, 0));
}
else for(auto& ts: arb::current.shapes) {
tcell *c = gen_tcell(ts.id);
c->dist = 0;
t_origin.push_back(c);
t_origin.push_back(twalker(c, 0));
}
bfs_queue = queue<tcell*>();
if(flags & w_bfs) for(auto c: t_origin) bfs_queue.push(c);
if(flags & w_bfs) for(auto c: t_origin) bfs_queue.push(c.at);
try_count = 0;
@ -2043,7 +2050,7 @@ EX void add_other_origins(hrmap *m0) {
cell_to_tcell[s] = c;
tcell_to_cell[c] = s;
c->dist = 0;
t_origin.push_back(c);
t_origin.push_back(twalker(c, 0));
m->extra_origins.push_back(extra_origin);
}