diff --git a/games/ground/src/lib.rs b/games/ground/src/lib.rs index 20fba88..4359b81 100644 --- a/games/ground/src/lib.rs +++ b/games/ground/src/lib.rs @@ -2162,6 +2162,19 @@ mod replay_probe { use cb_kernel::EventSeq; use std::time::Instant; + /// A fresh game at `seats` players, for the seat-count sweep. + fn fresh_n(seats: u8) -> GroundState { + GroundState::setup( + &Setup { + players: seats, + preset: format!("standard-{seats}p"), + patch: BTreeMap::new(), + }, + 42, + ) + .expect("a standard deal") + } + fn fresh(seed: u64) -> GroundState { GroundState::setup( &Setup { @@ -2441,6 +2454,56 @@ mod replay_probe { } } + /// **GD-0001: group success is arithmetically unreachable below 5 + /// seats**, and this is the reproduction rather than an argument. + /// + /// The maintainer played several 3-player games on 2026-08-03 and + /// could not win any of them. This says why: claim *every* Problem + /// the deal puts in play, concede nothing, and the total still falls + /// short of GR-E01's threshold at 2, 3 and 4 seats. + /// + /// It reads both numbers out of the engine โ€” `problem_priorities` + /// (GR-S01's deal) and `threshold` (GR-E01) โ€” so it cannot drift from + /// the rules it is testing, and it holds for **either dataset**: the + /// stand-in gives 3/6/10 and `Problems.csv` gives 4/6/9, against the + /// same 5/7/9. + /// + /// **This test asserts the defect.** It is expected to keep passing + /// until ground-game rules, and to be inverted when it does โ€” either + /// the deal count rises or the thresholds fall. + #[test] + fn gd0001_group_success_is_unreachable_below_five_seats() { + let mut verdicts = Vec::new(); + for seats in 2..=6u8 { + let state = fresh_n(seats); + let best: u32 = state.problems.values().map(|p| u32::from(p.value)).sum(); + let need = state.threshold(); + verdicts.push((seats, state.problems.len(), best, need, best >= need)); + println!( + " {seats}p: {} problem(s) worth {best} against a threshold of {need} \u{2014} {}", + state.problems.len(), + if best >= need { "reachable" } else { "UNREACHABLE" } + ); + } + let unreachable: Vec = verdicts + .iter() + .filter(|(_, _, _, _, ok)| !ok) + .map(|(s, _, _, _, _)| *s) + .collect(); + // Positive control: a run where everything is reachable would + // report a clean sheet and prove nothing. + assert!( + !verdicts.is_empty() && verdicts.iter().any(|(_, _, _, _, ok)| *ok), + "no seat count was reachable; the harness measured nothing useful" + ); + assert_eq!( + unreachable, + vec![2, 3, 4], + "GD-0001 has changed: ground-game may have ruled. Re-read the \ + finding before editing this test." + ); + } + /// AM-7 scaling floor from GameKernel ยง5: fold throughput at 100k /// events must be at least this fraction of throughput at 5k. ///