From 7156b052e773a41a29413c8bf341f25f0dce222c Mon Sep 17 00:00:00 2001 From: Mario Lang Date: Wed, 8 Jan 2025 21:57:19 +0100 Subject: [PATCH] Consolidate tests --- chessIO.cabal | 50 ++---------- package.yaml | 17 ++-- stack.yaml | 2 +- test/perft/Perft.hs | 91 --------------------- test/perft/perftsuite.epd | 126 ----------------------------- test/polyglot/Polyglot.hs | 17 ---- test/tests.hs | 161 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 172 insertions(+), 292 deletions(-) delete mode 100644 test/perft/Perft.hs delete mode 100644 test/perft/perftsuite.epd delete mode 100644 test/polyglot/Polyglot.hs create mode 100644 test/tests.hs diff --git a/chessIO.cabal b/chessIO.cabal index 2789c10..821b988 100644 --- a/chessIO.cabal +++ b/chessIO.cabal @@ -159,13 +159,13 @@ executable polyplay , vector-instances default-language: Haskell2010 -test-suite perft +test-suite tests type: exitcode-stdio-1.0 - main-is: Perft.hs + main-is: tests.hs other-modules: Paths_chessIO hs-source-dirs: - test/perft + test ghc-options: -O2 -threaded -rtsopts "-with-rtsopts=-N -s" build-depends: MonadRandom @@ -176,48 +176,6 @@ test-suite perft , chessIO , containers , deepseq - , directory - , extra - , file-embed - , hashable - , lens - , megaparsec >=9.0 - , mono-traversable - , o-clock - , parallel - , prettyprinter >=1.7.0 - , process - , random - , stm - , template-haskell >=2.9.0.0 - , text - , th-compat >=0.1.2 - , th-lift-instances - , time - , unordered-containers - , vector - , vector-binary-instances - , vector-instances - default-language: Haskell2010 - -test-suite polyglot - type: exitcode-stdio-1.0 - main-is: Polyglot.hs - other-modules: - Paths_chessIO - hs-source-dirs: - test/polyglot - ghc-options: -O2 - build-depends: - HUnit - , MonadRandom - , attoparsec - , base >=4.10 && <5 - , binary - , bytestring - , chessIO - , containers - , deepseq , extra , file-embed , hashable @@ -229,6 +187,8 @@ test-suite polyglot , process , random , stm + , tasty + , tasty-hunit , template-haskell >=2.9.0.0 , text , th-compat >=0.1.2 diff --git a/package.yaml b/package.yaml index 884a3f2..e1d97aa 100644 --- a/package.yaml +++ b/package.yaml @@ -89,18 +89,11 @@ executables: - time tests: - perft: - main: Perft.hs - source-dirs: test/perft + tests: + main: tests.hs + source-dirs: test ghc-options: -threaded -rtsopts "-with-rtsopts=-N -s" dependencies: - chessIO - - directory - - parallel - - time - polyglot: - main: Polyglot.hs - source-dirs: test/polyglot - dependencies: - - HUnit - - chessIO + - tasty + - tasty-hunit diff --git a/stack.yaml b/stack.yaml index 144fa6f..f0ecc6d 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: lts-23.0 +resolver: lts-23.3 packages: - . flags: diff --git a/test/perft/Perft.hs b/test/perft/Perft.hs deleted file mode 100644 index 0bf50e0..0000000 --- a/test/perft/Perft.hs +++ /dev/null @@ -1,91 +0,0 @@ -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE NamedFieldPuns #-} -module Main where - -import Control.Parallel.Strategies -import Data.MonoTraversable -import Data.Foldable -import Data.Maybe -import qualified Data.Vector.Unboxed as Vector -import Data.Monoid -import Data.Time.Clock -import Data.Traversable -import GHC.Generics (Generic) -import Game.Chess -import System.Directory -import System.Exit -import System.IO - -type Depth = Int -type Testsuite = [(Position, [(Depth, PerftResult)])] - -main :: IO () -main = do - start <- getCurrentTime - exists <- doesFileExist "test/perft/perftsuite.epd" - result <- if exists - then do - suite <- readTestSuite "test/perft/perftsuite.epd" - runTestSuite suite - else do - fmap (Just . fold) . for [0..6] $ \n -> do - let r = perft n startpos - putStrLn $ showResult n r - hFlush stdout - pure r - end <- getCurrentTime - case result of - Just PerftResult{nodes} -> putStrLn $ - "nps: " <> - show (floor (realToFrac (fromIntegral nodes) / realToFrac (diffUTCTime end start))) - _ -> pure () - putStrLn $ "Time: " <> show (diffUTCTime end start) - exitWith $ if isJust result then ExitSuccess else ExitFailure 1 - -data PerftResult = PerftResult { nodes :: !Integer } deriving (Eq, Generic, Show) -instance NFData PerftResult - -instance Semigroup PerftResult where - PerftResult n1 <> PerftResult n2 = PerftResult $ n1 + n2 - -instance Monoid PerftResult where - mempty = PerftResult 0 - -showResult :: Depth -> PerftResult -> String -showResult depth PerftResult{nodes} = show depth <> " " <> show nodes - -perft :: Depth -> Position -> PerftResult -perft 0 _ = PerftResult 1 -perft 1 p = PerftResult . fromIntegral . Vector.length $ legalPlies' p -perft n p - | n < 5 - = Vector.foldMap' (perft (pred n) . unsafeDoPly p) $ legalPlies' p - | otherwise - = fold . parMap rdeepseq (perft (pred n) . unsafeDoPly p) $ legalPlies p - -runTestSuite :: Testsuite -> IO (Maybe PerftResult) -runTestSuite = fmap (getAp . foldMap Ap) . traverse (uncurry (test mempty)) where - test sum pos ((depth, expected) : more) - | result == expected - = do - putStrLn $ "OK " <> fen <> " ;D" <> show depth <> " " - <> show (nodes expected) - hFlush stdout - test (sum <> result) pos more - | otherwise - = do - putStrLn $ "FAIL " <> fen <> " ;D" <> show depth <> " " - <> show (nodes expected) <> " /= " <> show (nodes result) - pure Nothing - where result = perft depth pos - fen = toFEN pos - test sum _ [] = pure (Just sum) - -readTestSuite :: FilePath -> IO Testsuite -readTestSuite fp = do - epd <- readFile fp - pure $ fmap readData . (\ws -> (fromJust (fromFEN (unwords $ take 6 ws)), drop 6 ws)) . words <$> lines epd - where - readData [] = [] - readData ((';':'D':d):v:xs) = (read d, PerftResult $ read v) : readData xs - readData _ = error "Failed to parse test suite" diff --git a/test/perft/perftsuite.epd b/test/perft/perftsuite.epd deleted file mode 100644 index ae7215c..0000000 --- a/test/perft/perftsuite.epd +++ /dev/null @@ -1,126 +0,0 @@ -rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 ;D1 20 ;D2 400 ;D3 8902 ;D4 197281 ;D5 4865609 ;D6 119060324 -r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1 ;D1 48 ;D2 2039 ;D3 97862 ;D4 4085603 ;D5 193690690 -4k3/8/8/8/8/8/8/4K2R w K - 0 1 ;D1 15 ;D2 66 ;D3 1197 ;D4 7059 ;D5 133987 ;D6 764643 -4k3/8/8/8/8/8/8/R3K3 w Q - 0 1 ;D1 16 ;D2 71 ;D3 1287 ;D4 7626 ;D5 145232 ;D6 846648 -4k2r/8/8/8/8/8/8/4K3 w k - 0 1 ;D1 5 ;D2 75 ;D3 459 ;D4 8290 ;D5 47635 ;D6 899442 -r3k3/8/8/8/8/8/8/4K3 w q - 0 1 ;D1 5 ;D2 80 ;D3 493 ;D4 8897 ;D5 52710 ;D6 1001523 -4k3/8/8/8/8/8/8/R3K2R w KQ - 0 1 ;D1 26 ;D2 112 ;D3 3189 ;D4 17945 ;D5 532933 ;D6 2788982 -r3k2r/8/8/8/8/8/8/4K3 w kq - 0 1 ;D1 5 ;D2 130 ;D3 782 ;D4 22180 ;D5 118882 ;D6 3517770 -8/8/8/8/8/8/6k1/4K2R w K - 0 1 ;D1 12 ;D2 38 ;D3 564 ;D4 2219 ;D5 37735 ;D6 185867 -8/8/8/8/8/8/1k6/R3K3 w Q - 0 1 ;D1 15 ;D2 65 ;D3 1018 ;D4 4573 ;D5 80619 ;D6 413018 -4k2r/6K1/8/8/8/8/8/8 w k - 0 1 ;D1 3 ;D2 32 ;D3 134 ;D4 2073 ;D5 10485 ;D6 179869 -r3k3/1K6/8/8/8/8/8/8 w q - 0 1 ;D1 4 ;D2 49 ;D3 243 ;D4 3991 ;D5 20780 ;D6 367724 -r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1 ;D1 26 ;D2 568 ;D3 13744 ;D4 314346 ;D5 7594526 ;D6 179862938 -r3k2r/8/8/8/8/8/8/1R2K2R w Kkq - 0 1 ;D1 25 ;D2 567 ;D3 14095 ;D4 328965 ;D5 8153719 ;D6 195629489 -r3k2r/8/8/8/8/8/8/2R1K2R w Kkq - 0 1 ;D1 25 ;D2 548 ;D3 13502 ;D4 312835 ;D5 7736373 ;D6 184411439 -r3k2r/8/8/8/8/8/8/R3K1R1 w Qkq - 0 1 ;D1 25 ;D2 547 ;D3 13579 ;D4 316214 ;D5 7878456 ;D6 189224276 -1r2k2r/8/8/8/8/8/8/R3K2R w KQk - 0 1 ;D1 26 ;D2 583 ;D3 14252 ;D4 334705 ;D5 8198901 ;D6 198328929 -2r1k2r/8/8/8/8/8/8/R3K2R w KQk - 0 1 ;D1 25 ;D2 560 ;D3 13592 ;D4 317324 ;D5 7710115 ;D6 185959088 -r3k1r1/8/8/8/8/8/8/R3K2R w KQq - 0 1 ;D1 25 ;D2 560 ;D3 13607 ;D4 320792 ;D5 7848606 ;D6 190755813 -4k3/8/8/8/8/8/8/4K2R b K - 0 1 ;D1 5 ;D2 75 ;D3 459 ;D4 8290 ;D5 47635 ;D6 899442 -4k3/8/8/8/8/8/8/R3K3 b Q - 0 1 ;D1 5 ;D2 80 ;D3 493 ;D4 8897 ;D5 52710 ;D6 1001523 -4k2r/8/8/8/8/8/8/4K3 b k - 0 1 ;D1 15 ;D2 66 ;D3 1197 ;D4 7059 ;D5 133987 ;D6 764643 -r3k3/8/8/8/8/8/8/4K3 b q - 0 1 ;D1 16 ;D2 71 ;D3 1287 ;D4 7626 ;D5 145232 ;D6 846648 -4k3/8/8/8/8/8/8/R3K2R b KQ - 0 1 ;D1 5 ;D2 130 ;D3 782 ;D4 22180 ;D5 118882 ;D6 3517770 -r3k2r/8/8/8/8/8/8/4K3 b kq - 0 1 ;D1 26 ;D2 112 ;D3 3189 ;D4 17945 ;D5 532933 ;D6 2788982 -8/8/8/8/8/8/6k1/4K2R b K - 0 1 ;D1 3 ;D2 32 ;D3 134 ;D4 2073 ;D5 10485 ;D6 179869 -8/8/8/8/8/8/1k6/R3K3 b Q - 0 1 ;D1 4 ;D2 49 ;D3 243 ;D4 3991 ;D5 20780 ;D6 367724 -4k2r/6K1/8/8/8/8/8/8 b k - 0 1 ;D1 12 ;D2 38 ;D3 564 ;D4 2219 ;D5 37735 ;D6 185867 -r3k3/1K6/8/8/8/8/8/8 b q - 0 1 ;D1 15 ;D2 65 ;D3 1018 ;D4 4573 ;D5 80619 ;D6 413018 -r3k2r/8/8/8/8/8/8/R3K2R b KQkq - 0 1 ;D1 26 ;D2 568 ;D3 13744 ;D4 314346 ;D5 7594526 ;D6 179862938 -r3k2r/8/8/8/8/8/8/1R2K2R b Kkq - 0 1 ;D1 26 ;D2 583 ;D3 14252 ;D4 334705 ;D5 8198901 ;D6 198328929 -r3k2r/8/8/8/8/8/8/2R1K2R b Kkq - 0 1 ;D1 25 ;D2 560 ;D3 13592 ;D4 317324 ;D5 7710115 ;D6 185959088 -r3k2r/8/8/8/8/8/8/R3K1R1 b Qkq - 0 1 ;D1 25 ;D2 560 ;D3 13607 ;D4 320792 ;D5 7848606 ;D6 190755813 -1r2k2r/8/8/8/8/8/8/R3K2R b KQk - 0 1 ;D1 25 ;D2 567 ;D3 14095 ;D4 328965 ;D5 8153719 ;D6 195629489 -2r1k2r/8/8/8/8/8/8/R3K2R b KQk - 0 1 ;D1 25 ;D2 548 ;D3 13502 ;D4 312835 ;D5 7736373 ;D6 184411439 -r3k1r1/8/8/8/8/8/8/R3K2R b KQq - 0 1 ;D1 25 ;D2 547 ;D3 13579 ;D4 316214 ;D5 7878456 ;D6 189224276 -8/1n4N1/2k5/8/8/5K2/1N4n1/8 w - - 0 1 ;D1 14 ;D2 195 ;D3 2760 ;D4 38675 ;D5 570726 ;D6 8107539 -8/1k6/8/5N2/8/4n3/8/2K5 w - - 0 1 ;D1 11 ;D2 156 ;D3 1636 ;D4 20534 ;D5 223507 ;D6 2594412 -8/8/4k3/3Nn3/3nN3/4K3/8/8 w - - 0 1 ;D1 19 ;D2 289 ;D3 4442 ;D4 73584 ;D5 1198299 ;D6 19870403 -K7/8/2n5/1n6/8/8/8/k6N w - - 0 1 ;D1 3 ;D2 51 ;D3 345 ;D4 5301 ;D5 38348 ;D6 588695 -k7/8/2N5/1N6/8/8/8/K6n w - - 0 1 ;D1 17 ;D2 54 ;D3 835 ;D4 5910 ;D5 92250 ;D6 688780 -8/1n4N1/2k5/8/8/5K2/1N4n1/8 b - - 0 1 ;D1 15 ;D2 193 ;D3 2816 ;D4 40039 ;D5 582642 ;D6 8503277 -8/1k6/8/5N2/8/4n3/8/2K5 b - - 0 1 ;D1 16 ;D2 180 ;D3 2290 ;D4 24640 ;D5 288141 ;D6 3147566 -8/8/3K4/3Nn3/3nN3/4k3/8/8 b - - 0 1 ;D1 4 ;D2 68 ;D3 1118 ;D4 16199 ;D5 281190 ;D6 4405103 -K7/8/2n5/1n6/8/8/8/k6N b - - 0 1 ;D1 17 ;D2 54 ;D3 835 ;D4 5910 ;D5 92250 ;D6 688780 -k7/8/2N5/1N6/8/8/8/K6n b - - 0 1 ;D1 3 ;D2 51 ;D3 345 ;D4 5301 ;D5 38348 ;D6 588695 -B6b/8/8/8/2K5/4k3/8/b6B w - - 0 1 ;D1 17 ;D2 278 ;D3 4607 ;D4 76778 ;D5 1320507 ;D6 22823890 -8/8/1B6/7b/7k/8/2B1b3/7K w - - 0 1 ;D1 21 ;D2 316 ;D3 5744 ;D4 93338 ;D5 1713368 ;D6 28861171 -k7/B7/1B6/1B6/8/8/8/K6b w - - 0 1 ;D1 21 ;D2 144 ;D3 3242 ;D4 32955 ;D5 787524 ;D6 7881673 -K7/b7/1b6/1b6/8/8/8/k6B w - - 0 1 ;D1 7 ;D2 143 ;D3 1416 ;D4 31787 ;D5 310862 ;D6 7382896 -B6b/8/8/8/2K5/5k2/8/b6B b - - 0 1 ;D1 6 ;D2 106 ;D3 1829 ;D4 31151 ;D5 530585 ;D6 9250746 -8/8/1B6/7b/7k/8/2B1b3/7K b - - 0 1 ;D1 17 ;D2 309 ;D3 5133 ;D4 93603 ;D5 1591064 ;D6 29027891 -k7/B7/1B6/1B6/8/8/8/K6b b - - 0 1 ;D1 7 ;D2 143 ;D3 1416 ;D4 31787 ;D5 310862 ;D6 7382896 -K7/b7/1b6/1b6/8/8/8/k6B b - - 0 1 ;D1 21 ;D2 144 ;D3 3242 ;D4 32955 ;D5 787524 ;D6 7881673 -7k/RR6/8/8/8/8/rr6/7K w - - 0 1 ;D1 19 ;D2 275 ;D3 5300 ;D4 104342 ;D5 2161211 ;D6 44956585 -R6r/8/8/2K5/5k2/8/8/r6R w - - 0 1 ;D1 36 ;D2 1027 ;D3 29215 ;D4 771461 ;D5 20506480 ;D6 525169084 -7k/RR6/8/8/8/8/rr6/7K b - - 0 1 ;D1 19 ;D2 275 ;D3 5300 ;D4 104342 ;D5 2161211 ;D6 44956585 -R6r/8/8/2K5/5k2/8/8/r6R b - - 0 1 ;D1 36 ;D2 1027 ;D3 29227 ;D4 771368 ;D5 20521342 ;D6 524966748 -6kq/8/8/8/8/8/8/7K w - - 0 1 ;D1 2 ;D2 36 ;D3 143 ;D4 3637 ;D5 14893 ;D6 391507 -6KQ/8/8/8/8/8/8/7k b - - 0 1 ;D1 2 ;D2 36 ;D3 143 ;D4 3637 ;D5 14893 ;D6 391507 -K7/8/8/3Q4/4q3/8/8/7k w - - 0 1 ;D1 6 ;D2 35 ;D3 495 ;D4 8349 ;D5 166741 ;D6 3370175 -6qk/8/8/8/8/8/8/7K b - - 0 1 ;D1 22 ;D2 43 ;D3 1015 ;D4 4167 ;D5 105749 ;D6 419369 -6KQ/8/8/8/8/8/8/7k b - - 0 1 ;D1 2 ;D2 36 ;D3 143 ;D4 3637 ;D5 14893 ;D6 391507 -K7/8/8/3Q4/4q3/8/8/7k b - - 0 1 ;D1 6 ;D2 35 ;D3 495 ;D4 8349 ;D5 166741 ;D6 3370175 -8/8/8/8/8/K7/P7/k7 w - - 0 1 ;D1 3 ;D2 7 ;D3 43 ;D4 199 ;D5 1347 ;D6 6249 -8/8/8/8/8/7K/7P/7k w - - 0 1 ;D1 3 ;D2 7 ;D3 43 ;D4 199 ;D5 1347 ;D6 6249 -K7/p7/k7/8/8/8/8/8 w - - 0 1 ;D1 1 ;D2 3 ;D3 12 ;D4 80 ;D5 342 ;D6 2343 -7K/7p/7k/8/8/8/8/8 w - - 0 1 ;D1 1 ;D2 3 ;D3 12 ;D4 80 ;D5 342 ;D6 2343 -8/2k1p3/3pP3/3P2K1/8/8/8/8 w - - 0 1 ;D1 7 ;D2 35 ;D3 210 ;D4 1091 ;D5 7028 ;D6 34834 -8/8/8/8/8/K7/P7/k7 b - - 0 1 ;D1 1 ;D2 3 ;D3 12 ;D4 80 ;D5 342 ;D6 2343 -8/8/8/8/8/7K/7P/7k b - - 0 1 ;D1 1 ;D2 3 ;D3 12 ;D4 80 ;D5 342 ;D6 2343 -K7/p7/k7/8/8/8/8/8 b - - 0 1 ;D1 3 ;D2 7 ;D3 43 ;D4 199 ;D5 1347 ;D6 6249 -7K/7p/7k/8/8/8/8/8 b - - 0 1 ;D1 3 ;D2 7 ;D3 43 ;D4 199 ;D5 1347 ;D6 6249 -8/2k1p3/3pP3/3P2K1/8/8/8/8 b - - 0 1 ;D1 5 ;D2 35 ;D3 182 ;D4 1091 ;D5 5408 ;D6 34822 -8/8/8/8/8/4k3/4P3/4K3 w - - 0 1 ;D1 2 ;D2 8 ;D3 44 ;D4 282 ;D5 1814 ;D6 11848 -4k3/4p3/4K3/8/8/8/8/8 b - - 0 1 ;D1 2 ;D2 8 ;D3 44 ;D4 282 ;D5 1814 ;D6 11848 -8/8/7k/7p/7P/7K/8/8 w - - 0 1 ;D1 3 ;D2 9 ;D3 57 ;D4 360 ;D5 1969 ;D6 10724 -8/8/k7/p7/P7/K7/8/8 w - - 0 1 ;D1 3 ;D2 9 ;D3 57 ;D4 360 ;D5 1969 ;D6 10724 -8/8/3k4/3p4/3P4/3K4/8/8 w - - 0 1 ;D1 5 ;D2 25 ;D3 180 ;D4 1294 ;D5 8296 ;D6 53138 -8/3k4/3p4/8/3P4/3K4/8/8 w - - 0 1 ;D1 8 ;D2 61 ;D3 483 ;D4 3213 ;D5 23599 ;D6 157093 -8/8/3k4/3p4/8/3P4/3K4/8 w - - 0 1 ;D1 8 ;D2 61 ;D3 411 ;D4 3213 ;D5 21637 ;D6 158065 -k7/8/3p4/8/3P4/8/8/7K w - - 0 1 ;D1 4 ;D2 15 ;D3 90 ;D4 534 ;D5 3450 ;D6 20960 -8/8/7k/7p/7P/7K/8/8 b - - 0 1 ;D1 3 ;D2 9 ;D3 57 ;D4 360 ;D5 1969 ;D6 10724 -8/8/k7/p7/P7/K7/8/8 b - - 0 1 ;D1 3 ;D2 9 ;D3 57 ;D4 360 ;D5 1969 ;D6 10724 -8/8/3k4/3p4/3P4/3K4/8/8 b - - 0 1 ;D1 5 ;D2 25 ;D3 180 ;D4 1294 ;D5 8296 ;D6 53138 -8/3k4/3p4/8/3P4/3K4/8/8 b - - 0 1 ;D1 8 ;D2 61 ;D3 411 ;D4 3213 ;D5 21637 ;D6 158065 -8/8/3k4/3p4/8/3P4/3K4/8 b - - 0 1 ;D1 8 ;D2 61 ;D3 483 ;D4 3213 ;D5 23599 ;D6 157093 -k7/8/3p4/8/3P4/8/8/7K b - - 0 1 ;D1 4 ;D2 15 ;D3 89 ;D4 537 ;D5 3309 ;D6 21104 -7k/3p4/8/8/3P4/8/8/K7 w - - 0 1 ;D1 4 ;D2 19 ;D3 117 ;D4 720 ;D5 4661 ;D6 32191 -7k/8/8/3p4/8/8/3P4/K7 w - - 0 1 ;D1 5 ;D2 19 ;D3 116 ;D4 716 ;D5 4786 ;D6 30980 -k7/8/8/7p/6P1/8/8/K7 w - - 0 1 ;D1 5 ;D2 22 ;D3 139 ;D4 877 ;D5 6112 ;D6 41874 -k7/8/7p/8/8/6P1/8/K7 w - - 0 1 ;D1 4 ;D2 16 ;D3 101 ;D4 637 ;D5 4354 ;D6 29679 -k7/8/8/6p1/7P/8/8/K7 w - - 0 1 ;D1 5 ;D2 22 ;D3 139 ;D4 877 ;D5 6112 ;D6 41874 -k7/8/6p1/8/8/7P/8/K7 w - - 0 1 ;D1 4 ;D2 16 ;D3 101 ;D4 637 ;D5 4354 ;D6 29679 -k7/8/8/3p4/4p3/8/8/7K w - - 0 1 ;D1 3 ;D2 15 ;D3 84 ;D4 573 ;D5 3013 ;D6 22886 -k7/8/3p4/8/8/4P3/8/7K w - - 0 1 ;D1 4 ;D2 16 ;D3 101 ;D4 637 ;D5 4271 ;D6 28662 -7k/3p4/8/8/3P4/8/8/K7 b - - 0 1 ;D1 5 ;D2 19 ;D3 117 ;D4 720 ;D5 5014 ;D6 32167 -7k/8/8/3p4/8/8/3P4/K7 b - - 0 1 ;D1 4 ;D2 19 ;D3 117 ;D4 712 ;D5 4658 ;D6 30749 -k7/8/8/7p/6P1/8/8/K7 b - - 0 1 ;D1 5 ;D2 22 ;D3 139 ;D4 877 ;D5 6112 ;D6 41874 -k7/8/7p/8/8/6P1/8/K7 b - - 0 1 ;D1 4 ;D2 16 ;D3 101 ;D4 637 ;D5 4354 ;D6 29679 -k7/8/8/6p1/7P/8/8/K7 b - - 0 1 ;D1 5 ;D2 22 ;D3 139 ;D4 877 ;D5 6112 ;D6 41874 -k7/8/6p1/8/8/7P/8/K7 b - - 0 1 ;D1 4 ;D2 16 ;D3 101 ;D4 637 ;D5 4354 ;D6 29679 -k7/8/8/3p4/4p3/8/8/7K b - - 0 1 ;D1 5 ;D2 15 ;D3 102 ;D4 569 ;D5 4337 ;D6 22579 -k7/8/3p4/8/8/4P3/8/7K b - - 0 1 ;D1 4 ;D2 16 ;D3 101 ;D4 637 ;D5 4271 ;D6 28662 -7k/8/8/p7/1P6/8/8/7K w - - 0 1 ;D1 5 ;D2 22 ;D3 139 ;D4 877 ;D5 6112 ;D6 41874 -7k/8/p7/8/8/1P6/8/7K w - - 0 1 ;D1 4 ;D2 16 ;D3 101 ;D4 637 ;D5 4354 ;D6 29679 -7k/8/8/1p6/P7/8/8/7K w - - 0 1 ;D1 5 ;D2 22 ;D3 139 ;D4 877 ;D5 6112 ;D6 41874 -7k/8/1p6/8/8/P7/8/7K w - - 0 1 ;D1 4 ;D2 16 ;D3 101 ;D4 637 ;D5 4354 ;D6 29679 -k7/7p/8/8/8/8/6P1/K7 w - - 0 1 ;D1 5 ;D2 25 ;D3 161 ;D4 1035 ;D5 7574 ;D6 55338 -k7/6p1/8/8/8/8/7P/K7 w - - 0 1 ;D1 5 ;D2 25 ;D3 161 ;D4 1035 ;D5 7574 ;D6 55338 -3k4/3pp3/8/8/8/8/3PP3/3K4 w - - 0 1 ;D1 7 ;D2 49 ;D3 378 ;D4 2902 ;D5 24122 ;D6 199002 -7k/8/8/p7/1P6/8/8/7K b - - 0 1 ;D1 5 ;D2 22 ;D3 139 ;D4 877 ;D5 6112 ;D6 41874 -7k/8/p7/8/8/1P6/8/7K b - - 0 1 ;D1 4 ;D2 16 ;D3 101 ;D4 637 ;D5 4354 ;D6 29679 -7k/8/8/1p6/P7/8/8/7K b - - 0 1 ;D1 5 ;D2 22 ;D3 139 ;D4 877 ;D5 6112 ;D6 41874 -7k/8/1p6/8/8/P7/8/7K b - - 0 1 ;D1 4 ;D2 16 ;D3 101 ;D4 637 ;D5 4354 ;D6 29679 -k7/7p/8/8/8/8/6P1/K7 b - - 0 1 ;D1 5 ;D2 25 ;D3 161 ;D4 1035 ;D5 7574 ;D6 55338 -k7/6p1/8/8/8/8/7P/K7 b - - 0 1 ;D1 5 ;D2 25 ;D3 161 ;D4 1035 ;D5 7574 ;D6 55338 -3k4/3pp3/8/8/8/8/3PP3/3K4 b - - 0 1 ;D1 7 ;D2 49 ;D3 378 ;D4 2902 ;D5 24122 ;D6 199002 -8/Pk6/8/8/8/8/6Kp/8 w - - 0 1 ;D1 11 ;D2 97 ;D3 887 ;D4 8048 ;D5 90606 ;D6 1030499 -n1n5/1Pk5/8/8/8/8/5Kp1/5N1N w - - 0 1 ;D1 24 ;D2 421 ;D3 7421 ;D4 124608 ;D5 2193768 ;D6 37665329 -8/PPPk4/8/8/8/8/4Kppp/8 w - - 0 1 ;D1 18 ;D2 270 ;D3 4699 ;D4 79355 ;D5 1533145 ;D6 28859283 -n1n5/PPPk4/8/8/8/8/4Kppp/5N1N w - - 0 1 ;D1 24 ;D2 496 ;D3 9483 ;D4 182838 ;D5 3605103 ;D6 71179139 -8/Pk6/8/8/8/8/6Kp/8 b - - 0 1 ;D1 11 ;D2 97 ;D3 887 ;D4 8048 ;D5 90606 ;D6 1030499 -n1n5/1Pk5/8/8/8/8/5Kp1/5N1N b - - 0 1 ;D1 24 ;D2 421 ;D3 7421 ;D4 124608 ;D5 2193768 ;D6 37665329 -8/PPPk4/8/8/8/8/4Kppp/8 b - - 0 1 ;D1 18 ;D2 270 ;D3 4699 ;D4 79355 ;D5 1533145 ;D6 28859283 -n1n5/PPPk4/8/8/8/8/4Kppp/5N1N b - - 0 1 ;D1 24 ;D2 496 ;D3 9483 ;D4 182838 ;D5 3605103 ;D6 71179139 diff --git a/test/polyglot/Polyglot.hs b/test/polyglot/Polyglot.hs deleted file mode 100644 index a5edb7c..0000000 --- a/test/polyglot/Polyglot.hs +++ /dev/null @@ -1,17 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} -module Main where - -import Game.Chess -import Game.Chess.Polyglot -import Test.HUnit - -tests = test - [ "t1" ~: "start position" ~: hashPosition startpos ~=? 0x463b96181691fc9c - , "t2" ~: "after e4" ~: hashPosition "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1" ~=? 0x823c9b50fd114196 - , "t3" ~: "after e4 d5" ~: hashPosition "rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 2" ~=? 0x0756b94461c50fb0 - , "t4" ~: "after e4 d5 e5" ~: hashPosition "rnbqkbnr/ppp1pppp/8/3pP3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2" ~=? 0x662fafb965db29d4 - , "t5" ~: "after e4 d5 e5 f5" ~: hashPosition "rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPP1PPP/RNBQKBNR w KQkq f6 0 3" ~=? 0x22a48b5a8e47ff78 - , "t6" ~: "after e4 d5 e5 f5 Ke2" ~: hashPosition "rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPPKPPP/RNBQ1BNR b kq - 0 3" ~=? 0x652a607ca3f242c1 - ] - -main = runTestTTAndExit tests diff --git a/test/tests.hs b/test/tests.hs new file mode 100644 index 0000000..ac9d4e8 --- /dev/null +++ b/test/tests.hs @@ -0,0 +1,161 @@ +{-# LANGUAGE OverloadedStrings #-} +import Data.Maybe (fromJust) +import qualified Data.Vector.Unboxed as Vector +import Game.Chess +import Game.Chess.Polyglot +import Test.Tasty +import Test.Tasty.HUnit + +main :: IO () +main = defaultMain $ testGroup "Tests" [perftSuite, polyglot] + +polyglot :: TestTree +polyglot = testGroup "Polyglot" [ + testCase "start position" $ hashPosition startpos @?= 0x463b96181691fc9c, + testCase "after e4" $ hashPosition "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1" @?= 0x823c9b50fd114196, + testCase "after e4 d5" $ hashPosition "rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 2" @?= 0x0756b94461c50fb0, + testCase "after e4 d5 e5" $ hashPosition "rnbqkbnr/ppp1pppp/8/3pP3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2" @?= 0x662fafb965db29d4, + testCase "after e4 d5 e5 f5" $ hashPosition "rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPP1PPP/RNBQKBNR w KQkq f6 0 3" @?= 0x22a48b5a8e47ff78, + testCase "after e4 d5 e5 f5 Ke2" $ hashPosition "rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPPKPPP/RNBQ1BNR b kq - 0 3" @?= 0x652a607ca3f242c1 + ] + +perftSuite :: TestTree +perftSuite = testGroup "PerftSuite" $ map f info where + f (fen, ds) = testGroup fen $ map g (zip [1..] ds) where + g (n, d) = testCase ("Depth=" ++ show n ++ ", Nodes=" ++ show d) $ + perft n <$> fromFEN fen @?= Just d + info = [ + ("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", [20, 400, 8902, 197281, 4865609, 119060324]), + ("r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1", [48, 2039, 97862, 4085603, 193690690]), + ("4k3/8/8/8/8/8/8/4K2R w K - 0 1", [15, 66, 1197, 7059, 133987, 764643]), + ("4k3/8/8/8/8/8/8/R3K3 w Q - 0 1", [16, 71, 1287, 7626, 145232, 846648]), + ("4k2r/8/8/8/8/8/8/4K3 w k - 0 1", [5, 75, 459, 8290, 47635, 899442]), + ("r3k3/8/8/8/8/8/8/4K3 w q - 0 1", [5, 80, 493, 8897, 52710, 1001523]), + ("4k3/8/8/8/8/8/8/R3K2R w KQ - 0 1", [26, 112, 3189, 17945, 532933, 2788982]), + ("r3k2r/8/8/8/8/8/8/4K3 w kq - 0 1", [5, 130, 782, 22180, 118882, 3517770]), + ("8/8/8/8/8/8/6k1/4K2R w K - 0 1", [12, 38, 564, 2219, 37735, 185867]), + ("8/8/8/8/8/8/1k6/R3K3 w Q - 0 1", [15, 65, 1018, 4573, 80619, 413018]), + ("4k2r/6K1/8/8/8/8/8/8 w k - 0 1", [3, 32, 134, 2073, 10485, 179869]), + ("r3k3/1K6/8/8/8/8/8/8 w q - 0 1", [4, 49, 243, 3991, 20780, 367724]), + ("r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1", [26, 568, 13744, 314346, 7594526, 179862938]), + ("r3k2r/8/8/8/8/8/8/1R2K2R w Kkq - 0 1", [25, 567, 14095, 328965, 8153719, 195629489]), + ("r3k2r/8/8/8/8/8/8/2R1K2R w Kkq - 0 1", [25, 548, 13502, 312835, 7736373, 184411439]), + ("r3k2r/8/8/8/8/8/8/R3K1R1 w Qkq - 0 1", [25, 547, 13579, 316214, 7878456, 189224276]), + ("1r2k2r/8/8/8/8/8/8/R3K2R w KQk - 0 1", [26, 583, 14252, 334705, 8198901, 198328929]), + ("2r1k2r/8/8/8/8/8/8/R3K2R w KQk - 0 1", [25, 560, 13592, 317324, 7710115, 185959088]), + ("r3k1r1/8/8/8/8/8/8/R3K2R w KQq - 0 1", [25, 560, 13607, 320792, 7848606, 190755813]), + ("4k3/8/8/8/8/8/8/4K2R b K - 0 1", [5, 75, 459, 8290, 47635, 899442]), + ("4k3/8/8/8/8/8/8/R3K3 b Q - 0 1", [5, 80, 493, 8897, 52710, 1001523]), + ("4k2r/8/8/8/8/8/8/4K3 b k - 0 1", [15, 66, 1197, 7059, 133987, 764643]), + ("r3k3/8/8/8/8/8/8/4K3 b q - 0 1", [16, 71, 1287, 7626, 145232, 846648]), + ("4k3/8/8/8/8/8/8/R3K2R b KQ - 0 1", [5, 130, 782, 22180, 118882, 3517770]), + ("r3k2r/8/8/8/8/8/8/4K3 b kq - 0 1", [26, 112, 3189, 17945, 532933, 2788982]), + ("8/8/8/8/8/8/6k1/4K2R b K - 0 1", [3, 32, 134, 2073, 10485, 179869]), + ("8/8/8/8/8/8/1k6/R3K3 b Q - 0 1", [4, 49, 243, 3991, 20780, 367724]), + ("4k2r/6K1/8/8/8/8/8/8 b k - 0 1", [12, 38, 564, 2219, 37735, 185867]), + ("r3k3/1K6/8/8/8/8/8/8 b q - 0 1", [15, 65, 1018, 4573, 80619, 413018]), + ("r3k2r/8/8/8/8/8/8/R3K2R b KQkq - 0 1", [26, 568, 13744, 314346, 7594526, 179862938]), + ("r3k2r/8/8/8/8/8/8/1R2K2R b Kkq - 0 1", [26, 583, 14252, 334705, 8198901, 198328929]), + ("r3k2r/8/8/8/8/8/8/2R1K2R b Kkq - 0 1", [25, 560, 13592, 317324, 7710115, 185959088]), + ("r3k2r/8/8/8/8/8/8/R3K1R1 b Qkq - 0 1", [25, 560, 13607, 320792, 7848606, 190755813]), + ("1r2k2r/8/8/8/8/8/8/R3K2R b KQk - 0 1", [25, 567, 14095, 328965, 8153719, 195629489]), + ("2r1k2r/8/8/8/8/8/8/R3K2R b KQk - 0 1", [25, 548, 13502, 312835, 7736373, 184411439]), + ("r3k1r1/8/8/8/8/8/8/R3K2R b KQq - 0 1", [25, 547, 13579, 316214, 7878456, 189224276]), + ("8/1n4N1/2k5/8/8/5K2/1N4n1/8 w - - 0 1", [14, 195, 2760, 38675, 570726, 8107539]), + ("8/1k6/8/5N2/8/4n3/8/2K5 w - - 0 1", [11, 156, 1636, 20534, 223507, 2594412]), + ("8/8/4k3/3Nn3/3nN3/4K3/8/8 w - - 0 1", [19, 289, 4442, 73584, 1198299, 19870403]), + ("K7/8/2n5/1n6/8/8/8/k6N w - - 0 1", [3, 51, 345, 5301, 38348, 588695]), + ("k7/8/2N5/1N6/8/8/8/K6n w - - 0 1", [17, 54, 835, 5910, 92250, 688780]), + ("8/1n4N1/2k5/8/8/5K2/1N4n1/8 b - - 0 1", [15, 193, 2816, 40039, 582642, 8503277]), + ("8/1k6/8/5N2/8/4n3/8/2K5 b - - 0 1", [16, 180, 2290, 24640, 288141, 3147566]), + ("8/8/3K4/3Nn3/3nN3/4k3/8/8 b - - 0 1", [4, 68, 1118, 16199, 281190, 4405103]), + ("K7/8/2n5/1n6/8/8/8/k6N b - - 0 1", [17, 54, 835, 5910, 92250, 688780]), + ("k7/8/2N5/1N6/8/8/8/K6n b - - 0 1", [3, 51, 345, 5301, 38348, 588695]), + ("B6b/8/8/8/2K5/4k3/8/b6B w - - 0 1", [17, 278, 4607, 76778, 1320507, 22823890]), + ("8/8/1B6/7b/7k/8/2B1b3/7K w - - 0 1", [21, 316, 5744, 93338, 1713368, 28861171]), + ("k7/B7/1B6/1B6/8/8/8/K6b w - - 0 1", [21, 144, 3242, 32955, 787524, 7881673]), + ("K7/b7/1b6/1b6/8/8/8/k6B w - - 0 1", [7, 143, 1416, 31787, 310862, 7382896]), + ("B6b/8/8/8/2K5/5k2/8/b6B b - - 0 1", [6, 106, 1829, 31151, 530585, 9250746]), + ("8/8/1B6/7b/7k/8/2B1b3/7K b - - 0 1", [17, 309, 5133, 93603, 1591064, 29027891]), + ("k7/B7/1B6/1B6/8/8/8/K6b b - - 0 1", [7, 143, 1416, 31787, 310862, 7382896]), + ("K7/b7/1b6/1b6/8/8/8/k6B b - - 0 1", [21, 144, 3242, 32955, 787524, 7881673]), + ("7k/RR6/8/8/8/8/rr6/7K w - - 0 1", [19, 275, 5300, 104342, 2161211, 44956585]), + ("R6r/8/8/2K5/5k2/8/8/r6R w - - 0 1", [36, 1027, 29215, 771461, 20506480, 525169084]), + ("7k/RR6/8/8/8/8/rr6/7K b - - 0 1", [19, 275, 5300, 104342, 2161211, 44956585]), + ("R6r/8/8/2K5/5k2/8/8/r6R b - - 0 1", [36, 1027, 29227, 771368, 20521342, 524966748]), + ("6kq/8/8/8/8/8/8/7K w - - 0 1", [2, 36, 143, 3637, 14893, 391507]), + ("6KQ/8/8/8/8/8/8/7k b - - 0 1", [2, 36, 143, 3637, 14893, 391507]), + ("K7/8/8/3Q4/4q3/8/8/7k w - - 0 1", [6, 35, 495, 8349, 166741, 3370175]), + ("6qk/8/8/8/8/8/8/7K b - - 0 1", [22, 43, 1015, 4167, 105749, 419369]), + ("6KQ/8/8/8/8/8/8/7k b - - 0 1", [2, 36, 143, 3637, 14893, 391507]), + ("K7/8/8/3Q4/4q3/8/8/7k b - - 0 1", [6, 35, 495, 8349, 166741, 3370175]), + ("8/8/8/8/8/K7/P7/k7 w - - 0 1", [3, 7, 43, 199, 1347, 6249]), + ("8/8/8/8/8/7K/7P/7k w - - 0 1", [3, 7, 43, 199, 1347, 6249]), + ("K7/p7/k7/8/8/8/8/8 w - - 0 1", [1, 3, 12, 80, 342, 2343]), + ("7K/7p/7k/8/8/8/8/8 w - - 0 1", [1, 3, 12, 80, 342, 2343]), + ("8/2k1p3/3pP3/3P2K1/8/8/8/8 w - - 0 1", [7, 35, 210, 1091, 7028, 34834]), + ("8/8/8/8/8/K7/P7/k7 b - - 0 1", [1, 3, 12, 80, 342, 2343]), + ("8/8/8/8/8/7K/7P/7k b - - 0 1", [1, 3, 12, 80, 342, 2343]), + ("K7/p7/k7/8/8/8/8/8 b - - 0 1", [3, 7, 43, 199, 1347, 6249]), + ("7K/7p/7k/8/8/8/8/8 b - - 0 1", [3, 7, 43, 199, 1347, 6249]), + ("8/2k1p3/3pP3/3P2K1/8/8/8/8 b - - 0 1", [5, 35, 182, 1091, 5408, 34822]), + ("8/8/8/8/8/4k3/4P3/4K3 w - - 0 1", [2, 8, 44, 282, 1814, 11848]), + ("4k3/4p3/4K3/8/8/8/8/8 b - - 0 1", [2, 8, 44, 282, 1814, 11848]), + ("8/8/7k/7p/7P/7K/8/8 w - - 0 1", [3, 9, 57, 360, 1969, 10724]), + ("8/8/k7/p7/P7/K7/8/8 w - - 0 1", [3, 9, 57, 360, 1969, 10724]), + ("8/8/3k4/3p4/3P4/3K4/8/8 w - - 0 1", [5, 25, 180, 1294, 8296, 53138]), + ("8/3k4/3p4/8/3P4/3K4/8/8 w - - 0 1", [8, 61, 483, 3213, 23599, 157093]), + ("8/8/3k4/3p4/8/3P4/3K4/8 w - - 0 1", [8, 61, 411, 3213, 21637, 158065]), + ("k7/8/3p4/8/3P4/8/8/7K w - - 0 1", [4, 15, 90, 534, 3450, 20960]), + ("8/8/7k/7p/7P/7K/8/8 b - - 0 1", [3, 9, 57, 360, 1969, 10724]), + ("8/8/k7/p7/P7/K7/8/8 b - - 0 1", [3, 9, 57, 360, 1969, 10724]), + ("8/8/3k4/3p4/3P4/3K4/8/8 b - - 0 1", [5, 25, 180, 1294, 8296, 53138]), + ("8/3k4/3p4/8/3P4/3K4/8/8 b - - 0 1", [8, 61, 411, 3213, 21637, 158065]), + ("8/8/3k4/3p4/8/3P4/3K4/8 b - - 0 1", [8, 61, 483, 3213, 23599, 157093]), + ("k7/8/3p4/8/3P4/8/8/7K b - - 0 1", [4, 15, 89, 537, 3309, 21104]), + ("7k/3p4/8/8/3P4/8/8/K7 w - - 0 1", [4, 19, 117, 720, 4661, 32191]), + ("7k/8/8/3p4/8/8/3P4/K7 w - - 0 1", [5, 19, 116, 716, 4786, 30980]), + ("k7/8/8/7p/6P1/8/8/K7 w - - 0 1", [5, 22, 139, 877, 6112, 41874]), + ("k7/8/7p/8/8/6P1/8/K7 w - - 0 1", [4, 16, 101, 637, 4354, 29679]), + ("k7/8/8/6p1/7P/8/8/K7 w - - 0 1", [5, 22, 139, 877, 6112, 41874]), + ("k7/8/6p1/8/8/7P/8/K7 w - - 0 1", [4, 16, 101, 637, 4354, 29679]), + ("k7/8/8/3p4/4p3/8/8/7K w - - 0 1", [3, 15, 84, 573, 3013, 22886]), + ("k7/8/3p4/8/8/4P3/8/7K w - - 0 1", [4, 16, 101, 637, 4271, 28662]), + ("7k/3p4/8/8/3P4/8/8/K7 b - - 0 1", [5, 19, 117, 720, 5014, 32167]), + ("7k/8/8/3p4/8/8/3P4/K7 b - - 0 1", [4, 19, 117, 712, 4658, 30749]), + ("k7/8/8/7p/6P1/8/8/K7 b - - 0 1", [5, 22, 139, 877, 6112, 41874]), + ("k7/8/7p/8/8/6P1/8/K7 b - - 0 1", [4, 16, 101, 637, 4354, 29679]), + ("k7/8/8/6p1/7P/8/8/K7 b - - 0 1", [5, 22, 139, 877, 6112, 41874]), + ("k7/8/6p1/8/8/7P/8/K7 b - - 0 1", [4, 16, 101, 637, 4354, 29679]), + ("k7/8/8/3p4/4p3/8/8/7K b - - 0 1", [5, 15, 102, 569, 4337, 22579]), + ("k7/8/3p4/8/8/4P3/8/7K b - - 0 1", [4, 16, 101, 637, 4271, 28662]), + ("7k/8/8/p7/1P6/8/8/7K w - - 0 1", [5, 22, 139, 877, 6112, 41874]), + ("7k/8/p7/8/8/1P6/8/7K w - - 0 1", [4, 16, 101, 637, 4354, 29679]), + ("7k/8/8/1p6/P7/8/8/7K w - - 0 1", [5, 22, 139, 877, 6112, 41874]), + ("7k/8/1p6/8/8/P7/8/7K w - - 0 1", [4, 16, 101, 637, 4354, 29679]), + ("k7/7p/8/8/8/8/6P1/K7 w - - 0 1", [5, 25, 161, 1035, 7574, 55338]), + ("k7/6p1/8/8/8/8/7P/K7 w - - 0 1", [5, 25, 161, 1035, 7574, 55338]), + ("3k4/3pp3/8/8/8/8/3PP3/3K4 w - - 0 1", [7, 49, 378, 2902, 24122, 199002]), + ("7k/8/8/p7/1P6/8/8/7K b - - 0 1", [5, 22, 139, 877, 6112, 41874]), + ("7k/8/p7/8/8/1P6/8/7K b - - 0 1", [4, 16, 101, 637, 4354, 29679]), + ("7k/8/8/1p6/P7/8/8/7K b - - 0 1", [5, 22, 139, 877, 6112, 41874]), + ("7k/8/1p6/8/8/P7/8/7K b - - 0 1", [4, 16, 101, 637, 4354, 29679]), + ("k7/7p/8/8/8/8/6P1/K7 b - - 0 1", [5, 25, 161, 1035, 7574, 55338]), + ("k7/6p1/8/8/8/8/7P/K7 b - - 0 1", [5, 25, 161, 1035, 7574, 55338]), + ("3k4/3pp3/8/8/8/8/3PP3/3K4 b - - 0 1", [7, 49, 378, 2902, 24122, 199002]), + ("8/Pk6/8/8/8/8/6Kp/8 w - - 0 1", [11, 97, 887, 8048, 90606, 1030499]), + ("n1n5/1Pk5/8/8/8/8/5Kp1/5N1N w - - 0 1", [24, 421, 7421, 124608, 2193768, 37665329]), + ("8/PPPk4/8/8/8/8/4Kppp/8 w - - 0 1", [18, 270, 4699, 79355, 1533145, 28859283]), + ("n1n5/PPPk4/8/8/8/8/4Kppp/5N1N w - - 0 1", [24, 496, 9483, 182838, 3605103, 71179139]), + ("8/Pk6/8/8/8/8/6Kp/8 b - - 0 1", [11, 97, 887, 8048, 90606, 1030499]), + ("n1n5/1Pk5/8/8/8/8/5Kp1/5N1N b - - 0 1", [24, 421, 7421, 124608, 2193768, 37665329]), + ("8/PPPk4/8/8/8/8/4Kppp/8 b - - 0 1", [18, 270, 4699, 79355, 1533145, 28859283]), + ("n1n5/PPPk4/8/8/8/8/4Kppp/5N1N b - - 0 1", [24, 496, 9483, 182838, 3605103, 71179139]) + ] + +type Depth = Int +type Nodes = Int + +perft :: Depth -> Position -> Nodes +perft 1 p = Vector.length $ legalPlies' p +perft n p = Vector.sum $ Vector.map (perft (pred n) . unsafeDoPly p) (legalPlies' p)