rabukasim / engine_rust_src /src /repro /mini_engine_tests.rs
trioskosmos's picture
Upload folder using huggingface_hub
463f868 verified
use crate::core::logic::card_db::LOGIC_ID_MASK;
use crate::core::logic::*;
// use std::collections::HashMap;
fn create_mini_db_with_bytecode(bc: Vec<i32>) -> CardDatabase {
let mut db = CardDatabase::default();
let mut m = MemberCard {
card_id: 101,
card_no: "MINI-101".to_string(),
name: "Mini Card".to_string(),
cost: 2,
..Default::default()
};
m.abilities.push(Ability {
trigger: TriggerType::Activated,
bytecode: bc,
..Default::default()
});
db.members.insert(101, m.clone());
db.members_vec[(101 as usize) & LOGIC_ID_MASK as usize] = Some(m);
db
}
fn create_mini_state() -> GameState {
let mut state = GameState::default();
state.players[0].player_id = 0;
state.players[1].player_id = 1;
state.phase = Phase::Main;
state.ui.silent = false;
// Place the card on stage so activate_ability_with_choice can find it
state.players[0].stage[0] = 101;
state
}
#[test]
fn mini_test_o_pay_energy_resumption() {
// Bytecode: PAY_ENERGY(1), DRAW(1), RETURN
let bc = vec![64, 1, 0, 0, 10, 1, 0, 1, 1, 0, 0, 0];
let db = create_mini_db_with_bytecode(bc);
let mut state = create_mini_state();
// Setup energy (2 untapped, need 1 -> should suspend for choice)
state.players[0].tapped_energy_mask = 0;
// Populate deck so DRAW works
state.players[0].deck.extend(vec![1, 2, 3, 4, 5]);
// Activate the ability at slot 0, ability 0
state.activate_ability_with_choice(&db, 0, 0, -1, 0).unwrap();
assert_eq!(state.phase, Phase::Response, "Should suspend for PAY_ENERGY selection");
assert_eq!(state.interaction_stack.last().map(|i| i.effect_opcode).unwrap_or(0), 64, "Pending opcode should be O_PAY_ENERGY");
// Resume with SelectResponseSlot action
state.step(&db, Action::SelectResponseSlot { slot_idx: 0 }.id() as i32).unwrap();
assert!(state.players[0].is_energy_tapped(0), "Energy should be tapped");
assert_eq!(state.players[0].hand.len(), 1, "Should have resumed and drawn a card");
assert_eq!(state.phase, Phase::Main, "Should return to Main phase");
}
#[test]
fn mini_test_o_select_mode_resumption() {
// Bytecode: SELECT_MODE(2 choices), jump targets, Option 1: DRAW(1)+RETURN, Option 2: DRAW(2)+RETURN
let bc = vec![
30, 2, 12, 20, // SELECT_MODE, v=2, Jmp0=12, Jmp1=20
3, 0, 0, 0, // Option 1 -> instruction 3 (*4 = IP 12)
5, 0, 0, 0, // Option 2 -> instruction 5 (*4 = IP 20)
10, 1, 0, 1, // IP 12: DRAW(1)
1, 0, 0, 0, // IP 16: RETURN
10, 2, 0, 1, // IP 20: DRAW(2)
1, 0, 0, 0 // IP 24: RETURN
];
let db = create_mini_db_with_bytecode(bc);
let mut state = create_mini_state();
// Populate deck so DRAW works
state.players[0].deck.extend(vec![1, 2, 3, 4, 5]);
// Activate the ability at slot 0, ability 0
state.activate_ability_with_choice(&db, 0, 0, -1, 0).unwrap();
assert_eq!(state.phase, Phase::Response, "Should suspend for SELECT_MODE");
assert_eq!(state.interaction_stack.last().map(|i| i.effect_opcode).unwrap_or(0), 30, "Pending opcode should be O_SELECT_MODE");
// Pick Option 2 (choice_idx=1)
state.step(&db, Action::SelectChoice { choice_idx: 1 }.id() as i32).unwrap();
assert_eq!(state.players[0].hand.len(), 2, "Should have picked Option 2 and drawn 2 cards");
assert_eq!(state.phase, Phase::Main, "Should return to Main phase");
}