mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 14:02:59 +00:00 
			
		
		
		
	expansion is now computed exactly and for most geometries
This commit is contained in:
		| @@ -1268,7 +1268,7 @@ void moreBigStuff(cell *c) { | ||||
|         } | ||||
|       if(d == 1) { | ||||
|         // roughly as many knights as table cells | ||||
|         if(hrand(PURE ? 2618 : 1720) < 1000)  | ||||
|         if(hrand(1000000) < 1000000 / expansion.get_growth()) | ||||
|           c->monst = moKnight; | ||||
|         if(!eubinary) for(int i=0; i<S7; i++) generateAlts(c->master->move(i)); | ||||
|         for(int i=0; i<c->type; i++)  | ||||
|   | ||||
| @@ -33,6 +33,7 @@ | ||||
| #include "archimedean.cpp" | ||||
| #include "language.cpp" | ||||
| #include "cell.cpp" | ||||
| #include "expansion.cpp" | ||||
| #include "goldberg.cpp" | ||||
| #include "irregular.cpp" | ||||
| #include "pattern2.cpp" | ||||
|   | ||||
							
								
								
									
										51
									
								
								game.cpp
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								game.cpp
									
									
									
									
									
								
							| @@ -6931,44 +6931,6 @@ void roundTableMessage(cell *c2) { | ||||
|     } | ||||
|   } | ||||
|  | ||||
| long long circlesize[100], disksize[100]; | ||||
| ld circlesizeD[10000]; | ||||
| int lastsize; | ||||
|  | ||||
| bool sizes_known() { | ||||
|   return euclid || (geometry == gNormal && STDVAR); | ||||
|   } | ||||
|  | ||||
| void computeSizes() { | ||||
|   lastsize = PURE ? 44 : 76; | ||||
|  | ||||
|   circlesize[0] = 1; | ||||
|    | ||||
|   if(euclid) { | ||||
|     for(int i=1; i<100; i++) circlesize[i] = 6 * i; | ||||
|     } | ||||
|    | ||||
|   else if(BITRUNCATED) { | ||||
|     circlesize[1] = 1*7; | ||||
|     circlesize[2] = 2*7; | ||||
|     circlesize[3] = 4*7; | ||||
|     circlesize[4] = 7*7; | ||||
|     for(int i=5; i<100; i++)  | ||||
|       circlesize[i] = circlesize[i-1] + circlesize[i-2] + circlesize[i-3] - circlesize[i-4]; | ||||
|     } | ||||
|   else { | ||||
|     // actually these are each second Fibonacci number | ||||
|     circlesize[1] = 1*7; | ||||
|     circlesize[2] = 3*7; | ||||
|     for(int i=3; i<100; i++)  | ||||
|       circlesize[i] = 3*circlesize[i-1] - circlesize[i-2]; | ||||
|     } | ||||
|      | ||||
|   disksize[0] = 0; | ||||
|   for(int i=1; i<100; i++)  | ||||
|     disksize[i] = disksize[i-1] + circlesize[i-1]; | ||||
|   } | ||||
|  | ||||
| void knightFlavorMessage(cell *c2) { | ||||
|  | ||||
|   if(!euclid && !c2->master->alt) { | ||||
| @@ -6981,8 +6943,6 @@ void knightFlavorMessage(cell *c2) { | ||||
|     return; | ||||
|     } | ||||
|  | ||||
|   computeSizes(); | ||||
|  | ||||
|   bool grailfound = grailWasFound(c2); | ||||
|   int rad = roundTableRadius(c2); | ||||
|   bool tooeasy = (rad < newRoundTableRadius()); | ||||
| @@ -7016,14 +6976,11 @@ void knightFlavorMessage(cell *c2) { | ||||
|   else if(msgid == 7 && items[itSpice] < 10 && !peace::on) { | ||||
|     addMessage(XLAT("\"Train in the Desert first!\"")); | ||||
|     } | ||||
|   else if(msgid == 8 && sizes_known()) { | ||||
|     if(rad <= lastsize) | ||||
|       addMessage(XLAT("\"Our Table seats %1 Knights!\"", llts(circlesize[rad]))); | ||||
|     else | ||||
|       addMessage(XLAT("\"By now, you should have your own formula, you know?\"")); | ||||
|   else if(msgid == 8 && sizes_known() && !tactic::on) { | ||||
|     addMessage(XLAT("\"Our Table seats %1 Knights!\"", expansion.get_descendants(rad).get_str(100))); | ||||
|     } | ||||
|   else if(msgid == 9 && rad <= lastsize && sizes_known()) { | ||||
|       addMessage(XLAT("\"There are %1 floor tiles inside our Table!\"", llts(disksize[rad]))); | ||||
|   else if(msgid == 9 && sizes_known() && !tactic::on) { | ||||
|     addMessage(XLAT("\"There are %1 floor tiles inside our Table!\"", expansion.get_descendants(rad-1, expansion.diskid).get_str(100))); | ||||
|     } | ||||
|   else if(msgid == 10 && !items[itPirate] && !items[itWhirlpool] && !peace::on) { | ||||
|     addMessage(XLAT("\"Have you tried to take a boat and go into the Ocean? Try it!\"")); | ||||
|   | ||||
							
								
								
									
										42
									
								
								hud.cpp
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								hud.cpp
									
									
									
									
									
								
							| @@ -346,46 +346,8 @@ bool nofps = false; | ||||
| void drawStats() { | ||||
|   if(nohud || stereo::mode == stereo::sLR) return; | ||||
|   if(callhandlers(false, hooks_prestats)) return; | ||||
|   if(viewdists && sidescreen) { | ||||
|     distcolors[0] = forecolor; | ||||
|     dialog::init(""); | ||||
|     int qty[64]; | ||||
|     vector<cell*>& ac = currentmap->allcells(); | ||||
|     for(int i=0; i<64; i++) qty[i] = 0; | ||||
|     for(int i=0; i<isize(ac); i++) { | ||||
|       int d = celldistance(ac[i], cwt.at); | ||||
|       if(d >= 0 && d < 64) qty[d]++; | ||||
|       } | ||||
|  | ||||
|     if(geometry == gNormal && BITRUNCATED) | ||||
|       for(int i=8; i<=15; i++)  | ||||
|         qty[i] = qty[i-1] + qty[i-2] + qty[i-3] - qty[i-4]; | ||||
|  | ||||
|     if(geometry == gNormal && PURE) | ||||
|       for(int i=6; i<=15; i++)  | ||||
|         qty[i] = 3*qty[i-1] - qty[i-2]; | ||||
|  | ||||
|     if(geometry == gEuclid) | ||||
|       for(int i=8; i<=15; i++) qty[i] = 6*i; | ||||
|     for(int i=0; i<64; i++) if(qty[i]) | ||||
|       dialog::addInfo(its(qty[i]), distcolors[i&7]); | ||||
|  | ||||
|     if(geometry == gNormal && BITRUNCATED) { | ||||
|       dialog::addBreak(200); | ||||
|       dialog::addHelp("a(d+4) = a(d+3) + a(d+2) + a(d+1) - a(d)"); | ||||
|       dialog::addInfo("a(d) ~ 1.72208ᵈ", forecolor); | ||||
|       } | ||||
|     if(geometry == gNormal && PURE) { | ||||
|       dialog::addBreak(200); | ||||
|       dialog::addHelp("a(d+2) = 3a(d+1) - a(d+2)"); | ||||
|       dialog::addInfo("a(d) ~ 2.61803ᵈ", forecolor); | ||||
|       } | ||||
|     if(geometry == gEuclid) { | ||||
|       dialog::addBreak(300); | ||||
|       dialog::addInfo("a(d) = 6d", forecolor); | ||||
|       } | ||||
|     dialog::display(); | ||||
|     } | ||||
|   if(viewdists && sidescreen)  | ||||
|     expansion.view_distances_dialog(); | ||||
|   if(sidescreen) return; | ||||
|  | ||||
|   { | ||||
|   | ||||
							
								
								
									
										64
									
								
								hyper.h
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								hyper.h
									
									
									
									
									
								
							| @@ -4106,5 +4106,69 @@ namespace anims { | ||||
| extern int animation_lcm; | ||||
| extern ld animation_factor; | ||||
| ld parseld(const string& s); | ||||
| pair<int, int> vec_to_pair(int vec); | ||||
|  | ||||
| struct bignum { | ||||
|   static const int BASE = 1000000000; | ||||
|   static const long long BASE2 = BASE * (long long)BASE; | ||||
|   vector<int> digits; | ||||
|   bignum() {} | ||||
|   bignum(int i) : digits() { digits.push_back(i); } | ||||
|   void be(int i) { digits.resize(1); digits[0] = i; } | ||||
|   bignum& operator +=(const bignum& b); | ||||
|   string get_str(int max_length); | ||||
|   ld approx() { | ||||
|     if(digits.empty()) return 0; | ||||
|     return digits.back() * pow(BASE, isize(digits) - 1); | ||||
|     } | ||||
|    | ||||
|   int approx_int() { | ||||
|     if(isize(digits) > 1) return BASE; | ||||
|     if(digits.empty()) return 0; | ||||
|     return digits[0]; | ||||
|     } | ||||
|    | ||||
|   long long approx_ll() { | ||||
|     if(isize(digits) > 2) return BASE2; | ||||
|     if(digits.empty()) return 0; | ||||
|     if(isize(digits) == 1) return digits[0]; | ||||
|     return digits[0] + digits[1] * (long long) BASE; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
| struct expansion_analyzer { | ||||
|   vector<int> gettype(cell *c); | ||||
|   int N; | ||||
|   vector<cell*> samples;   | ||||
|   map<vector<int>, int> codeid;   | ||||
|   vector<vector<int> > children;   | ||||
|   int rootid, diskid; | ||||
|   int coefficients_known; | ||||
|   vector<int> coef; | ||||
|   int valid_from, tested_to; | ||||
|   ld growth; | ||||
|    | ||||
|   int sample_id(cell *c); | ||||
|   void preliminary_grouping(); | ||||
|   void reduce_grouping(); | ||||
|   vector<vector<bignum>> descendants; | ||||
|   bignum& get_descendants(int level); | ||||
|   bignum& get_descendants(int level, int type); | ||||
|   void find_coefficients(); | ||||
|   void reset(); | ||||
|    | ||||
|   expansion_analyzer() { reset(); } | ||||
|  | ||||
|   string approximate_descendants(int d, int max_length); | ||||
|   void view_distances_dialog(); | ||||
|   ld get_growth(); | ||||
|  | ||||
|   private: | ||||
|   bool verify(int id); | ||||
|   int valid(int v, int step); | ||||
|   }; | ||||
|  | ||||
| extern expansion_analyzer expansion; | ||||
|  | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										25
									
								
								quit.cpp
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								quit.cpp
									
									
									
									
									
								
							| @@ -31,25 +31,6 @@ void noaction() {} | ||||
|  | ||||
| function<void()> cancel = noaction; | ||||
|  | ||||
| string circlesizestr(int r) { | ||||
|   computeSizes(); | ||||
|   string s; | ||||
|   int last = lastsize; | ||||
|   if(r <= last) | ||||
|     return llts(circlesize[r]); | ||||
|   else { | ||||
|     double d = log(circlesize[last]) + (log(circlesize[last]) - log(circlesize[last-1]))*(r-last); | ||||
|     int dlost = 0; | ||||
|     while(d > 10 * log(10)) d -= log(10), dlost++; | ||||
|     char buf[300]; sprintf(buf, "%.0f", exp(d));  | ||||
|     string ss = XLAT("about ") + buf; | ||||
|     while(dlost % 9) dlost--, ss += '0'; | ||||
|     for(int r = 0; r < 50 && dlost; r++) dlost -= 9, ss += " 000000000"; | ||||
|     if(dlost) ss += XLAT(" (%1 more digits)", its(dlost)); | ||||
|     return ss; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| hint hints[] = { | ||||
|  | ||||
|   { | ||||
| @@ -246,13 +227,13 @@ hint hints[] = { | ||||
|     0, | ||||
|     []() { return !canmove && sizes_known() && celldist(cwt.at) >= 50; }, | ||||
|     []() { | ||||
|       int c = celldist(cwt.at); | ||||
|       string s = circlesizestr(c); | ||||
|       int d = celldist(cwt.at); | ||||
|       string s = expansion.approximate_descendants(d, 10000); | ||||
|       dialog::addHelp(XLAT( | ||||
|         "You are %1 cells away from the starting point, or " | ||||
|         "the place where you used an Orb of Safety last time. " | ||||
|         "There are %2 such cells.\n", | ||||
|         its(c), s | ||||
|         its(d), s | ||||
|         )); | ||||
|       dialog::addBreak(50); | ||||
|       dialog::addItem(XLAT("expansion"), 'z'); | ||||
|   | ||||
| @@ -1267,6 +1267,7 @@ void start_game() { | ||||
|   game_active = true; | ||||
|   if(need_reset_geometry) resetGeometry(), need_reset_geometry = false; | ||||
|   initcells(); | ||||
|   expansion.reset(); | ||||
|  | ||||
|   if(randomPatternsMode) { | ||||
|     for(int i=0; i<landtypes; i++) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue