mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-20 23:50:27 +00:00
rotspace:: shift: implemented using cellwalkers, works correctly in bounded spaces now
This commit is contained in:
parent
33647a56c2
commit
475d16451a
@ -1114,28 +1114,27 @@ EX namespace hybrid {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX int& get_shift_current(cell *c, int i) {
|
EX int& get_shift_current(cellwalker cw) {
|
||||||
return make_shift(c)[i];
|
return make_shift(cw.at)[cw.spin];
|
||||||
}
|
}
|
||||||
|
|
||||||
EX bool have_shift(cell *c, int i) {
|
EX bool have_shift(cellwalker cw) {
|
||||||
return shifts.count(c) && get_shift_current(c, i) != SHIFT_UNKNOWN;
|
return shifts.count(cw.at) && get_shift_current(cw) != SHIFT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX int get_shift(cell *c, int i) {
|
EX int get_shift(cellwalker cw0) {
|
||||||
if(S3 >= OINF) return 0;
|
if(S3 >= OINF) return 0;
|
||||||
auto& v = get_shift_current(c, i);
|
auto& v = get_shift_current(cw0);
|
||||||
if(v != SHIFT_UNKNOWN) return v;
|
if(v != SHIFT_UNKNOWN) return v;
|
||||||
|
|
||||||
vector<int> candidates;
|
vector<int> candidates;
|
||||||
|
|
||||||
for(int a: {1, -1}) {
|
for(int a: {1, -1}) {
|
||||||
cellwalker cw0(c, i);
|
|
||||||
cellwalker cw = cw0;
|
cellwalker cw = cw0;
|
||||||
cw += wstep; cw += a;
|
cw += wstep; cw += a;
|
||||||
int s = 0;
|
int s = 0;
|
||||||
while(cw != cw0) {
|
while(cw != cw0) {
|
||||||
if(!have_shift(cw.at, cw.spin)) goto next;
|
if(!have_shift(cw)) goto next;
|
||||||
s += shifts[cw.at][cw.spin];
|
s += shifts[cw.at][cw.spin];
|
||||||
cw += wstep;
|
cw += wstep;
|
||||||
cw += a;
|
cw += a;
|
||||||
@ -1153,33 +1152,78 @@ EX namespace hybrid {
|
|||||||
|
|
||||||
int val = 0;
|
int val = 0;
|
||||||
|
|
||||||
|
auto cw1 = cw0+wstep;
|
||||||
if(1) {
|
if(1) {
|
||||||
/* the value from PSL, helps to draw the underlying space correctly */
|
/* the value from PSL, helps to draw the underlying space correctly */
|
||||||
auto ps = cgi.psl_steps;
|
auto ps = cgi.psl_steps;
|
||||||
val = i*ps / c->type - c->c.spin(i)*ps / c->move(i)->type + ps/2;
|
val = cw0.spin*ps / cw0.at->type - cw1.spin*ps / cw1.at->type + ps/2;
|
||||||
}
|
}
|
||||||
if(!candidates.empty()) val = candidates[0];
|
if(!candidates.empty()) val = candidates[0];
|
||||||
|
|
||||||
v = val;
|
v = val;
|
||||||
get_shift_current(c->move(i), c->c.spin(i)) = -val;
|
get_shift_current(cw1) = -val;
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void ensure_shifts(cell *c) {
|
EX void ensure_shifts(cell *c) {
|
||||||
if(S3 >= OINF) return;
|
if(S3 >= OINF) return;
|
||||||
if(have_shift(c, c->type)) return;
|
if(!make_shift(c)[c->type]) return;
|
||||||
forCellEx(c1, c)
|
forCellEx(c1, c)
|
||||||
for(int a=0; a<c->type; a++) {
|
for(int a=0; a<c->type; a++) {
|
||||||
cellwalker cw0(c, a);
|
cellwalker cw0(c, a);
|
||||||
cellwalker cw = cw0;
|
cellwalker cw = cw0;
|
||||||
while(cw != cw0) {
|
while(cw != cw0) {
|
||||||
get_shift(cw.at, cw.spin);
|
get_shift(cw);
|
||||||
cw += wstep;
|
cw += wstep;
|
||||||
cw += a;
|
cw += a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
get_shift_current(c, c->type) = 0;
|
make_shift(c)[c->type] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EX int cycle_discrepancy(cellwalker cw0) {
|
||||||
|
int total = 0;
|
||||||
|
auto cw = cw0;
|
||||||
|
do {
|
||||||
|
total += get_shift(cw);
|
||||||
|
cw += wstep;
|
||||||
|
cw++;
|
||||||
|
}
|
||||||
|
while(cw != cw0);
|
||||||
|
return total + cgi.single_step * (sphere ? -1 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void fix_bounded_cycles() {
|
||||||
|
if(!rotspace) return;
|
||||||
|
if(!bounded) return;
|
||||||
|
in_underlying([&] {
|
||||||
|
cellwalker final(currentmap->gamestart(), 0);
|
||||||
|
auto& ac = currentmap->allcells();
|
||||||
|
for(cell *c: ac) for(int i=0; i<c->type; i++) {
|
||||||
|
cellwalker cw(c, i);
|
||||||
|
int cd = cycle_discrepancy(cw);
|
||||||
|
if(!cd) continue;
|
||||||
|
while(cw != final) {
|
||||||
|
if(celldist(cw.peek()) < celldist(cw.at)) {
|
||||||
|
cw += wstep;
|
||||||
|
cw++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
get_shift_current(cw) -= cd;
|
||||||
|
get_shift_current(cw+wstep) += cd;
|
||||||
|
cw++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disc_quotient = abs(cycle_discrepancy(final));
|
||||||
|
|
||||||
|
if(debugflags & DF_GEOM) for(cell *c: ac) for(int i=0; i<c->type; i++) {
|
||||||
|
cellwalker cw(c, i);
|
||||||
|
if(cycle_discrepancy(cw)) println(hlog, cw, cycle_discrepancy(cw));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T> auto in_underlying(const T& t) -> decltype(t()) {
|
template<class T> auto in_underlying(const T& t) -> decltype(t()) {
|
||||||
@ -1214,6 +1258,7 @@ EX namespace hybrid {
|
|||||||
disc_quotient = 0;
|
disc_quotient = 0;
|
||||||
in_underlying([this] { initcells(); underlying_map = currentmap; });
|
in_underlying([this] { initcells(); underlying_map = currentmap; });
|
||||||
for(hrmap*& m: allmaps) if(m == underlying_map) m = NULL;
|
for(hrmap*& m: allmaps) if(m == underlying_map) m = NULL;
|
||||||
|
fix_bounded_cycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
~hrmap_hybrid() {
|
~hrmap_hybrid() {
|
||||||
@ -1249,7 +1294,7 @@ EX namespace hybrid {
|
|||||||
if(geometry == gRotSpace) {
|
if(geometry == gRotSpace) {
|
||||||
auto cm = (hrmap_hybrid*)currentmap;
|
auto cm = (hrmap_hybrid*)currentmap;
|
||||||
m->in_underlying([&] { cm->ensure_shifts(cu); });
|
m->in_underlying([&] { cm->ensure_shifts(cu); });
|
||||||
s = ((hrmap_hybrid*)currentmap)->get_shift(cu, d);
|
s = ((hrmap_hybrid*)currentmap)->get_shift(cellwalker(cu, d));
|
||||||
}
|
}
|
||||||
cell *c1 = get_at(cu1, m->where[c].second + s);
|
cell *c1 = get_at(cu1, m->where[c].second + s);
|
||||||
c->c.connect(d, c1, d1, cu->c.mirror(d));
|
c->c.connect(d, c1, d1, cu->c.mirror(d));
|
||||||
|
Loading…
Reference in New Issue
Block a user