Add chance and a cast that changes between runs, and a pack to try them

An option used to do exactly what it said. Now it may carry a check: one of
four attributes (Nerve, Wits, Charm, Resolve) against a set difficulty or
against a named person's own attribute, leaning on how they regard you, with a
success and a failure. The player sees only the odds in words ("a long shot",
"likely"), never a number. The roll is one draw from the run's generator, so a
run still replays exactly from its seed and choices.

A character may be a role with several authored candidates, one drawn per run,
or a group of two to four drawn into numbered slots. Everyone carries a name, a
description and the same four attributes as the player, so a replayed pack
meets a different office. Text names people as {partner} or {clerk}, and an
event about "a clerk" binds one present clerk for the turn. The draw and the
binding are saved with the run, and a save from before a pack drew a cast gets
the same one every time it is loaded.

All of it is generic and optional: Corporate Ladder and the Frontier use none
of it and play as before. The Counting House, a one-stage office about 1910
built from the story-to-pack catalogue, exercises it, and was tuned against the
conformance suite by measurement. DECISIONS #41. Version 0.4.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MhABSrqkwTdcybXmheDPr
This commit is contained in:
JesseMarkowitz
2026-09-23 22:12:26 -04:00
co-authored by Claude Opus 5.5
parent 112e558dbb
commit 3108319a2b
25 changed files with 2257 additions and 77 deletions
+114
View File
@@ -0,0 +1,114 @@
// A small pack for the cast and checks (DECISIONS #41): a drawn single role, a
// group role of two to four, a fixed character with attributes, opposed and
// unopposed checks, and an event about "one of the co-workers". Its checks run
// from 0 to 100 so tests can force an outcome; a real pack keeps a floor and a
// ceiling so nothing is ever certain.
export const castPack = {
id: 'castpack',
name: 'Cast Pack',
version: '1.0.0',
turnUnit: 'day',
startingStage: 'desk',
attributes: {
nerve: { label: 'Nerve' },
wits: { label: 'Wits' },
charm: { label: 'Charm' },
resolve: { label: 'Resolve' },
},
checks: {
base: 50, perPoint: 10, unopposed: 5,
relationshipPerPoint: 0.5, relationshipCentre: 50,
floor: 0, ceiling: 100,
},
state: {
'money': { initial: 100, min: -500, max: 10000 },
'attributes.nerve': { initial: 5, min: 0, max: 10 },
'attributes.wits': { initial: 5, min: 0, max: 10 },
'attributes.charm': { initial: 5, min: 0, max: 10 },
'attributes.resolve': { initial: 5, min: 0, max: 10 },
},
relationshipStats: {
trust: { label: 'Trusts you', initial: 50, min: 0, max: 100 },
regard: { label: 'Thinks of you', initial: 50, min: 0, max: 100 },
},
characters: [
{
id: 'boss',
role_type: 'boss',
title: 'Manager',
candidates: [
{ name: 'Agnes Pell', description: 'Reads every memo twice.', attributes: { nerve: 6, wits: 8, charm: 3, resolve: 7 } },
{ name: 'Walter Grose', description: 'Loud, and quicker than he looks.', attributes: { nerve: 7, wits: 6, charm: 6, resolve: 4 },
startingRelationship: { trust: 30 } },
{ name: 'Mina Hart', description: 'Has never raised her voice.', attributes: { nerve: 4, wits: 7, charm: 8, resolve: 6 } },
],
},
{
id: 'coworker',
role_type: 'peer',
title: 'Clerk',
count: [2, 4],
candidates: [
{ name: 'Ben Aske', description: 'Owes {boss} a favour.', attributes: { nerve: 3, wits: 4, charm: 6, resolve: 5 } },
{ name: 'Cora Dunn', description: 'First in, last out.', attributes: { nerve: 5, wits: 5, charm: 4, resolve: 8 } },
{ name: 'Del Fane', description: 'Knows everyone\'s business.', attributes: { nerve: 4, wits: 7, charm: 5, resolve: 3 } },
{ name: 'Edie Gow', description: 'Quiet until she is not.', attributes: { nerve: 7, wits: 5, charm: 3, resolve: 6 } },
{ name: 'Fitz Hale', description: 'Charming, unreliable.', attributes: { nerve: 5, wits: 3, charm: 8, resolve: 2 } },
],
},
{ id: 'porter', name: 'Old Sam', role_type: 'staff', description: 'Has seen everyone come and go.',
attributes: { nerve: 2, wits: 9, charm: 4, resolve: 9 } },
],
events: [
{
id: 'routine',
stage: 'desk',
weight: 100,
description: 'A day at the desk under {boss}.',
options: [
{ id: 'work', label: 'Work.', effects: [{ path: 'money', op: 'add', value: 10 }] },
{
id: 'ask_for_more',
label: 'Ask {boss.first} for more money.',
check: { attribute: 'charm', against: 'boss', opposedBy: 'wits', relationship: 'trust' },
effects: [{ path: 'relationships.boss.regard', op: 'add', value: -1 }],
success: { result: '{boss} agrees.', effects: [{ path: 'money', op: 'add', value: 50 }] },
failure: { result: '{boss} laughs.', effects: [{ path: 'relationships.boss.trust', op: 'add', value: -5 }] },
},
{
id: 'hard_sum',
label: 'Try the hard sum.',
check: { attribute: 'wits', difficulty: 5 },
success: { result: 'It adds up.', effects: [{ path: 'attributes.wits', op: 'add', value: 1 }] },
failure: { result: 'It does not.', effects: [] },
},
],
},
{
id: 'needled',
stage: 'desk',
weight: 100,
involves: ['coworker'],
description: '{coworker} makes a remark about your tie.',
options: [
{ id: 'ignore', label: 'Let it go.', effects: [{ path: 'relationships.{coworker}.regard', op: 'add', value: -2 }] },
{
id: 'retort',
label: 'Answer {coworker.first} back.',
check: { attribute: 'nerve', against: '{coworker}', relationship: 'regard' },
success: { result: '{coworker} laughs, and means it.', effects: [{ path: 'relationships.{coworker}.regard', op: 'add', value: 5 }] },
failure: { result: 'It lands badly.', effects: [{ path: 'relationships.{coworker}.trust', op: 'add', value: -5 }] },
},
],
},
],
};
export default castPack;