1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-07-21 02:12:49 +00:00

arb/rulegen:: trees can now be defined in tes files

This commit is contained in:
Zeno Rogue 2021-07-30 23:50:30 +02:00
parent 0559fce5fb
commit fa03033c99
3 changed files with 65 additions and 12 deletions

View File

@ -70,7 +70,7 @@ struct slider {
struct arbi_tiling { struct arbi_tiling {
int order; int order;
bool have_line, have_ph; bool have_line, have_ph, have_tree;
vector<shape> shapes; vector<shape> shapes;
string name; string name;
@ -212,7 +212,7 @@ void shape::build_from_angles_edges() {
for(auto& v: vertices) v = gpushxto0(ctr) * v; 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<class T> bool correct_index(int index, const T& v) { return correct_index(index, isize(v)); } template<class T> bool correct_index(int index, const T& v) { return correct_index(index, isize(v)); }
template<class T> 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()); } template<class T> 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.range = 0;
c.boundary_ratio = 1; c.boundary_ratio = 1;
c.floor_scale = .5; c.floor_scale = .5;
c.have_ph = c.have_line = false;
c.have_tree = false;
exp_parser ep; exp_parser ep;
ep.s = s; ep.s = s;
ld angleunit = 1, distunit = 1, angleofs = 0; 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(); c.cscale = ep.rparse();
ep.force_eat(")"); ep.force_eat(")");
} }
else if(ep.eat("treestate(")) {
rulegen::parse_treestate(c, ep);
}
else if(ep.eat("range(")) { else if(ep.eat("range(")) {
c.range = ep.iparse(); c.range = ep.iparse();
ep.force_eat(")"); ep.force_eat(")");
@ -639,8 +644,10 @@ EX void load(const string& fname, bool after_sliding IS(false)) {
if(do_unmirror) { if(do_unmirror) {
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; if(!after_sliding) slided = current;
} }
@ -708,7 +715,7 @@ void connection_debugger() {
dialog::add_action([k, last, con] { dialog::add_action([k, last, con] {
if(euclid) cgflags |= qAFFINE; 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; if(euclid) cgflags &= ~qAFFINE;
}); });
@ -742,7 +749,7 @@ EX hrmap *current_altmap;
heptagon *build_child(heptspin p, pair<int, int> adj); heptagon *build_child(heptspin p, pair<int, int> 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]; 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]; auto& co = sh.connections[dl];
if(xdl == -1) xdl = co.eid; 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()); int xdr = gmod(xdl+1, xsh.size());
hyperpoint vl = sh.vertices[dl]; hyperpoint vl = sh.vertices[dl];
@ -836,7 +845,7 @@ struct hrmap_arbi : hrmap {
void verify() override { } void verify() override { }
transmatrix adj(heptagon *h, int dl) 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 { heptagon *create_step(heptagon *h, int d) override {

View File

@ -68,7 +68,7 @@ struct hrmap_testproto : hrmap {
} }
transmatrix adj(heptagon *h, int dir) override { 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 { int shvid(cell *c) override {

View File

@ -299,6 +299,7 @@ void calc_distances(tcell *c) {
void prepare_around(tcell *c) { void prepare_around(tcell *c) {
vector<tcell*> q; vector<tcell*> q;
set<tcell*> visited; set<tcell*> visited;
auto visit = [&] (tcell *x) { auto visit = [&] (tcell *x) {
if(visited.count(x)) return; if(visited.count(x)) return;
@ -1433,19 +1434,21 @@ struct hrmap_rulegen : hrmap {
transmatrix adj(heptagon *h, int dir) override { transmatrix adj(heptagon *h, int dir) override {
if(h->fieldval == -1) 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 s = h->fieldval;
int dir0 = get_arb_dir(s, dir); int dir0 = get_arb_dir(s, dir);
int dir1 = -1; int dir1 = -1;
int sid1 = -1;
if(h->c.move(dir)) { 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)); 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 { int shvid(cell *c) override {
@ -1526,7 +1529,7 @@ string rules_known_for = "unknown";
string rule_status; string rule_status;
EX bool known() { 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() { EX bool prepare_rules() {
@ -1583,5 +1586,46 @@ auto hooks =
param_i(dlbonus, "dlbonus"); 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<N; i++) {
ep.force_eat(","); ep.skip_white();
if(ep.eat("PARENT")) ts.rules.push_back(DIR_PARENT);
else if(ep.eat("LEFT")) ts.rules.push_back(DIR_LEFT);
else if(ep.eat("RIGHT")) ts.rules.push_back(DIR_RIGHT);
else { int i = ep.iparse(); ts.rules.push_back(i); }
}
ep.force_eat(")");
}
EX void verify_parsed_treestates() {
println(hlog, arb::current.shapes[0].connections);
println(hlog, arb::current.shapes[1].connections);
println(hlog, arb::current.shapes[0].stretch_shear);
for(auto& ts: treestates) println(hlog, ts.rules);
for(auto& ts: treestates) for(auto& r: ts.rules) {
if(r < 0 && !among(r, DIR_PARENT, DIR_LEFT, DIR_RIGHT))
throw hr_parse_exception("negative number in treestates");
if(r > isize(treestates))
throw hr_parse_exception("undefined treestate");
}
for(auto& sh: arb::current.shapes) sh.cycle_length = sh.size();
find_possible_parents();
}
EX } EX }
} }