// Corporate Ladder — the default content pack for The Ladder. // // A modern office, the mailroom, and two people who have been there longer // than you. Everything the engine needs to run this setting is in this file // and the ones it imports; the engine itself knows nothing about mailrooms. import { characters } from './characters.js'; import { events } from './events/index.js'; export const corporateLadder = { id: 'corporateladder', name: 'Corporate Ladder', version: '0.1.0', turnUnit: 'day', startingStage: 'mailroom', stages: { mailroom: { label: 'Mailroom', title: 'Mail Associate I' }, dispatch: { label: 'Dispatch', title: 'Dispatch Coordinator' }, }, // Turn 1 is a Monday. Content can gate on the day — and, more importantly, // money arrives and leaves on a rhythm the player can plan around instead of // draining by an unexplained amount every day. calendar: { cycleLength: 7, cycleName: 'Week', unitNames: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'], }, // Money is tight but not hopeless. The baseline bleeds about three dollars a // day, so a careful player creeps forward and a careless one does not — the // pressure comes from what choices cost, not from an unexplained drain. state: { 'money': { initial: 520, min: -5000, max: 1000000 }, 'debt': { initial: 0, min: 0, max: 1000000 }, 'reputation': { initial: 50, min: 0, max: 100 }, 'skills.negotiation': { initial: 5, min: 0, max: 100 }, 'skills.logistics': { initial: 5, min: 0, max: 100 }, 'flags.took_loan': { initial: false }, 'flags.holds_the_envelope': { initial: false }, 'flags.covered_for_trevor': { initial: false }, 'flags.promoted': { initial: false }, 'flags.recommended_trevor': { initial: false }, // Moments the retrospective reads back. Content decides what is memorable; // the full turn-by-turn record lives in history regardless. 'notable': { initial: [] }, }, // Nobody fears a new hire. Trevor's defaults are lower still — see // characters.js, where he starts two weeks ahead of you and knows it. relationshipStats: { likes_you: { label: 'Likes you', initial: 50, min: 0, max: 100 }, fears_you: { label: 'Wary of you', initial: 10, min: 0, max: 100 }, wants_to_help_you: { label: 'Will help you', initial: 40, min: 0, max: 100 }, }, // Money moves on a schedule the player can feel: paid on alternate Fridays, // rent out every Monday, and only small change in between. // // Keep this arithmetic honest when tuning: wages, minus two rents, minus // fourteen days of small change. It should come to roughly forty dollars // down over a fortnight — a drift, not a bleed. Rent was once raised without // re-deriving it, which quietly made the baseline four times steeper and // trapped a real playtester below zero for 30% of a 182-turn run. upkeep: [ { label: 'Coffee, transit, lunch', effects: [{ path: 'money', op: 'add', value: -18 }] }, // Turn 1 is a Monday, so offset 4 is the first Friday and every 14 makes it // alternate Fridays. Rent lands on Mondays, starting the second week. // Wages depend on the job. Two entries rather than one, gated on stage: // the engine has no idea what a promotion is, and does not need to. { label: 'Wages', every: 14, offset: 4, requires: [{ path: 'stage', op: '==', value: 'mailroom' }], effects: [{ path: 'money', op: 'add', value: 1120 }], }, { label: 'Wages', every: 14, offset: 4, // A real raise, but not a different life — the coordinator job is, as // Marlene puts it, mostly the same work with a different phone. Net of // rent it comes to a few dollars a day ahead instead of behind. requires: [{ path: 'stage', op: '==', value: 'dispatch' }], effects: [{ path: 'money', op: 'add', value: 1260 }], }, { label: 'Rent', every: 7, offset: 7, effects: [{ path: 'money', op: 'add', value: -455 }] }, // 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. { label: 'Loan service charge', every: 7, offset: 7, requires: [{ path: 'debt', op: '>', value: 0 }], effects: [{ path: 'money', op: 'add', value: -70 }], }, { label: 'Loan service charge (arrears)', every: 7, offset: 7, requires: [{ path: 'debt', op: '>=', value: 1000 }], effects: [{ path: 'money', op: 'add', value: -40 }], }, { label: 'Loan service charge (collections)', every: 7, offset: 7, requires: [{ path: 'debt', op: '>=', value: 2000 }], effects: [{ path: 'money', op: 'add', value: -70 }], }, ], // How the interface names and formats this pack's state. The UI reads only // this map, so renaming a stat or reordering the header is content's job. display: { 'money': { label: 'Money', format: 'money', order: 1 }, 'debt': { label: 'Debt', format: 'money', order: 2, hideWhenZero: true }, 'reputation': { label: 'Standing', format: 'meter', order: 3 }, 'skills.negotiation': { label: 'Negotiation', format: 'meter', order: 4 }, 'skills.logistics': { label: 'Logistics', format: 'meter', order: 5 }, // Kept out of the header, and out of the ledger too: `notable` is the // retrospective's own list, and "Notable — changed" tells nobody anything. 'notable': { hidden: true, inLedger: false }, // Flags do belong in the ledger — a flag flipping is a fact about the // world — but as a sentence rather than as "now true". 'flags.took_loan': { label: 'The loan', hidden: true, whenTrue: 'You are carrying a loan now.', whenFalse: 'The loan is settled.', }, 'flags.holds_the_envelope': { label: 'The envelope', hidden: true, whenTrue: 'The envelope is in your locker.', whenFalse: 'The envelope is back in the system.', }, 'flags.covered_for_trevor': { label: "Trevor's Thursday", hidden: true, whenTrue: 'Trevor owes you a Thursday.', whenFalse: 'You and Trevor are square.', }, 'flags.promoted': { label: 'Promotion', hidden: true, whenTrue: 'You are out of the mailroom.', whenFalse: 'Back in the mailroom.', }, 'flags.recommended_trevor': { label: "Trevor's recommendation", hidden: true, whenTrue: "Trevor's name is in for the mailroom.", whenFalse: "Trevor's name is not in for the mailroom.", }, }, characters, events, }; export default corporateLadder;