mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-05-03 06:17:04 +02:00
Make grow formulas faster and more accurate. (#1044)
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { PlayerObject } from "../../src/PersonObjects/Player/PlayerObject";
|
||||
import { Server } from "../../src/Server/Server";
|
||||
import { calculateServerGrowth } from "../../src/Server/formulas/grow";
|
||||
import { numCycleForGrowthCorrected } from "../../src/Server/ServerHelpers";
|
||||
|
||||
test("Grow is accurate", () => {
|
||||
// Tests that certain special values work out to exactly what we'd expect,
|
||||
// given the formulas. The growth multiplier maxes out at 1.0035, and the
|
||||
// increment is .03 so with a difficulty of 10 it should be .003.
|
||||
// These tests are *exact* because the whole point is that the math should
|
||||
// get exactly the right value (or as close as is possible with floating-point).
|
||||
const server = new Server({ hostname: "foo", hackDifficulty: 5, serverGrowth: 100 });
|
||||
const player = new PlayerObject();
|
||||
expect(calculateServerGrowth(server, 1, player)).toBe(1.0035);
|
||||
expect(calculateServerGrowth(server, 2, player)).toBe(1.00701225);
|
||||
server.hackDifficulty = 10;
|
||||
expect(calculateServerGrowth(server, 1, player)).toBe(1.003);
|
||||
expect(calculateServerGrowth(server, 2, player)).toBe(1.006009);
|
||||
expect(calculateServerGrowth(server, 3, player)).toBe(1.009027027);
|
||||
expect(calculateServerGrowth(server, 4, player)).toBe(1.012054108081);
|
||||
});
|
||||
|
||||
describe("numCycleForGrowthCorrected reverses calculateServerGrowth", () => {
|
||||
// Test that numCycleForGrowthCorrected() functions properly as the inverse
|
||||
// of calculateServerGrowth().
|
||||
// calculateServerGrowth() works for *any* given number of threads, but is
|
||||
// usually passed an integer. numCycleForGrowthCorrected() *always* returns
|
||||
// an integer, the ceiling of the floating-point value. When reversing an
|
||||
// integer number of threads, it should *always* return the same integer.
|
||||
// Similarly, if we pass the next-highest representable number as a target,
|
||||
// it should *always* return the next largest integer, since the previous
|
||||
// number is no longer sufficient.
|
||||
|
||||
// This is an arbitrary transcedental constant.
|
||||
const multiplier = Math.exp(1.4);
|
||||
const server = new Server({ hostname: "foo", hackDifficulty: 10 * multiplier, serverGrowth: 100 });
|
||||
server.moneyMax = 1e308; // Not available as a constructor param
|
||||
const player = new PlayerObject();
|
||||
const tests = [];
|
||||
while (server.moneyAvailable < 5e49) {
|
||||
tests.push(server.moneyAvailable);
|
||||
server.moneyAvailable = (server.moneyAvailable + 59) * calculateServerGrowth(server, 59, player);
|
||||
}
|
||||
test.each(tests)("startMoney: %f", (money: number) => {
|
||||
// Do fewer threads to save on test time
|
||||
for (let threads = 0; threads < 30; threads++) {
|
||||
const newMoney = (money + threads) * calculateServerGrowth(server, threads, player);
|
||||
const eps = newMoney ? 2 ** (Math.floor(Math.log2(newMoney)) - 52) : Number.MIN_VALUE;
|
||||
expect(numCycleForGrowthCorrected(server, newMoney, money, 1, player)).toBe(threads);
|
||||
const value = numCycleForGrowthCorrected(server, newMoney + eps, money, 1, player);
|
||||
// Write our own check because Jest is a goblin that can't provide context
|
||||
if (value !== threads + 1) {
|
||||
console.log(
|
||||
`newMoney: ${newMoney} eps: ${eps} newMoney+eps: ${newMoney + eps} value: ${value} threads: ${threads}`,
|
||||
);
|
||||
expect(value).toBe(threads + 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
const tests2 = [];
|
||||
for (let t = 0; t <= 900000; t += 2000) {
|
||||
tests2.push([t, t * calculateServerGrowth(server, t, player)]);
|
||||
}
|
||||
test.each(tests2)("threads: %f newMoney: %f", (threads: number, newMoney: number) => {
|
||||
const eps = newMoney ? 2 ** (Math.floor(Math.log2(newMoney)) - 52) : Number.MIN_VALUE;
|
||||
expect(numCycleForGrowthCorrected(server, newMoney, 0, 1, player)).toBe(threads);
|
||||
const value = numCycleForGrowthCorrected(server, newMoney + eps, 0, 1, player);
|
||||
// Write our own check because Jest is a goblin that can't provide context
|
||||
if (value !== threads + 1) {
|
||||
console.log(
|
||||
`newMoney: ${newMoney} eps: ${eps} newMoney+eps: ${newMoney + eps} value: ${value} threads: ${threads}`,
|
||||
);
|
||||
expect(value).toBe(threads + 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user