142 lines
3.7 KiB
Rust
142 lines
3.7 KiB
Rust
// Module 2: The action queue, depth-first. Each test matches a heading in scenarios.md.
|
|
use engine::harness::*;
|
|
|
|
fn fillers(n: usize) -> Vec<String> {
|
|
vec!["Test Filler".to_string(); n]
|
|
}
|
|
|
|
/// Sources of the `Triggered` events, in log order.
|
|
fn triggered_sources(log: &[GameEvent]) -> Vec<Id> {
|
|
log.iter()
|
|
.filter_map(|e| match e {
|
|
GameEvent::Triggered { source, .. } => Some(*source),
|
|
_ => None,
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
#[test]
|
|
fn test_02_aoe_damage_then_triggers() {
|
|
let mut g = new_game(GameOpts {
|
|
decks: Some([fillers(5), fillers(5)]),
|
|
});
|
|
let s = g.summon("Armorsmith", 0);
|
|
let a = g.summon("Acolyte of Pain", 0);
|
|
g.clear_log();
|
|
|
|
g.cast("Whirlwind", 0, None);
|
|
let log = g.log();
|
|
|
|
let damaged: Vec<GameEvent> = log
|
|
.iter()
|
|
.filter(|e| matches!(e, GameEvent::Damaged { .. }))
|
|
.cloned()
|
|
.collect();
|
|
assert_eq!(
|
|
damaged,
|
|
vec![
|
|
GameEvent::Damaged {
|
|
target: s,
|
|
amount: 1
|
|
},
|
|
GameEvent::Damaged {
|
|
target: a,
|
|
amount: 1
|
|
},
|
|
]
|
|
);
|
|
let last_damaged = log
|
|
.iter()
|
|
.rposition(|e| matches!(e, GameEvent::Damaged { .. }))
|
|
.unwrap();
|
|
let first_triggered = log
|
|
.iter()
|
|
.position(|e| matches!(e, GameEvent::Triggered { .. }))
|
|
.unwrap();
|
|
assert!(last_damaged < first_triggered);
|
|
|
|
let sources = triggered_sources(&log);
|
|
assert_eq!(sources.iter().filter(|&&id| id == s).count(), 2);
|
|
assert_eq!(sources.iter().filter(|&&id| id == a).count(), 1);
|
|
assert_eq!(sources.len(), 3);
|
|
assert_eq!(g.armor(0), 2);
|
|
assert_eq!(g.hand(0).len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_02_mortally_wounded_still_triggers() {
|
|
let mut g = new_game(GameOpts {
|
|
decks: Some([fillers(5), vec![]]),
|
|
});
|
|
let a = g.summon("Acolyte of Pain", 0);
|
|
g.deal_damage(a, 3);
|
|
let n = g.hand(0).len();
|
|
g.clear_log();
|
|
|
|
g.cast("Whirlwind", 0, None);
|
|
let log = g.log();
|
|
|
|
assert!(log.contains(&GameEvent::Triggered {
|
|
source: a,
|
|
trigger: "damaged".to_string(),
|
|
}));
|
|
assert!(log
|
|
.iter()
|
|
.any(|e| matches!(e, GameEvent::Drew { player: 0, .. })));
|
|
assert_eq!(g.hand(0).len(), n + 1);
|
|
assert_eq!(g.health(a), 0);
|
|
assert_eq!(g.zone_of(a), Zone::Board);
|
|
}
|
|
|
|
#[test]
|
|
fn test_02_depth_first_nesting() {
|
|
let mut g = new_game(GameOpts::default());
|
|
let e = g.summon("Test Echo", 0);
|
|
let s = g.summon("Armorsmith", 0);
|
|
let r = g.summon("Test Reactor", 0);
|
|
g.clear_log();
|
|
|
|
g.deal_damage(s, 1);
|
|
let log = g.log();
|
|
|
|
assert_eq!(triggered_sources(&log), vec![e, r, s]);
|
|
let reactor_grew = log
|
|
.iter()
|
|
.position(|ev| matches!(ev, GameEvent::StatsChanged { id, .. } if *id == r))
|
|
.unwrap();
|
|
let armor_gained = log
|
|
.iter()
|
|
.position(|ev| matches!(ev, GameEvent::ArmorGained { .. }))
|
|
.unwrap();
|
|
assert!(reactor_grew < armor_gained);
|
|
assert_eq!(g.attack(r), 2);
|
|
assert_eq!(g.armor(0), 1);
|
|
assert_eq!(g.health(g.hero(1)), 29);
|
|
}
|
|
|
|
#[test]
|
|
fn test_02_empty_deck_draw_is_fatigue() {
|
|
let mut g = new_game(GameOpts::default());
|
|
let a = g.summon("Acolyte of Pain", 0);
|
|
g.clear_log();
|
|
|
|
g.deal_damage(a, 1);
|
|
|
|
assert_eq!(
|
|
g.log(),
|
|
vec![
|
|
GameEvent::Damaged {
|
|
target: a,
|
|
amount: 1
|
|
},
|
|
GameEvent::Triggered {
|
|
source: a,
|
|
trigger: "damaged".to_string(),
|
|
},
|
|
GameEvent::Fatigue { player: 0 },
|
|
]
|
|
);
|
|
assert_eq!(g.hand(0), Vec::<Id>::new());
|
|
assert_eq!(g.health(g.hero(0)), 30);
|
|
}
|