arbitrary-numbers 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -61
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,31 +33,52 @@ Requires TypeScript `"strict": true`.
|
|
|
33
33
|
```typescript
|
|
34
34
|
import { an, chain, formula, unitNotation } from "arbitrary-numbers";
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
let gold = an(5, 6); // 5,000,000
|
|
36
|
+
// JavaScript range limits
|
|
37
|
+
const jsHuge = Number("1e500"); // Infinity
|
|
38
|
+
const jsTiny = Number("1e-500"); // 0
|
|
40
39
|
|
|
41
|
-
//
|
|
42
|
-
const
|
|
43
|
-
|
|
40
|
+
// Arbitrary range in both directions
|
|
41
|
+
const huge = an(1, 500);
|
|
42
|
+
const tiny = an(1, -500);
|
|
43
|
+
|
|
44
|
+
// One-off pipeline with chain(): (6.2e15 - 8.5e13) * 0.75
|
|
45
|
+
const damage = chain(an(6.2, 15))
|
|
46
|
+
.subMul(an(8.5, 13), an(7.5, -1))
|
|
44
47
|
.floor()
|
|
45
48
|
.done();
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
// Reusable per-tick formula: gold = (gold * 1.08) + 2_500_000
|
|
51
|
+
const tick = formula("tick").mulAdd(an(1.08), an(2.5, 6));
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
let gold = an(7.5, 12);
|
|
54
|
+
for (let i = 0; i < 3; i += 1) {
|
|
55
|
+
gold = tick.apply(gold);
|
|
56
|
+
}
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
console.log("=== Range limits (JS vs arbitrary-numbers) ===");
|
|
59
|
+
console.log(`JS Number('1e500') -> ${jsHuge}`);
|
|
60
|
+
console.log(`AN an(1, 500) -> ${huge.toString()}`);
|
|
61
|
+
console.log(`JS Number('1e-500') -> ${jsTiny}`);
|
|
62
|
+
console.log(`AN an(1, -500) -> ${tiny.toString()}`);
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
console.log("");
|
|
65
|
+
console.log("=== Game math helpers ===");
|
|
66
|
+
console.log(`Damage (chain + fused subMul) -> ${damage.toString(unitNotation)}`);
|
|
67
|
+
console.log(`Gold after 3 ticks (formula) -> ${gold.toString(unitNotation)}`);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Example output when running this in a repository checkout (for example with `npx tsx examples/quickstart.ts`):
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
=== Range limits (JS vs arbitrary-numbers) ===
|
|
74
|
+
JS Number('1e500') -> Infinity
|
|
75
|
+
AN an(1, 500) -> 1.00e+500
|
|
76
|
+
JS Number('1e-500') -> 0
|
|
77
|
+
AN an(1, -500) -> 1.00e-500
|
|
78
|
+
|
|
79
|
+
=== Game math helpers ===
|
|
80
|
+
Damage (chain + fused subMul) -> 4.59 Qa
|
|
81
|
+
Gold after 3 ticks (formula) -> 9.45 T
|
|
61
82
|
```
|
|
62
83
|
|
|
63
84
|
## Table of contents
|
|
@@ -441,67 +462,117 @@ an(3.2, 6).toString(new TierNotation({ separator: " " })) // "3.20 M"
|
|
|
441
462
|
|
|
442
463
|
## Idle game example
|
|
443
464
|
|
|
444
|
-
A self-contained simulation showing
|
|
465
|
+
A self-contained simulation showing hyper-growth, fused ops, helpers, and where plain JS `number` overflows while `ArbitraryNumber` keeps working.
|
|
445
466
|
|
|
446
467
|
```typescript
|
|
447
468
|
import {
|
|
448
|
-
|
|
449
|
-
|
|
469
|
+
an, chain,
|
|
470
|
+
UnitNotation,
|
|
471
|
+
CLASSIC_UNITS,
|
|
472
|
+
letterNotation,
|
|
473
|
+
ArbitraryNumberHelpers as helpers,
|
|
450
474
|
} from "arbitrary-numbers";
|
|
475
|
+
import type { ArbitraryNumber } from "arbitrary-numbers";
|
|
451
476
|
|
|
452
|
-
let gold
|
|
453
|
-
let
|
|
477
|
+
let gold = an(5, 6); // 5,000,000
|
|
478
|
+
let gps = an(2, 5); // 200,000 per tick
|
|
479
|
+
let reactorCost = an(1, 9);
|
|
480
|
+
let reactors = 0;
|
|
454
481
|
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
] as const;
|
|
482
|
+
const display = new UnitNotation({
|
|
483
|
+
units: CLASSIC_UNITS,
|
|
484
|
+
fallback: letterNotation,
|
|
485
|
+
});
|
|
460
486
|
|
|
461
|
-
function
|
|
462
|
-
|
|
487
|
+
function fmt(value: ArbitraryNumber, decimals = 2): string {
|
|
488
|
+
return value.toString(display, decimals);
|
|
463
489
|
}
|
|
464
490
|
|
|
465
|
-
function
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
gold
|
|
469
|
-
|
|
470
|
-
console.log(` bought ${u.label} GPS: ${goldPerSec.toString(unitNotation)}`);
|
|
471
|
-
}
|
|
491
|
+
function snapshot(tick: number): void {
|
|
492
|
+
console.log(
|
|
493
|
+
`[t=${String(tick).padStart(4)}] SNAPSHOT `
|
|
494
|
+
+ `gold=${fmt(gold, 2).padStart(12)} gps=${fmt(gps, 2).padStart(12)}`,
|
|
495
|
+
);
|
|
472
496
|
}
|
|
473
497
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
498
|
+
console.log("=== Hyper-growth idle loop (720 ticks) ===");
|
|
499
|
+
console.log(`start gold=${fmt(gold)} gps=${fmt(gps)} reactorCost=${fmt(reactorCost)}`);
|
|
500
|
+
|
|
501
|
+
for (let t = 1; t <= 720; t += 1) {
|
|
502
|
+
// Core growth: gold = (gold * 1.12) + gps
|
|
503
|
+
gold = gold.mulAdd(an(1.12), gps);
|
|
504
|
+
|
|
505
|
+
if (t % 60 === 0 && helpers.meetsOrExceeds(gold, reactorCost)) {
|
|
506
|
+
const before = gps;
|
|
507
|
+
gold = gold.sub(reactorCost);
|
|
508
|
+
gps = chain(gps).mul(an(1, 25)).floor().done();
|
|
509
|
+
reactorCost = reactorCost.mul(an(8));
|
|
510
|
+
reactors += 1;
|
|
511
|
+
|
|
512
|
+
console.log(
|
|
513
|
+
`[t=${String(t).padStart(4)}] REACTOR #${String(reactors).padStart(2)} `
|
|
514
|
+
+ `gps ${fmt(before)} -> ${fmt(gps)} `
|
|
515
|
+
+ `nextCost=${fmt(reactorCost)}`,
|
|
516
|
+
);
|
|
517
|
+
}
|
|
481
518
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
console.log(`[t=${String(t).padStart(
|
|
519
|
+
if (t === 240 || t === 480) {
|
|
520
|
+
const before = gps;
|
|
521
|
+
gps = chain(gps)
|
|
522
|
+
.mul(an(1, 4))
|
|
523
|
+
.add(an(7.5, 6))
|
|
524
|
+
.floor()
|
|
525
|
+
.done();
|
|
526
|
+
console.log(`[t=${String(t).padStart(4)}] PRESTIGE gps ${fmt(before)} -> ${fmt(gps)}`);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (t % 120 === 0) {
|
|
530
|
+
snapshot(t);
|
|
490
531
|
}
|
|
491
532
|
}
|
|
533
|
+
|
|
534
|
+
console.log("\n=== Final scale check ===");
|
|
535
|
+
console.log(`reactors bought: ${reactors}`);
|
|
536
|
+
console.log(`final gold (unit+letter): ${fmt(gold)}`);
|
|
537
|
+
console.log(`final gps (unit+letter): ${fmt(gps)}`);
|
|
538
|
+
console.log(`final gold as JS Number: ${gold.toNumber()}`);
|
|
539
|
+
console.log(`final gps as JS Number : ${gps.toNumber()}`);
|
|
540
|
+
console.log("If JS shows Infinity while unit+letter output stays finite, the library is doing its job.");
|
|
492
541
|
```
|
|
493
542
|
|
|
494
543
|
Output:
|
|
495
544
|
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
[t=
|
|
502
|
-
[t=
|
|
503
|
-
[t=
|
|
504
|
-
[t=
|
|
545
|
+
```text
|
|
546
|
+
=== Hyper-growth idle loop (720 ticks) ===
|
|
547
|
+
start gold=5.00 M gps=200.00 K reactorCost=1.00 B
|
|
548
|
+
[t= 60] REACTOR # 1 gps 200.00 K -> 2.00 No nextCost=8.00 B
|
|
549
|
+
[t= 120] REACTOR # 2 gps 2.00 No -> 20.00 SpDc nextCost=64.00 B
|
|
550
|
+
[t= 120] SNAPSHOT gold= 14.94 Dc gps= 20.00 SpDc
|
|
551
|
+
[t= 180] REACTOR # 3 gps 20.00 SpDc -> 200.00 QiVg nextCost=512.00 B
|
|
552
|
+
[t= 240] REACTOR # 4 gps 200.00 QiVg -> 2.00 ai nextCost=4.10 T
|
|
553
|
+
[t= 240] PRESTIGE gps 2.00 ai -> 20.00 aj
|
|
554
|
+
[t= 240] SNAPSHOT gold= 1.49 SpVg gps= 20.00 aj
|
|
555
|
+
[t= 300] REACTOR # 5 gps 20.00 aj -> 200.00 ar nextCost=32.77 T
|
|
556
|
+
[t= 360] REACTOR # 6 gps 200.00 ar -> 2.00 ba nextCost=262.14 T
|
|
557
|
+
[t= 360] SNAPSHOT gold= 1.49 at gps= 2.00 ba
|
|
558
|
+
[t= 420] REACTOR # 7 gps 2.00 ba -> 20.00 bi nextCost=2.10 Qa
|
|
559
|
+
[t= 480] REACTOR # 8 gps 20.00 bi -> 200.00 bq nextCost=16.78 Qa
|
|
560
|
+
[t= 480] PRESTIGE gps 200.00 bq -> 2.00 bs
|
|
561
|
+
[t= 480] SNAPSHOT gold= 149.43 bj gps= 2.00 bs
|
|
562
|
+
[t= 540] REACTOR # 9 gps 2.00 bs -> 20.00 ca nextCost=134.22 Qa
|
|
563
|
+
[t= 600] REACTOR #10 gps 20.00 ca -> 200.00 ci nextCost=1.07 Qi
|
|
564
|
+
[t= 600] SNAPSHOT gold= 149.43 cb gps= 200.00 ci
|
|
565
|
+
[t= 660] REACTOR #11 gps 200.00 ci -> 2.00 cr nextCost=8.59 Qi
|
|
566
|
+
[t= 720] REACTOR #12 gps 2.00 cr -> 20.00 cz nextCost=68.72 Qi
|
|
567
|
+
[t= 720] SNAPSHOT gold= 14.94 cs gps= 20.00 cz
|
|
568
|
+
|
|
569
|
+
=== Final scale check ===
|
|
570
|
+
reactors bought: 12
|
|
571
|
+
final gold (unit+letter): 14.94 cs
|
|
572
|
+
final gps (unit+letter): 20.00 cz
|
|
573
|
+
final gold as JS Number: 1.494328222485101e+292
|
|
574
|
+
final gps as JS Number : Infinity
|
|
575
|
+
If JS shows Infinity while unit+letter output stays finite, the library is doing its job.
|
|
505
576
|
```
|
|
506
577
|
|
|
507
578
|
## Performance
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arbitrary-numbers",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Arbitrary-magnitude arithmetic for idle games and simulations, with fused operations, formula pipelines, and pluggable number formatting.",
|
|
5
5
|
"author": "Chris",
|
|
6
6
|
"license": "MIT",
|