expansion is now computed exactly and for most geometries

This commit is contained in:
Zeno Rogue 2018-09-12 04:23:15 +02:00
parent b5c0675daa
commit 9bf8842124
7 changed files with 76 additions and 110 deletions

View File

@ -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++)

View File

@ -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"

View File

@ -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
View File

@ -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
View File

@ -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;
}

View File

@ -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');

View File

@ -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++) {