1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-09-28 22:10:40 +00:00

simpler multi-connection system

This commit is contained in:
Zeno Rogue 2021-08-17 14:28:27 +02:00
parent 031d6a2c50
commit 631827c657

View File

@ -719,6 +719,7 @@ struct treestate {
int id; int id;
bool known; bool known;
vector<int> rules; vector<int> rules;
vector<int> sub_status; // 1 if DIR_LEFT or DIR_RIGHT and connected to a child
twalker giver; twalker giver;
int sid; int sid;
int parent_dir; int parent_dir;
@ -891,10 +892,6 @@ struct mismatch_error : rulegen_retry {
mismatch_error() : rulegen_retry("mismatch error") {} mismatch_error() : rulegen_retry("mismatch error") {}
}; };
struct double_edges: rulegen_surrender {
double_edges() : rulegen_surrender("double edges detected") {}
};
EX int rule_root; EX int rule_root;
vector<int> gen_rule(twalker cwmain); vector<int> gen_rule(twalker cwmain);
@ -907,8 +904,6 @@ vector<tcell*> cq;
#if HDR #if HDR
/* special codes */ /* special codes */
static const int DIR_UNKNOWN = -1; static const int DIR_UNKNOWN = -1;
static const int DIR_MULTI_GO_LEFT = -2;
static const int DIR_MULTI_GO_RIGHT = -3;
static const int DIR_LEFT = -4; static const int DIR_LEFT = -4;
static const int DIR_RIGHT = -5; static const int DIR_RIGHT = -5;
static const int DIR_PARENT = -6; static const int DIR_PARENT = -6;
@ -1107,7 +1102,6 @@ struct bad_tree : rulegen_retry {
bool equiv(twalker w1, twalker w2); bool equiv(twalker w1, twalker w2);
inline bool IS_DIR_MULTI(int d) { return among(d, DIR_MULTI_GO_LEFT, DIR_MULTI_GO_RIGHT); }
struct branchdata { struct branchdata {
int id; int id;
int dir; int dir;
@ -1133,11 +1127,6 @@ struct branchdata {
dir += i; dir += i;
dir = gmod(dir, isize(treestates[id].rules)); dir = gmod(dir, isize(treestates[id].rules));
} }
void spin_full(int i) {
spin(i);
while(IS_DIR_MULTI(treestates[id].rules[dir]))
spin(i);
}
}; };
inline void print(hstream& hs, const branchdata& bd) { print(hs, "[", bd.id,":",bd.dir, " ", bd.at, ":", bd.temporary, "]"); } inline void print(hstream& hs, const branchdata& bd) { print(hs, "[", bd.id,":",bd.dir, " ", bd.at, ":", bd.temporary, "]"); }
@ -1145,28 +1134,20 @@ inline void print(hstream& hs, const branchdata& bd) { print(hs, "[", bd.id,":",
/* we need to be careful with multiple edges */ /* we need to be careful with multiple edges */
bool paired(twalker w1, twalker w2) { bool paired(twalker w1, twalker w2) {
if(w1 + wstep == w2) return true; return w1 + wstep == w2;
if(w1.cpeek() == w2.at && w2.cpeek() == w1.at) {
return true;
}
return false;
} }
bool equiv(twalker w1, twalker w2) { bool equiv(twalker w1, twalker w2) {
if(w1 == w2) return true; return w1 == w2;
if(w1.at == w2.at && w1.cpeek() == w2.cpeek()) {
return true;
}
return false;
} }
void advance(vector<branchdata>& bdata, branchdata at, int dir, bool start_forward, bool stack, int distlimit) { void advance(vector<branchdata>& bdata, branchdata at, int dir, bool start_forward, bool stack, int distlimit) {
if(start_forward) { if(start_forward) {
at.step(); at.step();
at.spin_full(dir); at.spin(dir);
} }
else { else {
at.spin_full(dir); at.spin(dir);
} }
vector<branchdata> b; vector<branchdata> b;
int steps = 0; int steps = 0;
@ -1175,7 +1156,13 @@ void advance(vector<branchdata>& bdata, branchdata at, int dir, bool start_forwa
throw rulegen_failure("max_adv_steps exceeded"); throw rulegen_failure("max_adv_steps exceeded");
auto& ts = treestates[at.id]; auto& ts = treestates[at.id];
auto r = ts.rules[at.dir]; auto r = ts.rules[at.dir];
if(r < 0) { if(ts.sub_status[at.dir]) {
at.temporary = 0;
b.push_back(at);
b.push_back(at);
at.spin(dir);
}
else if(r < 0) {
at.temporary = 0; at.temporary = 0;
b.push_back(at); b.push_back(at);
break; break;
@ -1186,11 +1173,11 @@ void advance(vector<branchdata>& bdata, branchdata at, int dir, bool start_forwa
b.pop_back(); b.pop_back();
else else
advance(b, at, -dir, true, true, distlimit); advance(b, at, -dir, true, true, distlimit);
at.spin_full(dir); at.spin(dir);
} }
else { else {
at.step(); at.step();
if(at.at.at->dist < distlimit || !ts.is_live) at.spin_full(dir); if(at.at.at->dist < distlimit || !ts.is_live) at.spin(dir);
else { else {
at.temporary = dir; at.temporary = dir;
b.push_back(at); b.push_back(at);
@ -1207,7 +1194,8 @@ void advance(vector<branchdata>& bdata, branchdata at, int dir, bool start_forwa
} }
void verify_lr(branchdata bd, int dir) { void verify_lr(branchdata bd, int dir) {
if(dir) { bd.spin_full(dir); if(bd.dir == 0) bd.dir = bd.at.at->type; } return;
if(dir) { bd.spin(dir); if(bd.dir == 0) bd.dir = bd.at.at->type; }
auto& r = treestates[bd.id].rules; auto& r = treestates[bd.id].rules;
for(int i=0; i<isize(r); i++) { for(int i=0; i<isize(r); i++) {
int val = i < bd.dir ? DIR_LEFT : DIR_RIGHT; int val = i < bd.dir ? DIR_LEFT : DIR_RIGHT;
@ -1225,25 +1213,26 @@ void examine_branch(int id, int left, int right) {
auto rg = treestates[id].giver; auto rg = treestates[id].giver;
if(debugflags & DF_GEOM) if(debugflags & DF_GEOM)
println(hlog, "need to examine branches ", tie(left, right), " of ", id, " starting from ", rg); println(hlog, "need to examine branches ", tie(left, right), " of ", id, " starting from ", rg);
indenter ind(2);
vector<branchdata> bdata; vector<branchdata> bdata;
int dist_at = rg.at->dist; int dist_at = rg.at->dist;
do { do {
/* can be false in case of multi-edges */ if(true) {
if(treestates[id].rules[left] >= 0) {
if(bdata.size() && bdata.back().dir == 0)
bdata.pop_back();
else {
auto bl = branchdata{id, left, rg+left, dist_at+dlbonus}; auto bl = branchdata{id, left, rg+left, dist_at+dlbonus};
bl.temporary = 0;
if(treestates[id].rules[left] >= 0)
advance(bdata, bl, -1, true, true, dist_at+5); advance(bdata, bl, -1, true, true, dist_at+5);
} else bdata.push_back(bl);
} }
left++; left++;
if(left == rg.at->type) left = 0; if(left == rg.at->type) left = 0;
if(treestates[id].rules[left] >= 0) { if(true) {
auto br = branchdata{id, left, rg+left, dist_at+dlbonus}; auto br = branchdata{id, left, rg+left, dist_at+dlbonus};
br.temporary = 0;
if(treestates[id].rules[left] >= 0)
advance(bdata, br, +1, true, false, dist_at+5); advance(bdata, br, +1, true, false, dist_at+5);
else bdata.push_back(br);
} }
} }
while(left != right); while(left != right);
@ -1340,6 +1329,23 @@ void find_single_live_branch(twalker at) {
} }
} }
void find_sub_status() {
for(int id=0; id<isize(treestates); id++)
treestates[id].sub_status.resize(isize(treestates[id].rules), 0);
for(int id=0; id<isize(treestates); id++) {
auto& ts = treestates[id];
for(int im=0; im<isize(ts.rules); im++)
if(ts.rules[im] >= 0 || ts.rules[im] == DIR_PARENT)
for(int i=0; i<isize(ts.rules); i++) if(i != im) {
if((ts.giver+im).peek() == (ts.giver+i).peek()) {
println(hlog, "found multi connection at ", id, ":", i, " equals ", im, ts.rules[im] == DIR_PARENT ? " [parent]" : " [child]");
ts.sub_status[i] = 1;
}
}
}
}
void rules_iteration() { void rules_iteration() {
clear_codes(); clear_codes();
@ -1394,25 +1400,15 @@ void rules_iteration() {
} }
for(int id=0; id<isize(treestates); id++) { for(int id=0; id<isize(treestates); id++) {
auto& rg = treestates[id].giver;
auto& r = treestates[id].rules; auto& r = treestates[id].rules;
for(int p=0; p<2; p++)
for(int it=0; it<isize(r); it++) {
for(int i=0; i<isize(r); i++) {
int i1 = gmod(i+1, isize(r));
if((rg+i).peek() == (rg+i1).peek()) {
if(r[i1] == DIR_UNKNOWN && (r[i] >= (p?DIR_UNKNOWN:0) || r[i] == DIR_PARENT || r[i] == DIR_MULTI_GO_LEFT))
r[i1] = DIR_MULTI_GO_LEFT;
if(r[i] == DIR_UNKNOWN && (r[i1] >= 0 || r[i1] == DIR_PARENT || r[i+1] == DIR_MULTI_GO_RIGHT))
r[i] = DIR_MULTI_GO_RIGHT;
}
}
}
for(int i=0; i<isize(r); i++) if(r[i] == DIR_UNKNOWN) { for(int i=0; i<isize(r); i++) if(r[i] == DIR_UNKNOWN) {
int val = treestates[id].code.second[i+1]; int val = treestates[id].code.second[i+1];
if(val < 2 || val >= 8) throw rulegen_failure("wrong code in gen_rule"); if(val < 2 || val >= 8) {
debuglist = { treestates[id].giver };
println(hlog, "id = ", id, " i = ", i, " val = ", val, " code = ", treestates[id].code);
throw rulegen_failure("wrong code in gen_rule");
}
r[i] = ((val & 1) ? DIR_RIGHT : DIR_LEFT); r[i] = ((val & 1) ? DIR_RIGHT : DIR_LEFT);
} }
} }
@ -1424,6 +1420,8 @@ void rules_iteration() {
int q = isize(single_live_branch_close_to_root); int q = isize(single_live_branch_close_to_root);
find_sub_status();
for(int id=0; id<isize(treestates); id++) if(treestates[id].is_live) { for(int id=0; id<isize(treestates); id++) if(treestates[id].is_live) {
auto& r = treestates[id].rules; auto& r = treestates[id].rules;
int last_live_branch = -1; int last_live_branch = -1;