[project @ 2002-08-29 14:46:50 by simonpj]
authorsimonpj <unknown>
Thu, 29 Aug 2002 14:46:50 +0000 (14:46 +0000)
committersimonpj <unknown>
Thu, 29 Aug 2002 14:46:50 +0000 (14:46 +0000)
Add chess mate test

25 files changed:
spectral/mate/Board.hs [new file with mode: 0644]
spectral/mate/Main.hs [new file with mode: 0644]
spectral/mate/Makefile [new file with mode: 0644]
spectral/mate/Move.hs [new file with mode: 0644]
spectral/mate/Problem.hs [new file with mode: 0644]
spectral/mate/Solution.hs [new file with mode: 0644]
spectral/mate/ellerman.prob [new file with mode: 0644]
spectral/mate/ellerman.soln [new file with mode: 0644]
spectral/mate/fridlizius.prob [new file with mode: 0644]
spectral/mate/fridlizius.soln [new file with mode: 0644]
spectral/mate/heathcote3.prob [new file with mode: 0644]
spectral/mate/heathcote3.soln [new file with mode: 0644]
spectral/mate/holzhausen.prob [new file with mode: 0644]
spectral/mate/holzhausen.soln [new file with mode: 0644]
spectral/mate/kidson.prob [new file with mode: 0644]
spectral/mate/kohtz.prob [new file with mode: 0644]
spectral/mate/kohtz.soln [new file with mode: 0644]
spectral/mate/marin.prob [new file with mode: 0644]
spectral/mate/marin.soln [new file with mode: 0644]
spectral/mate/shinkman.prob [new file with mode: 0644]
spectral/mate/shinkman.soln [new file with mode: 0644]
spectral/mate/simple.prob [new file with mode: 0644]
spectral/mate/simple.soln [new file with mode: 0644]
spectral/mate/wurzburg.prob [new file with mode: 0644]
spectral/mate/wurzburg.soln [new file with mode: 0644]

diff --git a/spectral/mate/Board.hs b/spectral/mate/Board.hs
new file mode 100644 (file)
index 0000000..e320644
--- /dev/null
@@ -0,0 +1,98 @@
+module Board(Kind(..), Colour(..), Piece, Square, Board, \r
+               showBoard, showPiece, showSquare,\r
+               emptyBoard, pieceAt, rmPieceAt, putPieceAt,\r
+               emptyAtAll, kingSquare, forcesColoured,\r
+               colourOf, kindOf, opponent, onboard)  where\r
+\r
+import Char\r
+\r
+data Kind = King | Queen | Rook | Bishop | Knight | Pawn deriving (Eq,Ord)\r
+\r
+data Colour = Black | White deriving (Eq,Ord,Show,Read)\r
+\r
+type Piece = (Colour,Kind)\r
+type Square = (Int,Int)\r
+\r
+data Board = Board\r
+               [(Kind,Square)] -- white\r
+               [(Kind,Square)] -- black\r
+\r
+showBoard bd =\r
+       unlines (map showRank (reverse [1..8]))\r
+       where\r
+       showRank r = foldr consFile [] [1..8]\r
+               where\r
+               consFile f s =\r
+                       case pieceAt bd (f,r) of\r
+                       Nothing -> " -" ++ s\r
+                       Just p  -> ' ': pieceToChar p : s\r
+\r
+pieceToChar :: Piece -> Char\r
+pieceToChar (Black,k) = kindToChar k\r
+pieceToChar (White,k) = toLower (kindToChar k)\r
+\r
+kindToChar :: Kind -> Char\r
+kindToChar k =\r
+       case k of\r
+       King    -> 'K'\r
+       Queen   -> 'Q'\r
+       Rook    -> 'R'\r
+       Bishop  -> 'B'\r
+       Knight  -> 'N'\r
+       Pawn    -> 'P'\r
+\r
+showPiece :: Piece -> String\r
+showPiece (c,k) = [kindToChar k]\r
+\r
+showSquare :: Colour -> Square -> String\r
+showSquare c (x,y) =\r
+       ["QR","QN","QB","Q","K","KB","KN","KR"] !! (x-1) ++\r
+       show (  case c of\r
+               Black -> 9-y\r
+               White -> y )\r
+\r
+pieceAt :: Board -> Square -> Maybe Piece\r
+pieceAt (Board wkss bkss) sq =\r
+        pieceAtWith White (pieceAtWith Black Nothing bkss) wkss\r
+       where\r
+       pieceAtWith c n [] = n\r
+       pieceAtWith c n ((k,s):xs) = if s==sq then Just (c,k) else pieceAtWith c n xs\r
+\r
+emptyAtAll :: Board -> (Square->Bool) -> Bool\r
+emptyAtAll (Board wkss bkss) e =\r
+       emptyAtAllAnd (emptyAtAllAnd True bkss) wkss\r
+       where\r
+       emptyAtAllAnd b []         = b\r
+       emptyAtAllAnd b ((_,s):xs) = not (e s) && emptyAtAllAnd b xs\r
+\r
+rmPieceAt White sq (Board wkss bkss) = Board (rPa sq wkss) bkss\r
+rmPieceAt Black sq (Board wkss bkss) = Board wkss (rPa sq bkss)\r
+\r
+rPa sq (ks@(k,s):kss) = if s==sq then kss else ks : rPa sq kss\r
+\r
+putPieceAt sq (White,k) (Board wkss bkss) = Board ((k,sq):wkss) bkss\r
+putPieceAt sq (Black,k) (Board wkss bkss) = Board wkss ((k,sq):bkss)\r
+\r
+kingSquare :: Colour -> Board -> Square\r
+kingSquare White (Board kss _) = kSq kss\r
+kingSquare Black (Board _ kss) = kSq kss\r
+\r
+kSq ((King,s):_)   = s\r
+kSq (       _:kss) = kSq kss \r
+\r
+opponent Black = White\r
+opponent White = Black\r
+\r
+colourOf :: Piece -> Colour\r
+colourOf (c,_) = c\r
+\r
+kindOf :: Piece -> Kind\r
+kindOf (_,k) = k\r
+\r
+onboard :: Square -> Bool\r
+onboard (p,q) = 1<=p && p<=8 && 1<=q && q<=8\r
+\r
+forcesColoured White (Board kss _) = kss\r
+forcesColoured Black (Board _ kss) = kss\r
+\r
+emptyBoard = Board [] []\r
diff --git a/spectral/mate/Main.hs b/spectral/mate/Main.hs
new file mode 100644 (file)
index 0000000..10933c4
--- /dev/null
@@ -0,0 +1,23 @@
+module Main(main) where
+import Board
+import Solution
+import Problem
+import System.Environment( getArgs )
+
+main = do { files <- getArgs ;
+           mapM mateInN files }
+
+mateInN file
+  = do { putStrLn "" ;
+        putStrLn ("File: " ++ file) ;
+        input <- readFile file ;
+        let {  (bd, (c,n)) = readProblem input ;
+               result      = showBoard bd ++ 
+                               "\n" ++
+                               show c ++ " to move and mate in " ++ show n ++ "\n" ++
+                               "\n" ++
+                               solve bd c n
+               
+        } ;
+        putStr result  }
+        
diff --git a/spectral/mate/Makefile b/spectral/mate/Makefile
new file mode 100644 (file)
index 0000000..4775ac0
--- /dev/null
@@ -0,0 +1,13 @@
+TOP = ../..
+include $(TOP)/mk/boilerplate.mk
+
+# Arguments for the test program
+PROG_ARGS = holzhausen.prob
+
+#      Other problems
+# ellerman.prob heathcote3.prob kidson.prob marin.prob \
+#              simple.prob fridlizius.prob holzhausen.prob \
+#              kohtz.prob shinkman.prob wurzburg.prob
+
+include $(TOP)/mk/target.mk
+
diff --git a/spectral/mate/Move.hs b/spectral/mate/Move.hs
new file mode 100644 (file)
index 0000000..ff12914
--- /dev/null
@@ -0,0 +1,174 @@
+module Move (Move(..), MoveInFull(..), showMoveInFull, showMoves, moveDetailsFor, kingincheck) where\r
+\r
+import Board\r
+\r
+data Move = Move\r
+               Square          -- to here\r
+               (Maybe Piece)   -- capturing this\r
+               (Maybe Piece)   -- gaining promotion to this\r
+               deriving (Eq,Ord)\r
+\r
+data MoveInFull = MoveInFull Piece Square Move\r
+                  deriving (Eq, Ord)\r
+\r
+showMoveInFull :: MoveInFull -> String\r
+showMoveInFull = showMove True\r
+\r
+showMove withPiece (MoveInFull p@(c,k) sq (Move sq' mcp mpp)) =\r
+       let capt = mcp /= Nothing\r
+           prom = mpp /= Nothing in\r
+       ( if withPiece then \r
+               showPiece p ++\r
+               (if k==King || k==Pawn && not (capt||prom) then ""\r
+               else "/" ++ showSquare c sq)\r
+         else "" ) ++\r
+       (maybe "-" (\cp -> "x" ++ showPiece cp ++ "/") mcp) ++\r
+       showSquare c sq' ++\r
+       (maybe "" (\pp -> "(" ++ showPiece pp ++ ")") mpp)\r
+\r
+showMoves (mif:mifs) = showMoveInFull mif ++ showMovesAfter mif mifs\r
+\r
+showMovesAfter _ [] = ""\r
+showMovesAfter (MoveInFull p' sq' _) (mif@(MoveInFull p sq _):mifs) =\r
+       ", " ++ showMove (p/=p' || sq/=sq') mif ++ showMovesAfter mif mifs\r
+\r
+moveDetailsFor :: Colour -> Board -> [(MoveInFull,Board)]\r
+moveDetailsFor c bd =\r
+       foldr ( \ksq ms ->\r
+               foldr (\rm ms' -> maybe id (:) (tryMove c ksq rm bd) ms')\r
+                   ms\r
+                   (rawmoves c ksq bd) )\r
+             [] \r
+              (forcesColoured c bd)\r
+\r
+tryMove :: Colour -> (Kind,Square) -> Move -> Board -> Maybe (MoveInFull,Board)\r
+tryMove c ksq@(k,sq) m@(Move sq' mcp mpp) bd =\r
+       if not (kingincheck c bd2) then Just (MoveInFull p sq m, bd2)\r
+       else Nothing\r
+       where\r
+       p   =   (c,k)\r
+       bd1 =   rmPieceAt c sq bd\r
+       p'  =   maybe p id mpp\r
+       bd2 =   maybe (putPieceAt sq' p' bd1)\r
+                     (const (putPieceAt sq' p' (rmPieceAt (opponent c) sq' bd1)))\r
+                     mcp\r
\r
+-- NB raw move = might illegally leave the king in check.\r
+rawmoves :: Colour -> (Kind,Square) -> Board -> [Move]\r
+rawmoves c (k,sq) bd = m c sq bd\r
+       where\r
+        m = case k of\r
+           King   -> kingmoves\r
+           Queen  -> queenmoves\r
+           Rook   -> rookmoves\r
+           Bishop -> bishopmoves\r
+           Knight -> knightmoves\r
+           Pawn   -> pawnmoves\r
+\r
+bishopmoves :: Colour -> Square -> Board -> [Move]\r
+bishopmoves c sq bd =\r
+       ( moveLine bd c sq (\(x,y) -> (x-1,y+1)) $\r
+         moveLine bd c sq (\(x,y) -> (x+1,y+1)) $\r
+         moveLine bd c sq (\(x,y) -> (x-1,y-1)) $\r
+         moveLine bd c sq (\(x,y) -> (x+1,y-1)) id\r
+        ) []\r
+\r
+rookmoves :: Colour -> Square -> Board -> [Move]\r
+rookmoves c sq bd =\r
+       ( moveLine bd c sq (\(x,y) -> (x-1,y)) $\r
+         moveLine bd c sq (\(x,y) -> (x+1,y)) $\r
+         moveLine bd c sq (\(x,y) -> (x,y-1)) $\r
+         moveLine bd c sq (\(x,y) -> (x,y+1)) id\r
+        ) []\r
+\r
+moveLine :: Board -> Colour -> Square -> (Square->Square) -> ([Move]->a) -> [Move] -> a\r
+moveLine bd c sq inc cont = ml sq\r
+       where\r
+       ml sq ms =\r
+               let sq' = inc sq in\r
+               if onboard sq' then\r
+                       case pieceAt bd sq' of\r
+                       Nothing -> ml sq' (Move sq' Nothing Nothing : ms)\r
+                       Just p' -> if colourOf p' /= c then\r
+                                       cont (Move sq' (Just p') Nothing : ms)\r
+                                   else cont ms\r
+               else cont ms\r
+\r
+kingmoves :: Colour -> Square -> Board -> [Move]\r
+kingmoves c (p,q) bd =\r
+       sift c bd []     [(p-1,q+1), (p,q+1), (p+1,q+1),\r
+                         (p-1,q),            (p+1,q),\r
+                         (p-1,q-1), (p,q-1), (p+1,q-1)]\r
+\r
+knightmoves :: Colour -> Square -> Board -> [Move]\r
+knightmoves c (p,q) bd =\r
+       sift c bd [] [           (p-1,q+2),(p+1,q+2),\r
+                         (p-2,q+1),              (p+2,q+1),\r
+                          (p-2,q-1),             (p+2,q-1),\r
+                                (p-1,q-2),(p+1,q-2) ]\r
+\r
+sift :: Colour -> Board -> [Move] -> [Square] -> [Move]\r
+sift _ _  ms [] = ms\r
+sift c bd ms (sq:sqs) =\r
+       if onboard sq then\r
+               case pieceAt bd sq of\r
+                Nothing -> sift c bd (Move sq Nothing Nothing : ms) sqs\r
+               Just p' -> if colourOf p' == c then sift c bd ms sqs\r
+                           else sift c bd (Move sq (Just p') Nothing : ms) sqs\r
+       else sift c bd ms sqs\r
+\r
+pawnmoves :: Colour -> Square -> Board -> [Move]\r
+pawnmoves c (p,q) bd = movs ++ caps\r
+       where\r
+       movs =  let on1 = (p,q+fwd)\r
+                   on2 = (p,q+2*fwd) in\r
+               if pieceAt bd on1 == Nothing then\r
+                       promote on1 Nothing ++\r
+                       if (q==2 && c==White || q==7 && c==Black) &&\r
+                               pieceAt bd on2 == Nothing then [Move on2 Nothing Nothing] \r
+                       else []\r
+               else []\r
+       caps =  concat [ promote sq mcp\r
+                       | sq <- [(p+1,q+fwd), (p-1,q+fwd)],\r
+                         mcp@(Just p') <- [pieceAt bd sq], colourOf p'/=c ]\r
+       fwd  =  case c of\r
+                       White -> 1\r
+               Black -> -1\r
+       promote sq@(x,y) mcp =  \r
+               if (c==Black && y==1 || c==White && y==8) then\r
+                       map (Move sq mcp . Just)\r
+                           [(c,Queen), (c,Rook), (c,Bishop), (c,Knight)]\r
+               else [Move sq mcp Nothing]\r
+\r
+queenmoves :: Colour -> Square -> Board -> [Move]\r
+queenmoves c sq bd = bishopmoves c sq bd ++ rookmoves c sq bd\r
+\r
+kingincheck :: Colour -> Board -> Bool\r
+kingincheck c bd =\r
+       any givesCheck (forcesColoured (opponent c) bd)\r
+       where\r
+       givesCheck (k,(x,y)) = kthreat k\r
+               where\r
+               kthreat King =\r
+                       abs (x-xk) <= 1 && abs (y-yk) <= 1\r
+               kthreat Queen =\r
+                       kthreat Rook || kthreat Bishop\r
+               kthreat Rook =\r
+                       x==xk &&\r
+                        emptyAtAll bd (\(xe,ye) -> xe==xk && min y yk < ye && ye < max y yk) ||\r
+                       y==yk &&\r
+                        emptyAtAll bd (\(xe,ye) -> ye==yk && min x xk < xe && xe < max x xk)\r
+               kthreat Bishop =\r
+                       x+y==xk+yk &&\r
+                       emptyAtAll bd (\(xe,ye) -> xe+ye==xk+yk && min x xk < xe && xe < max x xk) ||\r
+                       x-y==xk-yk &&\r
+                       emptyAtAll bd (\(xe,ye) -> xe-ye==xk-yk && min x xk < xe && xe < max x xk)\r
+               kthreat Knight =\r
+                       abs (x-xk) == 2 && abs (y-yk) == 1 ||\r
+                       abs (x-xk) == 1 && abs (y-yk) == 2\r
+               kthreat Pawn =\r
+                       abs (x-xk) == 1 &&\r
+                       case c of\r
+                       Black -> yk == y+1\r
+                       White -> yk == y-1\r
+       (xk,yk) = kingSquare c bd\r
diff --git a/spectral/mate/Problem.hs b/spectral/mate/Problem.hs
new file mode 100644 (file)
index 0000000..a71e431
--- /dev/null
@@ -0,0 +1,44 @@
+module Problem where\r
+\r
+import Char\r
+import Board\r
+\r
+readProblem :: String -> (Board, (Colour, Int))\r
+readProblem = parseProblem . lines\r
+\r
+comment s = (s == [] || take 2 s == "--")\r
+\r
+parseProblem :: [String] -> (Board, (Colour, Int))\r
+parseProblem s = (bd, gl)\r
+       where\r
+       bd = parseBoard bdtxt\r
+       gl = parseGoal gltxt \r
+        (bdtxt, gltxt) = splitAt 8 (filter (not . comment) s)\r
+\r
+parseBoard :: [String] -> Board\r
+parseBoard = convert . concat . zipWith parseRank (reverse [1..8])\r
+       where\r
+       convert = foldr addPiece emptyBoard\r
+       addPiece (p,sq) = putPieceAt sq p\r
+\r
+parseRank r = concat . zipWith (parseSquare r) [1..8] . filter (/= ' ')\r
+\r
+parseSquare r f '-' = []\r
+parseSquare r f  c  = \r
+       [((clr,kin), (f,r))]\r
+       where\r
+       clr = if isUpper c then Black else White \r
+       kin = case toLower c of\r
+              'k' -> King \r
+             'q' -> Queen\r
+             'r' -> Rook\r
+             'b' -> Bishop\r
+             'n' -> Knight\r
+             'p' -> Pawn\r
+\r
+parseGoal :: [String] -> (Colour, Int)\r
+parseGoal [gltxt] = (c, n)\r
+       where\r
+       ws = words gltxt\r
+       c  = read (head ws)\r
+       n  = read (last ws)\r
diff --git a/spectral/mate/Solution.hs b/spectral/mate/Solution.hs
new file mode 100644 (file)
index 0000000..8ac28e6
--- /dev/null
@@ -0,0 +1,81 @@
+module Solution (solve) where\r
+\r
+import Board\r
+import Move\r
+import List (sortBy)\r
+\r
+solve :: Board -> Colour -> Int -> String\r
+solve bd c n = showResult (solution bd c (2*n-1))\r
+\r
+data Solution = Solution MoveInFull [(MoveInFull,Solution)]\r
+\r
+solution :: Board -> Colour -> Int -> Maybe Solution\r
+solution bd c n | n > 0 = \r
+       let mds = moveDetailsFor c bd in\r
+       foldr solnOr Nothing mds\r
+       where\r
+       solnOr (mif,b) other =\r
+               let rsm = replies b (opponent c) (n-1) in\r
+               case rsm of\r
+               Nothing -> other\r
+               Just [] -> if kingincheck (opponent c) b then\r
+                               Just (Solution mif [])\r
+                          else other\r
+               Just rs -> Just (Solution mif rs)\r
+\r
+replies :: Board -> Colour -> Int -> Maybe [(MoveInFull, Solution)]\r
+replies bd c n | n==0 = if null mds then Just [] else Nothing\r
+              | n>0  =\r
+       foldr solnAnd (Just []) mds\r
+       where\r
+       mds = moveDetailsFor c bd\r
+       solnAnd (mif,b) rest =\r
+               let sm = solution b (opponent c) (n-1) in\r
+               case sm of\r
+               Nothing -> Nothing\r
+               Just s ->  case rest of\r
+                               Nothing -> Nothing\r
+                               Just ms -> Just ((mif,s):ms)\r
+\r
+showResult Nothing = "No solution!\n"\r
+showResult (Just s) = showSoln (compact s) 1\r
+\r
+data Soln = Soln MoveInFull [([MoveInFull],Soln)] deriving (Eq,Ord)\r
+\r
+compact :: Solution -> Soln\r
+compact (Solution mif rs) = Soln mif (foldr insertCompact [] rs)\r
+\r
+insertCompact (mif,s) = ic\r
+       where\r
+       ic [] = [([mif],cs)]\r
+       ic crs@((mifs,cs'):etc) =\r
+               case compare (showSoln cs 1) (showSoln cs' 1) of\r
+               LT -> ([mif], cs) : crs\r
+               EQ -> (insert mif mifs,cs) : etc\r
+               GT -> (mifs,cs') : ic etc\r
+       cs = compact s\r
+       insert x [] = [x]\r
+       insert x (y:ys) = case compare x y of\r
+                         GT -> y : insert x ys\r
+                         _  -> x : y : ys\r
+\r
+showSoln (Soln mif rs) n =\r
+       show n ++ ". " ++ showMoveInFull mif ++\r
+       ( case rs of\r
+         []         -> "++\n"\r
+         [(mifs,s)] -> ", " ++\r
+                       ( if length mifs > 1 then "..." else showMoves mifs) ++\r
+                       "; " ++ showSoln s (n+1)\r
+         _          -> ",\n" ++ showReplies (sortBy cmpLen rs) n )\r
+       where\r
+       cmpLen (xs,_) (ys,_) = compare (length xs) (length ys)\r
+\r
+showReplies [] n = ""\r
+showReplies ((mifs,s):rs) n =\r
+       tab n ++ "if " ++\r
+       ( if null rs && length mifs > 1 then "others"\r
+         else showMoves mifs ) ++ "; " ++\r
+        showSoln s (n+1) ++ showReplies rs n\r
+\r
+tab :: Int -> String\r
+tab n = take n (repeat '\t')\r
diff --git a/spectral/mate/ellerman.prob b/spectral/mate/ellerman.prob
new file mode 100644 (file)
index 0000000..a1b7edb
--- /dev/null
@@ -0,0 +1,16 @@
+-- A. Ellerman
+-- 1st prize, Luigi Centurini, Genoa, 1925
+-- `One of the very best modern two-movers,
+-- unsurpassed for beauty of idea and
+-- execution.' (Phillips)
+
+b k - - - - - - 
+- n p - - - - - 
+- - - - - - - - 
+r - - - - p - - 
+R - - - K - - - 
+- - - r P - p - 
+- Q - - - - - - 
+- - - - - q B B 
+
+White to play and mate in 2
diff --git a/spectral/mate/ellerman.soln b/spectral/mate/ellerman.soln
new file mode 100644 (file)
index 0000000..a3c9c20
--- /dev/null
@@ -0,0 +1,20 @@
+ b k - - - - - -\r
+ - n p - - - - -\r
+ - - - - - - - -\r
+ r - - - - p - -\r
+ R - - - K - - -\r
+ - - - r P - p -\r
+ - Q - - - - - -\r
+ - - - - - q B B\r
+\r
+White to move and mate in 2\r
+\r
+1. R/Q3-Q7,\r
+       if R/QR5-Q5;  2. R/Q7-K7 ++\r
+       if B/KN8-KB7;  2. QxB/KR1 ++\r
+       if B/KR8-KB6;  2. Q-Q3 ++\r
+       if Q-K4;  2. N/QN7-QB5 ++\r
+       if Q-Q5;  2. N/QN7-Q6 ++\r
+       if QxN/QN2;  2. B/QR8xQ/QN7 ++\r
+       if Q-K7, -KB7, -KN2, -KN7, -KR1, -KR7, -QR6, -QR8;  2. N/QN7-Q8 ++\r
+        ... ;  2. Q-KB4 ++\r
diff --git a/spectral/mate/fridlizius.prob b/spectral/mate/fridlizius.prob
new file mode 100644 (file)
index 0000000..851e1fb
--- /dev/null
@@ -0,0 +1,16 @@
+-- J. Fridlizius
+-- 1st Prize, St Petersburg, 1898.
+-- `In the best three-movers beauty of mating positions is an
+-- essential attribute.  Four diverse model mates are skilfully
+-- combined here.'  (Phillips)
+
+- - - - - - - - 
+B - - - - P k - 
+- P - b - - - - 
+N - - n - - P - 
+p - p K - - - - 
+- - r - - - - - 
+- - p P B - - - 
+- - - - - - - q 
+
+White to play and mate in 3
diff --git a/spectral/mate/fridlizius.soln b/spectral/mate/fridlizius.soln
new file mode 100644 (file)
index 0000000..b9c65b0
--- /dev/null
@@ -0,0 +1,60 @@
+ - - - - - - - -\r
+ B - - - - P k -\r
+ - P - b - - - -\r
+ N - - n - - P -\r
+ p - p K - - - -\r
+ - - r - - - - -\r
+ - - p P B - - -\r
+ - - - - - - - q\r
+\r
+White to move and mate in 3\r
+\r
+1. R/QB3-KB3,\r
+       if B/QR2-QN1; 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if P-KB3; 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if P-KB4; 2. Q-QR1,\r
+               if K-K5; 3. R/KB3-K3 mate.\r
+               if KxP/QB5; 3. N/Q5-K3 mate.\r
+       if P-QN4; 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if N/QR4-QN6; 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if N/QR4-QB3; 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if N/QR4-QN2; 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if N/QR4xP/QB5; 2. R/KB3-Q3, B/K7xR/Q6; 3. P-QB3 mate.\r
+       if P-KN5; 2. R/KB3-KB4 mate.\r
+       if K-K5; 2. R/KB3-KB4 mate.\r
+       if KxP/QB5; 2. R/KB3-KB4, P/KN4xR/KB5; 3. Q-K4 mate.\r
+       if P/Q7-Q8(Q); 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if P/Q7-Q8(R); 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if P/Q7-Q8(B); 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if P/Q7-Q8(N); 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if B/K7-KB8; 2. Q-KR4,\r
+               if P-KN5; 3. QxP/KN4 mate.\r
+               if P/KN4xQ/KR5; 3. R/KB3-KB4 mate.\r
+       if B/K7-Q8; 2. R/KB3-Q3, KxP/QB5; 3. N/Q5-K3 mate.\r
+       if B/K7-Q6; 2. R/KB3xB/Q3, KxP/QB5; 3. N/Q5-K3 mate.\r
+       if B/K7xR/KB6; 2. Q-QR1,\r
+               if K-K5; 3. Q-K5 mate.\r
+               if KxP/QB5; 3. N/Q5-K3 mate.\r
+       if B/K7xP/QB5; 2. P-QB3,\r
+               if K-K5; 3. N/Q5-KB6 mate.\r
+               if KxN/Q4; 3. R/KB3-KB6 mate.\r
diff --git a/spectral/mate/heathcote3.prob b/spectral/mate/heathcote3.prob
new file mode 100644 (file)
index 0000000..7b1db1c
--- /dev/null
@@ -0,0 +1,15 @@
+-- G. Heathcote
+-- Reading Observer, 1904
+-- `A charming little three-mover constructed with
+-- the art that conceals art.'  (Phillips)
+
+- - - - - - - - 
+- - - - - - - - 
+- - - - - - - - 
+- - - - P - - - 
+- - - - p - k b 
+- P n - K - - - 
+- P - - - - - - 
+- q - - - - - - 
+
+White to play and mate in 3
diff --git a/spectral/mate/heathcote3.soln b/spectral/mate/heathcote3.soln
new file mode 100644 (file)
index 0000000..b7bcc39
--- /dev/null
@@ -0,0 +1,18 @@
+ - - - - - - - -\r
+ - - - - - - - -\r
+ - - - - - - - -\r
+ - - - - P - - -\r
+ - - - - p - k b\r
+ - P n - K - - -\r
+ - P - - - - - -\r
+ - q - - - - - -\r
+\r
+White to move and mate in 3\r
+\r
+1. N/QB3-QR2,\r
+       if P/QN6xN/QR7;  2. Q-QB2, ... ; 3. B/KR4-KB2 ++\r
+       if K-K7;  2. N/QR2-QN4,\r
+               if K-K6;  3. Q-Q3 ++\r
+               if K-Q7;  3. Q-K1 ++\r
+       if K-Q7;  2. K-KB3, P/QN6xN/QR7; 3. B/KR4-K1 ++\r
+       if K-Q5;  2. B/KR4-KB2, K-QB5; 3. Q-KB1 ++\r
diff --git a/spectral/mate/holzhausen.prob b/spectral/mate/holzhausen.prob
new file mode 100644 (file)
index 0000000..2ef7a18
--- /dev/null
@@ -0,0 +1,13 @@
+-- W. von Holzhausen
+-- Deutsches Wochenschach, 1913
+
+- - - - R - - K 
+- - - - - - - b 
+- b - - N - q - 
+- - - - - - - - 
+- - - - - - P - 
+- r - - - - p - 
+- - p - - - - k 
+- - - - - - - - 
+
+White to play and mate in 4
diff --git a/spectral/mate/holzhausen.soln b/spectral/mate/holzhausen.soln
new file mode 100644 (file)
index 0000000..32b1d89
--- /dev/null
@@ -0,0 +1,56 @@
+ - - - - R - - K\r
+ - - - - - - - b\r
+ - b - - N - q -\r
+ - - - - - - - -\r
+ - - - - - - P -\r
+ - r - - - - p -\r
+ - - p - - - - k\r
+ - - - - - - - -\r
+\r
+White to move and mate in 4\r
+\r
+1. B/QN6-QB7,\r
+       if N/K3xB/QB2;  2. R/QN3-QN8,\r
+               if R/K1-QB1;  3. R/QN8xR/QB8, N/QB2-K1; 4. R/QB8xN/K8 ++\r
+               if R/K1-Q1;  3. R/QN8xR/Q8, N/QB2-K1; 4. R/Q8xN/K8 ++\r
+               if R/K1-KN1;  3. R/QN8xR/KN8 ++\r
+               if R/K1-KB1;  3. R/QN8xR/KB8 ++\r
+               if N/QB2-K3;  3. R/QN8xR/K8, N/K3-KB1; 4. R/K8xN/KB8 ++\r
+               if R/K1xR/QN1;  3. B/KR7-KN8,\r
+                       if R/QN1xB/KN1;  4. Q-KR6 ++\r
+                        ... ;  4. Q-KR7 ++\r
+                ... ;  3. R/QN8xR/K8 ++\r
+       if N/K3-KN2;  2. R/QN3-QN8,\r
+               if R/K1-QB1;  3. R/QN8xR/QB8, N/KN2-K1; 4. R/QB8xN/K8 ++\r
+               if R/K1-Q1;  3. R/QN8xR/Q8, N/KN2-K1; 4. R/Q8xN/K8 ++\r
+               if R/K1-KN1;  3. R/QN8xR/KN8 ++\r
+               if R/K1-KB1;  3. R/QN8xR/KB8 ++\r
+               if N/KN2-K3;  3. R/QN8xR/K8, N/K3-KB1; 4. R/K8xN/KB8 ++\r
+               if R/K1xR/QN1;  3. B/QB7xR/QN8, ... ; 4. Q-KN8 ++\r
+                ... ;  3. R/QN8xR/K8 ++\r
+       if R/K1-QN1;  2. B/QB7-KB4,\r
+               if N/K3xB/KB5;  3. R/QN3xR/QN8 ++\r
+               if R/QN1-QN2;  3. Q-KN8 ++\r
+               if R/QN1-KN1;  3. B/KR7xR/KN8,\r
+                       if N/K3-KN2, N/K3xB/KB5;  4. Q-KR7 ++\r
+                        ... ;  4. B/KB4-K5 ++\r
+               if N/K3-KN2;  3. B/KB4xR/QN8, ... ; 4. Q-KN8 ++\r
+               if R/QN1-QN4;  3. B/KB4-K5,\r
+                       if R/QN4xB/K4;  4. Q-KN8 ++\r
+                       if N/K3-KN2;  4. B/K5xN/KN7 ++\r
+               if R/QN1-KB1;  3. B/KB4-K5,\r
+                       if R/KB1-KB3;  4. Q-KN8 ++\r
+                       if N/K3-KN2;  4. B/K5xN/KN7 ++\r
+               if N/K3-KB1, -KN4, -Q1, -Q5, -QB2, -QB4;  3. B/KB4-K5 ++\r
+                ... ;  3. B/KB4-K5, N/K3-KN2; 4. B/K5xN/KN7 ++\r
+       if R/K1-KB1;  2. B/QB7-K5,\r
+               if R/KB1-KB3;  3. B/K5xR/KB6, N/K3-KN2; 4. B/KB6xN/KN7 ++\r
+               if N/K3-KN2;  3. B/K5xN/KN7 ++\r
+       if R/K1-K2;  2. B/QB7-K5,\r
+               if N/K3-KN2;  3. R/QN3-QN8, R/K2-K1; 4. R/QN8xR/K8 ++\r
+               if R/K2-KN2;  3. B/K5-KB6, ... ; 4. B/KB6xR/KN7 ++\r
+       if R/K1-KN1;  2. B/QB7-K5,\r
+               if N/K3-KN2;  3. B/K5-QR1, ... ; 4. B/QR1xN/KN7 ++\r
+               if R/KN1-KN2;  3. B/K5-KB6, ... ; 4. B/KB6xR/KN7 ++\r
+       if R/K1-Q1, -QB1, -QR1;  2. B/QB7-K5, N/K3-KN2; 3. B/K5xN/KN7 ++\r
+        ... ;  2. B/QB7-K5, R/K1xB/K4; 3. Q-KN8 ++\r
diff --git a/spectral/mate/kidson.prob b/spectral/mate/kidson.prob
new file mode 100644 (file)
index 0000000..e712e09
--- /dev/null
@@ -0,0 +1,15 @@
+-- H. E. Kidson
+-- Westminster Club Papers, 1868
+-- `Quite a pleasant old-time conceit.  The ultimate use
+-- of white's QR is well hidden.' (Phillips)
+
+- - - - - - - - 
+- - - - P - - - 
+- - - - - - - R 
+- - - - b p P - 
+- p n - - - r - 
+- p - P - K - p 
+- - - p P - - - 
+r - - - k - - - 
+
+White to play and mate in 4
diff --git a/spectral/mate/kohtz.prob b/spectral/mate/kohtz.prob
new file mode 100644 (file)
index 0000000..1e3edff
--- /dev/null
@@ -0,0 +1,16 @@
+-- Kohtz and Kockelkorn
+-- Schachaufgaben, 1875
+--
+-- Looks on the surface like a four-mover,
+-- so where is the fallacy?
+
+- - - - - - - K 
+- - - - - - - - 
+- - - - - n - p 
+- - - - - - - - 
+- - - - - - - - 
+- - - - - B P - 
+- - - - - - - - 
+b - - - - - k - 
+
+White to move and mate in 5
diff --git a/spectral/mate/kohtz.soln b/spectral/mate/kohtz.soln
new file mode 100644 (file)
index 0000000..e5d0a2f
--- /dev/null
@@ -0,0 +1,11 @@
+ - - - - - - - K\r
+ - - - - - - - -\r
+ - - - - - n - p\r
+ - - - - - - - -\r
+ - - - - - - - -\r
+ - - - - - B P -\r
+ - - - - - - - -\r
+ b - - - - - k -\r
+\r
+White to move and mate in 5\r
+\r
diff --git a/spectral/mate/marin.prob b/spectral/mate/marin.prob
new file mode 100644 (file)
index 0000000..a7ec5c3
--- /dev/null
@@ -0,0 +1,15 @@
+-- V. Marin
+-- 1st Prize, Spanish Tournament, 1920
+-- `... combining a sparkling key with quiet strategy and
+-- pure mates.' (Phillips)
+
+- N - - - - n - 
+- - - - r - P k 
+- - - P - - - - 
+- - P b - K - P 
+- - - P - - - p 
+- P - - P - p - 
+- - - - p p P - 
+Q N - - q - - B 
+
+White to play and mate in 3
diff --git a/spectral/mate/marin.soln b/spectral/mate/marin.soln
new file mode 100644 (file)
index 0000000..5625bea
--- /dev/null
@@ -0,0 +1,31 @@
+ - N - - - - n -\r
+ - - - - r - P k\r
+ - - - P - - - -\r
+ - - P b - K - P\r
+ - - - P - - - p\r
+ - P - - P - p -\r
+ - - - - p p P -\r
+ Q N - - q - - B\r
+\r
+White to move and mate in 3\r
+\r
+1. Q-QB3,\r
+       if QxQ/QB6;  2. R/K7xP/KN7, ... ; 3. R/KN7-KN5 ++\r
+       if P/Q5xQ/QB6;  2. R/K7xP/K3, ... ; 3. B/Q5-K6 ++\r
+       if P-Q6;  2. QxP/Q3, K-KN5; 3. B/Q5-K6 ++\r
+       if N/QN8-Q7;  2. Q-Q3,\r
+               if N/Q7-K5;  3. QxN/K4 ++\r
+               if K-KN5;  3. B/Q5-K6 ++\r
+       if P/K6xP/KB7;  2. Q-KB3 ++\r
+       if N/QN8xQ/QB6;  2. KxP/KN7,\r
+               if K-KN5;  3. B/Q5-K6 ++\r
+                ... ;  3. N/KN8-KR6 ++\r
+       if K-KN5;  2. B/Q5-K6 ++\r
+       if P-QB5, Q-QR3;  2. KxP/KN7,\r
+               if P/K6xP/KB7;  3. Q-KB3 ++\r
+               if K-KN5;  3. B/Q5-K6 ++\r
+                ... ;  3. N/KN8-KR6 ++\r
+       if P/KN7-KN8(B), -KN8(N), -KN8(Q), -KN8(R);  2. Q-Q3,\r
+               if B/KR8-K5;  3. QxB/K4 ++\r
+               if K-KN5;  3. B/Q5-K6 ++\r
+        ... ;  2. Q-Q3, K-KN5; 3. B/Q5-K6 ++\r
diff --git a/spectral/mate/shinkman.prob b/spectral/mate/shinkman.prob
new file mode 100644 (file)
index 0000000..a657fae
--- /dev/null
@@ -0,0 +1,16 @@
+-- W. A. Shinkman
+-- Western Advertiser, 1872
+-- `A masterly little four-mover with a definite message.
+-- Greater strategy could hardly be exacted from eight
+-- pieces.'  (Phillips)
+
+- - - - - - - - 
+- - - - - - - - 
+- - - - P b - - 
+- - P - - - - - 
+- - K P p - - - 
+- - - - - - - - 
+- r - k - - - - 
+- - - - - - - - 
+
+White to play and mate in 4
diff --git a/spectral/mate/shinkman.soln b/spectral/mate/shinkman.soln
new file mode 100644 (file)
index 0000000..af13410
--- /dev/null
@@ -0,0 +1,14 @@
+ - - - - - - - -\r
+ - - - - - - - -\r
+ - - - - P b - -\r
+ - - P - - - - -\r
+ - - K P p - - -\r
+ - - - - - - - -\r
+ - r - k - - - -\r
+ - - - - - - - -\r
+\r
+White to move and mate in 4\r
+\r
+1. R/QN2-QN1,\r
+       if P-K4; 2. B/KB6-Q8, P-Q6; 3. B/Q8-QN6, K-Q5; 4. R/QN1-QN4 mate.\r
+       if P-Q6; 2. B/KB6-QR1, P-K4; 3. R/QN1-QN2, K-Q5; 4. R/QN2-QN4 mate.\r
diff --git a/spectral/mate/simple.prob b/spectral/mate/simple.prob
new file mode 100644 (file)
index 0000000..4556518
--- /dev/null
@@ -0,0 +1,12 @@
+-- Castled king trapped behind the pawns.
+
+- K - - - - - - 
+P P P - - - - - 
+- - - - - - - - 
+- - - - - - - - 
+- - - - - - - - 
+- p - - - - - - 
+- - p - - - - - 
+- k - r - - - - 
+
+White to move and mate in 1
diff --git a/spectral/mate/simple.soln b/spectral/mate/simple.soln
new file mode 100644 (file)
index 0000000..a9df6b2
--- /dev/null
@@ -0,0 +1,12 @@
+ - K - - - - - -\r
+ P P P - - - - -\r
+ - - - - - - - -\r
+ - - - - - - - -\r
+ - - - - - - - -\r
+ - p - - - - - -\r
+ - - p - - - - -\r
+ - k - r - - - -\r
+\r
+White to move and mate in 1\r
+\r
+1. R/Q1-Q8 mate.\r
diff --git a/spectral/mate/wurzburg.prob b/spectral/mate/wurzburg.prob
new file mode 100644 (file)
index 0000000..fa2bbe9
--- /dev/null
@@ -0,0 +1,15 @@
+-- O. Wurzburg
+-- Pittsburgh Gazette-Times, 1914
+-- A striking task achievement presented with due
+-- regard to artistic canons.  (Phillips)
+
+- - k - - - - - 
+r - - - - - - - 
+- - - p K - - - 
+- - - - P - - - 
+- - - p p b - - 
+- - - p - p - - 
+- - - - - - - - 
+- - - - - - - - 
+
+White to play and mate in 3
diff --git a/spectral/mate/wurzburg.soln b/spectral/mate/wurzburg.soln
new file mode 100644 (file)
index 0000000..94e1409
--- /dev/null
@@ -0,0 +1,19 @@
+ - - k - - - - -\r
+ r - - - - - - -\r
+ - - - p K - - -\r
+ - - - - P - - -\r
+ - - - p p b - -\r
+ - - - p - p - -\r
+ - - - - - - - -\r
+ - - - - - - - -\r
+\r
+White to move and mate in 3\r
+\r
+1. P-Q7,\r
+       if P/K4xP/Q5;  2. P/Q7-Q8(R), K-KB3; 3. R/Q8-Q6 ++\r
+       if K-K2;  2. P/Q7-Q8(Q), K-K3; 3. Q-K7 ++\r
+       if K-Q3;  2. P/Q7-Q8(N), P/K4xB/KB5; 3. R/QR7-Q7 ++\r
+       if P/K4xB/KB5;  2. P/Q7-Q8(B), K-Q3; 3. R/QR7-QR6 ++\r
+        ... ;  2. P/Q7-Q8(Q),\r
+               if K-KN3;  3. Q-KN5 ++\r
+               if K-K3;  3. Q-K7 ++\r