flybrain/services/flysim/crates/flybrain-gb/src/pokemon_red/macros/mod.rs
acamilo 660c3cf00d
Some checks failed
ci / node 22 (test + typecheck) (push) Has been cancelled
ci / rust stable (cargo test --workspace --release) (push) Has been cancelled
ci / infra/tests/lint.sh (push) Has been cancelled
ci / playwright apps/stage (allowed to fail) (push) Has been cancelled
flybrain v0.4.0: public tree (history retained privately)
2026-09-21 15:09:46 +00:00

67 lines
3.1 KiB
Rust

//! The macro palette: scene-appropriate actions, and the executor that runs them.
//!
//! `docs/design/macros.md` is the binding contract. This module is agent B's
//! (`Palette::for_scene`, A* pathing, the macro scripts, `MacroExecutor`); [`state`] is the seam
//! it is written against and belongs to agent A, who implements it in
//! [`crate::pokemon_red::state`].
//!
//! In one paragraph: the population decoder and its six channels do not change, and palette mode
//! gives those same channels a *scene-dependent meaning* in the game layer. UP is slot 0, DOWN
//! slot 1, LEFT slot 2, RIGHT slot 3, A slot 4, B slot 5; [`Palette::for_scene`] says what each
//! slot means in the current scene and leaves a slot unbound when its precondition fails;
//! [`MacroMachine`] runs the chosen slot's script with the same button register the fly's raw
//! presses use, for at most six hundred frames, giving the buttons back the moment the scene
//! changes.
//!
//! What is *not* here is as much the point as what is:
//!
//! - **No choosing.** Nothing in this module picks a macro. `start` is handed a slot, and the
//! slot comes from the readout. There is no default, no fallback on timeout and no objective
//! (`docs/design/macros.md` section 1).
//! - **No addresses.** Every read goes through [`state::GameState`] and [`cartridge::MacroState`].
//! The executor cannot drift from the decomp because it never names an offset.
//! - **No new button path.** A macro presses the emulator's button register, the same one the
//! decoder's raw masks go to. There is still no button endpoint on the control API.
//!
//! ## Wiring it (agent C)
//!
//! [`cartridge::MacroState`] is one extension of agent A's trait for the four things section 3
//! names and the seam does not carry, and every method is defaulted, so agent A's reader needs
//! one line:
//!
//! ```ignore
//! impl MacroState for PokeState<'_> {}
//! ```
//!
//! That compiles today, and it is checked: a trial merge of `feat/macros-executor` and
//! `feat/macros-scene` builds and passes both halves' tests, conflicting only in the two module
//! lists. Overriding a default is what turns `BUY POTION` on, gives `ATTACK` the real move table
//! and type chart, and points the three ways out at the adapter's exploration ledger; until then the
//! palette offers less rather than guessing.
//!
//! ```text
//! decoder channels --> MacroId --> Palette::for_scene --> MacroMachine::start
//! |
//! per frame: MacroMachine::step --> button mask --> emulator
//! ```
pub mod cartridge;
pub mod driver;
pub mod executor;
pub mod geography;
pub mod palette;
pub mod path;
pub mod plan;
pub mod state;
#[cfg(test)]
mod tests;
pub use cartridge::{Edge, ExitId, Listing, MacroState, Tile};
pub use driver::PokemonPalette;
pub use executor::{
Executor, FRAME_CAP, MAX_FAILED_STEPS, MacroAbort, MacroExecutor, MacroMachine, MacroRefused,
Refusal, StateSource,
};
pub use palette::{MacroId, MacroKind, MacroSpec, Palette, SLOTS};
pub use path::{Exit, Route, exits, route};