Spaces:
Running
Running
File size: 5,288 Bytes
88d4171 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
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]);
}
|