mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-03-08 04:28:17 +00:00
hyperbolic_celldistance algorithm implemented for all hyperbolic tilings (minor bugs known in irregular, still ugly in bitrunc a45)
This commit is contained in:
parent
7b4bdbea1c
commit
b5542c66ba
68
cell.cpp
68
cell.cpp
@ -1436,7 +1436,6 @@ int heptdistance(cell *c1, cell *c2) {
|
||||
map<pair<cell*, cell*>, int> saved_distances;
|
||||
|
||||
int celldistance(cell *c1, cell *c2) {
|
||||
int d = 0;
|
||||
|
||||
if((masterless) && (euclid6 || (euclid4 && PURE))) {
|
||||
if(!torus)
|
||||
@ -1463,7 +1462,7 @@ int celldistance(cell *c1, cell *c2) {
|
||||
return 64;
|
||||
}
|
||||
|
||||
if(NONSTDVAR || masterless || archimedean || binarytiling) {
|
||||
if(masterless || archimedean) {
|
||||
|
||||
if(saved_distances.count(make_pair(c1,c2)))
|
||||
return saved_distances[make_pair(c1,c2)];
|
||||
@ -1481,70 +1480,7 @@ int celldistance(cell *c1, cell *c2) {
|
||||
return 64;
|
||||
}
|
||||
|
||||
int d1 = celldist(c1), d2 = celldist(c2);
|
||||
|
||||
cell *cl1=c1, *cr1=c1, *cl2=c2, *cr2=c2;
|
||||
while(true) {
|
||||
|
||||
if(weirdhyperbolic) {
|
||||
if(cl1 == cl2) return d;
|
||||
if(cl1 == cr2) return d;
|
||||
if(cr1 == cl2) return d;
|
||||
if(cr1 == cr2) return d;
|
||||
|
||||
if(isNeighbor(cl1, cl2)) return d+1;
|
||||
if(isNeighbor(cl1, cr2)) return d+1;
|
||||
if(isNeighbor(cr1, cl2)) return d+1;
|
||||
if(isNeighbor(cr1, cr2)) return d+1;
|
||||
}
|
||||
|
||||
if(d1 == d2) for(int u=0; u<2; u++) {
|
||||
cell *ac0 = u ? cr1 : cr2, *ac = ac0;
|
||||
cell *tgt = u ? cl2 : cl1;
|
||||
cell *xtgt = u ? cr2 : cr1;
|
||||
if(ac == tgt) return d;
|
||||
ac = chosenDown(ac, 1, 1, celldist);
|
||||
if(ac == tgt) return d+1;
|
||||
if(ac == xtgt) return d;
|
||||
ac = chosenDown(ac, 1, 1, celldist);
|
||||
if(ac == tgt) return d+2;
|
||||
if(BITRUNCATED) {
|
||||
ac = chosenDown(ac, 1, 1, celldist);
|
||||
if(ac == tgt) {
|
||||
if(chosenDown(ac0, 1, 0, celldist) ==
|
||||
chosenDown(tgt, -1, 0, celldist))
|
||||
return d+2;
|
||||
return d+3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(weirdhyperbolic) {
|
||||
forCellEx(c, cl2) if(isNeighbor(c, cr1)) return d+2;
|
||||
forCellEx(c, cl1) if(isNeighbor(c, cr2)) return d+2;
|
||||
|
||||
forCellEx(ca, cl2) forCellEx(cb, cr1) if(isNeighbor(ca, cb)) return d+3;
|
||||
forCellEx(ca, cl1) forCellEx(cb, cr2) if(isNeighbor(ca, cb)) return d+3;
|
||||
|
||||
forCellEx(ca, cl2) forCellEx(cb, cr1) forCellEx(cc, cb) if(isNeighbor(ca, cc)) return d+4;
|
||||
forCellEx(ca, cl1) forCellEx(cb, cr2) forCellEx(cc, cb) if(isNeighbor(ca, cc)) return d+4;
|
||||
}
|
||||
|
||||
if(d1 >= d2) {
|
||||
cl1 = chosenDown(cl1, -1, 0, celldist);
|
||||
// cl1->item = eItem(rand() % 10);
|
||||
cr1 = chosenDown(cr1, 1, 0, celldist);
|
||||
// cr1->item = eItem(rand() % 10);
|
||||
d++; d1--;
|
||||
}
|
||||
if(d1 < d2) {
|
||||
cl2 = chosenDown(cl2, -1, 0, celldist);
|
||||
// cl2->item = eItem(rand() % 10);
|
||||
cr2 = chosenDown(cr2, 1, 0, celldist);
|
||||
// cr2->item = eItem(rand() % 10);
|
||||
d++; d2--;
|
||||
}
|
||||
}
|
||||
return hyperbolic_celldistance(c1, c2);
|
||||
}
|
||||
|
||||
void clearCellMemory() {
|
||||
|
@ -750,4 +750,98 @@ auto ea_hook = addHook(hooks_args, 100, readArgs);
|
||||
|
||||
expansion_analyzer expansion;
|
||||
|
||||
int sibling_limit = 0;
|
||||
|
||||
void set_sibling_limit() {
|
||||
if(IRREGULAR) sibling_limit = 3;
|
||||
auto p = gp::univ_param();
|
||||
sibling_limit = 2 * p.first + p.second;
|
||||
}
|
||||
|
||||
bool in_segment(cell *left, cell *mid, cell *right) {
|
||||
while(true) {
|
||||
if(mid == left) return true;
|
||||
if(left == right) return false;
|
||||
int v = chosenDownId(left, 1, celldist);
|
||||
if(S3 == 3) left = (cellwalker(left, v) + 1).cpeek();
|
||||
else left = (cellwalker(left, v) + wstep - 1).cpeek();
|
||||
}
|
||||
}
|
||||
|
||||
int sibling_distance(cell *a, cell *b, int limit) {
|
||||
int counting = 0;
|
||||
while(true) {
|
||||
if(a == b) return counting;
|
||||
if(limit == 0) return INF;
|
||||
counting++; limit--;
|
||||
a = chosenDown(a, 1, 1, celldist);
|
||||
}
|
||||
}
|
||||
|
||||
int hyperbolic_celldistance(cell *c1, cell *c2) {
|
||||
int found_distance = INF;
|
||||
|
||||
int d = 0, d1 = celldist(c1), d2 = celldist(c2), sl_used = 0;
|
||||
|
||||
cell *cl1=c1, *cr1=c1, *cl2=c2, *cr2=c2;
|
||||
while(true) {
|
||||
|
||||
if(a45 && BITRUNCATED) {
|
||||
// some cells in this tiling have three parents,
|
||||
// making the usual algorithm fail
|
||||
if(d2 == d1+1) {
|
||||
swap(d1, d2); swap(cl1, cl2); swap(c1, c2); swap(cr1, cr2);
|
||||
}
|
||||
auto short_distances = [cl1, cr1, d, &found_distance] (cell *c) {
|
||||
celllister cl(c, 4, 1000, cl1);
|
||||
if(cl.listed(cl1)) found_distance = min(found_distance, d + cl.getdist(cl1));
|
||||
if(cl.listed(cr1)) found_distance = min(found_distance, d + cl.getdist(cr1));
|
||||
};
|
||||
|
||||
if(d1 <= d2+1) {
|
||||
short_distances(cl2);
|
||||
if(cl2 != cr2) short_distances(cr2);
|
||||
}
|
||||
}
|
||||
|
||||
if(d >= found_distance) {
|
||||
if(sl_used == sibling_limit && IRREGULAR) {
|
||||
printf("sibling_limit used: %d\n", sibling_limit); sibling_limit++;
|
||||
}
|
||||
return found_distance;
|
||||
}
|
||||
|
||||
if(d1 == d2) {
|
||||
if(cl1 == c1 && in_segment(cl2, c1, cr2)) return d;
|
||||
if(cl2 == c2 && in_segment(cl1, c2, cr1)) return d;
|
||||
if(VALENCE == 3) {
|
||||
int dx = min(sibling_distance(cr1, cl2, sibling_limit), sibling_distance(cr2, cl1, sibling_limit));
|
||||
if(d + dx <= found_distance) {
|
||||
found_distance = d + dx;
|
||||
sl_used = dx;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(cl1 == cr2 || cr1 == cl2) found_distance = d;
|
||||
}
|
||||
}
|
||||
|
||||
if(d >= found_distance) {
|
||||
if(sl_used == sibling_limit) { printf("sibling_limit used: %d\n", sibling_limit); sibling_limit++; }
|
||||
return found_distance;
|
||||
}
|
||||
|
||||
if(d1 >= d2) {
|
||||
cl1 = chosenDown(cl1, -1, 0, celldist);
|
||||
cr1 = chosenDown(cr1, 1, 0, celldist);
|
||||
d++; d1--;
|
||||
}
|
||||
if(d1 < d2) {
|
||||
cl2 = chosenDown(cl2, -1, 0, celldist);
|
||||
cr2 = chosenDown(cr2, 1, 0, celldist);
|
||||
d++; d2--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -189,6 +189,8 @@ void precalc() {
|
||||
floorrad0 = hexvdist * .9,
|
||||
floorrad1 = rhexf * .8;
|
||||
}
|
||||
|
||||
set_sibling_limit();
|
||||
}
|
||||
|
||||
transmatrix xspinpush(ld dir, ld dist) {
|
||||
|
4
hyper.h
4
hyper.h
@ -2208,6 +2208,7 @@ bool doexiton(int sym, int uni);
|
||||
void switchFullscreen();
|
||||
string turnstring(int i);
|
||||
int celldistance(cell *c1, cell *c2);
|
||||
int hyperbolic_celldistance(cell *c1, cell *c2);
|
||||
bool behindsphere(const transmatrix& V);
|
||||
extern hyperpoint pirateCoords;
|
||||
|
||||
@ -3432,6 +3433,7 @@ namespace gp {
|
||||
int solve_triangle(int dmain, int d0, int d1, loc at);
|
||||
|
||||
array<heptagon*, 3> get_masters(cell *c);
|
||||
loc univ_param();
|
||||
}
|
||||
|
||||
int get_sightrange();
|
||||
@ -4199,5 +4201,7 @@ struct expansion_analyzer {
|
||||
|
||||
extern expansion_analyzer expansion;
|
||||
|
||||
int chosenDownId(cell *c, int which, cellfunction* cf);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user