1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-20 23:50:27 +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 { heptagon *getOrigin() override {
return clone(t_origin[0]); return clone(t_origin[0].at);
} }
heptagon *create_step(heptagon *h, int d) override { 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)); 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); auto [d, id] = get_code(c);
twalker cw(c, d); twalker cw(c.at, d);
cur_sprawl = spread(get_analyzer(cw), cw); cur_sprawl = spread(get_analyzer(cw), cw);
println(hlog, "sprawl result = ", cur_sprawl); println(hlog, "sprawl result = ", cur_sprawl);
println(hlog, "code = ", treestates[id].code); println(hlog, "code = ", treestates[id].code);
@ -211,7 +211,7 @@ void debug_menu() {
dialog::addItem("sprawl", 's'); dialog::addItem("sprawl", 's');
dialog::add_action([m] { dialog::add_action([m] {
sprawl(m->counterpart[centerover->master]); sprawl(twalker(m->counterpart[centerover->master], 0));
}); });
dialog::addItem("parent_dir", 'p'); dialog::addItem("parent_dir", 'p');
@ -228,7 +228,8 @@ void debug_menu() {
c->parent_dir = MYSTERY; c->parent_dir = MYSTERY;
parent_debug = true; parent_debug = true;
try { try {
get_parent_dir(c); twalker cw(c, 0);
get_parent_dir(cw);
} }
catch(rulegen_failure& f) { catch(rulegen_failure& f) {
println(hlog, "catched: ", f.what()); println(hlog, "catched: ", f.what());
@ -984,9 +985,10 @@ void label_all(int i, int mode) {
if(cdist == i) break; if(cdist == i) break;
} }
try { try {
twalker cw(c, 0);
if(mode & 4) index_pointer(c); if(mode & 4) index_pointer(c);
if(mode & 1) get_parent_dir(c); if(mode & 1) get_parent_dir(cw);
if(mode & 2) get_code(c); if(mode & 2) get_code(cw);
} }
catch(hr_exception& ex) { catch(hr_exception& ex) {
} }

View File

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