survey: FLY_PROBE_SAVE_RANK writes the first safe overworld frame at a rung as a checkpoint
This commit is contained in:
parent
4d82f7db74
commit
288e958d19
1 changed files with 57 additions and 14 deletions
|
|
@ -1346,7 +1346,12 @@ fn dialog_survey(gb: &mut Emulator, adapter: &mut PokemonRedReward, ms: &mut f64
|
||||||
/// (comma-separated names) presses those buttons whenever they are dealt.
|
/// (comma-separated names) presses those buttons whenever they are dealt.
|
||||||
///
|
///
|
||||||
/// [`PokemonPalette`]: flybrain_gb::pokemon_red::macros::PokemonPalette
|
/// [`PokemonPalette`]: flybrain_gb::pokemon_red::macros::PokemonPalette
|
||||||
fn route_survey(gb: &mut Emulator, adapter: &mut PokemonRedReward, ms: &mut f64) {
|
fn route_survey(
|
||||||
|
gb: &mut Emulator,
|
||||||
|
adapter: &mut PokemonRedReward,
|
||||||
|
ms: &mut f64,
|
||||||
|
checkpoint: &flysim::store::Checkpoint,
|
||||||
|
) {
|
||||||
use flybrain_gb::MacroPalette;
|
use flybrain_gb::MacroPalette;
|
||||||
use flybrain_gb::pokemon_red::macros::cartridge::{FACINGS, MacroState, TalkTarget, TargetKey};
|
use flybrain_gb::pokemon_red::macros::cartridge::{FACINGS, MacroState, TalkTarget, TargetKey};
|
||||||
use flybrain_gb::pokemon_red::macros::path::Way;
|
use flybrain_gb::pokemon_red::macros::path::Way;
|
||||||
|
|
@ -1380,6 +1385,9 @@ fn route_survey(gb: &mut Emulator, adapter: &mut PokemonRedReward, ms: &mut f64)
|
||||||
let mut entries = 0usize;
|
let mut entries = 0usize;
|
||||||
let mut arrived_at = 0usize;
|
let mut arrived_at = 0usize;
|
||||||
let mut last_map: Option<u8> = None;
|
let mut last_map: Option<u8> = None;
|
||||||
|
let save_rank: Option<u32> =
|
||||||
|
std::env::var("FLY_PROBE_SAVE_RANK").ok().and_then(|value| value.parse().ok());
|
||||||
|
let mut saved = false;
|
||||||
|
|
||||||
// `FLY_PROBE_HOLD=right:96,up:32` holds raw directions first and prints where the fly is
|
// `FLY_PROBE_HOLD=right:96,up:32` holds raw directions first and prints where the fly is
|
||||||
// every eight frames: what the cartridge does with a press, before any macro is asked.
|
// every eight frames: what the cartridge does with a press, before any macro is asked.
|
||||||
|
|
@ -1508,6 +1516,28 @@ fn route_survey(gb: &mut Emulator, adapter: &mut PokemonRedReward, ms: &mut f64)
|
||||||
gb.run_frame().expect("a frame should complete");
|
gb.run_frame().expect("a frame should complete");
|
||||||
*ms += MS_PER_FRAME;
|
*ms += MS_PER_FRAME;
|
||||||
adapter.sample(gb, *ms);
|
adapter.sample(gb, *ms);
|
||||||
|
// `FLY_PROBE_SAVE_RANK=11` with `FLY_PROBE_SAVE` writes the first frame at or past that
|
||||||
|
// rung where the fly has the buttons in the overworld and no macro is running: a state the
|
||||||
|
// stream could be restored into next (row 59, after the badge), carried forward by the
|
||||||
|
// survey from the source checkpoint. The session ledgers are not in it, as they are in no
|
||||||
|
// checkpoint.
|
||||||
|
if let Some(want) = save_rank
|
||||||
|
&& !saved
|
||||||
|
&& adapter.progress().rank >= want
|
||||||
|
&& !running
|
||||||
|
&& matches!(observed.scene, flybrain_gb::SceneId::Overworld)
|
||||||
|
&& state::controllable(gb)
|
||||||
|
&& let Some(path) = std::env::var_os("FLY_PROBE_SAVE")
|
||||||
|
{
|
||||||
|
saved = true;
|
||||||
|
let bytes = save_state(checkpoint, gb, adapter, frame, &path);
|
||||||
|
println!(
|
||||||
|
"f{frame:<6} {:?} saved rank {} to `{}` ({bytes} bytes)",
|
||||||
|
state::player(gb).map(|p| (p.map, p.x, p.y)),
|
||||||
|
adapter.progress().rank,
|
||||||
|
std::path::Path::new(&path).display()
|
||||||
|
);
|
||||||
|
}
|
||||||
if single_refusals >= catch_after {
|
if single_refusals >= catch_after {
|
||||||
caught_at = Some(frame);
|
caught_at = Some(frame);
|
||||||
break;
|
break;
|
||||||
|
|
@ -1673,6 +1703,28 @@ fn separator_table(classes: &BTreeMap<(bool, bool, bool), u64>) -> String {
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This state as a `FLYSIM01` checkpoint: the agent half is the source checkpoint's, unchanged --
|
||||||
|
/// the release box's own run carried forward by the stub, not a synthesised save -- and `.local/`
|
||||||
|
/// is not tracked, exactly as every other checkpoint in this workspace. Returns the size written.
|
||||||
|
fn save_state(
|
||||||
|
checkpoint: &flysim::store::Checkpoint,
|
||||||
|
gb: &mut Emulator,
|
||||||
|
adapter: &PokemonRedReward,
|
||||||
|
frame: usize,
|
||||||
|
path: &std::ffi::OsStr,
|
||||||
|
) -> usize {
|
||||||
|
let mut runtime = checkpoint.runtime.clone();
|
||||||
|
runtime.emulator = gb.export_state().expect("the emulator should export");
|
||||||
|
runtime.reward = adapter.export_state();
|
||||||
|
runtime.framebuffer = gb.framebuffer().to_vec();
|
||||||
|
runtime.emulator_frame = frame as u64;
|
||||||
|
let bytes =
|
||||||
|
flysim::store::encode(&checkpoint.agent, &runtime).expect("the envelope should encode");
|
||||||
|
flysim::store::write_atomic(std::path::Path::new(path), &bytes)
|
||||||
|
.expect("the checkpoint should be writable");
|
||||||
|
bytes.len()
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let Some(path) = std::env::var_os("FLY_ROM") else {
|
let Some(path) = std::env::var_os("FLY_ROM") else {
|
||||||
println!("FLY_ROM is not set, so there is nothing to probe.");
|
println!("FLY_ROM is not set, so there is nothing to probe.");
|
||||||
|
|
@ -1764,7 +1816,7 @@ fn main() {
|
||||||
// Row 57's pad survey: earn the session's ledgers from the checkpoint with the real palette,
|
// Row 57's pad survey: earn the session's ledgers from the checkpoint with the real palette,
|
||||||
// and read the frame the pad comes down to one refusing button on.
|
// and read the frame the pad comes down to one refusing button on.
|
||||||
if std::env::var("FLY_PROBE_CATCH").is_ok_and(|value| value == "route") {
|
if std::env::var("FLY_PROBE_CATCH").is_ok_and(|value| value == "route") {
|
||||||
route_survey(&mut gb, &mut adapter, &mut ms);
|
route_survey(&mut gb, &mut adapter, &mut ms, &checkpoint);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1877,19 +1929,10 @@ fn main() {
|
||||||
// release box's own run carried forward by the stub, not a synthesised save -- and
|
// release box's own run carried forward by the stub, not a synthesised save -- and
|
||||||
// `.local/` is not tracked, exactly as every other checkpoint in this workspace.
|
// `.local/` is not tracked, exactly as every other checkpoint in this workspace.
|
||||||
if let Some(save) = std::env::var_os("FLY_PROBE_SAVE") {
|
if let Some(save) = std::env::var_os("FLY_PROBE_SAVE") {
|
||||||
let mut runtime = checkpoint.runtime.clone();
|
let bytes = save_state(&checkpoint, &mut gb, &adapter, frame, &save);
|
||||||
runtime.emulator = gb.export_state().expect("the emulator should export");
|
|
||||||
runtime.reward = adapter.export_state();
|
|
||||||
runtime.framebuffer = gb.framebuffer().to_vec();
|
|
||||||
runtime.emulator_frame = frame as u64;
|
|
||||||
let bytes = flysim::store::encode(&checkpoint.agent, &runtime)
|
|
||||||
.expect("the envelope should encode");
|
|
||||||
flysim::store::write_atomic(std::path::Path::new(&save), &bytes)
|
|
||||||
.expect("the checkpoint should be writable");
|
|
||||||
println!(
|
println!(
|
||||||
"\nWrote this state to `{}` ({} bytes).",
|
"\nWrote this state to `{}` ({bytes} bytes).",
|
||||||
std::path::Path::new(&save).display(),
|
std::path::Path::new(&save).display()
|
||||||
bytes.len()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// The survey method on the one question the fix turns on: **what does the
|
// The survey method on the one question the fix turns on: **what does the
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue