mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 05:52:59 +00:00 
			
		
		
		
	tailored allocation, and increased MAX_EDGE to 14
This commit is contained in:
		| @@ -410,7 +410,8 @@ struct hrmap_archimedean : hrmap { | |||||||
|   heptagon *getOrigin() { return origin; } |   heptagon *getOrigin() { return origin; } | ||||||
|  |  | ||||||
|   hrmap_archimedean() { |   hrmap_archimedean() { | ||||||
|     origin = new heptagon; |     int N0 = isize(current.adjacent[0]); | ||||||
|  |     origin = tailored_alloc<heptagon> (N0); | ||||||
|     origin->s = hsOrigin; |     origin->s = hsOrigin; | ||||||
|     origin->emeraldval = 0; |     origin->emeraldval = 0; | ||||||
|     origin->zebraval = 0; |     origin->zebraval = 0; | ||||||
| @@ -418,23 +419,21 @@ struct hrmap_archimedean : hrmap { | |||||||
|     origin->fieldval = 0; |     origin->fieldval = 0; | ||||||
|     origin->rval0 = origin->rval1 = 0; |     origin->rval0 = origin->rval1 = 0; | ||||||
|     origin->cdata = NULL; |     origin->cdata = NULL; | ||||||
|     origin->c.clear(); |  | ||||||
|     origin->alt = NULL; |     origin->alt = NULL; | ||||||
|     origin->distance = 0; |     origin->distance = 0; | ||||||
|  |  | ||||||
|     parent_index_of(origin) = 0; |     parent_index_of(origin) = 0; | ||||||
|     id_of(origin) = 0; |     id_of(origin) = 0; | ||||||
|     origin->c7 = newCell(isize(current.adjacent[0]), origin); |     origin->c7 = newCell(N0, origin); | ||||||
|      |      | ||||||
|     heptagon *alt = NULL; |     heptagon *alt = NULL; | ||||||
|      |      | ||||||
|     if(hyperbolic) { |     if(hyperbolic) { | ||||||
|       dynamicval<eGeometry> g(geometry, gNormal);  |       dynamicval<eGeometry> g(geometry, gNormal);  | ||||||
|       alt = new heptagon; |       alt = tailored_alloc<heptagon> (S7); | ||||||
|       alt->s = hsOrigin; |       alt->s = hsOrigin; | ||||||
|       alt->emeraldval = 0; |       alt->emeraldval = 0; | ||||||
|       alt->zebraval = 0; |       alt->zebraval = 0; | ||||||
|       alt->c.clear(); |  | ||||||
|       alt->distance = 0; |       alt->distance = 0; | ||||||
|       alt->c7 = NULL; |       alt->c7 = NULL; | ||||||
|       alt->alt = alt; |       alt->alt = alt; | ||||||
| @@ -491,7 +490,7 @@ transmatrix adjcell_matrix(heptagon *h, int d); | |||||||
|  |  | ||||||
| heptagon *build_child(heptspin p, pair<int, int> adj) { | heptagon *build_child(heptspin p, pair<int, int> adj) { | ||||||
|   indenter ind; |   indenter ind; | ||||||
|   auto h = buildHeptagon1(new heptagon, p.at, p.spin, hstate(1), 0); |   auto h = buildHeptagon1(tailored_alloc<heptagon> (isize(current.adjacent[adj.first])), p.at, p.spin, hstate(1), 0); | ||||||
|   SDEBUG( printf("NEW %p.%d ~ %p.0\n", p.at, p.spin, h); ) |   SDEBUG( printf("NEW %p.%d ~ %p.0\n", p.at, p.spin, h); ) | ||||||
|   id_of(h) = adj.first; |   id_of(h) = adj.first; | ||||||
|   parent_index_of(h) = adj.second; |   parent_index_of(h) = adj.second; | ||||||
|   | |||||||
| @@ -741,7 +741,7 @@ bool buildBarrierNowall(cell *c, eLand l2, int forced_dir) { | |||||||
|   bool warpv = warped_version(c->land, l2); |   bool warpv = warped_version(c->land, l2); | ||||||
|   if(warpv && !archimedean && !pseudohept(c)) return false; |   if(warpv && !archimedean && !pseudohept(c)) return false; | ||||||
|    |    | ||||||
|   int ds[8]; |   int ds[MAX_EDGE]; | ||||||
|   for(int i=0; i<c->type; i++) ds[i] = i; |   for(int i=0; i<c->type; i++) ds[i] = i; | ||||||
|   for(int j=0; j<c->type; j++) swap(ds[j], ds[hrand(j+1)]); |   for(int j=0; j<c->type; j++) swap(ds[j], ds[hrand(j+1)]); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -202,13 +202,12 @@ heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special) { | |||||||
|     if(polarb50(c) != 1) return NULL; |     if(polarb50(c) != 1) return NULL; | ||||||
|     } |     } | ||||||
|    |    | ||||||
|   heptagon *alt = new heptagon; |   heptagon *alt = tailored_alloc<heptagon> (S7); | ||||||
|   allmaps.push_back(newAltMap(alt)); |   allmaps.push_back(newAltMap(alt)); | ||||||
| //printf("new alt {%p}\n", alt); | //printf("new alt {%p}\n", alt); | ||||||
|   alt->s = firststate; |   alt->s = firststate; | ||||||
|   alt->emeraldval = 0; |   alt->emeraldval = 0; | ||||||
|   alt->zebraval = 0; |   alt->zebraval = 0; | ||||||
|   alt->c.clear(); |  | ||||||
|   alt->distance = 0; |   alt->distance = 0; | ||||||
|   alt->c7 = NULL; |   alt->c7 = NULL; | ||||||
|   alt->alt = alt; |   alt->alt = alt; | ||||||
|   | |||||||
| @@ -77,7 +77,7 @@ namespace binary { | |||||||
|     } |     } | ||||||
|    |    | ||||||
|   heptagon *build(heptagon *parent, int d, int d1, int t, int side, int delta) { |   heptagon *build(heptagon *parent, int d, int d1, int t, int side, int delta) { | ||||||
|     auto h = buildHeptagon1(new heptagon, parent, d, hsOrigin, d1); |     auto h = buildHeptagon1(tailored_alloc<heptagon> (t), parent, d, hsOrigin, d1); | ||||||
|     h->distance = parent->distance + delta; |     h->distance = parent->distance + delta; | ||||||
|     h->c7 = newCell(t, h); |     h->c7 = newCell(t, h); | ||||||
|     h->cdata = NULL; |     h->cdata = NULL; | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								cell.cpp
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								cell.cpp
									
									
									
									
									
								
							| @@ -22,10 +22,9 @@ int cellcount = 0; | |||||||
| void initcell(cell *c); // from game.cpp | void initcell(cell *c); // from game.cpp | ||||||
|  |  | ||||||
| cell *newCell(int type, heptagon *master) { | cell *newCell(int type, heptagon *master) { | ||||||
|   cell *c = new cell; |   cell *c = tailored_alloc<cell> (type); | ||||||
|   c->type = type; |   c->type = type; | ||||||
|   c->master = master; |   c->master = master; | ||||||
|   for(int i=0; i<MAX_EDGE; i++) c->move(i) = NULL; |  | ||||||
|   initcell(c); |   initcell(c); | ||||||
|   return c; |   return c; | ||||||
|   } |   } | ||||||
| @@ -52,7 +51,7 @@ hrmap *newAltMap(heptagon *o) { return new hrmap_alternate(o); } | |||||||
|  |  | ||||||
| hrmap_hyperbolic::hrmap_hyperbolic() { | hrmap_hyperbolic::hrmap_hyperbolic() { | ||||||
|   // printf("Creating hyperbolic map: %p\n", this); |   // printf("Creating hyperbolic map: %p\n", this); | ||||||
|   origin = new heptagon; |   origin = tailored_alloc<heptagon> (S7); | ||||||
|   heptagon& h = *origin; |   heptagon& h = *origin; | ||||||
|   h.s = hsOrigin; |   h.s = hsOrigin; | ||||||
|   h.emeraldval = a46 ? 0 : 98; |   h.emeraldval = a46 ? 0 : 98; | ||||||
| @@ -61,7 +60,6 @@ hrmap_hyperbolic::hrmap_hyperbolic() { | |||||||
|   h.fieldval = 0; |   h.fieldval = 0; | ||||||
|   h.rval0 = h.rval1 = 0; |   h.rval0 = h.rval1 = 0; | ||||||
|   h.cdata = NULL; |   h.cdata = NULL; | ||||||
|   h.c.clear(); |  | ||||||
|   h.alt = NULL; |   h.alt = NULL; | ||||||
|   h.distance = 0; |   h.distance = 0; | ||||||
|   isnonbitrunc = nonbitrunc; |   isnonbitrunc = nonbitrunc; | ||||||
| @@ -109,7 +107,7 @@ struct hrmap_spherical : hrmap { | |||||||
|       h.rval0 = h.rval1 = 0; |       h.rval0 = h.rval1 = 0; | ||||||
|       h.alt = NULL; |       h.alt = NULL; | ||||||
|       h.cdata = NULL; |       h.cdata = NULL; | ||||||
|       h.c.clear(); |       h.c.fullclear(); | ||||||
|       h.fieldval = i; |       h.fieldval = i; | ||||||
|       if(!irr::on) h.c7 = newCell(S7, &h); |       if(!irr::on) h.c7 = newCell(S7, &h); | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -69,14 +69,13 @@ template<class... T> auto iprintf(T... t) { for(int i=0; i<indent; i++) putchar( | |||||||
| heptagon *buildHeptagon1(heptagon *h, heptagon *parent, int d, hstate s, int pard = 0, int fixdistance = COMPUTE) { | heptagon *buildHeptagon1(heptagon *h, heptagon *parent, int d, hstate s, int pard = 0, int fixdistance = COMPUTE) { | ||||||
|   h->alt = NULL; |   h->alt = NULL; | ||||||
|   h->s = s; |   h->s = s; | ||||||
|   h->c.clear(); |  | ||||||
|   h->c.connect(pard, parent, d, false); |   h->c.connect(pard, parent, d, false); | ||||||
|   h->cdata = NULL; |   h->cdata = NULL; | ||||||
|   return h; |   return h; | ||||||
|   } |   } | ||||||
|    |    | ||||||
| heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0, int fixdistance = COMPUTE) { | heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0, int fixdistance = COMPUTE) { | ||||||
|   heptagon *h = buildHeptagon1(new heptagon, parent, d, s, pard, fixdistance); |   heptagon *h = buildHeptagon1(tailored_alloc<heptagon> (S7), parent, d, s, pard, fixdistance); | ||||||
|   if(binarytiling || archimedean) return h; |   if(binarytiling || archimedean) return h; | ||||||
|   if(parent->c7) { |   if(parent->c7) { | ||||||
|     if(irr::on) |     if(irr::on) | ||||||
|   | |||||||
							
								
								
									
										61
									
								
								hyper.h
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								hyper.h
									
									
									
									
									
								
							| @@ -320,30 +320,43 @@ struct gcell { | |||||||
| #define NOBARRIERS 15 | #define NOBARRIERS 15 | ||||||
| #define MODFIXER 10090080 | #define MODFIXER 10090080 | ||||||
|  |  | ||||||
| #define MAX_EDGE 12 | #define MAX_EDGE 14 | ||||||
|  |  | ||||||
| template<class T> struct walker; | template<class T> struct walker; | ||||||
|  |  | ||||||
| template<class T> struct connection_table { | template<class T> struct connection_table { | ||||||
|  |  | ||||||
|  |   // Assumption: class T has a field c of type connection_table<T>. | ||||||
|  |  | ||||||
|  |   // NOTE: since aconnection_table may be allocated with | ||||||
|  |   // less than MAX_EDGE neighbors (see tailored_alloc), | ||||||
|  |   // the order of fields matters. | ||||||
|  |  | ||||||
|   unsigned char spintable[6]; |   unsigned char spintable[6]; | ||||||
|   unsigned short mirrortable; |   unsigned short mirrortable; | ||||||
|   // neighbors; move[0] always goes towards origin, and then we go clockwise |  | ||||||
|   T* move_table[MAX_EDGE]; |   T* move_table[MAX_EDGE]; | ||||||
|  |   unsigned char spintable_extra[2]; | ||||||
|  |    | ||||||
|   T* full() { T* x; return (T*)((char*)this - ((char*)(&(x->c)) - (char*)x)); } |   T* full() { T* x; return (T*)((char*)this - ((char*)(&(x->c)) - (char*)x)); } | ||||||
|  |   unsigned char& get_spinchar(int d) { | ||||||
|  |     if(d < 12) return spintable[d>>1]; | ||||||
|  |     else return spintable_extra[(d-12)>>1]; | ||||||
|  |     } | ||||||
|   void setspin(int d, int spin, bool mirror) {  |   void setspin(int d, int spin, bool mirror) {  | ||||||
|     spintable[d>>1] &= ~(15 << ((d&1) << 2)); |     unsigned char& c = get_spinchar(d); | ||||||
|     spintable[d>>1] |= spin << ((d&1) << 2); |     c &= ~(15 << ((d&1) << 2)); | ||||||
|  |     c |= spin << ((d&1) << 2); | ||||||
|     if(mirror) mirrortable |= (1 << d); |     if(mirror) mirrortable |= (1 << d); | ||||||
|     else mirrortable &=~ (1 << d); |     else mirrortable &=~ (1 << d); | ||||||
|     } |     } | ||||||
|   // we are spin(i)-th neighbor of move[i] |   // we are spin(i)-th neighbor of move[i] | ||||||
|   int spin(int d) { return (spintable[d>>1] >> ((d&1)<<2)) & 15; } |   int spin(int d) { return (get_spinchar(d) >> ((d&1)<<2)) & 15; } | ||||||
|   bool mirror(int d) { return (mirrortable >> d) & 1; }   |   bool mirror(int d) { return (mirrortable >> d) & 1; }   | ||||||
|   int fix(int d) { return (d + MODFIXER) % full()->degree(); } |   int fix(int d) { return (d + MODFIXER) % full()->degree(); } | ||||||
|   T*& modmove(int i) { return move(fix(i)); } |   T*& modmove(int i) { return move(fix(i)); } | ||||||
|   T*& move(int i) { return move_table[i]; } |   T*& move(int i) { return move_table[i]; } | ||||||
|   unsigned char modspin(int i) { return spin(fix(i)); } |   unsigned char modspin(int i) { return spin(fix(i)); } | ||||||
|   void clear() {  |   void fullclear() {  | ||||||
|     for(int i=0; i<MAX_EDGE; i++) move_table[i] = NULL; |     for(int i=0; i<MAX_EDGE; i++) move_table[i] = NULL; | ||||||
|     } |     } | ||||||
|   void connect(int d0, T* c1, int d1, bool m) { |   void connect(int d0, T* c1, int d1, bool m) { | ||||||
| @@ -357,6 +370,29 @@ template<class T> struct connection_table { | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  | // Allocate a class T with a connection_table, but  | ||||||
|  | // with only `degree` connections. Also set yet | ||||||
|  | // unknown connections to NULL. | ||||||
|  |  | ||||||
|  | // Generating the hyperbolic world consumes lots of | ||||||
|  | // RAM, so we really need to be careful on low memory devices.  | ||||||
|  |  | ||||||
|  | template<class T> T* tailored_alloc(int degree) { | ||||||
|  |   const T* sample = (T*) °ree; | ||||||
|  |   T* result; | ||||||
|  | #ifndef NO_TAILORED_ALLOC | ||||||
|  |   if(degree <= 12) { | ||||||
|  |     int b = (char*)&sample->c.move_table[degree] - (char*) sample; | ||||||
|  |     result = (T*) new char[b]; | ||||||
|  |     new (result) T(); | ||||||
|  |     } | ||||||
|  |   else  | ||||||
|  | #endif | ||||||
|  |     result = new T; | ||||||
|  |   for(int i=0; i<degree; i++) result->c.move_table[i] = NULL; | ||||||
|  |   return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
| static const struct wstep_t { wstep_t() {} } wstep; | static const struct wstep_t { wstep_t() {} } wstep; | ||||||
| static const struct wmirror_t { wmirror_t() {}} wmirror; | static const struct wmirror_t { wmirror_t() {}} wmirror; | ||||||
| static const struct rev_t { rev_t() {} } rev; | static const struct rev_t { rev_t() {} } rev; | ||||||
| @@ -415,8 +451,6 @@ template<class T> struct walker { | |||||||
|   walker<T> mirrorat(int d) { return walker<T> (at, at->c.fix(d+d - spin), !mirrored); } |   walker<T> mirrorat(int d) { return walker<T> (at, at->c.fix(d+d - spin), !mirrored); } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| inline int fix42(int a) { return (a+MODFIXER)% S42; } |  | ||||||
|  |  | ||||||
| struct cell; | struct cell; | ||||||
|  |  | ||||||
| // automaton state | // automaton state | ||||||
| @@ -455,6 +489,11 @@ struct heptagon { | |||||||
|   ~heptagon () { heptacount--; } |   ~heptagon () { heptacount--; } | ||||||
|   heptagon *cmove(int d) { return createStep(this, d); } |   heptagon *cmove(int d) { return createStep(this, d); } | ||||||
|   inline int degree();  |   inline int degree();  | ||||||
|  |  | ||||||
|  |   // prevent accidental copying | ||||||
|  |   heptagon(const heptagon&) = delete; | ||||||
|  |   heptagon& operator=(const heptagon&) = delete; | ||||||
|  |   // do not add any fields after connection_table (see tailored_alloc) | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| struct cell : gcell { | struct cell : gcell { | ||||||
| @@ -472,6 +511,12 @@ struct cell : gcell { | |||||||
|   cell*& move(int d) { return c.move(d); } |   cell*& move(int d) { return c.move(d); } | ||||||
|   cell*& modmove(int d) { return c.modmove(d); } |   cell*& modmove(int d) { return c.modmove(d); } | ||||||
|   cell* cmove(int d) { return createMov(this, d); } |   cell* cmove(int d) { return createMov(this, d); } | ||||||
|  |   cell() {} | ||||||
|  |  | ||||||
|  |   // prevent accidental copying | ||||||
|  |   cell(const cell&) = delete; | ||||||
|  |   heptagon& operator=(const cell&) = delete; | ||||||
|  |   // do not add any fields after connection_table (see tailored_alloc) | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| int heptagon::degree() { if(archimedean) return c7->type; else return S7; } | int heptagon::degree() { if(archimedean) return c7->type; else return S7; } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue