Replace clustering with a catalogue, and hand-write the references to judge it against
The pipeline's embed-and-cluster step is dead, and this commit holds both the evidence for that and the step proposed to replace it. Predicaments. Scenes are re-described as "what the person is up against", with no names, jobs or places, then embedded and clustered (redescribe.py, topic_words.py, topic_share.py). The pilot chose qwen3:14b over 3b by reading both side by side. Two defects the pilot exposed are fixed: split.py missed titles in quotes and a contents subtitle after a dash, so three stories had been merged into their neighbours, and strip_names.py read New York place names as people. The corrected corpus is probe/v2 (97 stories, 839 scenes); carry_summaries.py reuses the 829 unchanged v1 summaries. Topic share fell from 20% to 13% at k=60, short of the pre-registered 10%. Hand references. Three corpora were read scene by scene and written up by hand, under the same prompt rules the local models get, as a baseline to judge them against: O. Henry (probe/v2/claude, 839 scenes, 20 situations), Wharton's Descent of Man (probe/wharton, 262 scenes, 16 groups) and Jacobs's The Lady of the Barge (probe/jacobs, 157 scenes, 19 groups). Each has its own README and a readable page. No inference was used for any of them. Catalogue. probe/catalogue maps every hand group in the three references onto 36 situation entries, with an answer key per corpus and one recurrence rule applied to all three. classify.py assigns a scene one entry or none, leave-one-corpus- out; score.py checks it against the key, with a self-test on random labels. Why clustering is out: hand-written predicaments, embedded and clustered exactly as the model's were, agree with the hand grouping at ARI 0.05 — no better than the 14B text's 0.07. Better rewriting cannot rescue it. Embeddings cannot even shortlist: the hand label is the nearest entry 13% of the time and in the top 8 half the time. The classification runs are not here. The dev and test runs are pre-registered in probe/catalogue/README.md with the bar set beforehand, and are blocked on the inference host, whose GPU has fallen off the PCIe bus three times. The 30-scene partial output in out/ is not a result. Review page. The situation review is now a browser page rather than JSON edited by hand (review_page.py, review_page_logic.cjs with Node tests, format schema v2). It has never been rendered in a real browser. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014BygvsUXV9eU6oHkTCkKZ1
This commit is contained in:
co-authored by
Claude Opus 5
parent
fa3769d0fe
commit
e5617b86ba
@@ -0,0 +1,482 @@
|
||||
"""Claude's situations and options for the O. Henry corpus, as data. Run to validate and write situations-claude.json.
|
||||
|
||||
Written by hand in-session (claude-opus-5), 2026-09-17. Per DESIGN.md the numbers are left to the search: each
|
||||
effect names a path, a direction and a rough size (small / medium / large), never a value.
|
||||
"""
|
||||
import json, re, sys, pathlib, collections
|
||||
HERE = pathlib.Path(__file__).resolve().parent
|
||||
sys.path.insert(0, str(HERE))
|
||||
from assign import ASSIGN
|
||||
|
||||
PLAYER_ROLE = "a young clerk newly arrived in the big city, on eighteen dollars a week"
|
||||
STAGES = {
|
||||
"rooming_house": "No standing yet: a hall bedroom, a counter job, the park bench is never far off.",
|
||||
"counter": "A steady place: a raise, a regular table, people who know your name.",
|
||||
"swell": "Money and a place among the well-dressed; what the city charges for staying there.",
|
||||
}
|
||||
CAST = {
|
||||
"sweetheart": "the one you court",
|
||||
"partner": "the one you married, or live with",
|
||||
"rival": "whoever wants what you want",
|
||||
"employer": "the boss, the firm",
|
||||
"patron": "someone powerful above you: the district leader, the rich benefactor",
|
||||
"pal": "a friend from your own level",
|
||||
"landlady": "the house you lodge in",
|
||||
"officer": "the law, on the beat",
|
||||
"stranger": "the plausible stranger: swell, sharper or tramp",
|
||||
}
|
||||
REL_STATS = {"trusts_you", "likes_you", "wary_of_you", "owes_you"}
|
||||
SKILLS = {"skills.front": "bluff, manners, looking the part (the corpus's own word: 'front does it')",
|
||||
"skills.nerve": "daring, the stomach to act"}
|
||||
|
||||
def e(path, d, size): return {"path": path, "dir": d, "size": size}
|
||||
def note(text): return {"path": "notable", "push": text}
|
||||
def flag(name): return {"path": "flags." + name, "set": True}
|
||||
|
||||
EVENTS = [
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="pose", situation="pose", title="Passing for more than you are",
|
||||
sentence="A young person of small means wants to be taken for someone grander by a stranger they want to impress.",
|
||||
roles=["you", "sweetheart"], stages=["rooming_house", "counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="Ten weeks of putting a dollar aside have bought one evening in good clothes. At the corner a young woman slips on the ice, and when you help her up she takes you, plainly, for what the clothes say you are.", sources=[603, 604, 605, 606]),
|
||||
dict(text="The stranger across the table has just told you something about themselves that is a little too good to be true. You have one ready that is better.", sources=[46, 402, 404, 799]),
|
||||
dict(text="The present you can afford and the present you want to be seen giving are two different things, and there is a shop two streets over that sells a very good copy of the second.", sources=[722, 723, 726]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Tell them what you really are.", result="The evening is smaller than you planned. It is also the only part of it you get to keep.",
|
||||
effects=[e("relationships.sweetheart.trusts_you", "+", "medium"), e("skills.front", "-", "small"), note("Told the truth on the one evening it cost something.")], source=dict(kind="scene", chunks=[139, 140, 610])),
|
||||
dict(label="Play the part the clothes promise.", result="Clubs, a yacht you have never seen, a friend with a famous name. It goes over well. Once, you catch a look of disappointment.",
|
||||
effects=[e("skills.front", "+", "medium"), e("relationships.sweetheart.likes_you", "+", "small"), e("relationships.sweetheart.trusts_you", "-", "medium"), flag("passed_for_a_swell")], source=dict(kind="scene", chunks=[404, 608, 800])),
|
||||
dict(label="Spend what the part would really cost.", result="It is real money, and for one evening it buys the real thing.",
|
||||
effects=[e("money", "-", "large"), e("standing", "+", "small"), e("relationships.sweetheart.likes_you", "+", "medium")], source=dict(kind="scene", chunks=[135, 139, 723])),
|
||||
dict(label="Say little and let them decide.", result="You neither claim nor deny. What they make of you is theirs to be wrong about.",
|
||||
effects=[e("skills.front", "+", "small")], source=dict(kind="archetype", chunks=[])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="benefactor_offered", situation="benefactor", title="Help with a sermon attached",
|
||||
sentence="A well-off benefactor wants to do good to you on their own terms, and help comes with a price in pride.",
|
||||
roles=["you", "patron"], stages=["rooming_house"],
|
||||
descriptions=[
|
||||
dict(text="There is a free bed tonight, fifteen cents' worth, if you stand in the line and hear the man on the box out. It is cold enough that the man on the box knows it.", sources=[234, 509]),
|
||||
dict(text="You had the job, or nearly. Then a lady from an association explained why you must not take it, and drove away in her carriage.", sources=[832, 833, 834, 835]),
|
||||
dict(text="A well-dressed stranger has asked you to dine. You know the price of dinner by now: your story, from the beginning, told the way he wants it.", sources=[649, 651, 440]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Take it, and pay in the coin they ask.", result="You tell them what they came to hear. The meal is excellent, and afterwards you feel you have sold something.",
|
||||
effects=[e("money", "+", "small"), e("skills.front", "+", "small"), e("standing", "-", "small")], source=dict(kind="scene", chunks=[651, 652])),
|
||||
dict(label="Refuse it.", result="Pride is warm for about an hour.",
|
||||
effects=[e("money", "-", "small"), e("skills.nerve", "+", "small"), e("relationships.patron.wary_of_you", "+", "small")], source=dict(kind="scene", chunks=[441, 509])),
|
||||
dict(label="Take the help, and tell them the plain truth instead.", result="It is not the story they wanted. It is the one they remember.",
|
||||
effects=[e("relationships.patron.trusts_you", "+", "medium"), e("money", "+", "small"), note("Told a benefactor the truth over dinner.")], source=dict(kind="scene", chunks=[652, 653])),
|
||||
dict(label="Find your own way round it.", result="It takes longer and costs more, and nobody lectures you.",
|
||||
effects=[e("money", "-", "small"), e("skills.nerve", "+", "small"), e("standing", "+", "small")], source=dict(kind="gap", chunks=[])),
|
||||
]),
|
||||
dict(id="benefactor_playing", situation="benefactor", title="Playing the benefactor",
|
||||
sentence="You, with money to spare, want to do good to someone below you, and want to see it done.",
|
||||
roles=["you", "stranger", "patron"], stages=["swell"],
|
||||
descriptions=[
|
||||
dict(text="Money is coming in faster than you can find uses for it. Your last gift to an institution came back as three lines in the evening paper with your name misspelled. You want, this once, to see somebody's face.", sources=[361, 362, 363]),
|
||||
dict(text="Down past the shopping district you own a row of houses you have never been inside. Somebody has finally told you what it is like to live in one.", sources=[704, 710, 711, 712]),
|
||||
dict(text="A young man is throwing silver into the street for a crowd to scramble after, with a face like a funeral. You could ask him why.", sources=[340, 341, 342]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Write a cheque to an institution and be done.", result="It is received, acknowledged and misprinted.",
|
||||
effects=[e("money", "-", "medium"), e("standing", "+", "small")], source=dict(kind="scene", chunks=[362])),
|
||||
dict(label="Go down and hand it out yourself.", result="Somebody already owns the gratitude in that neighbourhood, and explains this to you between a barber's pole and the ash cans.",
|
||||
effects=[e("money", "-", "small"), e("relationships.patron.wary_of_you", "+", "medium"), e("skills.nerve", "+", "small")], source=dict(kind="scene", chunks=[363, 364])),
|
||||
dict(label="Fix the thing you own.", result="It costs a year of what the houses bring in. Nobody thanks you. The girls on the ground floor have a parlour.",
|
||||
effects=[e("money", "-", "large"), e("standing", "+", "small"), flag("fixed_the_row"), note("Gave the tenants their parlours back.")], source=dict(kind="scene", chunks=[712])),
|
||||
dict(label="Ask what they want before you give anything.", result="The answer is small, specific and cheap, and nothing like what you had in mind.",
|
||||
effects=[e("money", "-", "small"), e("relationships.stranger.trusts_you", "+", "medium")], source=dict(kind="gap", chunks=[439, 442])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="taken_for_granted", situation="taken_for_granted", title="The one you stopped noticing",
|
||||
sentence="A partner at home wants to be noticed by the person who has stopped seeing them.",
|
||||
roles=["you", "partner", "pal"], stages=["counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="You know how tonight will go: the supper, the paper, and at a quarter past eight you reach for your hat. Tonight there is a note pinned to the gas jet instead.", sources=[665, 666, 667]),
|
||||
dict(text="Three years, and this morning the one you married asked you, quite calmly, to take them out to dinner.", sources=[24, 25]),
|
||||
dict(text="Upstairs they fight on Saturdays and make it up with presents. Downstairs you read the paper in your stocking feet, and the one you married has begun to look at you as though that were worse.", sources=[759, 761, 762]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Go out as usual.", result="Nothing is said. Nothing needs to be; it has all been said before.",
|
||||
effects=[e("relationships.partner.likes_you", "-", "medium"), e("relationships.pal.likes_you", "+", "small"), e("money", "-", "small")], source=dict(kind="scene", chunks=[666, 671])),
|
||||
dict(label="Take them somewhere good.", result="You watch a room turn toward them, and you sit there with nothing to say, ashamed of three years.",
|
||||
effects=[e("money", "-", "medium"), e("relationships.partner.likes_you", "+", "large"), e("standing", "+", "small")], source=dict(kind="scene", chunks=[26, 27, 28])),
|
||||
dict(label="Promise to do better.", result="You mean it at eight. By a quarter past you are less sure.",
|
||||
effects=[e("relationships.partner.trusts_you", "+", "small")], source=dict(kind="scene", chunks=[670, 671])),
|
||||
dict(label="Do the job nobody asked you to.", result="It is not what was wanted, and it is noticed.",
|
||||
effects=[e("relationships.partner.likes_you", "+", "small"), e("skills.nerve", "-", "small")], source=dict(kind="scene", chunks=[764])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="station", situation="station", title="Across the gap in station",
|
||||
sentence="Someone above or below you in station wants you, and each of you must decide how much to show of where you really stand.",
|
||||
roles=["you", "sweetheart"], stages=["rooming_house", "counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="The one you want is far outside your circle and there is no proper way to be introduced. There is a counter, and a card, and a street corner at half past seven.", sources=[17, 18]),
|
||||
dict(text="You met on an excursion boat. They take you for exactly what you appear to be, and you have not corrected them.", sources=[366, 368, 705, 706]),
|
||||
dict(text="Your partner, born to everything, has found a letter from your people and announced that the two of you will go and visit them.", sources=[67, 68]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Show them where you live.", result="The shabby thing turns out to be the thing they wanted to see.",
|
||||
effects=[e("relationships.sweetheart.trusts_you", "+", "medium"), e("skills.front", "-", "small")], source=dict(kind="scene", chunks=[70, 71, 73])),
|
||||
dict(label="Keep to neutral ground.", result="Street corners and park benches. It works, and goes on working, until somebody asks why.",
|
||||
effects=[e("relationships.sweetheart.likes_you", "+", "small"), flag("courting_on_street_corners")], source=dict(kind="scene", chunks=[18, 711])),
|
||||
dict(label="Describe the life you are offering.", result="You paint it with care. They hear something else entirely.",
|
||||
effects=[e("skills.front", "+", "small"), e("relationships.sweetheart.trusts_you", "-", "small")], source=dict(kind="scene", chunks=[20, 21, 22])),
|
||||
dict(label="Tell them the gap plainly and let them choose.", result="They take longer to answer than you would like.",
|
||||
effects=[e("relationships.sweetheart.trusts_you", "+", "small"), e("skills.nerve", "+", "small")], source=dict(kind="scene", chunks=[374])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="newcomer", situation="newcomer", title="The city that does not notice you",
|
||||
sentence="A newcomer wants a foothold in a place that neither sees them nor lets them stay as they were.",
|
||||
roles=["you", "pal", "stranger"], stages=["rooming_house", "counter"],
|
||||
descriptions=[
|
||||
dict(text="All afternoon nobody has looked at you. Not one face in ten thousand. You would take a kick, by now, for the company.", sources=[715, 716, 101]),
|
||||
dict(text="An old friend from home has done well here, and orders for both of you in a language you do not speak. He says the place is comfortable. He says it as though apologising.", sources=[273, 274, 275, 431]),
|
||||
dict(text="What impressed them back home is in a trunk under the bed. Here it has not impressed anybody.", sources=[83, 157, 158]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Do as the place does.", result="It pays. Some weeks later you notice you order the small drink too.",
|
||||
effects=[e("money", "+", "small"), e("standing", "+", "small"), e("skills.front", "+", "small"), e("skills.nerve", "-", "small")], source=dict(kind="scene", chunks=[432, 433])),
|
||||
dict(label="Refuse to be made over.", result="You say so, loudly and often. At midnight you sit at the window a long time.",
|
||||
effects=[e("skills.nerve", "+", "small"), e("standing", "-", "small"), note("Swore the city would never change you.")], source=dict(kind="scene", chunks=[434, 435])),
|
||||
dict(label="Stop a stranger and ask.", result="It fails twice, and then it does not.",
|
||||
effects=[e("relationships.stranger.likes_you", "+", "small"), e("skills.nerve", "+", "small")], source=dict(kind="scene", chunks=[718, 719])),
|
||||
dict(label="Go home.", result="It is still there, and smaller than you remember.",
|
||||
effects=[e("standing", "-", "medium"), e("money", "+", "small"), flag("went_home")], source=dict(kind="archetype", chunks=[89, 147, 164])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="easy_money", situation="easy_money", title="The sure thing",
|
||||
sentence="A plausible stranger wants your money, and offers a sure thing to get it.",
|
||||
roles=["you", "stranger", "landlady", "pal"], stages=["rooming_house", "counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="A great man wants a painting he cannot find and would pay anything for it. Walking home after, you pass a pawnshop, and there it is in the window.", sources=[222, 223, 224]),
|
||||
dict(text="The man who pulled you out of the traffic and dusted your hat has a friend in the government who can arrange everything. Keep the drafts in your inside pocket, he says, till tomorrow.", sources=[210, 211, 212]),
|
||||
dict(text="Somebody you hardly know has a scheme that pays ten thousand and needs only a little nerve and a little of your money to start.", sources=[267, 268]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Put your money in.", result="It was a sure thing. It was sure for somebody.",
|
||||
effects=[e("money", "-", "large"), e("skills.nerve", "+", "small"), note("Bought the sure thing.")], source=dict(kind="scene", chunks=[224, 225])),
|
||||
dict(label="Say you will look again tomorrow, in daylight.", result="By morning the great man is abroad, and so is the chance.",
|
||||
effects=[e("skills.front", "+", "small")], source=dict(kind="archetype", chunks=[])),
|
||||
dict(label="Ask somebody with no stake in it.", result="The person you ask has watched a great many sure things walk out of the front door.",
|
||||
effects=[e("relationships.landlady.trusts_you", "+", "small"), e("relationships.stranger.wary_of_you", "+", "medium")], source=dict(kind="scene", chunks=[215])),
|
||||
dict(label="Run the game yourself.", result="It works, and pays, and afterwards there is a kind of face you cannot quite look at.",
|
||||
effects=[e("money", "+", "medium"), e("skills.front", "+", "medium"), e("standing", "-", "small"), flag("ran_a_game")], source=dict(kind="scene", chunks=[681, 682, 686])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="sacrifice", situation="sacrifice", title="What you would give up for them",
|
||||
sentence="Someone you love needs something you can only get by giving up what you value most, and they must not know.",
|
||||
roles=["you", "partner", "rival"], stages=["rooming_house", "counter"],
|
||||
descriptions=[
|
||||
dict(text="A dollar and eighty-seven cents, and tomorrow is the holiday. There is one thing in the flat worth anything, and it is yours to sell.", sources=[454, 455, 456]),
|
||||
dict(text="The money for lessons has run out. One of you will have to take work well beneath what you came here for, and the other will have to not know about it.", sources=[488, 489, 492]),
|
||||
dict(text="You have four dollars put by for the thing you have waited all year for. Your rival at work has been locked out of her room for exactly four dollars.", sources=[738]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Sell it, and say nothing.", result="They find out, of course. It is the only thing about the day either of you remembers.",
|
||||
effects=[e("relationships.partner.likes_you", "+", "large"), e("skills.front", "-", "small"), note("Sold the thing that mattered, for a present.")], source=dict(kind="scene", chunks=[456, 460, 461])),
|
||||
dict(label="Keep it.", result="The holiday comes. It is a perfectly good holiday.",
|
||||
effects=[e("relationships.partner.likes_you", "-", "small")], source=dict(kind="archetype", chunks=[])),
|
||||
dict(label="Take the humble work in secret.", result="Your hands give you away within a fortnight.",
|
||||
effects=[e("money", "+", "medium"), e("standing", "-", "small"), e("relationships.partner.trusts_you", "+", "medium")], source=dict(kind="scene", chunks=[491, 492])),
|
||||
dict(label="Give it to the one who needs it and ask for nothing.", result="She promises a dollar a week back. You go without the thing you waited for.",
|
||||
effects=[e("money", "-", "small"), e("relationships.rival.owes_you", "+", "medium"), e("relationships.rival.likes_you", "+", "small")], source=dict(kind="scene", chunks=[738, 739])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="rival", situation="rival", title="Someone else wants them too",
|
||||
sentence="A rival wants the same person you do, and has something you have not.",
|
||||
roles=["you", "rival", "sweetheart"], stages=["rooming_house", "counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="The other suitor has learning, a silk hat, and an invitation to take her up to the roof to see the view. You have a very small shop and a joke about its size.", sources=[333, 334, 335]),
|
||||
dict(text="Your rival has come to you, of all people, for help: they mean to run away with the one you both want, tonight at nine.", sources=[532, 533, 534]),
|
||||
dict(text="A rich newcomer has walked in, looked once at the one you have all admired for a year, and put down his fork.", sources=[519, 520, 521]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Let the rival show off.", result="The display does your work for you.",
|
||||
effects=[e("relationships.sweetheart.likes_you", "+", "small"), e("relationships.rival.wary_of_you", "+", "small")], source=dict(kind="scene", chunks=[336, 337])),
|
||||
dict(label="Help the rival, and quietly warn the family.", result="It is clever. Your rival is honest, which you had not allowed for.",
|
||||
effects=[e("relationships.rival.wary_of_you", "+", "medium"), e("relationships.sweetheart.trusts_you", "-", "small"), e("skills.front", "+", "small")], source=dict(kind="scene", chunks=[535, 536])),
|
||||
dict(label="Get the rival out of the way.", result="It takes a night and every dollar you have.",
|
||||
effects=[e("money", "-", "medium"), e("relationships.rival.wary_of_you", "+", "medium"), flag("saw_off_a_rival")], source=dict(kind="scene", chunks=[522, 523])),
|
||||
dict(label="Say what you want, plainly, before they do.", result="Nobody has said it to them that way before.",
|
||||
effects=[e("relationships.sweetheart.likes_you", "+", "medium"), e("skills.nerve", "+", "medium")], source=dict(kind="gap", chunks=[122, 785])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="price", situation="price", title="The offer that would feed you",
|
||||
sentence="Someone with money wants something from you that you would rather not give, and you are hungry.",
|
||||
roles=["you", "stranger", "employer"], stages=["rooming_house"],
|
||||
descriptions=[
|
||||
dict(text="You spent your supper money on a collar because a man known for spending has asked you to dinner. He is downstairs now.", sources=[570, 571, 573, 574]),
|
||||
dict(text="Your employer has told the customer you would be glad to dine with him this evening. That is part of the work now.", sources=[691, 694]),
|
||||
dict(text="Two days without dinner, and a prosperous lodger has stopped you in the hall to propose.", sources=[483]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Go.", result="The dinner is very good.",
|
||||
effects=[e("money", "+", "small"), e("relationships.stranger.likes_you", "+", "small"), flag("went_to_dinner")], source=dict(kind="archetype", chunks=[])),
|
||||
dict(label="Send word that you are ill.", result="Crackers and jam, and a good feeling that lasts until you have to do it again.",
|
||||
effects=[e("money", "-", "small"), e("skills.nerve", "+", "small"), note("Sent word of being ill.")], source=dict(kind="scene", chunks=[574, 575, 576])),
|
||||
dict(label="Go, and draw the line at the door.", result="They take it in a way you did not expect.",
|
||||
effects=[e("money", "+", "small"), e("skills.front", "+", "small"), e("relationships.employer.wary_of_you", "+", "small")], source=dict(kind="scene", chunks=[693, 694, 695])),
|
||||
dict(label="Ask for work instead of dinner.", result="Nobody has asked them that before, and they are not sure what to say.",
|
||||
effects=[e("relationships.employer.trusts_you", "+", "small"), e("money", "+", "small")], source=dict(kind="gap", chunks=[])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="despised", situation="despised", title="The one nobody thinks much of",
|
||||
sentence="Someone everybody around you looks down on wants a chance, and may be the only one who can help.",
|
||||
roles=["you", "stranger", "pal"], stages=["rooming_house", "counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="The man who caused the accident keeps coming back, grinning, to apologise. Everybody you work with throws him out. Your boy has started to like him.", sources=[745, 746, 747]),
|
||||
dict(text="A tramp has turned up at the door with the very thing the household has been advertising a reward for, and he is plainly drunk.", sources=[350, 354]),
|
||||
dict(text="Your new friend is, by his own account, a burglar. He is also the best company you have had in a year.", sources=[174, 176, 177]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Throw them out.", result="Your people approve. The door does not stay shut long.",
|
||||
effects=[e("relationships.pal.likes_you", "+", "small"), e("relationships.stranger.wary_of_you", "+", "medium")], source=dict(kind="scene", chunks=[746])),
|
||||
dict(label="Let them in and hear them out.", result="It turns out they can do the one thing nobody else in the room can.",
|
||||
effects=[e("relationships.stranger.trusts_you", "+", "medium"), e("relationships.pal.wary_of_you", "+", "small"), flag("took_in_an_outsider")], source=dict(kind="scene", chunks=[747, 748, 749])),
|
||||
dict(label="Pay them and be done.", result="Money settles it, as far as money goes.",
|
||||
effects=[e("money", "-", "small"), e("relationships.stranger.likes_you", "+", "small")], source=dict(kind="scene", chunks=[355])),
|
||||
dict(label="Bring them among your own people.", result="They outshine the whole table, and nobody believes a word of how you met.",
|
||||
effects=[e("skills.nerve", "+", "small"), e("standing", "+", "small"), note("Brought a burglar to dinner.")], source=dict(kind="scene", chunks=[177])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="loyalty", situation="loyalty", title="Turn in a friend",
|
||||
sentence="Someone with power wants you to turn on a friend you owe, and will pay or punish accordingly.",
|
||||
roles=["you", "pal", "officer", "patron"], stages=["counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="The man who lent you a thousand dollars when your furniture was on the sidewalk is sitting across from you, and you are fairly sure what he did last week.", sources=[148, 149, 150, 151]),
|
||||
dict(text="A man from the organisation has five hundred dollars and a request: stand up in court and say what you know about the man who used to be over you.", sources=[778]),
|
||||
dict(text="An old friend has come a thousand miles to keep an appointment, and his face matches a description on your desk.", sources=[598, 599, 601]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Do your duty.", result="It is the right thing, and you will be reminded of it at every reunion for the rest of your life.",
|
||||
effects=[e("standing", "+", "medium"), e("relationships.pal.trusts_you", "-", "large"), flag("turned_in_a_friend")], source=dict(kind="archetype", chunks=[])),
|
||||
dict(label="Refuse, and take what comes.", result="You are down and out, and nobody's traitor.",
|
||||
effects=[e("money", "-", "small"), e("standing", "-", "medium"), e("relationships.pal.trusts_you", "+", "large"), e("relationships.patron.wary_of_you", "+", "medium")], source=dict(kind="scene", chunks=[151, 778])),
|
||||
dict(label="Send someone else to do it.", result="You leave a note. You could not do it yourself.",
|
||||
effects=[e("standing", "+", "small"), e("relationships.pal.trusts_you", "-", "small"), note("Could not make the arrest in person.")], source=dict(kind="scene", chunks=[602])),
|
||||
dict(label="Let them convict themselves.", result="Vanity does the rest; you only had to hand them the telephone.",
|
||||
effects=[e("skills.front", "+", "medium"), e("standing", "+", "small"), e("relationships.pal.wary_of_you", "+", "small")], source=dict(kind="scene", chunks=[153, 154, 156])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="appearances", situation="appearances", title="What it looked like",
|
||||
sentence="Someone whose opinion matters has judged you by what it looked like, and will not hear an explanation.",
|
||||
roles=["you", "sweetheart", "officer"], stages=["rooming_house", "counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="You were turning them down, as it happens. What the one you love saw, walking in, was a kiss on the hand.", sources=[287, 288]),
|
||||
dict(text="Something went missing from a house you worked in yesterday, and you have been seen in public with something very like it.", sources=[725]),
|
||||
dict(text="You are exactly what you look like, and that is the difficulty: nobody here believes anybody is.", sources=[250, 251, 253, 254]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Explain.", result="They listen to the first sentence.",
|
||||
effects=[e("relationships.sweetheart.trusts_you", "+", "small"), e("skills.nerve", "+", "small")], source=dict(kind="archetype", chunks=[])),
|
||||
dict(label="Say nothing and let them think it.", result="Pride settles it. Pride has a long memory.",
|
||||
effects=[e("relationships.sweetheart.trusts_you", "-", "large"), flag("left_it_unexplained")], source=dict(kind="scene", chunks=[288, 614])),
|
||||
dict(label="Send the proof, and leave it with them.", result="A letter, from somebody with nothing to gain. It says everything you would have.",
|
||||
effects=[e("relationships.sweetheart.trusts_you", "+", "medium"), e("skills.front", "+", "small")], source=dict(kind="scene", chunks=[615, 616])),
|
||||
dict(label="Change how you look.", result="Now you look worth robbing.",
|
||||
effects=[e("money", "-", "medium"), e("skills.front", "+", "medium"), e("relationships.stranger.likes_you", "+", "small")], source=dict(kind="scene", chunks=[254, 255])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="sign", situation="sign", title="A sign",
|
||||
sentence="Someone in a bad way wants a sign to tell them what to do, and one has turned up.",
|
||||
roles=["you", "stranger", "pal"], stages=["rooming_house", "counter"],
|
||||
descriptions=[
|
||||
dict(text="The fortune-teller said a dark man, a fair woman, a voyage and a loss, then luck from a man with a crooked nose. It has been a very accurate afternoon.", sources=[444, 445, 446]),
|
||||
dict(text="The man handing out cards gave you one with three words written on it in ink, and nobody else. He did it again when you went back round.", sources=[556, 557]),
|
||||
dict(text="Four roses have appeared in the window across the garden, and you are sure they are meant for you.", sources=[107, 108]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Follow it.", result="It leads somewhere. Not where it said, but somewhere.",
|
||||
effects=[e("skills.nerve", "+", "small"), e("relationships.stranger.likes_you", "+", "small"), flag("followed_a_sign")], source=dict(kind="scene", chunks=[447, 558])),
|
||||
dict(label="Ignore it.", result="Nothing happens, which is what you expected, mostly.",
|
||||
effects=[], source=dict(kind="archetype", chunks=[])),
|
||||
dict(label="Ask around first.", result="It turns out to mean something perfectly ordinary, to somebody else.",
|
||||
effects=[e("skills.front", "+", "small"), note("Found out what the roses meant.")], source=dict(kind="scene", chunks=[109, 562])),
|
||||
dict(label="Make the sign yourself, for someone who needs one.", result="It holds through two nights of weather. It costs more than you told anyone.",
|
||||
effects=[e("relationships.pal.likes_you", "+", "large"), e("money", "-", "small"), e("standing", "-", "small")], source=dict(kind="scene", chunks=[793, 796])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="honest_work", situation="honest_work", title="They want the flattering version",
|
||||
sentence="A client or editor wants your work made false in the way they like, and will not pay for the true version.",
|
||||
roles=["you", "employer", "partner"], stages=["counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="The editor likes everything about your work except the part you believe is true.", sources=[388, 389, 390, 391]),
|
||||
dict(text="Your portraits keep showing what the sitters would rather not have seen, and the sitters have stopped coming.", sources=[653, 654]),
|
||||
dict(text="Your genuine article came back marked 'too artificial'. A friend who has never left the city wrote the same thing badly, and it sold.", sources=[249, 256]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Give them what they want.", result="The cheque comes round on Thursday, as usual.",
|
||||
effects=[e("money", "+", "medium"), e("skills.front", "+", "small"), e("standing", "+", "small")], source=dict(kind="scene", chunks=[256])),
|
||||
dict(label="Keep doing it your way.", result="The envelopes keep coming back. The work is good.",
|
||||
effects=[e("money", "-", "medium"), e("skills.nerve", "+", "small")], source=dict(kind="scene", chunks=[387])),
|
||||
dict(label="Try to prove you are right.", result="Life supplies the proof, and it is not the proof you wanted.",
|
||||
effects=[e("skills.nerve", "+", "small"), e("relationships.partner.trusts_you", "-", "medium"), note("Proved the point, and lost by it.")], source=dict(kind="scene", chunks=[392, 393, 394, 395])),
|
||||
dict(label="Quit the trade.", result="You would rather sell ploughs for your father.",
|
||||
effects=[e("standing", "-", "medium"), e("money", "+", "small"), flag("quit_the_trade")], source=dict(kind="scene", chunks=[89])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="unspoken", situation="unspoken", title="You cannot say it",
|
||||
sentence="Someone you want is waiting for you to say it, and you cannot find the words or the moment.",
|
||||
roles=["you", "sweetheart", "patron"], stages=["rooming_house", "counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="You can handle any customer in the place. When the owner's daughter comes down the stairs you tell her it looks like rain.", sources=[750, 751]),
|
||||
dict(text="You will have eight minutes alone with them in a cab, between the train and the theatre, and then they sail for two years.", sources=[540]),
|
||||
dict(text="The partnership is strictly business. That was your own condition. It was a very good condition, two years ago.", sources=[196, 197, 202]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Say it now.", result="It comes out wrong, and it comes out.",
|
||||
effects=[e("skills.nerve", "+", "medium"), e("relationships.sweetheart.likes_you", "+", "small")], source=dict(kind="archetype", chunks=[])),
|
||||
dict(label="Find the nerve in a glass.", result="Two spoonfuls of something golden, and you lift them clean off the floor.",
|
||||
effects=[e("skills.nerve", "+", "small"), e("money", "-", "small"), e("relationships.sweetheart.likes_you", "+", "medium")], source=dict(kind="scene", chunks=[756])),
|
||||
dict(label="Buy the moment.", result="Somebody arranges a very large traffic jam. It is expensive. It works.",
|
||||
effects=[e("money", "-", "large"), e("relationships.sweetheart.likes_you", "+", "medium"), e("relationships.patron.owes_you", "-", "small")], source=dict(kind="scene", chunks=[542, 543, 544])),
|
||||
dict(label="Wait for a better time.", result="There is always a better time.",
|
||||
effects=[e("relationships.sweetheart.likes_you", "-", "small")], source=dict(kind="archetype", chunks=[])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="strings", situation="strings", title="Money with conditions",
|
||||
sentence="Family with money wants to decide how you live, and will pay you to let them.",
|
||||
roles=["you", "patron", "sweetheart"], stages=["counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="Your people have money, and they have made it plain you can have it back the day you give up the person you mean to marry.", sources=[126, 129]),
|
||||
dict(text="The inheritance is a thousand dollars and a single condition: a full account of exactly how you spend it.", sources=[58]),
|
||||
dict(text="The family will take you back, every cent of it, if you marry the heiress they have chosen for you.", sources=[779]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Do as they ask.", result="The allowance arrives on the first of the month. So does the heiress.",
|
||||
effects=[e("money", "+", "large"), e("relationships.sweetheart.trusts_you", "-", "large"), e("relationships.patron.likes_you", "+", "medium")], source=dict(kind="archetype", chunks=[])),
|
||||
dict(label="Refuse, and live on what you earn.", result="Sausages for breakfast, credit at the corner restaurant, and the person you chose.",
|
||||
effects=[e("money", "-", "medium"), e("relationships.sweetheart.likes_you", "+", "large"), flag("cut_off")], source=dict(kind="scene", chunks=[126, 780])),
|
||||
dict(label="Take the money and give it away where it is owed.", result="The account you write is one line long. You tear it up before they can read it.",
|
||||
effects=[e("money", "-", "small"), e("relationships.sweetheart.trusts_you", "+", "medium"), note("Gave the legacy to the ward.")], source=dict(kind="scene", chunks=[62, 63, 64])),
|
||||
dict(label="Bring them to meet the person you chose.", result="It takes a year of not speaking and one evening in a restaurant.",
|
||||
effects=[e("relationships.patron.trusts_you", "+", "medium"), e("skills.nerve", "+", "small")], source=dict(kind="scene", chunks=[132, 133])),
|
||||
]),
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
dict(id="overlooked", situation="overlooked", title="Beside the admired one",
|
||||
sentence="The plain one working beside the admired one wants, once, to be noticed.",
|
||||
roles=["you", "pal", "employer"], stages=["rooming_house", "counter"],
|
||||
descriptions=[
|
||||
dict(text="At the next table they court your partner six at a time. At yours they read you the bill of fare.", sources=[627, 628, 629]),
|
||||
dict(text="For two years you have gone to the dance on your best friend's arm and her young man's charity.", sources=[493]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Make the most of the first sign of notice.", result="It was nothing, it turns out. For two days it was everything.",
|
||||
effects=[e("standing", "+", "small"), e("money", "+", "small"), note("Was, for two days, somebody worth insulting.")], source=dict(kind="scene", chunks=[630, 631, 632])),
|
||||
dict(label="Bring an escort of your own, whoever he is.", result="He is splendid and he is not who he says, and for one evening nobody cares.",
|
||||
effects=[e("skills.front", "+", "small"), e("standing", "+", "small"), flag("brought_a_borrowed_escort")], source=dict(kind="scene", chunks=[494, 495, 496])),
|
||||
dict(label="Stay content in the other's shadow.", result="You are glad for them. Mostly you are.",
|
||||
effects=[e("relationships.pal.likes_you", "+", "medium")], source=dict(kind="scene", chunks=[629])),
|
||||
dict(label="Save for one thing to wear.", result="Eight months of it. It had better be purple.",
|
||||
effects=[e("money", "-", "medium"), e("standing", "+", "small")], source=dict(kind="scene", chunks=[735, 736])),
|
||||
]),
|
||||
dict(id="homecoming", situation="homecoming", title="Word from home",
|
||||
sentence="The people you left want you back, and someone has brought word of them.",
|
||||
roles=["you", "stranger", "partner"], stages=["counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="A stranger from your village has brought news of your mother, who keeps your chair where it was, and a rose from the front step.", sources=[144, 145, 146]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Laugh it off.", result="You laugh it off. You keep the rose.",
|
||||
effects=[e("skills.front", "+", "small")], source=dict(kind="scene", chunks=[147])),
|
||||
dict(label="Go back.", result="Your engagements are cancelled by the next morning.",
|
||||
effects=[e("standing", "-", "large"), flag("went_home"), note("Went home.")], source=dict(kind="scene", chunks=[147])),
|
||||
dict(label="Send money instead.", result="It is gratefully received. It is not what was asked for.",
|
||||
effects=[e("money", "-", "medium")], source=dict(kind="gap", chunks=[])),
|
||||
]),
|
||||
dict(id="patron", situation="patron", title="A handshake from the top",
|
||||
sentence="Someone powerful could be seen with you, and being seen with them will cost you.",
|
||||
roles=["you", "patron", "partner"], stages=["rooming_house", "counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="The district's great man is celebrating across the room. You could walk over, put out your hand, and stand the whole party a round with a week's wages.", sources=[728, 729]),
|
||||
dict(text="The most powerful man you know has promised to come to your wedding, and there is a reason he must not.", sources=[802, 803]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Walk over and stand the round.", result="He shakes your hand. At home there is shrieking about the wages, which you hardly hear.",
|
||||
effects=[e("money", "-", "large"), e("relationships.patron.likes_you", "+", "small"), e("relationships.partner.likes_you", "-", "medium"), note("Shook the great man's hand.")], source=dict(kind="scene", chunks=[729, 730])),
|
||||
dict(label="Offer him something he needs.", result="He takes your hand in front of the whole room, and the room remembers your name.",
|
||||
effects=[e("standing", "+", "medium"), e("relationships.patron.owes_you", "+", "small")], source=dict(kind="scene", chunks=[732])),
|
||||
dict(label="Nod from where you are.", result="He nods back. That is the whole of it.",
|
||||
effects=[e("relationships.patron.likes_you", "+", "small")], source=dict(kind="archetype", chunks=[])),
|
||||
]),
|
||||
dict(id="habit", situation="habit", title="The old habit",
|
||||
sentence="An old habit wants out at exactly the moment you need to be someone new.",
|
||||
roles=["you", "sweetheart"], stages=["counter", "swell"],
|
||||
descriptions=[
|
||||
dict(text="A year of being polished, and the gentleman approaches your stall at the charity bazaar through a brass wicket exactly like the one at your old cash desk.", sources=[383]),
|
||||
],
|
||||
options=[
|
||||
dict(label="Answer the way you always did.", result="Your check, please.",
|
||||
effects=[e("standing", "-", "medium"), e("skills.front", "-", "small")], source=dict(kind="scene", chunks=[383])),
|
||||
dict(label="Catch yourself.", result="Only you noticed the pause.",
|
||||
effects=[e("skills.front", "+", "medium")], source=dict(kind="gap", chunks=[])),
|
||||
dict(label="Own it, out loud.", result="Some of them are charmed. The ones that matter are not sure.",
|
||||
effects=[e("skills.nerve", "+", "small"), e("relationships.sweetheart.likes_you", "+", "small"), e("standing", "-", "small")], source=dict(kind="gap", chunks=[])),
|
||||
]),
|
||||
]
|
||||
|
||||
# --- validate -----------------------------------------------------------------------------------
|
||||
chunks = json.load(open(HERE.parent / 'chunks.json'))
|
||||
stories = json.load(open(HERE.parent / 'stories.json'))
|
||||
sit_members = collections.defaultdict(list)
|
||||
for c, s in ASSIGN.items(): sit_members[s].append(c)
|
||||
problems = []
|
||||
for ev in EVENTS:
|
||||
if not 3 <= len(ev['options']) <= 5: problems.append(f"{ev['id']}: {len(ev['options'])} options")
|
||||
for d in ev['descriptions'] + ev['options']:
|
||||
for fld in ('text', 'label', 'result'):
|
||||
s = d.get(fld, '')
|
||||
OK = {'I', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Saturdays', 'Sunday', 'Sundays'}
|
||||
caps = [t for sent in re.split(r"[.!?:;]\s+", s) for t in re.findall(r"[A-Za-z']+", sent)[1:]
|
||||
if t[0].isupper() and t not in OK]
|
||||
if caps: problems.append(f"{ev['id']}: capitalised word(s) {caps} in {fld}")
|
||||
for d in ev['descriptions']:
|
||||
for c in d['sources']:
|
||||
if c not in sit_members[ev['situation']] and c not in range(len(chunks)): problems.append(f"{ev['id']}: bad source {c}")
|
||||
for o in ev['options']:
|
||||
for ef in o['effects']:
|
||||
p = ef['path']
|
||||
ok = p in ('money', 'debt', 'standing', 'notable') or p in SKILLS or p.startswith('flags.') or \
|
||||
(p.startswith('relationships.') and p.split('.')[1] in CAST and p.split('.')[2] in REL_STATS)
|
||||
if not ok: problems.append(f"{ev['id']}: bad path {p}")
|
||||
if 'dir' in ef and ef['dir'] not in '+-': problems.append(f"{ev['id']}: bad dir")
|
||||
if 'size' in ef and ef['size'] not in ('small', 'medium', 'large'): problems.append(f"{ev['id']}: bad size")
|
||||
sigs = [json.dumps(sorted(json.dumps(x, sort_keys=True) for x in o['effects'])) for o in ev['options']]
|
||||
if len(set(sigs)) != len(sigs): problems.append(f"{ev['id']}: two options with identical effects")
|
||||
if problems:
|
||||
print('\n'.join(problems)); sys.exit(1)
|
||||
|
||||
def member_rows(s):
|
||||
rows = []
|
||||
for c in sorted(sit_members[s]):
|
||||
rows.append({'chunk': c, 'story': chunks[c]['story'], 'title': chunks[c]['title'].title()})
|
||||
return rows
|
||||
|
||||
out = {
|
||||
'made_by': 'claude-opus-5, in-session by hand, 2026-09-17',
|
||||
'player_role': PLAYER_ROLE, 'stages': STAGES, 'cast': CAST, 'skills': SKILLS,
|
||||
'relationship_stats': sorted(REL_STATS),
|
||||
'effects_note': 'Directions and rough sizes only; values are for the numeric search (DESIGN.md: the model never chooses a number).',
|
||||
'situations': [],
|
||||
}
|
||||
for s in sorted(sit_members, key=lambda s: -len(sit_members[s])):
|
||||
mem = member_rows(s)
|
||||
st = collections.Counter(r['story'] for r in mem)
|
||||
dom = max(st.values()) / len(mem)
|
||||
out['situations'].append({
|
||||
'id': s, 'scenes': len(mem), 'stories': len(st), 'dominant_story_share': round(dom, 2),
|
||||
'passes_pipeline_candidate_rule': len(mem) >= 5 and len(st) >= 4 and dom <= 0.40,
|
||||
'members': mem,
|
||||
'events': [ev for ev in EVENTS if ev['situation'] == s],
|
||||
})
|
||||
missing = [s for s in sit_members if not any(ev['situation'] == s for ev in EVENTS)]
|
||||
if missing: print('situations without an event:', missing); sys.exit(1)
|
||||
(HERE / 'situations-claude.json').write_text(json.dumps(out, indent=1, ensure_ascii=False), encoding='utf-8')
|
||||
print(f"ok: {len(out['situations'])} situations, {len(EVENTS)} events, "
|
||||
f"{sum(len(ev['options']) for ev in EVENTS)} options, {sum(len(ev['descriptions']) for ev in EVENTS)} descriptions")
|
||||
kinds = collections.Counter(o['source']['kind'] for ev in EVENTS for o in ev['options'])
|
||||
print('option sources:', dict(kinds))
|
||||
Reference in New Issue
Block a user