mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-16 18:24:48 +00:00
285 lines
6.8 KiB
C++
285 lines
6.8 KiB
C++
// mycell -- information about the given vertex of a triangulation
|
|
// cell is the relevant struct from HyperRogue; we do not use cell directly to conserve memory
|
|
|
|
namespace dhrg {
|
|
|
|
int mycellcount;
|
|
|
|
struct segmentlist {
|
|
segment *s;
|
|
segmentlist *next;
|
|
};
|
|
|
|
struct mycell {
|
|
#ifdef BUILD_ON_HR
|
|
cell *c;
|
|
#else
|
|
int type;
|
|
#endif
|
|
int lev;
|
|
mycell *leftparent, *rightparent;
|
|
mycell *leftsibling, *rightsibling;
|
|
mycell *leftchild;
|
|
#ifdef LONG_BRACKETS
|
|
segmentlist* bracketing;
|
|
#endif
|
|
|
|
#ifdef BUILD_ON_HR
|
|
mycell(cell *_c) : c(_c) {
|
|
leftparent = rightparent =
|
|
leftsibling = rightsibling =
|
|
NULL;
|
|
#ifdef LONG_BRACKETS
|
|
bracketing = NULL;
|
|
#endif
|
|
mycellcount++;
|
|
for(int i=0; i<SETS; i++)
|
|
byleft[i] = byright[i] = NULL;
|
|
}
|
|
#else
|
|
mycell() {
|
|
leftsibling = rightsibling = leftchild = NULL;
|
|
mycellcount++;
|
|
for(int i=0; i<SETS; i++)
|
|
byleft[i] = byright[i] = NULL;
|
|
#ifdef LONG_BRACKETS
|
|
bracketing = NULL;
|
|
#endif
|
|
}
|
|
#endif
|
|
segment *byleft[SETS];
|
|
segment *byright[SETS];
|
|
~mycell() { mycellcount--; }
|
|
#ifdef BUILD_ON_HR
|
|
void build();
|
|
mycell *grightsibling() { return rightsibling; }
|
|
mycell *gleftsibling() { return leftsibling; }
|
|
mycell *gleftchild() { return leftchild; }
|
|
void gchildren() {}
|
|
cell *ascell() { return c; }
|
|
int gettype() { return celltype(c); }
|
|
#else
|
|
void build() {}
|
|
mycell *grightsibling();
|
|
mycell *gleftsibling();
|
|
mycell *gleftchild();
|
|
void gchildren();
|
|
cell *ascell();
|
|
int gettype() { return type; }
|
|
#endif
|
|
};
|
|
|
|
#ifdef BUILD_ON_HR
|
|
map<cell*, mycell*> mymap;
|
|
|
|
mycell *find_mycell(cell *c) {
|
|
mycell*& mc = mymap[c];
|
|
if(mc == NULL) mc = new mycell(c);
|
|
return mc;
|
|
}
|
|
|
|
void mycell::build() {
|
|
const auto m = this;
|
|
if(m->leftsibling) return; // already computed
|
|
cell *c2[MAX_EDGE+1];
|
|
int dist[MAX_EDGE+1];
|
|
int t = m->c->type;
|
|
int d = celldist(m->c);
|
|
m->lev = d;
|
|
if(d == 0) {
|
|
m->leftsibling = m->rightsibling = m;
|
|
m->leftchild = find_mycell(createMov(m->c,0));
|
|
forCellCM(c2, croot()) find_mycell(c2)->build();
|
|
}
|
|
else {
|
|
for(int i=0; i<t; i++) c2[i] = createMov(m->c, i);
|
|
for(int i=0; i<t; i++) dist[i] = celldist(c2[i]);
|
|
dist[t] = dist[0]; c2[t] = c2[0];
|
|
for(int i=0; i<t; i++) {
|
|
if(dist[i] < d && dist[i+1] == d) {
|
|
m->leftparent = find_mycell(c2[i]);
|
|
m->leftsibling = find_mycell(c2[i+1]);
|
|
m->leftchild = find_mycell(c2[(i+2)%t]);
|
|
}
|
|
if(dist[i] == d && dist[i+1] < d) {
|
|
m->rightparent = find_mycell(c2[i+1]);
|
|
m->rightsibling = find_mycell(c2[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
mycell *mroot;
|
|
|
|
void generate_root() {
|
|
#if BUILD_ON_HR
|
|
mroot = find_mycell(croot());
|
|
#else
|
|
int origtype = cgi.expansion->rootid;
|
|
|
|
mroot = new mycell();
|
|
mroot->lev = 0;
|
|
mroot->type = origtype;
|
|
mroot->leftsibling = mroot->rightsibling = mroot;
|
|
mroot->leftparent = mroot->rightparent = NULL;
|
|
|
|
mycell *child;
|
|
bool first = true;
|
|
for(int c: cgi.expansion->children[origtype]) {
|
|
if(first) {
|
|
first = false;
|
|
mroot->leftchild = child = new mycell();
|
|
}
|
|
else {
|
|
child->rightsibling = new mycell();
|
|
child->rightsibling->leftsibling = child;
|
|
child = child->rightsibling;
|
|
}
|
|
|
|
child->leftparent = child->rightparent = mroot;
|
|
child->type = c;
|
|
child->lev = 1;
|
|
}
|
|
child->rightsibling = mroot->leftchild;
|
|
mroot->leftchild->leftsibling = child;
|
|
#endif
|
|
}
|
|
|
|
#ifndef BUILD_ON_HR
|
|
|
|
/* mycell *find_mycell(cell *c) {
|
|
printf("find_mycell not implemented\n");
|
|
exit(1);
|
|
} */
|
|
|
|
mycell* mycell::gleftsibling() {
|
|
if(leftsibling) return leftsibling;
|
|
leftparent->gchildren();
|
|
if(!leftsibling) {
|
|
printf("error: no left sibling found\n");
|
|
exit(1);
|
|
}
|
|
return leftsibling;
|
|
}
|
|
|
|
mycell* mycell::grightsibling() {
|
|
if(rightsibling) return rightsibling;
|
|
rightparent->gchildren();
|
|
if(!rightsibling) {
|
|
printf("error: no right sibling found\n");
|
|
}
|
|
return rightsibling;
|
|
}
|
|
|
|
mycell* mycell::gleftchild() {
|
|
if(leftchild) return leftchild;
|
|
leftchild = new mycell();
|
|
leftchild->leftparent = gleftsibling();
|
|
leftchild->rightparent = this;
|
|
leftchild->lev = lev+1;
|
|
leftchild->type = cgi.expansion->children[type][0];
|
|
return leftchild;
|
|
}
|
|
|
|
void mycell::gchildren() {
|
|
mycell *child = gleftchild();
|
|
if(child->rightsibling) return;
|
|
bool first = true;
|
|
for(int c: cgi.expansion->children[type]) {
|
|
if(first) {
|
|
first = false;
|
|
continue;
|
|
}
|
|
child->rightsibling = new mycell();
|
|
child->rightsibling->leftsibling = child;
|
|
child = child->rightsibling;
|
|
child->leftparent = child->rightparent = this;
|
|
child->type = c;
|
|
child->lev = lev + 1;
|
|
}
|
|
child->rightsibling = grightsibling()->gleftchild();
|
|
child->rightsibling->leftsibling = child;
|
|
}
|
|
#endif
|
|
|
|
vector<mycell*> allchildren(mycell *m, int dir=0) {
|
|
m->build();
|
|
vector<mycell*> res;
|
|
if(m->lev == 0) {
|
|
mycell *f = mroot->leftchild;
|
|
int origtype = cgi.expansion->rootid;
|
|
for(int i: cgi.expansion->children[origtype]) {
|
|
ignore(i);
|
|
res.push_back(f);
|
|
f = f->rightsibling;
|
|
}
|
|
return res;
|
|
}
|
|
auto m1 = m->gleftchild();
|
|
while(true) {
|
|
m1->build();
|
|
bool isright = m1->rightparent == m;
|
|
bool isleft = m1->leftparent == m;
|
|
if(!isright && !isleft) return res;
|
|
if(dir > 0 && !isright) ;
|
|
else if(dir < 0 && !isleft) ;
|
|
else res.push_back(m1);
|
|
m1 = m1->grightsibling();
|
|
}
|
|
}
|
|
|
|
vector<mycell*> allneighbors(mycell *m) {
|
|
auto ret = allchildren(m);
|
|
if(m->gleftsibling() != m) {
|
|
ret.push_back(m->leftsibling);
|
|
ret.push_back(m->grightsibling());
|
|
}
|
|
if(m->leftparent) {
|
|
ret.push_back(m->leftparent);
|
|
if(m->rightparent != m->leftparent)
|
|
ret.push_back(m->rightparent);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
mycell *find_mycell_by_path(const string& s) {
|
|
mycell *at = mroot;
|
|
for(char c: s) {
|
|
at = at->gleftchild();
|
|
while(c > '0') c--, at = at->grightsibling();
|
|
}
|
|
return at;
|
|
}
|
|
|
|
int childindex(mycell *c) {
|
|
mycell *p = c->rightparent->leftchild;
|
|
int i = 0;
|
|
while(p != c) p = p->grightsibling(), i++;
|
|
return i;
|
|
}
|
|
|
|
string get_path(mycell *c) {
|
|
string s;
|
|
while(c != mroot) s += '0' + childindex(c), c = c->rightparent;
|
|
reverse(s.begin(), s.end());
|
|
return s;
|
|
}
|
|
|
|
#ifndef BUILD_ON_HR
|
|
cell *mycell::ascell() {
|
|
if(lev == 0) return croot();
|
|
auto m = this; m->build();
|
|
auto c = rightparent->ascell();
|
|
int childid = 0;
|
|
while(m != m->rightparent->leftchild)
|
|
childid++, m = m->gleftsibling();
|
|
if(lev == 1) return createMov(croot(), childid);
|
|
cell *c2 = ts::child_number(c, childid, celldist);
|
|
|
|
return c2;
|
|
}
|
|
#endif
|
|
|
|
}
|