mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-20 23:50:27 +00:00
rulegen:: smarter get_side by caching data inside tcell and by noting down known information on the way
This commit is contained in:
parent
d7d3d21d2a
commit
d40ea1d6ba
58
rulegen.cpp
58
rulegen.cpp
@ -113,6 +113,10 @@ struct tcell {
|
|||||||
/** can we assume that dist is correct? if we assumed that the dist is correct but then find out it was wrong, throw an error */
|
/** can we assume that dist is correct? if we assumed that the dist is correct but then find out it was wrong, throw an error */
|
||||||
bool is_solid;
|
bool is_solid;
|
||||||
bool distance_fixed;
|
bool distance_fixed;
|
||||||
|
/** is side info cached? */
|
||||||
|
unsigned long long known_sides;
|
||||||
|
/** which side is it */
|
||||||
|
unsigned long long which_side;
|
||||||
/** sometimes we find out that multiple tcells represent the same actual cell -- in this case we unify them; unified_to is used for the union-find algorithm */
|
/** sometimes we find out that multiple tcells represent the same actual cell -- in this case we unify them; unified_to is used for the union-find algorithm */
|
||||||
walker<tcell> unified_to;
|
walker<tcell> unified_to;
|
||||||
int degree() { return type; }
|
int degree() { return type; }
|
||||||
@ -183,6 +187,8 @@ tcell *gen_tcell(int id) {
|
|||||||
c->code = MYSTERY_LARGE;
|
c->code = MYSTERY_LARGE;
|
||||||
c->parent_dir = MYSTERY;
|
c->parent_dir = MYSTERY;
|
||||||
c->old_parent_dir = MYSTERY;
|
c->old_parent_dir = MYSTERY;
|
||||||
|
c->known_sides = 0;
|
||||||
|
c->which_side = 0;
|
||||||
first_tcell = c;
|
first_tcell = c;
|
||||||
// println(hlog, c, " is a new tcell of id ", id);
|
// println(hlog, c, " is a new tcell of id ", id);
|
||||||
tcellcount++;
|
tcellcount++;
|
||||||
@ -1098,7 +1104,32 @@ void treewalk(twalker& cw, int delta) {
|
|||||||
cw+=delta;
|
cw+=delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX map<twalker, int> sidecache;
|
EX vector<tcell*> sidecaches_to_clear;
|
||||||
|
|
||||||
|
void clear_sidecache() {
|
||||||
|
if(sidecaches_to_clear.size()) {
|
||||||
|
for(auto c: sidecaches_to_clear)
|
||||||
|
c->which_side = c->known_sides = 0;
|
||||||
|
sidecaches_to_clear.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_sidecache(twalker what, int side) {
|
||||||
|
auto c = what.at;
|
||||||
|
if(c->known_sides == 0) sidecaches_to_clear.push_back(c);
|
||||||
|
unsigned long long bit = 1ll<<what.spin;
|
||||||
|
c->known_sides |= bit;
|
||||||
|
if(side > 0)
|
||||||
|
c->which_side |= bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_sidecache(twalker what) {
|
||||||
|
auto c = what.at;
|
||||||
|
unsigned long long bit = 1ll<<what.spin;
|
||||||
|
if(c->known_sides & bit)
|
||||||
|
return (c->which_side & bit) ? 1 : -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int get_side(twalker what) {
|
int get_side(twalker what) {
|
||||||
|
|
||||||
@ -1106,8 +1137,8 @@ int get_side(twalker what) {
|
|||||||
bool fast = !(flags & w_slow_side);
|
bool fast = !(flags & w_slow_side);
|
||||||
|
|
||||||
if(side) {
|
if(side) {
|
||||||
auto ww = at_or_null(sidecache, what);
|
auto w = get_sidecache(what);
|
||||||
if(ww) return *ww;
|
if(w) return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = 99;
|
int res = 99;
|
||||||
@ -1154,6 +1185,8 @@ int get_side(twalker what) {
|
|||||||
auto to_what = what + wstep;
|
auto to_what = what + wstep;
|
||||||
auto ws = what; treewalk(ws, 0); if(ws == to_what) res = 0;
|
auto ws = what; treewalk(ws, 0); if(ws == to_what) res = 0;
|
||||||
|
|
||||||
|
static vector<twalker> lstack = {nullptr}, rstack = {nullptr};
|
||||||
|
lstack.resize(1); rstack.resize(1);
|
||||||
while(res == 99) {
|
while(res == 99) {
|
||||||
handle_distance_errors();
|
handle_distance_errors();
|
||||||
steps++; if(steps > max_getside) {
|
steps++; if(steps > max_getside) {
|
||||||
@ -1164,16 +1197,31 @@ int get_side(twalker what) {
|
|||||||
bool gl = wl.at->dist <= wr.at->dist;
|
bool gl = wl.at->dist <= wr.at->dist;
|
||||||
bool gr = wl.at->dist >= wr.at->dist;
|
bool gr = wl.at->dist >= wr.at->dist;
|
||||||
if(gl) {
|
if(gl) {
|
||||||
|
if(get_sidecache(wl) == 1) wl += wstep;
|
||||||
treewalk(wl, -1);
|
treewalk(wl, -1);
|
||||||
if(wl == to_what) { res = 1; }
|
if(wl == to_what) { res = 1; }
|
||||||
|
if(lstack.back() == wl+wstep) {
|
||||||
|
set_sidecache(lstack.back(), 1);
|
||||||
|
set_sidecache(wl, -1);
|
||||||
|
lstack.pop_back();
|
||||||
|
}
|
||||||
|
else if(wl.at->parent_dir != wl.spin && (wl+wstep).at->parent_dir != (wl+wstep).spin) lstack.push_back(wl);
|
||||||
}
|
}
|
||||||
if(gr) {
|
if(gr) {
|
||||||
|
if(get_sidecache(wr) == -1) wr += wstep;
|
||||||
treewalk(wr, +1);
|
treewalk(wr, +1);
|
||||||
if(wr == to_what) {res = -1; }
|
if(wr == to_what) {res = -1; }
|
||||||
|
if(rstack.back() == wr+wstep) {
|
||||||
|
set_sidecache(rstack.back(), -1);
|
||||||
|
set_sidecache(wr, +1);
|
||||||
|
rstack.pop_back();
|
||||||
|
}
|
||||||
|
else if(wr.at->parent_dir != wr.spin && (wr+wstep).at->parent_dir != (wr+wstep).spin) rstack.push_back(wr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(side) sidecache[what] = res, sidecache[what + wstep] = -res;
|
if(side && res)
|
||||||
|
set_sidecache(what, res), set_sidecache(what + wstep, -res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1708,7 +1756,7 @@ EX void clean_data() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EX void clear_sidecache_and_codes() {
|
EX void clear_sidecache_and_codes() {
|
||||||
sidecache.clear();
|
clear_sidecache();
|
||||||
need_clear_codes = true;
|
need_clear_codes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user