sea affinity scroll log: personalized per-Role prose with pronouns (draws POSS Sea of cards, where the CARD ...) — TDD

Replaces the generic 'finding affinity with the X in the Crown' SEA_DRAWN prose with a role-specific clause per user-spec 2026-06-09 — the @handle is template-prepended, pronouns (subj/poss) resolve via the actor:

  PC: draws POSS Sea of cards, where the CARD crowns all POSS loftiest illusions. NC: ...the CARD traces all the narratives SUBJ leaves behind. EC: ...always looms before POSS calling. SC: ...covers all POSS righteous conduct. AC: ...always crosses POSS sinister connections. BC: ...lays all POSS foundational work.

to_prose branches on data['role']; 'The ' still stripped so a qualifier butts the proper name; an unknown role falls back to a generic 'marks POSS affinity' clause. The stored position_label/corner_rank/suit_icon are now unused by the prose but left in the event data (harmless). TDD: drama prose tests reworked (per-role clauses + bawlmorese pronoun substitution) + the epic affinity-prose IT updated to the PC crown clause. 49 drama+epic ITs green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-06-08 22:08:31 -04:00
parent 144ec78b1f
commit b0d153ebc1
3 changed files with 55 additions and 38 deletions

View File

@@ -163,26 +163,22 @@ class GameEvent(models.Model):
f"which yields {obj} equal {joined} capacities."
)
if self.verb == self.SEA_DRAWN:
# Affinity statement: the card drawn into the gamer's Role-correlated
# Celtic position. `card_name`/`corner_rank`/`suit_icon` mirror
# SIG_READY (qualifier-prefixed name + abbrev, "The " stripped so a
# qualifier butts the proper name); `position_label` is the
# spread-specific label for the role's position key.
card_name = d.get("card_name", "a card")
corner_rank = d.get("corner_rank", "")
suit_icon = d.get("suit_icon", "")
position_label = d.get("position_label", "spread")
if corner_rank:
icon_html = f' <i class="fa-solid {suit_icon}"></i>' if suit_icon else ""
abbrev = f" ({corner_rank}{icon_html})"
else:
abbrev = ""
card_name = card_name.replace("The ", "", 1)
_, _, poss = _actor_pronouns(self.actor)
return (
f"draws {poss} Celtic Cross, finding affinity with "
f"the {card_name}{abbrev} in the {position_label}."
)
# Personalized per-Role affinity (user-spec 2026-06-09): the card drawn
# into the gamer's Role-correlated Celtic position, woven into a
# role-specific clause. The actor's @handle is prepended by the
# template; pronouns resolve via the actor (subj/poss). "The " is
# stripped so a levity/gravity qualifier butts the proper name.
card = d.get("card_name", "a card").replace("The ", "", 1)
subj, _, poss = _actor_pronouns(self.actor)
clause = {
"PC": f"the {card} crowns all {poss} loftiest illusions",
"NC": f"the {card} traces all the narratives {subj} leaves behind",
"EC": f"the {card} always looms before {poss} calling",
"SC": f"the {card} covers all {poss} righteous conduct",
"AC": f"the {card} always crosses {poss} sinister connections",
"BC": f"the {card} lays all {poss} foundational work",
}.get(d.get("role", ""), f"the {card} marks {poss} affinity")
return f"draws {poss} Sea of cards, where {clause}."
if self.verb == self.SEA_RELINQUISHED:
card_name = d.get("card_name", "a card").replace("The ", "", 1)
_, _, poss = _actor_pronouns(self.actor)