LovecaSim / engine_rust_src /src /opcode_tests.rs
trioskosmos's picture
Upload folder using huggingface_hub
88d4171 verified
raw
history blame
5.29 kB
use crate::core::logic::*;
use crate::core::enums::*;
use crate::core::models::*;
use std::collections::HashMap;
fn create_test_db() -> CardDatabase {
let mut db = CardDatabase {
members: HashMap::new(),
lives: HashMap::new(),
members_vec: vec![None; 1000],
lives_vec: vec![None; 40000],
};
// Member with cost 5
db.members.insert(10, MemberCard {
card_id: 10,
card_no: "M-10".to_string(),
name: "Member 10".to_string(),
cost: 5,
..Default::default()
});
db.members_vec[10] = Some(db.members[&10].clone());
// Member with cost 15
db.members.insert(15, MemberCard {
card_id: 15,
card_no: "M-15".to_string(),
name: "Member 15".to_string(),
cost: 15,
..Default::default()
});
db.members_vec[15] = Some(db.members[&15].clone());
// Live card
db.lives.insert(10050, LiveCard {
card_id: 10050,
card_no: "L-10050".to_string(),
name: "Live 10050".to_string(),
..Default::default()
});
db.lives_vec[50] = Some(db.lives[&10050].clone());
db
}
fn create_test_state() -> GameState {
let mut state = GameState::default();
state.players[0].player_id = 0;
state.players[1].player_id = 1;
state.phase = Phase::Main;
state
}
#[test]
fn test_opcode_draw_until() {
let db = create_test_db();
let mut state = create_test_state();
state.players[0].deck = vec![1, 2, 3, 4, 5];
state.players[0].hand = vec![101, 102]; // Hand size 2
let ctx = AbilityContext { player_id: 0, ..Default::default() };
// O_DRAW_UNTIL 5 (Draw up to 5)
let bc = vec![O_DRAW_UNTIL, 5, 0, 0, O_RETURN, 0, 0, 0];
state.resolve_bytecode(&db, &bc, &ctx);
assert_eq!(state.players[0].hand.len(), 5);
assert_eq!(state.players[0].deck.len(), 2);
}
#[test]
fn test_opcode_reveal_until_type_live() {
let db = create_test_db();
let mut state = create_test_state();
// Deck: 10 (member), 15 (member), 10050 (live), 1 (fallback)
state.players[0].deck = vec![1, 10050, 15, 10];
let ctx = AbilityContext { player_id: 0, ..Default::default() };
// O_REVEAL_UNTIL 33 (TYPE_CHECK) attr: 1 (Live), target: 6 (Hand)
let bc = vec![O_REVEAL_UNTIL, 33, 1, 6, O_RETURN, 0, 0, 0];
state.resolve_bytecode(&db, &bc, &ctx);
// Should have popped 10, 15, then 10050.
// 10050 matches Live. It goes to hand.
// 10 and 15 go to discard.
assert!(state.players[0].hand.contains(&10050));
assert_eq!(state.players[0].discard.len(), 2); // 10 and 15
assert!(state.players[0].discard.contains(&10));
assert!(state.players[0].discard.contains(&15));
assert_eq!(state.players[0].deck.len(), 1); // 1 remains
}
#[test]
fn test_opcode_reveal_until_cost_ge() {
let db = create_test_db();
let mut state = create_test_state();
// Deck: 10 (cost 5), 15 (cost 15), 1 (fallback)
state.players[0].deck = vec![1, 15, 10];
let ctx = AbilityContext { player_id: 0, ..Default::default() };
// O_REVEAL_UNTIL 16 (COST_GE) attr: (10 << 1) | 0x40 = 20 | 64 = 84, target: 6 (Hand)
// Wait, attr in logic.rs: min_cost = (a >> 1) & 0x1F
let bc = vec![O_REVEAL_UNTIL, 16, 84, 6, O_RETURN, 0, 0, 0];
state.resolve_bytecode(&db, &bc, &ctx);
// Should pop 10 (cost 5 < 10), then 15 (cost 15 >= 10).
// 15 goes to hand. 10 goes to discard.
assert!(state.players[0].hand.contains(&15));
assert_eq!(state.players[0].discard.len(), 1);
assert!(state.players[0].discard.contains(&10));
}
#[test]
fn test_opcode_immunity() {
let db = create_test_db();
let mut state = create_test_state();
assert!(!state.players[0].has_immunity);
let ctx = AbilityContext { player_id: 0, ..Default::default() };
// O_IMMUNITY 1
let bc = vec![O_IMMUNITY, 1, 0, 0, O_RETURN, 0, 0, 0];
state.resolve_bytecode(&db, &bc, &ctx);
assert!(state.players[0].has_immunity);
// O_IMMUNITY 0
let bc = vec![O_IMMUNITY, 0, 0, 0, O_RETURN, 0, 0, 0];
state.resolve_bytecode(&db, &bc, &ctx);
assert!(!state.players[0].has_immunity);
}
#[test]
fn test_opcode_pay_energy() {
let db = create_test_db();
let mut state = create_test_state();
state.players[0].tapped_energy = vec![false, false, false];
let ctx = AbilityContext { player_id: 0, ..Default::default() };
// O_PAY_ENERGY 2
let bc = vec![O_PAY_ENERGY, 2, 0, 0, O_RETURN, 0, 0, 0];
state.resolve_bytecode(&db, &bc, &ctx);
assert_eq!(state.players[0].tapped_energy.iter().filter(|&&t| t).count(), 2);
}
#[test]
fn test_opcode_look_deck() {
let db = create_test_db();
let mut state = create_test_state();
state.players[0].deck = vec![1, 2, 3, 4, 5];
let ctx = AbilityContext { player_id: 0, ..Default::default() };
// O_LOOK_DECK 3
let bc = vec![O_LOOK_DECK, 3, 0, 0, O_RETURN, 0, 0, 0];
state.resolve_bytecode(&db, &bc, &ctx);
assert_eq!(state.players[0].looked_cards.len(), 3);
assert_eq!(state.players[0].deck.len(), 2);
assert_eq!(state.players[0].looked_cards, vec![5, 4, 3]);
}