rabukasim / engine_rust_src /src /enforcement_tests.rs
trioskosmos's picture
Upload folder using huggingface_hub
463f868 verified
//! Tests for core rule enforcement (Referee Logic).
//! These tests verify that the engine correctly prevents actions when costs or conditions are not met.
use crate::core::logic::card_db::LOGIC_ID_MASK;
use crate::core::logic::*;
use crate::test_helpers::{create_test_db, create_test_state};
#[test]
fn test_enforce_cost_failure() {
let mut db = create_test_db();
let mut state = create_test_state();
// Create member with cost 2 energy
let cid = 3991;
let mut m = MemberCard::default();
m.card_id = cid;
m.abilities.push(Ability {
trigger: TriggerType::Activated,
costs: vec![Cost {
cost_type: AbilityCostType::Energy,
value: 2,
..Default::default()
}],
bytecode: vec![O_DRAW, 1, 0, 0, O_RETURN, 0, 0, 0],
..Default::default()
});
db.members.insert(cid, m.clone());
db.members_vec[(cid as usize) & LOGIC_ID_MASK as usize] = Some(m);
state.players[0].stage[0] = cid;
state.players[0].energy_zone.clear(); // 0 Energy
state.debug.debug_ignore_conditions = false; // ENSURE ENFORCEMENT IS ON
// Attempt to activate (0, 0)
let res = state.activate_ability(&db, 0, 0);
assert!(res.is_err(), "Should fail due to insufficient energy");
assert!(res.unwrap_err().contains("Cannot afford cost"));
}
#[test]
fn test_enforce_condition_failure() {
let mut db = create_test_db();
let mut state = create_test_state();
// Create member with condition Stage >= 3
let cid = 3992;
let mut m = MemberCard::default();
m.card_id = cid;
m.abilities.push(Ability {
trigger: TriggerType::Activated,
conditions: vec![Condition {
condition_type: ConditionType::CountStage,
value: 3,
..Default::default()
}],
bytecode: vec![O_DRAW, 1, 0, 0, O_RETURN, 0, 0, 0],
..Default::default()
});
db.members.insert(cid, m.clone());
db.members_vec[(cid as usize) & LOGIC_ID_MASK as usize] = Some(m);
state.players[0].stage = [cid, -1, -1]; // Only 1 member
state.debug.debug_ignore_conditions = false;
// Attempt to activate (0, 0)
let res = state.activate_ability(&db, 0, 0);
assert!(
res.is_err(),
"Should fail due to conditions not met (Stage count < 3)"
);
assert!(res.unwrap_err().contains("Conditions not met"));
}
#[test]
fn test_enforce_once_per_turn_failure() {
let mut db = create_test_db();
let mut state = create_test_state();
// Create member with Once Per Turn
let cid = 3993;
let mut m = MemberCard::default();
m.card_id = cid;
m.abilities.push(Ability {
trigger: TriggerType::Activated,
is_once_per_turn: true,
bytecode: vec![O_DRAW, 1, 0, 0, O_RETURN, 0, 0, 0],
..Default::default()
});
db.members.insert(cid, m.clone());
db.members_vec[(cid as usize) & LOGIC_ID_MASK as usize] = Some(m);
state.players[0].stage[0] = cid;
state.players[0].deck = vec![1, 2, 3].into();
state.debug.debug_ignore_conditions = false;
// First activation - Success
let res1 = state.activate_ability(&db, 0, 0);
assert!(
res1.is_ok(),
"First activation should succeed. Error: {:?}",
res1.err()
);
// Second activation - Failure
let res2 = state.activate_ability(&db, 0, 0);
assert!(
res2.is_err(),
"Second activation should fail due to Once-Per-Turn"
);
assert!(res2.unwrap_err().contains("Ability already used this turn"));
}
#[test]
fn test_enforce_play_member_cost_failure() {
let mut db = create_test_db();
let mut state = create_test_state();
// Member with cost 2
let cid = 3994;
let mut m = MemberCard::default();
m.card_id = cid;
m.cost = 2;
db.members.insert(cid, m.clone());
db.members_vec[(cid as usize) & LOGIC_ID_MASK as usize] = Some(m);
state.players[0].hand = vec![cid].into();
state.players[0].energy_zone.clear(); // 0 Energy
state.debug.debug_ignore_conditions = false;
// Attempt to play to slot 0
let res = state.play_member(&db, 0, 0);
assert!(
res.is_err(),
"Should fail to play member due to insufficient energy"
);
assert!(res.unwrap_err().contains("Not enough energy"));
}