CB-WP-0049 T02/T03: a seat that plays its objective, and F27 splits in two
Some checks failed
ci / check (push) Has been cancelled
Some checks failed
ci / check (push) Has been cancelled
objective() reads GroundState::score (now public) rather than restating
what winning is; a copy in the bot would disagree with the kernel the
first time ground-game rules on F28.
Working out WHERE the modes can differ was most of the task and it
bounds the result: SOLVE always claims for the actor, so own-score and
group-score want the same SOLVE nearly everywhere. That is a fact about
GROUND's action set, not a shortcoming of the bot. Two real divergences,
both readable off the table: SUPPORT regulates someone else (worth less
against a rival, worth MORE under coalitions where a Bond merges them
into my side), and SOLVE's value is the card's value, which greedy
ignores entirely.
THE RESULT — F27 splits in two:
group success UNCHANGED in 34 of 36 cells
who wins MOVES: BONDED COALITIONS at 4p goes 2.04 -> 2.98,
2.12 -> 3.29, 2.05 -> 3.01 winning seats per game
So "the competitive modes are scoring lenses over cooperative play" was
too strong and is withdrawn. The sharper claim: GROUND's scoring modes
change WHO WINS, not WHETHER THE GROUP SUCCEEDS. And the effect is
seat-band dependent -- 2p none, 4p largest, 6p none under coalitions;
two relation slots capping network growth is a candidate explanation and
is untested.
The panel now prints BOTH policies side by side. That was a correction
mid-task: the first version printed only the new one and I compared it
against a figure remembered from CB-WP-0047 -- a comparison against a
board nobody re-ran.
Control that makes the numbers mean anything: under SHARED GROUND the
two policies agree at all but <=2 decision points across 12 boards, so a
moving column is mode-awareness and not simply a different bot.
Also: two T01 tests keyed on `status: proposed`, which ground-game
renamed to `ready-for-implement` mid-session. They now find the module
by asking resolve() -- the structural property is ours and does not move
when another repo edits its vocabulary.
Also: `make vendor` replaces three hand re-vendors with a tool that
regenerates digests by walking editions/, and reports one-sided files
rather than resolving them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
82b9e7df31
commit
3045eb03f8
16 changed files with 859 additions and 94 deletions
|
|
@ -17,7 +17,7 @@
|
|||
//! and the column is expected to match, which is itself a control.
|
||||
|
||||
use cb_game_runtime::{ScenarioGame, Setup};
|
||||
use games_ground::bot::{play, GreedyPolicy, Policy};
|
||||
use games_ground::bot::{play, GreedyPolicy, ObjectivePolicy, Policy};
|
||||
use games_ground::{GroundState, ScoringMode};
|
||||
|
||||
/// Games per cell. Named once so the banner and the assertion cannot
|
||||
|
|
@ -41,7 +41,17 @@ struct Cell {
|
|||
setup_fails: u32,
|
||||
}
|
||||
|
||||
fn sweep(scenario: &str, mode: ScoringMode, players: u8) -> Cell {
|
||||
/// Which bot fills every seat. CB-WP-0049 T03: F27 says the three modes
|
||||
/// produce identical play because greedy never reads `state.mode`; the
|
||||
/// only way to know whether that is a fact about GROUND or a fact about
|
||||
/// our bot is to run the same panel with a seat that does read it.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum Seat {
|
||||
Greedy,
|
||||
Objective,
|
||||
}
|
||||
|
||||
fn sweep(scenario: &str, mode: ScoringMode, players: u8, who: Seat) -> Cell {
|
||||
let mut c = Cell {
|
||||
games: 0,
|
||||
played: 0,
|
||||
|
|
@ -74,7 +84,10 @@ fn sweep(scenario: &str, mode: ScoringMode, players: u8) -> Cell {
|
|||
// scenario it did not play.
|
||||
assert_eq!(st.scenario, scenario, "{preset} dealt {}", st.scenario);
|
||||
let mut ps: Vec<Box<dyn Policy>> = (0..players)
|
||||
.map(|_| Box::new(GreedyPolicy) as Box<dyn Policy>)
|
||||
.map(|_| match who {
|
||||
Seat::Greedy => Box::new(GreedyPolicy) as Box<dyn Policy>,
|
||||
Seat::Objective => Box::new(ObjectivePolicy) as Box<dyn Policy>,
|
||||
})
|
||||
.collect();
|
||||
let g = match play(st, &mut ps) {
|
||||
Ok(g) => g,
|
||||
|
|
@ -131,16 +144,23 @@ fn main() {
|
|||
for players in [2u8, 4, 6] {
|
||||
println!("{players} players");
|
||||
println!(
|
||||
" {:<32} {:<18} {:>5} {:>7} {:>6} {:>9}",
|
||||
"scenario", "mode", "won", "win/g", "pts", "threshold"
|
||||
" {:<32} {:<18} {:>5} {:>5} {:>7} {:>7} {:>6} {:>9}",
|
||||
"scenario", "mode", "grdy", "obj", "win/g g", "win/g o", "pts", "threshold"
|
||||
);
|
||||
for s in &scenarios {
|
||||
for (label, mode) in &modes {
|
||||
let c = sweep(&s.id, *mode, players);
|
||||
let g = sweep(&s.id, *mode, players, Seat::Greedy);
|
||||
let c = sweep(&s.id, *mode, players, Seat::Objective);
|
||||
println!(
|
||||
" {:<32} {label} {:>5} {:>7.2} {:>6.1} {:>9}",
|
||||
" {:<32} {label} {:>5} {:>5} {:>7.2} {:>7.2} {:>6.1} {:>9}",
|
||||
format!("{} {}", s.id, s.title),
|
||||
g.group_success,
|
||||
c.group_success,
|
||||
// **Both, side by side.** Reading one policy's number
|
||||
// against a figure remembered from an earlier pass is
|
||||
// how a comparison gets made against a board nobody
|
||||
// re-ran.
|
||||
f64::from(g.winners) / f64::from(g.games),
|
||||
f64::from(c.winners) / f64::from(c.games),
|
||||
f64::from(c.total) / f64::from(c.games),
|
||||
c.threshold,
|
||||
|
|
@ -150,6 +170,11 @@ fn main() {
|
|||
println!();
|
||||
}
|
||||
|
||||
println!("`grdy` is GreedyPolicy, which never reads state.mode; `obj`");
|
||||
println!("is ObjectivePolicy, which plays its seat's own objective.");
|
||||
println!("If the obj column varies ACROSS modes where grdy does not,");
|
||||
println!("F27 was a fact about our bot. If it does not, it is a fact");
|
||||
println!("about GROUND.\n");
|
||||
println!("SCN_01 and SCN_02 are the same board — identical suits and");
|
||||
println!("values at every priority. Their rows are expected to MATCH,");
|
||||
println!("and a divergence means one of the two decks was edited.");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue