use std::{ fs::File, io::{prelude::*, BufReader}, }; use shakmaty::{fen::Fen, perft, CastlingMode, Chess, FromSetup, Position, PositionError}; fn test_perft_file

(path: &str, node_limit: u64) where P: Position + FromSetup + Default + Clone, { let file = File::open(path).expect("failed to open test suite"); let reader = BufReader::new(file); let mut pos = P::default(); for line in reader.lines().map(|l| l.unwrap()) { println!("{}", line); let trimmed = line.trim(); let mut slices = trimmed.splitn(2, ' '); match slices.next() { Some("epd") => { pos = slices .next() .expect("missing epd") .parse::() .expect("invalid fen") .into_position(CastlingMode::Chess960) .or_else(PositionError::ignore_impossible_check) .expect("illegal fen"); } Some("perft") => { let mut params = slices.next().expect("missing perft params").splitn(2, ' '); let depth = params .next() .expect("missing perft depth") .parse() .expect("depth not an integer"); let nodes = params .next() .expect("missing perft nodes") .parse() .expect("nodes not an integer"); if nodes <= node_limit { assert_eq!(perft(&pos, depth), nodes); } } _ => {} } } } // macro for generating tests macro_rules! gen_tests { ($($fn_name:ident, $t:ty, $path:tt, $num:expr,)+) => { $( #[test] #[cfg_attr(miri, ignore)] fn $fn_name() { test_perft_file::<$t>($path, $num); } )+ } } gen_tests! { test_tricky, Chess, "tests/tricky.perft", 100_000, test_random, Chess, "tests/random.perft", 10_000, test_chess960, Chess, "tests/chess960.perft", 100_000, } #[cfg(feature = "variant")] use shakmaty::variant::{Antichess, Atomic, Crazyhouse, Horde, RacingKings, ThreeCheck}; #[cfg(feature = "variant")] gen_tests! { test_atomic, Atomic, "tests/atomic.perft", 1_000_000, test_antichess, Antichess, "tests/antichess.perft", 1_000_000, test_crazyhouse, Crazyhouse, "tests/crazyhouse.perft", 1_000_000, test_racingkings, RacingKings, "tests/racingkings.perft", 1_000_000, test_horde, Horde, "tests/horde.perft", 1_000_000, test_3check, ThreeCheck, "tests/3check.perft", 1_000_000, }