1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-29 19:40:35 +00:00

rulegen3:: new features

This commit is contained in:
Zeno Rogue 2022-07-13 19:31:24 +02:00
parent 6bc3dc9d6f
commit 0b4df47964
2 changed files with 109 additions and 5 deletions

View File

@ -86,6 +86,8 @@ static const flagtype w_less_smart_retrace = Flag(22); /*< stop early when exami
static const flagtype w_less_smart_advance = Flag(23); /*< stop early when examining smart shortcut advancement */
static const flagtype w_no_queued_extensions = Flag(24); /*< consider extensions one by one */
static const flagtype w_no_branch_skipping = Flag(24); /*< do not skip branches */
static const flagtype w_vertex_edges = Flag(25); /*< in reg3 all_edges, consider vertex adjacency */
static const flagtype w_ae_extra_step = Flag(26); /*< in reg3 all_edges, make one extra step */
#endif
EX flagtype flags = 0;
@ -186,15 +188,17 @@ twalker addstep(twalker x) {
return x + wstep;
}
EX int less_states;
int number_of_types() {
if(arb::in()) return isize(arb::current.shapes);
if(WDIM == 3) return reg3::quotient_count_sub();
if(WDIM == 3) return gcd(reg3::quotient_count_sub(), less_states);
throw hr_exception("unknown number_of_types");
}
int get_id(cell *c) {
if(arb::in()) return shvid(c);
if(GDIM == 3) return reg3::get_aid(c);
if(GDIM == 3) return zgmod(reg3::get_aid(c), less_states);
throw hr_exception("unknown get_id");
}
@ -753,7 +757,7 @@ EX void handle_distance_errors() {
}
/** make sure that we know c->dist */
void be_solid(tcell *c) {
EX void be_solid(tcell *c) {
if(c->is_solid) return;
if(tcellcount >= max_tcellcount)
throw rulegen_surrender("max_tcellcount exceeded");
@ -1797,7 +1801,7 @@ bool examine_branch(int id, int left, int right) {
bool need_clear_codes;
void clear_codes() {
EX void clear_codes() {
need_clear_codes = false;
for(auto a: all_analyzers) {
for(auto tw: a->inhabitants) tw.at->code = MYSTERY_LARGE;
@ -2015,6 +2019,10 @@ EX void rules_iteration() {
if(isize(important) != N)
throw rulegen_retry("need more rules after examine");
if(WDIM == 3) {
check_road_shortcuts();
}
if(skipped_branches.size()) {
checks_to_skip.clear();
for(auto sb: skipped_branches) sb();

View File

@ -11,6 +11,78 @@ namespace hr {
EX namespace rulegen {
struct road_shortcut_trie_vertex {
set<vector<int>> backpaths;
map<int, shared_ptr<struct road_shortcut_trie_vertex>> children;
};
EX map<int, shared_ptr<struct road_shortcut_trie_vertex>> road_shortcuts;
int qroad;
map<int, int> qroad_for;
map<tcell*, int> qroad_memo;
EX void add_road_shortcut(tcell *s, tcell *t) {
shared_ptr<road_shortcut_trie_vertex> u;
vector<int> tpath;
if(!road_shortcuts.count(s->id)) road_shortcuts[s->id] = make_shared<road_shortcut_trie_vertex>();
u = road_shortcuts[s->id];
while(true) {
// println(hlog, s, " dist=", s->dist, " parent = ", s->parent_dir, " vs ", t, " dist=", t->dist, " parent = ", t->parent_dir);
if(s == t) {
reverse(tpath.begin(), tpath.end());
auto& ba = u->backpaths;
if(!ba.count(tpath)) qroad++, qroad_for[s->id]++;
ba.insert(tpath);
return;
}
if(s->dist >= t->dist) {
twalker sw = s;
get_parent_dir(sw);
if(s->parent_dir == MYSTERY) throw hr_exception("unknown parent_dir (s) in add_road_shortcut");
if(!u->children.count(s->parent_dir)) u->children[s->parent_dir] = make_shared<road_shortcut_trie_vertex>();
u = u->children[s->parent_dir];
s = s->move(s->parent_dir);
}
if(t->dist > s->dist) {
twalker tw = t;
get_parent_dir(tw);
if(t->parent_dir == MYSTERY) throw hr_exception("unknown parent_dir (t) in add_road_shortcut");
tpath.push_back(t->c.spin(t->parent_dir));
t = t->move(t->parent_dir);
}
}
}
EX int newcon;
EX void apply_road_shortcut(tcell *s) {
auto& mem = qroad_memo[s];
if(mem == qroad_for[s->id]) return;
mem = qroad_for[s->id];
shared_ptr<road_shortcut_trie_vertex> u;
if(!road_shortcuts.count(s->id)) return;
u = road_shortcuts[s->id];
int q = tcellcount;
while(true) {
for(auto& v: u->backpaths) {
auto s1 = s;
for(auto x: v) {
s1 = s1->cmove(x);
be_solid(s1);
}
}
twalker s0 = s; get_parent_dir(s0);
if(!u->children.count(s->parent_dir)) break;
u = u->children[s->parent_dir];
s = s->move(s->parent_dir);
}
static int qmax = 0;
newcon += tcellcount - q;
if(tcellcount > q + qmax) println(hlog, "road shortcuts created ", qmax = tcellcount-q, " new connections");
}
/** next roadsign ID -- they start at -100 and go downwards */
int next_roadsign_id = -100;
@ -20,6 +92,7 @@ EX map<vector<int>, int> roadsign_id;
EX int get_roadsign(twalker what) {
int dlimit = what.at->dist - 1;
tcell *s = what.at, *t = what.peek();
apply_road_shortcut(s);
vector<int> result;
while(s->dist > dlimit) {
twalker s0 = s;
@ -55,6 +128,7 @@ EX int get_roadsign(twalker what) {
visit(c->move(i), c->c.spin(i));
}
while(t != s) {
add_road_shortcut(s, t);
int d = visited.at(t);
tail.push_back(t->dist - dlimit);
tail.push_back(t->c.spin(d));
@ -73,6 +147,7 @@ EX vector<pair<int, int>>& check_all_edges(twalker cw, analyzer_state* a, int id
if(ae.empty()) {
set<tcell*> seen;
vector<pair<twalker, transmatrix> > visited;
vector<pair<int, int>> ae1;
auto visit = [&] (twalker tw, const transmatrix& T, int id, int dir) {
if(seen.count(tw.at)) return;
seen.insert(tw.at);
@ -88,7 +163,12 @@ EX vector<pair<int, int>>& check_all_edges(twalker cw, analyzer_state* a, int id
for(auto w: rotated)
if(sqhypot_d(MDIM, v-w) < 1e-6)
common++;
if(common < 2) return;
if(flags & w_vertex_edges) {
if(common < 1) { ae1.emplace_back(id, dir); return; }
}
else {
if(common < 2) { ae1.emplace_back(id, dir); return; }
}
visited.emplace_back(tw, T);
ae.emplace_back(id, dir);
};
@ -99,6 +179,7 @@ EX vector<pair<int, int>>& check_all_edges(twalker cw, analyzer_state* a, int id
visit(tw + j + wstep, visited[i].second * currentmap->adj(tcell_to_cell[tw.at], (tw+j).spin), i, j);
}
}
if(flags & w_ae_extra_step) for(auto p: ae1) ae.push_back(p);
println(hlog, "for ", tie(cw.at->id, cw.spin), " generated all_edges structure: ", ae, " of size ", isize(ae));
}
return ae;
@ -110,6 +191,21 @@ EX void cleanup3() {
next_roadsign_id = -100;
}
int last_qroad;
EX void check_road_shortcuts() {
println(hlog, "road shortcuts = ", qroad, " treestates = ", isize(treestates), " roadsigns = ", next_roadsign_id);
if(qroad > last_qroad) {
println(hlog, "qroad_for = ", qroad_for);
println(hlog, "newcon = ", newcon, " tcellcount = ", tcellcount); newcon = 0;
clear_codes();
last_qroad = qroad;
roadsign_id.clear();
next_roadsign_id = -100;
throw rulegen_retry("new road shortcuts");
}
}
void genhoneycomb(string fname) {
if(WDIM != 3) throw hr_exception("genhoneycomb not in honeycomb");