Skip to content

Add AddMember, a referee command that adds a party member - #191

Merged
mmacy merged 3 commits into
mainfrom
chunk/add-member
Oct 30, 2026
Merged

mmacy merged 3 commits into
mainfrom
chunk/add-member

Conversation

@mmacy

@mmacy mmacy commented Oct 30, 2026

Copy link
Copy Markdown
Owner

A running session had no way to add a party member, so a game couldn't bring in a replacement for a character who died, or a retainer. This adds AddMember, a logged referee command that adds a character to the party. It's the first part of #172. The retainer rules (the hiring roll, loyalty, and experience and treasure shares) come in a later pull request on top of it.

What changed

  • AddMember takes a character built with create_character. It's legal in town and exploring. During an encounter or a battle, or after the game ends, the session refuses it with session.command.wrong_mode.
  • The session adds a copy of the character at the back of the marching order, gives it the next character-NNNN id, and reports a player-visible MemberAddedEvent (session.member.added).
  • The character must be new to the game. The session refuses a character who already has an id (party.add.id_assigned), one with a condition or stat modifier (party.add.under_effects), and one who carries a magic item or a valuable (party.add.carries_instances). Those came from another game's effects ledger or id space and could clash with this one.
  • Coins the new member brings into a dungeon earn no experience. A member who joins during a delve gets an equal share of the experience the party earns on that delve.
  • The command makes no draws and takes no time, and replay reproduces the new member's id.

What to check

  • The experience share for a member who joins mid-delve. The retainer chunk can refine it, since the SRD gives retainers half shares.
  • GameSession.new still doesn't skip a pre-set id when it allocates ids, so a starting party with a pre-set character-0002 on its second member can get a duplicate. That's older than this change. I'll fix it with the API hygiene items.

https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD

mmacy added 3 commits October 30, 2026 13:59
Issue #172 asks for a logged referee command that adds a member to a running party. This commit adds the contract and the tests. The handler is a stub that raises NotImplementedError, so the chunk's tests are marked xfail for chunk: add-member.

The contract:

- AddMember(character=...) is legal in town and exploring. Every other mode refuses it with session.command.wrong_mode. During an encounter or a battle, surprise, the chase pace, and who declares are already settled. Once the session has ended, a new member would restart play.
- The character must have no id (party.add.id_assigned), no condition or stat modifier (party.add.under_effects), and no magic item or valuable (party.add.carries_instances).
- The session adds a copy at the back of the marching order. Its id is the next character-NNNN from the allocator, passing over ids that members already have.
- It emits a player-visible MemberAddedEvent with the code session.member.added.
- Coins the new member brings into a dungeon are added to the treasure snapshot, so they earn no experience.
- The command isn't an authored consequence, because adventure documents carry no characters. The spec's consequence exclusions now name it.

Existing tests changed with the census: the referee command set, its mode carve-outs, the samples, and the consequence exclusions. The fuzz leaves AddMember out until the chunk merges, and test_add_member.py fuzzes it under the marker. The rejection-code docs gate is marked xfail until the handler emits the new codes. The catalog page check now ignores the JSON Schema pattern on Character.race, which it read as cross-reference markup.

Claude-Session: https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD
…ing play

The handler checks the character in the contract's order: no id, then no condition or stat modifier, then no magic item or valuable. A refusal returns before anything changes. An accepted command appends a deep copy of the command's character at the back of the marching order, gives it the next character id from the session's allocator (skipping any id a member already has), adds its coins to the treasure snapshot when a delve is under way, and emits MemberAddedEvent. It makes no draws and takes no time.

The three rejection codes have descriptions in tools/docs/rejection_codes.json. The docstrings that said ReorderParty is the only command that changes the party, or that only GameSession.new assigns character ids, now name AddMember. The LLM referee page lists the command, and the changelog has an Added bullet. No golden file changed.

Claude-Session: https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD
…e share

The fuzz in test_crawl_properties now draws AddMember too, and the docs
gate for rejection codes runs unmarked.

Claude-Session: https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD
@mmacy
mmacy merged commit ed4e335 into main Oct 30, 2026
5 checks passed
@mmacy
mmacy deleted the chunk/add-member branch October 30, 2026 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant