diff --git a/rulegen.cpp b/rulegen.cpp index 28ed1bc5..7e85ed8c 100644 --- a/rulegen.cpp +++ b/rulegen.cpp @@ -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(); diff --git a/rulegen3.cpp b/rulegen3.cpp index c12f1487..243fbac7 100644 --- a/rulegen3.cpp +++ b/rulegen3.cpp @@ -11,6 +11,78 @@ namespace hr { EX namespace rulegen { +struct road_shortcut_trie_vertex { + set> backpaths; + map> children; + }; + +EX map> road_shortcuts; + +int qroad; + +map qroad_for; +map qroad_memo; + +EX void add_road_shortcut(tcell *s, tcell *t) { + shared_ptr u; + vector tpath; + if(!road_shortcuts.count(s->id)) road_shortcuts[s->id] = make_shared(); + 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(); + 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 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, 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 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>& check_all_edges(twalker cw, analyzer_state* a, int id if(ae.empty()) { set seen; vector > visited; + vector> 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>& 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>& 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");