CB-WP-0050 T02: F31 falsified — the module is unreachable, then real
Some checks failed
ci / check (push) Failing after 4s
Some checks failed
ci / check (push) Failing after 4s
GateAttackPolicy ranks ATTACK above GROUND at the stress gate and delegates everything else. A PROBE, not a better bot: it wins 12/100 where greedy wins 60/100 under the same module, and the panel's banner says so, because a column that looks like a policy comparison will be read as one. (a) THE MODULE IS UNREACHABLE IN THE PRINTED GAME. Selected alone it still never fires: peak Stress never exceeds 2, so the gate never bites and no ATTACK is ever gated. A module can be unreachable because of an aspect it does not name -- attack_relief needs a problem_stress module before it can act at all, and nothing in its own declaration says so. (b) ONCE REACHABLE IT IS REAL. Holding the probe fixed and varying only the module: group wins 12->21, 19->28, 50->57 at 3/4/6p, and DARVO arms 299->221, 294->213, 334->164. Under flat pressure the same shape appears in DARVO alone: h1 arms 200 against flat_any_open's 300/400/600. Stated as the conditional it is: GIVEN seats that attack at the gate. Not advice to attack, and not evidence against F17. AND IT CHANGES WHAT WE TOLD GROUND-GAME. CB-EV-0030 rejected H1 with policies that never attacked, so H1-B was inert for every game behind that verdict. The rejection stands on flat pressure alone -- wins are 0 either way -- but "H1-B does nothing" was never established and is now known to be false. We owe them that correction. Sensitivity: vary only the ATTACK rank. At 10 (greedy) and +55 (module-aware) the module never fires; at 110 it fires in every game. Nothing about the module changed -- only whether any seat gave it a turn. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
1b6a68fb39
commit
4a72420e01
4 changed files with 224 additions and 11 deletions
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
use cb_game_runtime::{ScenarioGame, Setup};
|
||||
use cb_kernel::PlayerId;
|
||||
use games_ground::bot::{play, GreedyPolicy, ModuleAwarePolicy, Policy};
|
||||
use games_ground::bot::{play, GateAttackPolicy, GreedyPolicy, ModuleAwarePolicy, Policy};
|
||||
use games_ground::config::Configuration;
|
||||
use games_ground::{GroundState, ScoringMode};
|
||||
|
||||
|
|
@ -94,6 +94,10 @@ fn fired(m: &str, g: &games_ground::bot::BotGame) -> bool {
|
|||
enum Seat {
|
||||
Greedy,
|
||||
ModuleAware,
|
||||
/// F31's falsifier: a seat that attacks at the stress gate, so
|
||||
/// `attack_relief.self_soothe_ge4` gets an opportunity at all. **A
|
||||
/// probe, not a recommendation** — its win rate is not advice.
|
||||
GateAttack,
|
||||
}
|
||||
|
||||
fn sweep(cfg: &Configuration, players: u8, who: Seat) -> Cell {
|
||||
|
|
@ -120,6 +124,7 @@ fn sweep(cfg: &Configuration, players: u8, who: Seat) -> Cell {
|
|||
.map(|_| match who {
|
||||
Seat::Greedy => Box::new(GreedyPolicy) as Box<dyn Policy>,
|
||||
Seat::ModuleAware => Box::new(ModuleAwarePolicy) as Box<dyn Policy>,
|
||||
Seat::GateAttack => Box::new(GateAttackPolicy) as Box<dyn Policy>,
|
||||
})
|
||||
.collect();
|
||||
let g = match play(st, &mut ps) {
|
||||
|
|
@ -227,6 +232,11 @@ fn main() {
|
|||
println!("ModuleAwarePolicy. A row flat under `grdy` and moving under");
|
||||
println!("`mod` is a module that needs a seat able to see it — not a");
|
||||
println!("module that does nothing (F27's distinction).\n");
|
||||
println!("`atk!` is GateAttackPolicy, which attacks at the stress gate so");
|
||||
println!("attack_relief gets an opportunity at all (F31). It is a PROBE:");
|
||||
println!("its win rate is not a recommendation. The peak/darvo/atk columns");
|
||||
println!("are its games, because they are the only ones where ATTACK");
|
||||
println!("happens.\n");
|
||||
println!("`never fired: UNMEASURED` means no seat created that module's");
|
||||
println!("precondition in any game, so its contribution to the row is not");
|
||||
println!("a null result — it is an absence of evidence. The other numbers");
|
||||
|
|
@ -235,8 +245,8 @@ fn main() {
|
|||
for players in [3u8, 4, 6] {
|
||||
println!("{players} players");
|
||||
println!(
|
||||
" {:<18} {:<38} {:>5} {:>5} {:>6} {:>6} {:>6}",
|
||||
"aspect", "module / profile", "grdy", "mod", "peak", "darvo", "atk"
|
||||
" {:<18} {:<38} {:>5} {:>5} {:>5} {:>6} {:>6} {:>6}",
|
||||
"aspect", "module / profile", "grdy", "mod", "atk!", "peak", "darvo", "atk"
|
||||
);
|
||||
for (aspect, name, cfg) in points() {
|
||||
let cfg = match cfg {
|
||||
|
|
@ -257,6 +267,7 @@ fn main() {
|
|||
}
|
||||
let g = sweep(&cfg, players, Seat::Greedy);
|
||||
let m = sweep(&cfg, players, Seat::ModuleAware);
|
||||
let a = sweep(&cfg, players, Seat::GateAttack);
|
||||
// **A module that never acted is UNMEASURED, not null.**
|
||||
// Printing win counts for it invites the reading that it does
|
||||
// nothing, when what happened is that no seat ever created
|
||||
|
|
@ -269,7 +280,10 @@ fn main() {
|
|||
// every game and drives group success to 0, which is a real
|
||||
// result about that module even though its ATTACK half never
|
||||
// gets an opportunity.
|
||||
let never: Vec<&String> = m
|
||||
// **The probe's row decides "never fired", not the others.**
|
||||
// A module is unreachable only if the seat built to reach it
|
||||
// could not either.
|
||||
let never: Vec<&String> = a
|
||||
.unfired
|
||||
.iter()
|
||||
.filter(|(_, n)| **n == GAMES)
|
||||
|
|
@ -288,8 +302,8 @@ fn main() {
|
|||
)
|
||||
};
|
||||
println!(
|
||||
" {aspect:<18} {name:<38} {:>5} {:>5} {:>6} {:>6} {:>6}{note}",
|
||||
g.won, m.won, m.peak_stress, m.darvo, m.attacks
|
||||
" {aspect:<18} {name:<38} {:>5} {:>5} {:>5} {:>6} {:>6} {:>6}{note}",
|
||||
g.won, m.won, a.won, a.peak_stress, a.darvo, a.attacks
|
||||
);
|
||||
}
|
||||
println!();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue