Keep money mattering at the top, and fix the instruments that hid it

Both settings now carry a charge levied by standing itself, which no purchase
ends. Corporate Ladder's steps on money (1200/-60, 2400/-120, 3600/-240): a flat
charge cannot flatten a slope, since late income scales with how well the player
plays, and the flat charge needed to stop an optimiser accumulating put ordinary
archetypes below zero for 44% of a run. Stepped, the balance settles around
$4,250 and ordinary play comes out better than before it existed. The Frontier's
is flat at -4 a run, because its late game never accumulated in the first place.

Found in the first two human sessions of this work:

- A career saved before a pack gained a stat had no path for it, and conditions
  compare numbers only, so every event, option and upkeep entry gated on a new
  stat silently did not exist for that run. Loading now fills those in.
- 'Wrap up my career' sat immediately after the last option in tab order, so one
  Tab too many and Enter read as the game ending at day 31. It goes last, and
  the retrospective says plainly that it is a summary.
- A 181-turn session ran against a stale bundle and the change under test never
  fired. Every logged turn now records app_version and build.
- src/version.js had reported 0.3.0 since 0.3.0, while playtesters were told to
  check the status bar. A test now holds it to package.json.
- 'Put money against the book' was shown locked to a player who owed nothing,
  six times. Options gated on a state the player cannot choose to enter are now
  hidden rather than greyed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxdJFbLq1rBKsUeticGV1g
This commit is contained in:
JesseMarkowitz
2026-09-12 23:07:35 -04:00
co-authored by Claude Opus 5
parent 5d645e6452
commit d84ae495f4
17 changed files with 318 additions and 23 deletions
+52 -3
View File
@@ -170,6 +170,54 @@ export const corporateLadder = {
],
effects: [{ path: 'reputation', op: 'add', value: -14 }],
},
// The charge that never stops, and the only one with no purchase that ends
// it. Everything above is a ladder with a top: buy both tiers, reach 100
// standing, and every charge switches off. A real 96-turn session arrived
// there at turn 84 with nothing left to spend on and a balance that only
// climbed.
//
// It steps on money rather than being flat, and that is the whole design.
// A flat charge cannot flatten a slope: late income comes from choices and
// scales with how well the player is playing, so a charge big enough to
// stop an optimiser accumulating (-360 a week, measured) put ordinary
// archetypes below zero for 44% of a run and ended them $1,385 in debt.
// Stepping on money lands it on whoever has it. Measured: the balance
// settles around $4,250 and stops climbing (-3 a week), while ordinary play
// gets *better* than before it existed — 13% of a run below zero against
// 17%, and a tier-2 run ending +$175 rather than -$25.
{
label: 'What the standing costs',
every: 7,
offset: 7,
requires: [
{ path: 'stage', op: '==', value: 'dispatch' },
{ path: 'reputation', op: '>=', value: 85 },
{ path: 'money', op: '>=', value: 1200 },
],
effects: [{ path: 'money', op: 'add', value: -60 }],
},
{
label: 'What the standing costs',
every: 7,
offset: 7,
requires: [
{ path: 'stage', op: '==', value: 'dispatch' },
{ path: 'reputation', op: '>=', value: 85 },
{ path: 'money', op: '>=', value: 2400 },
],
effects: [{ path: 'money', op: 'add', value: -120 }],
},
{
label: 'What the standing costs',
every: 7,
offset: 7,
requires: [
{ path: 'stage', op: '==', value: 'dispatch' },
{ path: 'reputation', op: '>=', value: 85 },
{ path: 'money', op: '>=', value: 3600 },
],
effects: [{ path: 'money', op: 'add', value: -240 }],
},
// The service charge steps up with the size of the debt, so the spiral
// tightens instead of flattening out. A step function in data costs the
// engine nothing; a percentage would have needed a multiply operation.
@@ -206,9 +254,10 @@ export const corporateLadder = {
mailroom: [-45, 5],
dispatch: [5, 125],
},
// Upkeep gated on these is excluded from that baseline: both are states a
// player opts into, and the baseline is the floor underneath everybody.
baselineExcludes: ['debt', 'lifestyle'],
// Upkeep gated on these is excluded from that baseline: a debt taken on, a
// lifestyle bought, a standing earned. The baseline is the floor underneath
// everybody — what a player faces having none of the three.
baselineExcludes: ['debt', 'lifestyle', 'reputation'],
},
// How the interface names and formats this pack's state. The UI reads only