// Module 2: The action queue, depth-first. Each test matches a heading in scenarios.md. use engine::harness::*; fn fillers(n: usize) -> Vec { vec!["Test Filler".to_string(); n] } /// Sources of the `Triggered` events, in log order. fn triggered_sources(log: &[GameEvent]) -> Vec { 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 = 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); } #[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::::new()); assert_eq!(g.health(g.hero(0)), 30); }