mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-02-17 11:30:09 +00:00
expansion is now computed exactly and for most geometries
This commit is contained in:
parent
b5c0675daa
commit
9bf8842124
@ -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++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user