macros: the move list deals BACK only where the moves can be read
The v0.4.3 residual: BACK was 263 of 797 macro starts and every one of them was over an open move list. A move list whose battler the seam cannot place binds no MOVE n at all -- move_slot_bound needs wBattleMon* -- so its pad was BACK alone, and the only thing that button does is close the list MOVE 1 on the menu underneath had just opened. That is section 12.10's pair with MOVE 1 standing where NEXT used to. So BACK is dealt on the move list only while battle.own reads, and MOVE 1 keeps the backstop it has over the top-level menu: with nothing readable the pad is MOVE 1 alone and its script confirms wherever the cursor stands, which is the press that ends a turn. With the moves readable the pad is unchanged.
This commit is contained in:
parent
3807fff422
commit
029a3446fb
2 changed files with 50 additions and 2 deletions
|
|
@ -526,7 +526,20 @@ pub fn scene_set(scene: Scene, state: &mut dyn MacroState) -> Vec<MacroKind> {
|
|||
// between them. Two buttons that undo each other with nothing else changing are section
|
||||
// 12.2's trap spread over two sub-states of one turn.
|
||||
Scene::Battle { own_turn: true, .. } => match battle_menu(state) {
|
||||
BattleMenu::Moves { .. } => vec![Move1, Move2, Move3, Move4, Back],
|
||||
// The move list. `BACK` is a button here because there is a list to leave (12.9) --
|
||||
// but only while the moves can be *read*: a battler the seam cannot place leaves all
|
||||
// four `MOVE n` unbound, and a pad of `BACK` alone closes the list that `MOVE 1` on
|
||||
// the menu underneath had just opened. That is 12.10's pair again, with `MOVE 1` in
|
||||
// `NEXT`'s place. With nothing readable the pad is `MOVE 1` alone and its script
|
||||
// confirms wherever the cursor stands, which is the press that ends the turn
|
||||
// (section 12.11).
|
||||
BattleMenu::Moves { .. } => {
|
||||
if state.battle().and_then(|battle| battle.own).is_some() {
|
||||
vec![Move1, Move2, Move3, Move4, Back]
|
||||
} else {
|
||||
vec![Move1]
|
||||
}
|
||||
}
|
||||
BattleMenu::Party { .. } => vec![Switch, Back],
|
||||
// The bag, which is the fly's turn since 12.10. Its three answers: use the thing the
|
||||
// cursor is on (`ITEM`), throw the ball (`THROW BALL`), or leave the list (`BACK`).
|
||||
|
|
@ -1643,7 +1656,14 @@ pub fn move_slot_bound(state: &mut dyn MacroState, kind: MacroKind) -> bool {
|
|||
if index == 0 && matches!(battle.menu, BattleMenu::Main { .. }) {
|
||||
return true;
|
||||
}
|
||||
let Some(own) = battle.own else { return false };
|
||||
// And the same backstop over an **open move list** whose battler the seam cannot read
|
||||
// (section 12.11). That frame used to deal `BACK` alone -- the only button on it closed the
|
||||
// list `MOVE 1` on the menu underneath had just opened, which is 12.10's pair with `MOVE 1` in
|
||||
// `NEXT`'s place. `MOVE 1`'s script over an open list confirms wherever the cursor stands, so
|
||||
// it reads no move either, and confirming a move is what ends a turn.
|
||||
let Some(own) = battle.own else {
|
||||
return index == 0 && matches!(battle.menu, BattleMenu::Moves { cursor: Some(_), .. });
|
||||
};
|
||||
let holds = |slot: usize| -> Option<&Move> {
|
||||
own.moves.get(slot).and_then(|entry| entry.as_ref()).filter(|entry| entry.id != 0)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4318,6 +4318,34 @@ fn an_overworld_pad_is_never_one_button_that_undoes_itself() {
|
|||
}
|
||||
}
|
||||
|
||||
/// Section 12.11: the move list deals `BACK` only where the moves can be read.
|
||||
///
|
||||
/// The v0.4.3 residual (`infra/docs/macros-traps.md`): `BACK` was 263 of 797 macro starts, every
|
||||
/// one over an open move list, and 142 of the run's `NEXT` starts were on a move list whose cursor
|
||||
/// the seam could not place. A move list the seam cannot read the battler for binds no `MOVE n` at
|
||||
/// all, so its pad was `BACK` alone -- and the only thing that button does is close the list that
|
||||
/// `MOVE 1` on the menu underneath had just opened. That is 12.10's pair with `MOVE 1` in `NEXT`'s
|
||||
/// place. `MOVE 1` alone confirms wherever the cursor stands, which is the press that ends a turn.
|
||||
#[test]
|
||||
fn the_move_list_deals_back_only_where_the_moves_can_be_read() {
|
||||
let mut world = World::battle();
|
||||
world.list = List::Moves(3);
|
||||
world.grid = false;
|
||||
world.cursor_max = 2;
|
||||
assert_eq!(pad_of(&mut world), ["BACK", "MOVE 1", "MOVE 2", "MOVE 3"]);
|
||||
|
||||
// The battler the seam cannot place: no active slot, so `battle.own` is `None`.
|
||||
world.active = None;
|
||||
let pad = pad_of(&mut world);
|
||||
assert_eq!(pad, ["MOVE 1"], "one button, and it ends the turn: {pad:?}");
|
||||
assert!(move_slot_bound(&mut world, MacroKind::Move1));
|
||||
assert!(!move_slot_bound(&mut world, MacroKind::Move2));
|
||||
// And it really presses: the cursor is confirmed where it stands, which is Struggle's own
|
||||
// path (row 30a) and the only reading available here.
|
||||
assert_eq!(run(&mut world, MacroKind::Move1).unwrap(), MacroAbort::Done);
|
||||
assert_eq!(world.pulses.last(), Some(&buttons::A));
|
||||
}
|
||||
|
||||
/// Row 37 of `infra/docs/macros-traps.md`: a tile the cartridge pushes the fly off is not a tile
|
||||
/// to stand on, and the ground beside a villager is not the villager's fault.
|
||||
///
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue