mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 05:52:59 +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
 | |
| 
 | |
| }
 | 
