SAVE SKY provenance + sky→hex (not sky→sea) transition — TDD
Some checks failed
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline failed

- drama.GameEvent.SKY_SAVED verb + to_prose branch: "X beholds the skyscape of {poss} birth, which yields {obj} a unique {Cap} capacity."; tied highest scores switch "a unique" → "equal", join w. "and" (2-way) or Oxford comma (3+), and pluralize "capacity" → "capacities"; pronouns resolved from actor.pronouns at render time, same machinery as SIG_READY/ROLE_SELECTED
- epic.utils.ELEMENT_CAPACITOR_NAMES + ELEMENT_ORDER + top_capacitors(elements) helper: maps Fire→Ardor Stone→Ossum Time→Tempo Space→Nexus Air→Pneuma Water→Humor; tolerates both flat-int and enriched-dict (`{count, contributors}`) chart_data shapes; returns capacitor names tied for highest count, ordered by canonical wheel ring
- epic.natus_save: on action=confirm, records GameEvent.SKY_SAVED w. top_capacitors=[…] before _notify_sky_confirmed; per-room billscroll AND billboard Most Recent Scroll pick up the new prose
- _natus_overlay.html _onSkyConfirmed: removed sea-partial fetch+inject; now calls closeNatus() + window.location.reload() so the gamer lands on the table hex w. the PICK SKY → PICK SEA btn swap (server-side, driven by sky_confirmed=True), then opts into the sea overlay manually. The auto-launch via 39e12d6 was buried by FTs that were pinning the wrong contract — gamer never had a chance to witness PICK SEA on the hex
- test_room_sea_select.py: three FTs renamed/rewired from auto-launch assertions (sea_overlay_appears_without_page_refresh, natus_overlay_not_visible_after_sky_confirm, sea_open_class_on_html_after_confirm) to (pick_sea_btn_visible_after_sky_confirm, natus_overlay_closed_after_sky_confirm, clicking_pick_sea_btn_opens_sea_overlay) — sea overlay now requires explicit PICK SEA click

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-05-04 01:57:35 -04:00
parent 5413e63585
commit c9563308d8
7 changed files with 238 additions and 53 deletions

View File

@@ -24,6 +24,8 @@ class GameEvent(models.Model):
# Sig Select phase
SIG_READY = "sig_ready"
SIG_UNREADY = "sig_unready"
# Sky Select phase
SKY_SAVED = "sky_saved"
VERB_CHOICES = [
(ROOM_CREATED, "Room created"),
@@ -37,6 +39,7 @@ class GameEvent(models.Model):
(ROLES_REVEALED, "Roles revealed"),
(SIG_READY, "Sig claim staked"),
(SIG_UNREADY, "Sig claim withdrawn"),
(SKY_SAVED, "Sky saved"),
]
room = models.ForeignKey(
@@ -114,6 +117,26 @@ class GameEvent(models.Model):
if self.verb == self.SIG_UNREADY:
_, _, poss = _actor_pronouns(self.actor)
return f"disembodies {poss} Significator."
if self.verb == self.SKY_SAVED:
_, obj, poss = _actor_pronouns(self.actor)
caps = list(d.get("top_capacitors") or [])
if not caps:
return f"beholds the skyscape of {poss} birth."
if len(caps) == 1:
return (
f"beholds the skyscape of {poss} birth, "
f"which yields {obj} a unique {caps[0]} capacity."
)
# Tied highest: "equal X and Y capacities" (2-way) or
# "equal X, Y, and Z capacities" (3+, Oxford comma).
if len(caps) == 2:
joined = f"{caps[0]} and {caps[1]}"
else:
joined = ", ".join(caps[:-1]) + f", and {caps[-1]}"
return (
f"beholds the skyscape of {poss} birth, "
f"which yields {obj} equal {joined} capacities."
)
return self.verb
@property

View File

@@ -119,6 +119,49 @@ class GameEventModelTest(TestCase):
role="PC", role_display="Player")
self.assertIn("it will start the game", event.to_prose())
# ── to_prose — SKY_SAVED ──────────────────────────────────────────────
def test_sky_saved_prose_single_capacitor(self):
# Default user pronouns = pluralism → "their" + "them".
event = record(self.room, GameEvent.SKY_SAVED, actor=self.user,
top_capacitors=["Ardor"])
prose = event.to_prose()
self.assertIn(
"beholds the skyscape of their birth, which yields them a unique Ardor capacity.",
prose,
)
def test_sky_saved_prose_two_way_tie(self):
# Tied highest scores: pluralize "a unique" → "equal", join w. "and",
# pluralize "capacity" → "capacities".
event = record(self.room, GameEvent.SKY_SAVED, actor=self.user,
top_capacitors=["Ardor", "Ossum"])
prose = event.to_prose()
self.assertIn(
"beholds the skyscape of their birth, which yields them equal Ardor and Ossum capacities.",
prose,
)
def test_sky_saved_prose_three_way_tie_uses_oxford_comma(self):
event = record(self.room, GameEvent.SKY_SAVED, actor=self.user,
top_capacitors=["Ardor", "Ossum", "Pneuma"])
prose = event.to_prose()
self.assertIn(
"beholds the skyscape of their birth, which yields them equal Ardor, Ossum, and Pneuma capacities.",
prose,
)
def test_sky_saved_prose_uses_actor_pronouns(self):
self.user.pronouns = "bawlmorese"
self.user.save(update_fields=["pronouns"])
event = record(self.room, GameEvent.SKY_SAVED, actor=self.user,
top_capacitors=["Tempo"])
# Bawlmorese → poss "yos", obj "yo".
self.assertIn(
"beholds the skyscape of yos birth, which yields yo a unique Tempo capacity.",
event.to_prose(),
)
def test_sig_ready_prose_degrades_without_corner_rank(self):
# Old events recorded before this change have no corner_rank key
event = record(self.room, GameEvent.SIG_READY, actor=self.user,