CB-WP-0038: variant selection, H1 implemented, and H1 measured
Some checks failed
ci / check (push) Failing after 3s
Some checks failed
ci / check (push) Failing after 3s
ground-game packages hypotheses as selectable rules variants — a catalog, a rules_delta.yaml, and prose — and their note is explicit that CSV text alone is not executable here. So the kernel gains a Variant in game state: in the state, therefore in the hash, therefore in the recording, because a scenario replayed under a different variant would diverge silently. Baseline is bit-for-bit what it was, asserted across seat counts and seeds. A variant system that perturbs the baseline invalidates every measurement this repo has. H1-A and H1-B implemented from rules_delta.yaml and mutation-proven on their own defects: "unclaimed" misread as face-up-and-unsolved, and the attacker's Stress read after the attack's effects. Their `unchanged:` list is asserted rather than trusted — that list is their claim about their own experiment. Measured, and three of their four criteria fail. DARVO arm rate is still 0 under greedy; ATTACK selection does not rise and falls for the rank-75 policy; group success collapses from 165/190/200 to 0 at 3/4/6 seats. The mechanism is not the assumed one: greedy answers the pressure by regulating, Stress plateaus at 3, so it never reaches the gate at 4 or the arm at 5 — H1-A acts as a solve-rate tax and H1-B is unreachable under competent play. A harness defect was caught before the claim: sweep discarded refused games silently and never reported its count, so "nobody won" and "nothing played" printed identically. Reporting H1 as unwinnable on that basis would have been the ADR-0018 family aimed at another repo's design. All 200 games ran in every cell; the zeros are real. Chaos d8 = 8 — the window's first override, redrew L against a structural L, so it changed nothing. Window 3 recorded in ChaosRollHistory. NOT REVIEWED: tier L owes a separate-agent adversarial review, and no H1 result may reach ground-game until it has run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
627992bc85
commit
a928b5925c
15 changed files with 928 additions and 28 deletions
|
|
@ -87,12 +87,19 @@ impl Policy for Attacker {
|
|||
}
|
||||
|
||||
/// `(games, good outcomes, attacks, DARVO armings)` over 200 seeds.
|
||||
///
|
||||
/// **`games` is reported, not assumed to be 200.** A rules variant can
|
||||
/// make the engine refuse a position, and a harness that skips those
|
||||
/// silently reports "nobody won" for a run in which nobody played.
|
||||
fn sweep(
|
||||
mode: ScoringMode,
|
||||
variant: games_ground::Variant,
|
||||
players: u8,
|
||||
mk: &dyn Fn(u8) -> Vec<Box<dyn Policy>>,
|
||||
) -> (u32, u32, u32, u32) {
|
||||
let (mut games, mut won, mut atk, mut darvo) = (0, 0, 0, 0);
|
||||
let mut errs: Vec<String> = Vec::new();
|
||||
let mut setup_fails = 0u32;
|
||||
for seed in 0..200u64 {
|
||||
let Ok(mut st) = GroundState::setup(
|
||||
&Setup {
|
||||
|
|
@ -102,11 +109,26 @@ fn sweep(
|
|||
},
|
||||
seed,
|
||||
) else {
|
||||
setup_fails += 1;
|
||||
continue;
|
||||
};
|
||||
st.mode = mode;
|
||||
// CB-WP-0038 T03: the SAME instrument measures both rule sets in
|
||||
// the same run. Two harnesses would compare harnesses.
|
||||
st.variant = variant;
|
||||
let mut ps = mk(players);
|
||||
let Ok(g) = play(st, &mut ps) else { continue };
|
||||
// CB-WP-0038 T03: a game the engine REFUSES is not a game the
|
||||
// table lost, and `else { continue }` made the two identical.
|
||||
// H1's first run showed won/atk/darvo all exactly 0 at 3+ seats,
|
||||
// which is the signature of every game being discarded rather
|
||||
// than played -- so the count is now reported, not swallowed.
|
||||
let g = match play(st, &mut ps) {
|
||||
Ok(g) => g,
|
||||
Err(e) => {
|
||||
errs.push(format!("{e:?}"));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
games += 1;
|
||||
|
||||
// In the co-op mode the table wins together. In the other two the
|
||||
|
|
@ -139,47 +161,73 @@ fn sweep(
|
|||
}
|
||||
}
|
||||
}
|
||||
if setup_fails > 0 {
|
||||
eprintln!(" !! {setup_fails} of 200 SETUPS failed ({players}p)");
|
||||
}
|
||||
if games != 200 {
|
||||
eprintln!(" !! only {games} of 200 games ran ({players}p, {mode:?})");
|
||||
}
|
||||
if !errs.is_empty() {
|
||||
eprintln!(
|
||||
" !! {} of 200 games did not run ({}p): first = {}",
|
||||
errs.len(),
|
||||
players,
|
||||
errs[0]
|
||||
);
|
||||
}
|
||||
(games, won, atk, darvo)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("F17 — what is ATTACK worth, in each scoring mode?\n");
|
||||
println!("CB-WP-0038 T03: run for BOTH rule sets. ground-game's H1 asks");
|
||||
println!("whether problem pressure plus a high-Stress self-soothe make");
|
||||
println!("ATTACK and DARVO relevant without making always-ATTACK optimal.\n");
|
||||
println!("`won` is group success in SHARED GROUND, and \"seat 0 is among the");
|
||||
println!("winners\" in the other two, because ATTACK is an individual's choice");
|
||||
println!("and that is what an individual's incentive turns on.\n");
|
||||
|
||||
for (label, mode) in [
|
||||
("SHARED GROUND (GR-E02, co-op)", ScoringMode::SharedGround),
|
||||
for (vlabel, variant) in [
|
||||
("BASELINE ground-darvo-r0", games_ground::Variant::Baseline),
|
||||
(
|
||||
"COMMON PROBLEM (GR-E03, semi-co-op)",
|
||||
ScoringMode::CommonProblem,
|
||||
"H1 h1-problem-stress",
|
||||
games_ground::Variant::H1ProblemStress,
|
||||
),
|
||||
("BONDED COALITIONS (GR-E04)", ScoringMode::BondedCoalitions),
|
||||
] {
|
||||
println!("{label}");
|
||||
println!(" rank=10 (greedy) rank=75 (sometimes) rank=95 (always)");
|
||||
println!("seats won atk darvo won atk darvo won atk darvo");
|
||||
for players in [2u8, 3, 4, 6] {
|
||||
let (_, gw, ga, gd) = sweep(mode, players, &|n| {
|
||||
(0..n)
|
||||
.map(|_| Box::new(GreedyPolicy) as Box<dyn Policy>)
|
||||
.collect()
|
||||
});
|
||||
let cell = |r: i32| {
|
||||
sweep(mode, players, &move |n| {
|
||||
println!("================ {vlabel} ================\n");
|
||||
for (label, mode) in [
|
||||
("SHARED GROUND (GR-E02, co-op)", ScoringMode::SharedGround),
|
||||
(
|
||||
"COMMON PROBLEM (GR-E03, semi-co-op)",
|
||||
ScoringMode::CommonProblem,
|
||||
),
|
||||
("BONDED COALITIONS (GR-E04)", ScoringMode::BondedCoalitions),
|
||||
] {
|
||||
println!("{label}");
|
||||
println!(" rank=10 (greedy) rank=75 (sometimes) rank=95 (always)");
|
||||
println!("seats won atk darvo won atk darvo won atk darvo");
|
||||
for players in [2u8, 3, 4, 6] {
|
||||
let (_, gw, ga, gd) = sweep(mode, variant, players, &|n| {
|
||||
(0..n)
|
||||
.map(|_| Box::new(Attacker(r)) as Box<dyn Policy>)
|
||||
.map(|_| Box::new(GreedyPolicy) as Box<dyn Policy>)
|
||||
.collect()
|
||||
})
|
||||
};
|
||||
let (_, mw, ma, md) = cell(75);
|
||||
let (_, aw, aa, ad) = cell(95);
|
||||
println!(
|
||||
" {players}p {gw:>4} {ga:>4} {gd:>5} {mw:>4} {ma:>4} {md:>5} \
|
||||
});
|
||||
let cell = |r: i32| {
|
||||
sweep(mode, variant, players, &move |n| {
|
||||
(0..n)
|
||||
.map(|_| Box::new(Attacker(r)) as Box<dyn Policy>)
|
||||
.collect()
|
||||
})
|
||||
};
|
||||
let (_, mw, ma, md) = cell(75);
|
||||
let (_, aw, aa, ad) = cell(95);
|
||||
println!(
|
||||
" {players}p {gw:>4} {ga:>4} {gd:>5} {mw:>4} {ma:>4} {md:>5} \
|
||||
{aw:>4} {aa:>4} {ad:>5}"
|
||||
);
|
||||
);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
println!();
|
||||
}
|
||||
println!("(200 games per cell)");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue