1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-06-18 11:19:59 +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 {
int order;
bool have_line, have_ph;
bool have_line, have_ph, have_tree;
vector<shape> 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<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()); }
@ -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<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];
@ -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 {

View File

@ -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 {

View File

@ -299,6 +299,7 @@ void calc_distances(tcell *c) {
void prepare_around(tcell *c) {
vector<tcell*> q;
set<tcell*> 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<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 }
}