trap hunt: report the battle sub-state, its pad and the starts on it
A scene histogram says "battle" and a battle deals five different pads (docs/design/macros.md 12.6, 13.1), so a loop inside one of them is invisible in the tables the hunt already prints. Three more: frames per sub-state, every macro channel ever bound in each one, and the macro starts by the sub-state they started on.
This commit is contained in:
parent
1a3cfb714a
commit
097a11196b
1 changed files with 72 additions and 0 deletions
|
|
@ -214,9 +214,42 @@ struct Trace {
|
||||||
font_corners_no_border: u64,
|
font_corners_no_border: u64,
|
||||||
font_no_corners: u64,
|
font_no_corners: u64,
|
||||||
corners_no_font: u64,
|
corners_no_font: u64,
|
||||||
|
/// Frames spent in each battle sub-state, by [`battle_sub_state`]'s name.
|
||||||
|
///
|
||||||
|
/// The scene histogram says "battle" and a battle has five sub-states with five different
|
||||||
|
/// pads (`docs/design/macros.md` section 12.6, 13.1), so a loop inside one of them is
|
||||||
|
/// invisible above. This is what names it.
|
||||||
|
battle_frames: BTreeMap<&'static str, u64>,
|
||||||
|
/// Macro starts by battle sub-state: which button the fly pressed on which of the five pads.
|
||||||
|
battle_starts: BTreeMap<(&'static str, &'static str), u64>,
|
||||||
|
/// Every macro channel that was bound in each battle sub-state, over the whole run.
|
||||||
|
///
|
||||||
|
/// The pad's composition, measured rather than read off the table: "which sub-state offers
|
||||||
|
/// `BACK`" is a question about the build under test and not about the document.
|
||||||
|
battle_pads: BTreeMap<&'static str, BTreeSet<String>>,
|
||||||
wall_seconds: f64,
|
wall_seconds: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Which sub-state of a battle this frame is, or `None` when no battle is running.
|
||||||
|
///
|
||||||
|
/// The five the pad is dealt by: the top-level menu, the move list, the party list, the bag, the
|
||||||
|
/// forced switch, and the frames between turns where no list is accepting input.
|
||||||
|
fn battle_sub_state(emulator: &mut flybrain_gb::Emulator) -> Option<&'static str> {
|
||||||
|
use flybrain_gb::pokemon_red::macros::state::BattleMenu;
|
||||||
|
let battle = flybrain_gb::pokemon_red::state::battle(emulator)?;
|
||||||
|
if battle.forced_switch {
|
||||||
|
return Some("forced switch");
|
||||||
|
}
|
||||||
|
Some(match battle.menu {
|
||||||
|
BattleMenu::Main { .. } => "main menu",
|
||||||
|
BattleMenu::Moves { cursor: Some(_), .. } => "move list",
|
||||||
|
BattleMenu::Moves { cursor: None, .. } => "move list, no cursor",
|
||||||
|
BattleMenu::Party { .. } => "party list",
|
||||||
|
BattleMenu::Bag { .. } => "bag",
|
||||||
|
BattleMenu::None => "between turns",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// The macro that owns the buttons, with where it began and the ground it has covered since.
|
/// The macro that owns the buttons, with where it began and the ground it has covered since.
|
||||||
struct Running {
|
struct Running {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
|
|
@ -350,6 +383,9 @@ fn run(
|
||||||
font_corners_no_border: 0,
|
font_corners_no_border: 0,
|
||||||
font_no_corners: 0,
|
font_no_corners: 0,
|
||||||
corners_no_font: 0,
|
corners_no_font: 0,
|
||||||
|
battle_frames: BTreeMap::new(),
|
||||||
|
battle_starts: BTreeMap::new(),
|
||||||
|
battle_pads: BTreeMap::new(),
|
||||||
wall_seconds: 0.0,
|
wall_seconds: 0.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -406,6 +442,14 @@ fn run(
|
||||||
let dialog_map = (layer_scene == "dialog" || layer_scene == "unknown")
|
let dialog_map = (layer_scene == "dialog" || layer_scene == "unknown")
|
||||||
.then(|| flybrain_gb::pokemon_red::state::player(&mut emulator).map(|p| p.map))
|
.then(|| flybrain_gb::pokemon_red::state::player(&mut emulator).map(|p| p.map))
|
||||||
.flatten();
|
.flatten();
|
||||||
|
let battle_sub = battle_sub_state(&mut emulator);
|
||||||
|
if let Some(sub) = battle_sub {
|
||||||
|
*trace.battle_frames.entry(sub).or_insert(0) += 1;
|
||||||
|
let pad = trace.battle_pads.entry(sub).or_default();
|
||||||
|
for channel in bound.as_deref().unwrap_or_default() {
|
||||||
|
pad.insert(channel.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(layer) = macros.as_mut() {
|
if let Some(layer) = macros.as_mut() {
|
||||||
let ledger = AdapterLedger(&adapter);
|
let ledger = AdapterLedger(&adapter);
|
||||||
let decision = layer.decide(&active, mask, ms, &mut emulator, &ledger);
|
let decision = layer.decide(&active, mask, ms, &mut emulator, &ledger);
|
||||||
|
|
@ -419,6 +463,9 @@ fn run(
|
||||||
if let Some(map) = dialog_map {
|
if let Some(map) = dialog_map {
|
||||||
*trace.dialog_macros.entry((event.name, map)).or_insert(0) += 1;
|
*trace.dialog_macros.entry((event.name, map)).or_insert(0) += 1;
|
||||||
}
|
}
|
||||||
|
if let Some(sub) = battle_sub {
|
||||||
|
*trace.battle_starts.entry((event.name, sub)).or_insert(0) += 1;
|
||||||
|
}
|
||||||
running = Some(Running {
|
running = Some(Running {
|
||||||
name: event.name,
|
name: event.name,
|
||||||
from: location,
|
from: location,
|
||||||
|
|
@ -801,6 +848,31 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !trace.battle_frames.is_empty() {
|
||||||
|
println!("\n| battle sub-state | frames | pad |");
|
||||||
|
println!("| --- | ---: | --- |");
|
||||||
|
for (sub, frames) in &trace.battle_frames {
|
||||||
|
let pad = trace
|
||||||
|
.battle_pads
|
||||||
|
.get(sub)
|
||||||
|
.map(|set| {
|
||||||
|
set.iter()
|
||||||
|
.map(|c| c.strip_prefix("macro_").unwrap_or(c).to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(" ")
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
println!("| {sub} | {frames} | {pad} |");
|
||||||
|
}
|
||||||
|
println!("\n| macro start | battle sub-state | n |");
|
||||||
|
println!("| --- | --- | ---: |");
|
||||||
|
let mut rows: Vec<((&str, &str), u64)> =
|
||||||
|
trace.battle_starts.iter().map(|(key, n)| (*key, *n)).collect();
|
||||||
|
rows.sort_by_key(|(_, n)| std::cmp::Reverse(*n));
|
||||||
|
for ((name, sub), n) in rows {
|
||||||
|
println!("| {name} | {sub} | {n} |");
|
||||||
|
}
|
||||||
|
}
|
||||||
println!("\n| scene | frames | longest run | run began (brain min) |");
|
println!("\n| scene | frames | longest run | run began (brain min) |");
|
||||||
println!("| --- | ---: | ---: | ---: |");
|
println!("| --- | ---: | ---: | ---: |");
|
||||||
for (scene, frames) in &trace.scenes {
|
for (scene, frames) in &trace.scenes {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue