feat: Making the game harder to 'beat'

This commit is contained in:
gauvainboiche
2026-10-08 17:17:21 +02:00
parent 2f7c307f0e
commit 8b15c76b14
20 changed files with 637 additions and 91 deletions
+19 -2
View File
@@ -35,7 +35,8 @@ public/
ui/ DOM helpers · main view · one view per section · tabs/menu · settings · toasts ·
fx (the quick purchase animations)
main.js wires everything together
tests/ node:test suites (engine, systems, save import/export, server, content completeness)
scripts/ tools: campaign bot (pacing), icon list generator
tests/ node:test suites (engine, systems, balance and pacing, save import/export, server, content completeness)
```
The key idea: **mechanics are shared, themes are skins.** `public/data/` defines generators and upgrades by id (`gen1`, `click_1`, …) with their numbers; a theme only gives those ids a name, a colour palette and, later, images. Rebalancing the game is a change in `public/data/`, not in each theme.
@@ -50,7 +51,7 @@ The production screen is the core loop. Further sections appear in the menu as y
| Investments | 100 K | 9 societies in 3 risk tiers (low ±5 %, medium ±15 %, high ±50 % every 60 s), dividends, a 0.5 % fee. Themed names. |
| Research | 500 K | Labs (bought with funds) produce research points slowly; a tree of 15 permanent bonuses, including a late one that reveals the balanced price. |
| Gamble (themed: Quantum Computer, Crystal Ball…) | 5 M | Chips are costly and each one costs more. Stake them on a cycle: win, jackpot or crash. Reliability upgrades tilt the odds; chips boost demand with diminishing returns. |
| Legacy | 500 M | Restart the run for permanent points: a passive bonus per point plus repeatable perks. Research, achievements and statistics survive. |
| Legacy | 500 M | Restart the run for permanent points, earned from *everything you have ever produced* with diminishing returns (the first point at 10 trillion, each further one costs more). A modest passive bonus plus repeatable perks. Research, achievements and statistics survive. |
| Achievements | always | 23 milestones, each with a small permanent bonus. |
Everything is data-driven: `tabs.json` (unlocks), `investments.json`, `research.json`, `legacy.json`, `achievements.json` and the `gamble`, `research`, `legacy`, `contracts` and `events` blocks of `rules.json`. All bonuses share one vocabulary of effects (`engine/effects.js`). Texts for research, perks and achievements are in the core locale files; only the theme vocabulary (the gamble's name, the chip/research/legacy currencies, the nine societies) is per theme.
@@ -91,6 +92,22 @@ Everything numeric is in `public/data/`: `rules.json` (market, raw material, mar
- **Selling:** demand is a smooth curve, `baseDemand × demandMultiplier × (referencePrice / price) ^ elasticity` units/s: lower the price and more people buy, with no ceiling. The best price is where demand just matches your output (selling for less gains no volume, selling for more leaves stock unsold). That point moves with every generator, upgrade and marketing level, and the game does not display it: the market hint only says whether you are selling too cheap, too dear, or about right.
- **Raw material** (wire, herbs…): the price per unit starts high (`startUnitPrice`, about a third of the sale price) and falls towards `floorUnitPrice` as total production grows (economies of scale). A lot covers about 10 s of current output (in doublings), multiplied by the "stack" upgrades (`batch_size_mult`, a chain of five, ×180 in total). A lot costs in proportion to its size, so bigger stacks cost more per purchase while the price per unit still falls with scale. The market is erratic: the price is re-drawn every 10 s (`updateEverySeconds`) with wide random swings plus frequent shortages and gluts (`spikeChance`, `spikeSize`), and is shown to the cent, with ▲/▼ for its last move. The auto-buy upgrade is patient: it waits for a fair price unless stock is nearly gone.
### Pacing: how long the game lasts
A bot plays the whole game (automation, upgrades, endless levels, labs, research, legacy restarts) so the pacing can be measured instead of guessed:
```bash
npm run campaign -- 120 10 # 120 simulated hours, one step = 10 s (takes a few seconds)
```
It prints the restarts, how fast each run starts, and when each long-term goal is reached. Knobs can be tried without editing the data files (see the top of `scripts/campaign.mjs`), e.g. `THRESH=1e14 PERK_GROWTH=2.5 npm run campaign -- 200 10`. The bot is a careful player that never gambles, invests or does contracts, so a person takes at least as long.
Where the game stands (bot hours): first restart about 10 h; 5 research nodes about 7 h, all 15 about 60 h; the first restarts are 10 to 20 h apart and get longer; no legacy perk is maxed after 200 h. `tests/balance.test.js` plays 40 hours on every `npm test` and fails if the game is finished too quickly (first restart before 6 h, all research or a perk maxed within 40 h) or runs away (a restarted run producing more than a million units per second after 2 minutes).
The levers, from the biggest: `legacy.threshold`, `exponent` and the passive bonus in `rules.json` (how fast restarts pay), perk `costGrowth` in `legacy.json`, research `cost` and `rpPerLabPerSecond`, endless `baseCost` / `costGrowth`.
**A lesson kept in the code.** The first legacy system multiplied output by 1.05 *per point* and gave points from a single run's production. A few thousand points gave ×1e100 and a run took seconds (a player reached 6e136 units/s two minutes into their fourth game). Now points come from lifetime production with diminishing returns, the passive bonus grows with the square root of the points and never compounds, and saves from older versions are repaired on load: runaway legacy points and perks are capped and the run restarts (research and achievements are kept). The player is told with a message that stays until clicked.
## Icons to produce
Every icon the game shows is a grey square until a theme provides an image. The exhaustive work list is in **[ICONS.txt](ICONS.txt)**: a checklist per theme, with the file name, the key and what to draw for each icon. It is generated from the game data, so it is always complete. All 23 achievements share a single `trophy` icon.