Three reports from the 2026-08-08 sessions. H2 lands ("that seemed more
interesting"), two legibility gaps do not.
The number was only a FALLBACK for a missing title, so it showed exactly
when it was least useful. That was survivable while Problems sat in one
ordered row -- position WAS the number. CB-WP-0043 scattered them by
scope and took the implicit index with it, with nothing going red because
no test named the number.
DARVO.csv's mandatory_effect and Actions.csv's GROUND rules_text were
both vendored, both used only as tripwires, and neither ever reached the
player -- F18's shape again. The modes now explain themselves at the
point of choice, and NOT when no mode is on offer.
Tests assert the edition's own words verbatim (ADR-0015), the number over
every key in view.problems, and both halves of the mode explanation.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
d9b88d3140
commit
fd76db4f71
7 changed files with 809 additions and 0 deletions
|
|
@ -401,6 +401,9 @@ fn problem_svg(out: &mut String, priority: u32, p: &ProblemView, x: i32) {
|
|||
out,
|
||||
"<g data-drop=\"problem-{priority}\"><rect x=\"{x}\" y=\"10\" width=\"120\" height=\"78\" rx=\"8\" \
|
||||
fill=\"{fill}\" stroke=\"#5a6b7a\"/>\
|
||||
<circle cx=\"{bx}\" cy=\"24\" r=\"11\" fill=\"#1b1e26\" stroke=\"#5a6b7a\"/>\
|
||||
<text x=\"{bx}\" y=\"29\" fill=\"#9cf\" font-size=\"13\" text-anchor=\"middle\">\
|
||||
{priority}</text>\
|
||||
<text x=\"{tx}\" y=\"36\" fill=\"#dde\" font-size=\"13\">{label}</text>\
|
||||
<text x=\"{tx}\" y=\"56\" fill=\"#89a\" font-size=\"11\">{name}</text>\
|
||||
<text x=\"{tx}\" y=\"74\" fill=\"#fc9\" font-size=\"11\">{sub}</text></g>",
|
||||
|
|
@ -410,6 +413,14 @@ fn problem_svg(out: &mut String, priority: u32, p: &ProblemView, x: i32) {
|
|||
// not remove the only identifier the player had.
|
||||
name = esc(&problem_title(priority).unwrap_or_else(|| format!("priority {priority}"))),
|
||||
tx = x + 10,
|
||||
// CB-WP-0045: the number, on the card.
|
||||
//
|
||||
// Every move label says "Problem 7" and nothing on the table said
|
||||
// which card that was. In the old row the position was a hint;
|
||||
// once Problems are placed by scope the row is gone and the hint
|
||||
// with it. The number was only ever a FALLBACK for a missing
|
||||
// title — visible exactly when it was least useful.
|
||||
bx = x + 104,
|
||||
label = esc(&label),
|
||||
sub = esc(&sub),
|
||||
);
|
||||
|
|
@ -941,6 +952,21 @@ fn player_card(out: &mut String, id: PlayerId, p: &PlayerView, view: &GroundView
|
|||
//
|
||||
// The `support` line is the one the maintainer reported: it read
|
||||
// `support AcceptBond`, which names the answer and not the person.
|
||||
// CB-WP-0045: **what this DARVO stage will do**, in the edition's own
|
||||
// words. `DARVO.csv` carries `mandatory_effect` per stage; we vendored
|
||||
// it for tripwires and never showed it, so the page said "DARVO
|
||||
// Reverse" and left the player to guess. Reported as *"the GROUND and
|
||||
// DARVO logic is far from self explanatory"*.
|
||||
if p.darvo != games_ground::DarvoStage::Off {
|
||||
if let Some(text) = darvo_stage_text(p.darvo) {
|
||||
let _ = write!(
|
||||
out,
|
||||
"<details><summary>what {:?} does</summary>{}</details>",
|
||||
p.darvo,
|
||||
esc(&text)
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(m) = view.ground_modes.get(&id) {
|
||||
let _ = write!(
|
||||
out,
|
||||
|
|
@ -1432,6 +1458,38 @@ fn support_words(r: &games_ground::SupportResponse, who: Option<PlayerId>) -> St
|
|||
}
|
||||
}
|
||||
|
||||
/// The edition's own words for what a DARVO stage does (CB-WP-0045).
|
||||
///
|
||||
/// From `DARVO.csv`'s `mandatory_effect`. **Not our paraphrase**: the game
|
||||
/// says what its stages do and ADR-0015's discipline is to use that.
|
||||
fn darvo_stage_text(stage: games_ground::DarvoStage) -> Option<String> {
|
||||
use games_ground::DarvoStage;
|
||||
let want = match stage {
|
||||
DarvoStage::Off => return None,
|
||||
DarvoStage::Deny => "DENY",
|
||||
DarvoStage::Attack => "ATTACK",
|
||||
DarvoStage::Reverse => "REVERSE",
|
||||
};
|
||||
games_ground::edition::darvo_stages()
|
||||
.ok()?
|
||||
.into_iter()
|
||||
.find(|s| s.stage == want)
|
||||
.map(|s| s.mandatory_effect)
|
||||
}
|
||||
|
||||
/// The GROUND card's own account of its three modes (CB-WP-0045).
|
||||
///
|
||||
/// Shown where the mode is chosen. The card explains GR, OU and ND in one
|
||||
/// passage; by the Reveal step the action card is no longer on screen, so
|
||||
/// the explanation has to travel to the decision.
|
||||
fn ground_modes_text() -> Option<String> {
|
||||
games_ground::edition::actions()
|
||||
.ok()?
|
||||
.into_iter()
|
||||
.find(|c| c.id.to_uppercase().contains("GROUND"))
|
||||
.map(|c| c.rules_text)
|
||||
}
|
||||
|
||||
/// A GROUND sub-choice, in words, naming whoever it touches.
|
||||
fn ground_choice_label(c: &games_ground::GroundChoice) -> String {
|
||||
use games_ground::GroundChoice as G;
|
||||
|
|
@ -1605,6 +1663,23 @@ fn move_section(
|
|||
);
|
||||
}
|
||||
}
|
||||
// CB-WP-0045: when a GROUND mode is on offer, the card's own
|
||||
// account of the three modes travels with the decision. By the
|
||||
// Reveal step the action card has left the screen, so the player
|
||||
// was choosing GR / OU / ND from three names alone.
|
||||
if legal
|
||||
.iter()
|
||||
.any(|c| matches!(c, games_ground::GroundCommand::ChooseGroundMode { .. }))
|
||||
{
|
||||
if let Some(text) = ground_modes_text() {
|
||||
let _ = write!(
|
||||
s,
|
||||
"<details class=\"card\" open><summary>what the GROUND modes do\
|
||||
</summary>{}</details>",
|
||||
esc(&text)
|
||||
);
|
||||
}
|
||||
}
|
||||
s.push_str("</div><div class=\"row\">");
|
||||
for (i, c) in legal.iter().enumerate() {
|
||||
let spatial = seat.is_some_and(|seat| crate::input::affordance(c, seat).is_some());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue