Got an iPhone or iPad? We have a brand new Pastebin App for both devices, and it's totally free! Click here to download the new Pastebin App for iOS.
Guest

Chess

By: YAAntonDubovik on Feb 12th, 2012  |  syntax: Haskell  |  size: 4.81 KB  |  hits: 126  |  expires: Never
download  |  raw  |  embed  |  report abuse
Copied
  1. import Data.List
  2. import Control.Monad
  3. import Data.Char
  4.  
  5. data Side = Black | White
  6.         deriving (Show,Eq)
  7.  
  8. data Figure = Pawn | King | Queen | Rook | Knight | Bishop
  9.         deriving (Eq,Ord)
  10.  
  11. data Fig = Fig {
  12.         figure::Figure,
  13.         pos::(Int,Int),
  14.         side::Side
  15.         }
  16.         deriving Eq
  17.  
  18. instance Show Figure where
  19.         show Pawn = "p"
  20.         show Rook = "r"
  21.         show King = "k"
  22.         show Knight = "n"
  23.         show Queen = "q"
  24.         show Bishop = "b"
  25.  
  26. showFigLetter (Fig{figure=f, side=s}) =
  27.         toL s (show f)
  28.                 where
  29.                         toL White = map toUpper
  30.                         toL Black = id
  31.  
  32. instance Show Fig where
  33.         show o@(Fig{pos=(x,y)}) = showFigLetter o ++ show x ++ show y
  34.  
  35. data Cond = Capture | Free | Stay
  36.         deriving (Show,Eq,Ord)
  37.  
  38. data Step = Step {
  39.         spos :: (Int,Int),
  40.         cond :: Cond,
  41.         trans:: Figure
  42.         }
  43.         deriving (Show,Eq,Ord)
  44.  
  45. type Move = [Step]
  46. data Board = Board [Fig] Side
  47.  
  48. instance Show Board where
  49.         show (Board l s) = show s ++ "\n" ++ unlines (reverse table)
  50.                 where
  51.                         table = do
  52.                                 i <- [1..8]
  53.                                 return $ do
  54.                                         j <- [1..8]
  55.                                         let l' = filter ((==(j,i)) . pos) l
  56.                                         if null l'
  57.                                                 then "."
  58.                                                 else concatMap showFigLetter l'
  59.  
  60. chessPos (x,y) = toCh x : show y
  61.         where
  62.                 toCh i = chr (i-1+(ord 'a'))
  63.  
  64. switchSide White = Black
  65. switchSide Black = White
  66.  
  67. moveAndCapture (x,y) (dx,dy) n c tr =
  68.         map f . map (reverse . map (\p -> Step{spos=p,cond=Free,trans=tr})) . filter (not . null) . inits $ l
  69.                 where
  70.                         onTheBoard (x,y) = x `elem` [1..8] && y `elem` [1..8]
  71.                         l = filter onTheBoard [(x+i*dx,y+i*dy) | i <- [1..n]]
  72.                         f (o:os) = o{cond=c}:os
  73.  
  74. movesGen fig pred len = do
  75.         dx <- [-2..2]
  76.         dy <- [-2..2]
  77.         guard . pred . sort . map abs $ [dx,dy]
  78.         cond <- [Stay, Capture]
  79.         tr <- [figure fig]
  80.         moveAndCapture (pos fig) (dx,dy) len cond tr
  81.  
  82. moves fig@(Fig {figure=f, pos=p, side=s}) =
  83.         case f of
  84.                 Rook    -> movesGen fig (==[0,1]) 8
  85.                 Bishop  -> movesGen fig (==[1,1]) 8
  86.                 Knight  -> movesGen fig (==[1,2]) 1
  87.                 Queen   -> movesGen fig (`elem` [[1,1],[0,1]]) 8
  88.                 King    -> movesGen fig (`elem` [[1,1],[0,1]]) 1
  89.                 Pawn    -> concatMap transCheck $
  90.                         concat [moveAndCapture p (dx,dy) 1 Capture f | dx <- [-1,1]] ++
  91.                         moveAndCapture p (0,dy) len Stay f
  92.                                 where
  93.                                         transCheck l
  94.                                                 | any (mod . snd . spos) l = [ map (\st -> st{trans=fig}) l | fig <- [Queen, Knight]]
  95.                                                 | otherwise = [l]
  96.                                         mod y
  97.                                                 | y==8 && s==White      = True
  98.                                                 | y==1 && s==Black      = True
  99.                                                 | otherwise                     = False
  100.                                         y = snd p
  101.                                         dy      | s==White                      = 1
  102.                                                 | otherwise                     = -1
  103.                                         len     | s==White && y==2      = 2
  104.                                                 | s==Black && y==7      = 2
  105.                                                 | otherwise                     = 1
  106.  
  107. amIaLoser :: Side -> Board -> Bool
  108. amIaLoser s (Board b _) =
  109.         null . filter ((==s) . side) . filter ((==King) . figure) $ b
  110.  
  111. correctMove :: Board -> Fig -> Move -> Bool
  112. correctMove (Board b _) f@Fig{side=s} m = all correct m
  113.         where
  114.                 correct (Step p cond _)
  115.                         | cond `elem` [Free,Stay]       = all ((/=p) . pos) b
  116.                         | cond == Capture                       = any ((/=s) . side) . filter ((==p) . pos) $ b
  117.  
  118. makeMove :: Board -> Fig -> Move -> Board
  119. makeMove (Board b s) f m = Board (f':b'') (switchSide s)
  120.         where
  121.                 to = head . filter ((/=Free) . cond) $ m
  122.                 b' = delete f b
  123.                 b'' = filter ((/= spos to) . pos) b'
  124.                 f' = f{pos=spos to, figure=trans to}
  125.  
  126. dfs b 0 = []
  127. dfs b@(Board figl s) d = do
  128.         guard (not $ amIaLoser s b)
  129.         fig <- figl
  130.         guard (side fig == s)
  131.         move <- moves fig
  132.         guard (correctMove b fig move)
  133.         let b' = makeMove b fig move
  134.         let l = dfs b' (d-1)
  135.         guard (null l)
  136.         let move' = head . filter ((/=Free) . cond) $ move
  137.         return (fig, move')
  138.  
  139. solve :: Board -> [String]
  140. solve b@(Board _ s) = fu sol
  141.         where
  142.                 sol = dfs b 4
  143.                 fu [] = ["I can't help you"]
  144.                 fu l = map (\(f,mv) -> showFigLetter f ++ chessPos (pos f) ++ "--" ++ showFigLetter f{figure=trans mv} ++ chessPos (spos mv)) l
  145.  
  146. readBoard :: String -> Board
  147. readBoard s = Board (parse s 1 8) (brSide $ last s)
  148.         where
  149.                 brSide 'w' = White
  150.                 brSide 'b' = Black
  151.                 fig 'p' = Pawn
  152.                 fig 'r' = Rook
  153.                 fig 'k' = King
  154.                 fig 'q' = Queen
  155.                 fig 'n' = Knight
  156.                 fig 'b' = Bishop
  157.                 sd c = if c == toUpper c then White else Black
  158.                 parse [] _ _ = []
  159.                 parse (c:cs) x y
  160.                         | c == '/'              = parse cs 1 (y-1)
  161.                         | x > 8                 = []
  162.                         | isLetter c    = Fig{figure=fig (toLower c), pos=(x,y), side=sd c} : parse cs (x+1) y
  163.                         | otherwise             = parse cs (x + read [c]) y
  164.  
  165. board1 = "4k3/8/4K3/8/8/8/R7/8 w"
  166. board2 = "4k3/R7/8/8/8/3K4/8/7R w"
  167. board3 = "6k1/5ppp/8/8/8/6P1/5PK1/R7 w"
  168. board4 = "2rqk2N/1p3n2/4b2p/p5pQ/P2B4/8/1P3PPP/4R1K1 w"
  169. board5 = "r3r1k1/pq3p2/R2Bp1p1/1pp1P111/6P1/1PP1b2b/1P3Q1N/R5K1 b" --140
  170. board6 = "7k/pp4b1/3p3p/8/2PPP3/5bB1/5pBP/7K b" --148
  171. board7 = "N1n5/1kPP4/8/8/4K3/8/Q7/8 w" -- 132
  172.  
  173. main' b = do
  174.         let b' = readBoard b
  175.         putStrLn $ show b'
  176.         sequence_ . fmap putStrLn $ solve b'
  177.  
  178. main = do
  179.         putStrLn $ "Set the board in the same manner " ++ show board1
  180.         s <- getLine
  181.         let b = readBoard s
  182.         putStrLn $ show b
  183.         sequence_ . fmap putStrLn $ solve b