"""The sigil glossary: every mechanic on one page, for deck decisions. Reachable with [g] from the board and the draft — rules text comes from the same SIGIL_EXPLAIN dict the per-card magnifier uses, so the glossary can never disagree with the card under your cursor. """ from __future__ import annotations from rich import box from rich.panel import Panel from rich.table import Table from rich.text import Text from textual import events from textual.app import ComposeResult from textual.containers import Vertical from textual.screen import Screen from textual.widgets import Static from scrypt.ui import palette as pal from scrypt.ui.render import SIGIL_EXPLAIN, SIGIL_GLYPHS COSTS = [ ("free", "costs nothing to play"), ("♦", "mem: mark your own board processes to kill (most pay 1♦, ≡priv pays 3♦)"), ("⊙", "core dumps: banked each time a process of yours dies"), ("0/1 bit", "free fodder from the side pile [s] — born to be sacrificed"), ] class SigilGlossaryScreen(Screen): CSS = """ #glossary { height: 1fr; align: center middle; } #glossary-page { width: 84; height: auto; } #glossary-prompt { height: 1; dock: bottom; background: $panel; content-align: center middle; } """ def compose(self) -> ComposeResult: with Vertical(id="glossary"): yield Static(id="glossary-page") yield Static(Text("[any key] back"), id="glossary-prompt") def on_mount(self) -> None: sigils = Table.grid(padding=(0, 2)) sigils.add_column(justify="right") sigils.add_column() for sigil in sorted(SIGIL_EXPLAIN): sigils.add_row( Text(SIGIL_GLYPHS[sigil], style=pal.TREASURE), Text(SIGIL_EXPLAIN[sigil], style=pal.FG), ) sigils.add_row("", "") for glyph, rule in COSTS: sigils.add_row(Text(glyph, style="bold"), Text(rule, style=pal.MUTED)) self.query_one("#glossary-page", Static).update( Panel( sigils, box=box.HEAVY, border_style=pal.BORDER_BRIGHT, title=Text("⟪ sigils & costs ⟫", style=f"bold {pal.WARDEN}"), padding=(1, 3), ) ) def on_key(self, event: events.Key) -> None: self.app.pop_screen()