diff --git a/arbitrile.cpp b/arbitrile.cpp index 1abfb8a9..e411c9b4 100644 --- a/arbitrile.cpp +++ b/arbitrile.cpp @@ -70,7 +70,7 @@ struct slider { struct arbi_tiling { int order; - bool have_line, have_ph; + bool have_line, have_ph, have_tree; vector shapes; string name; @@ -212,7 +212,7 @@ void shape::build_from_angles_edges() { for(auto& v: vertices) v = gpushxto0(ctr) * v; } -bool correct_index(int index, int size) { return index >= 0 && index < size; } +EX bool correct_index(int index, int size) { return index >= 0 && index < size; } template bool correct_index(int index, const T& v) { return correct_index(index, isize(v)); } template void verify_index(int index, const T& v, exp_parser& ep) { if(!correct_index(index, v)) throw hr_parse_exception("bad index: " + its(index) + " at " + ep.where()); } @@ -395,6 +395,8 @@ EX void load(const string& fname, bool after_sliding IS(false)) { c.range = 0; c.boundary_ratio = 1; c.floor_scale = .5; + c.have_ph = c.have_line = false; + c.have_tree = false; exp_parser ep; ep.s = s; ld angleunit = 1, distunit = 1, angleofs = 0; @@ -506,6 +508,9 @@ EX void load(const string& fname, bool after_sliding IS(false)) { c.cscale = ep.rparse(); ep.force_eat(")"); } + else if(ep.eat("treestate(")) { + rulegen::parse_treestate(c, ep); + } else if(ep.eat("range(")) { c.range = ep.iparse(); ep.force_eat(")"); @@ -639,8 +644,10 @@ EX void load(const string& fname, bool after_sliding IS(false)) { if(do_unmirror) { unmirror(); - compute_vertex_valence(); } + if(!c.have_tree) compute_vertex_valence(); + + if(c.have_tree) rulegen::verify_parsed_treestates(); if(!after_sliding) slided = current; } @@ -708,7 +715,7 @@ void connection_debugger() { dialog::add_action([k, last, con] { if(euclid) cgflags |= qAFFINE; - debug_polys.emplace_back(last.first * get_adj(debugged, last.second, k, -1), con.sid); + debug_polys.emplace_back(last.first * get_adj(debugged, last.second, k, -1, -1), con.sid); if(euclid) cgflags &= ~qAFFINE; }); @@ -742,7 +749,7 @@ EX hrmap *current_altmap; heptagon *build_child(heptspin p, pair adj); -EX transmatrix get_adj(arbi_tiling& c, int t, int dl, int xdl) { +EX transmatrix get_adj(arbi_tiling& c, int t, int dl, int t1, int xdl) { auto& sh = c.shapes[t]; @@ -751,7 +758,9 @@ EX transmatrix get_adj(arbi_tiling& c, int t, int dl, int xdl) { auto& co = sh.connections[dl]; if(xdl == -1) xdl = co.eid; - auto& xsh = c.shapes[co.sid]; + if(t1 == -1) t1 = co.sid; + + auto& xsh = c.shapes[t1]; int xdr = gmod(xdl+1, xsh.size()); hyperpoint vl = sh.vertices[dl]; @@ -836,7 +845,7 @@ struct hrmap_arbi : hrmap { void verify() override { } transmatrix adj(heptagon *h, int dl) override { - return get_adj(current_or_slided(), id_of(h), dl, h->c.move(dl) ? h->c.spin(dl) : -1); + return get_adj(current_or_slided(), id_of(h), dl, -1, h->c.move(dl) ? h->c.spin(dl) : -1); } heptagon *create_step(heptagon *h, int d) override { diff --git a/devmods/rulegen-tests.cpp b/devmods/rulegen-tests.cpp index 3a867275..82dc4e51 100644 --- a/devmods/rulegen-tests.cpp +++ b/devmods/rulegen-tests.cpp @@ -68,7 +68,7 @@ struct hrmap_testproto : hrmap { } transmatrix adj(heptagon *h, int dir) override { - return arb::get_adj(arb::current_or_slided(), shvid(h->c7), dir, h->c.move(dir) ? h->c.spin(dir) : -1); + return arb::get_adj(arb::current_or_slided(), shvid(h->c7), dir, -1, h->c.move(dir) ? h->c.spin(dir) : -1); } int shvid(cell *c) override { diff --git a/rulegen.cpp b/rulegen.cpp index 07ad8376..6f95bd08 100644 --- a/rulegen.cpp +++ b/rulegen.cpp @@ -299,6 +299,7 @@ void calc_distances(tcell *c) { void prepare_around(tcell *c) { vector q; + set visited; auto visit = [&] (tcell *x) { if(visited.count(x)) return; @@ -1433,19 +1434,21 @@ struct hrmap_rulegen : hrmap { transmatrix adj(heptagon *h, int dir) override { if(h->fieldval == -1) - return arb::get_adj(arb::current_or_slided(), h->zebraval, dir, -1); + return arb::get_adj(arb::current_or_slided(), h->zebraval, dir, -1, -1); int s = h->fieldval; int dir0 = get_arb_dir(s, dir); int dir1 = -1; + int sid1 = -1; if(h->c.move(dir)) { - int s1 = h->c.move(dir)->fieldval; + auto s1 = h->c.move(dir)->fieldval; dir1 = get_arb_dir(s1, h->c.spin(dir)); + sid1 = treestates[s1].sid; } - return arb::get_adj(arb::current_or_slided(), treestates[s].sid, dir0, dir1); + return arb::get_adj(arb::current_or_slided(), treestates[s].sid, dir0, sid1, dir1); } int shvid(cell *c) override { @@ -1526,7 +1529,7 @@ string rules_known_for = "unknown"; string rule_status; EX bool known() { - return rules_known_for == arb::current.name; + return arb::current.have_tree || rules_known_for == arb::current.name; } EX bool prepare_rules() { @@ -1583,5 +1586,46 @@ auto hooks = param_i(dlbonus, "dlbonus"); }); +EX void parse_treestate(arb::arbi_tiling& c, exp_parser& ep) { + if(!c.have_tree) { + c.have_tree = true; + treestates.clear(); + rule_root = 0; + } + treestates.emplace_back(); + auto& ts = treestates.back(); + ts.id = isize(treestates) - 1; + + ts.sid = ep.iparse(); + ts.parent_dir = 0; + if(!arb::correct_index(ts.sid, isize(c.shapes))) + throw hr_parse_exception("incorrect treestate index at " + ep.where()); + + int N = c.shapes[ts.sid].size(); + for(int i=0; i isize(treestates)) + throw hr_parse_exception("undefined treestate"); + } + for(auto& sh: arb::current.shapes) sh.cycle_length = sh.size(); + find_possible_parents(); + } + EX } }