[project @ 2001-08-22 12:24:41 by simonmar]
[ghc-hetmet.git] / ghc / tests / programs / andy_cherry / DataTypes.lhs
diff --git a/ghc/tests/programs/andy_cherry/DataTypes.lhs b/ghc/tests/programs/andy_cherry/DataTypes.lhs
deleted file mode 100644 (file)
index a800394..0000000
+++ /dev/null
@@ -1,621 +0,0 @@
-> module DataTypes where
-
-> import GenUtils
-> import Array -- 1.3
-> import Ix
-> import Char
-> infix 1 =: -- 1.3
-> (=:) a b = (a,b)
-
-%------------------------------------------------------------------------------
-
-The `presentable' class, my own co-class for Text
-
-> class Presentable a where
->      userFormat :: a -> String       -- in prefered display format
-
-Defaults, in terms of each other
-
-And the default for lists.
-
-> instance (Presentable a) => Presentable [a] where
->     userFormat xs = unlines (map userFormat xs)
-
-%------------------------------------------------------------------------------
- Here are all the pieces allowed in chess.
-
-> data Piece
->      = King
->      | Queen
->      | Rook
->      | Knight
->      | Bishop
->      | Pawn deriving(Eq)
-
-> instance Presentable Piece where
->   userFormat King   = "K"
->   userFormat Queen  = "Q"
->   userFormat Rook   = "R"
->   userFormat Knight = "N"
->   userFormat Bishop = "B"
->   userFormat Pawn   = "P"
-
-
-%------------------------------------------------------------------------------
-
-> castleK = "O-O"
-> castleQ = "O-O-O"
-
-%------------------------------------------------------------------------------
-
-Here are the two sides.
-
-> data Colour = Black | White deriving (Eq)
-
-> instance Presentable Colour where
->      userFormat White = "White"
->      userFormat Black = "Black"
-
-> changeColour :: Colour -> Colour
-> changeColour White = Black
-> changeColour Black = White
-
-%------------------------------------------------------------------------------
-
-Now the ranks and files.
-
-> type ChessRank = Int -- 1-8
-> type ChessFile = Int -- 1-8
-
-> type BoardPos = (ChessFile,ChessRank)        -- ChessFile (0-7) and ChessRank (0-7)
-> type ExBoardPos = (Maybe ChessFile,Maybe ChessRank)
-
-> extendBP :: BoardPos -> ExBoardPos 
-> extendBP (a,b) = (Just a,Just b)
-
-> compExBPandBP :: ExBoardPos -> BoardPos -> Bool
-> compExBPandBP (a,b) (c,d) = a `cmp` c && b `cmp` d
->    where 
->      cmp Nothing  _ = True
->      cmp (Just x) y = x == y
-
-> userFormatBoardPos :: BoardPos -> String
-> userFormatBoardPos (f,r) = userFormatFile f ++ userFormatRank r
-> userFormatExBoardPos :: ExBoardPos -> String
-> userFormatExBoardPos (Just f,Just r)  = userFormatFile f ++ userFormatRank r
-> userFormatExBoardPos (Just f,Nothing) = userFormatFile f 
-> userFormatExBoardPos (Nothing,Just r) = userFormatRank r
-> userFormatExBoardPos _ = ""
-> userFormatRank r = [toEnum (r + 48)]
-> userFormatFile f = [toEnum (f + 96)]
-
-%------------------------------------------------------------------------------
-
-These are the components of a move.
-
-> data MoveTok 
->      = PieceTok Piece        -- Q,K,R,B,N
->      | RankTok ChessRank     -- 1 .. 8
->      | FileTok ChessFile     -- a .. h
->      | PartCastleTok         -- 0 | O | o
->      | CaptureTok            -- x
->      | MoveToTok             -- -
->      | QueensWith            -- =
->      | CheckTok              -- +
->      | MateTok               -- #
-
-> charToMoveTok 'Q' = Just (PieceTok Queen)
-> charToMoveTok 'K' = Just (PieceTok King)
-> charToMoveTok 'R' = Just (PieceTok Rook)
-> charToMoveTok 'B' = Just (PieceTok Bishop)
-> charToMoveTok 'N' = Just (PieceTok Knight)
-> charToMoveTok '1' = Just (RankTok 1)
-> charToMoveTok '2' = Just (RankTok 2)
-> charToMoveTok '3' = Just (RankTok 3)
-> charToMoveTok '4' = Just (RankTok 4)
-> charToMoveTok '5' = Just (RankTok 5)
-> charToMoveTok '6' = Just (RankTok 6)
-> charToMoveTok '7' = Just (RankTok 7)
-> charToMoveTok '8' = Just (RankTok 8)
-> charToMoveTok 'a' = Just (FileTok 1)
-> charToMoveTok 'b' = Just (FileTok 2)
-> charToMoveTok 'c' = Just (FileTok 3)
-> charToMoveTok 'd' = Just (FileTok 4)
-> charToMoveTok 'e' = Just (FileTok 5)
-> charToMoveTok 'f' = Just (FileTok 6)
-> charToMoveTok 'g' = Just (FileTok 7)
-> charToMoveTok 'h' = Just (FileTok 8)
-> charToMoveTok '0' = Just (PartCastleTok)
-> charToMoveTok 'O' = Just (PartCastleTok)
-> charToMoveTok 'o' = Just (PartCastleTok)
-> charToMoveTok 'x' = Just (CaptureTok)
-> charToMoveTok '-' = Just (MoveToTok)
-> charToMoveTok '=' = Just (QueensWith)
-> charToMoveTok '+' = Just (CheckTok)
-> charToMoveTok '#' = Just (MateTok)
-> charToMoveTok _   = Nothing
-
-%------------------------------------------------------------------------------
-
-> data Quantum 
->      = QuantumMove   String          -- Short Description of move
->                      String          -- Check or Mate (+ or #)
->                      String          -- !,??,?!, etc
->                      Board           -- Snap Shot of Board
->      | QuantumNAG Int                -- !,??,?! stuff
->      | QuantumComment [String]       -- { comment }
->      | QuantumResult String          -- 1-0, etc (marks end of game)
->      | QuantumAnalysis [Quantum]     -- ( analysis )
->      | QuantumPrintBoard             -- {^D}
-
-> instance Presentable Quantum where
->      userFormat (QuantumMove mv ch ann _) 
->              = mv ++ ch ++ ann
->      userFormat (QuantumNAG nag) = "$" ++ show nag
->      userFormat (QuantumComment comment) 
->              = "[" ++ unwords comment ++ "]"
->      --userFormat (QuantumNumber num)  = userFormat num
->      userFormat (QuantumResult str) = str
->      userFormat (QuantumAnalysis anal) =
->              "( " ++ unwords (map userFormat anal) ++ " )"
-
-%------------------------------------------------------------------------------
-
-> data Result = Win | Draw | Loss | Unknown
-
-> instance Presentable Result where
->      userFormat Win     = "1-0"
->      userFormat Draw    = "1/2-1/2"
->      userFormat Loss    = "0-1"
->      userFormat Unknown = "*"
-
-> mkResult :: String -> Result
-> mkResult "1-0"     = Win
-> mkResult "1/2-1/2" = Draw
-> mkResult "0-1"     = Loss
-> mkResult _         = Unknown
-
-%------------------------------------------------------------------------------
-
-> data TagStr = TagStr String String
-
-> instance Presentable TagStr where
->      userFormat (TagStr tag str) = "[" ++ tag ++ " \"" ++ str ++ "\"]"
-
-> getTagStr :: String -> String -> [TagStr] -> String
-> getTagStr str def [] = def
-> getTagStr str def (TagStr st ans:rest) 
->              | str == st = ans
->              | otherwise = getTagStr str def rest
-
-> getHeaderInfo 
->      :: [TagStr]
->      -> (
->              String,         -- Date
->              String,         -- Site
->              Maybe Int,      -- Game Number
->              Result,         -- W/D/L
->              String,         -- White
->              String,         -- Black
->              String          -- Opening
->      )
-> getHeaderInfo tags = (
->              date,
->              site,
->              gameno,
->              result,
->              white `par` whiteElo,
->              black `par` blackElo,
->              opening)
->   where
->      date   = case getTagStr "Date" "?" tags of
->                 [a,b,c,d,'.','?','?','.','?','?'] -> [a,b,c,d]
->                 [a,b,c,d,'.',x,y,'.','?','?'] -> getMonth [x,y] ++ " " ++ [a,b,c,d]
->                 def -> "?"
->      site     = getTagStr "Site" "?" tags
->      gameno   = case getTagStr "GameNumber" "" tags of
->                      xs | all isDigit xs && not (null xs) -> Just (read xs)
->                      _ -> Nothing
->      result   = mkResult (getTagStr "Result" "*" tags)
->      white    = cannon (getTagStr "White" "?" tags)
->      whiteElo = getTagStr "WhiteElo" "" tags
->      black    = cannon (getTagStr "Black" "?" tags)
->      blackElo = getTagStr "BlackElo" "" tags
->      opening  = getOpening (getTagStr "ECO" "" tags)
-
->      par xs "" = xs
->      par xs ys = xs ++ " (" ++ ys ++ ")"
-
->      getMonth "01" = "Jan"
->      getMonth "02" = "Feb"
->      getMonth "03" = "Mar"
->      getMonth "04" = "Apr"
->      getMonth "05" = "May"
->      getMonth "06" = "Jun"
->      getMonth "07" = "Jul"
->      getMonth "08" = "Aug"
->      getMonth "09" = "Sep"
->      getMonth "10" = "Oct"
->      getMonth "11" = "Nov"
->      getMonth "12" = "Dec"
-
->      cannon name = case span (/= ',') name of
->                      (a,[',',' ',b]) -> b : ". " ++ a
->                      (a,[',',b]) -> b : ". " ++ a
->                      (a,',':' ':b) -> b ++ " " ++ a
->                      (a,',':b) -> b ++ " " ++ a
->                      _ -> name
-
-
-> getOpening eco@[a,b,c] |  a >= 'A' && a <= 'E' && isDigit b && isDigit c 
->    = getOpenName ((fromEnum a - fromEnum 'A') * 100 
->              + (fromEnum b - fromEnum '0') * 10 
->              + (fromEnum c - fromEnum '0')) ++ " " ++ eco
-> getOpening other = other
-
-> getOpenName :: Int -> String
-> getOpenName eco 
->      | otherwise = "Foo"
-> {-
->      | eco == 000 = "Irregular Openings"
->      | eco == 001 = "Larsen Opening"
->      | eco == 002 = "From's Gambit and Bird's Open"
->      | eco == 003 = "Bird's Opening"
->      | eco == 004 = "Dutch System"
->      | eco == 005 = "Transposition to various Open"
->      | eco == 006 = "Zukertort Opening"
->      | eco >= 007 && eco <= 008
->                   = "Barcza System"
->      | eco == 009 = "Reti Opening"
->      | eco == 010 = "Variations of Dutch, QI, KI"
->      | eco >= 011 && eco <= 014
->                   = "Reti Opening"
->      | eco == 015 = "English counter King's Fianch"
->      | eco >= 016 && eco <= 039
->                   = "English Opening"
->      | eco == 040 = "Unusual replies to 1.d4"
->      | eco == 041 = "Modern Defence counter 1.d4"
->      | eco == 042 = "Modern Defence with c2-c4"
->      | eco >= 043 && eco <= 044
->                   = "Old Benoni"
->      | eco == 045 = "Queen's Pawn-Trompowski Var"
->      | eco == 046 = "Queen's Pawn Opening"
->      | eco == 047 = "Queen's Indian"
->      | eco >= 048 && eco <= 049
->                   = "King's Indian"
->      | eco == 050 = "Queen's Indian"
->      | eco >= 051 && eco <= 052
->                   = "Budapest Defence"
->      | eco >= 053 && eco <= 056
->                   = "Old Indian Defence"
->      | eco >= 057 && eco <= 059
->                   = "Volga-Benko Gambit"
->      | eco >= 060 && eco <= 079
->                   = "Benoni"
->      | eco >= 080 && eco <= 099
->                   = "Dutch Defence"
->      | eco == 100 = "Owen Def, Nimzowitsch Def"
->      | eco == 101 = "Center Counter"
->      | eco >= 102 && eco <= 105
->                   = "Alekhine's Defence"
->      | eco == 106 = "Modern Defence"
->      | eco >= 107 && eco <= 109
->                   = "Pirc Defence"
->      | eco >= 110 && eco <= 119
->                   = "Caro-Kann Defence"
->      | eco >= 120 && eco <= 199
->                   = "Sicilian Defence"
->      | eco >= 200 && eco <= 219
->                   = "French Defence"
->      | eco == 220 = "Rare moves"
->      | eco == 221 = "Nordic Gambit"
->      | eco == 222 = "Central Gambit"
->      | eco >= 223 && eco <= 224
->                   = "Bishop's Opening"
->      | eco >= 225 && eco <= 229
->                   = "Vienna Game"
->      | eco == 230 = "King's Gambit Declined"
->      | eco >= 231 && eco <= 232
->                   = "Falkbeer Counter Gambit"
->      | eco >= 233 && eco <= 239
->                   = "King's Gambit"
->      | eco == 240 = "Latvian Gambit"
->      | eco == 241 = "Philidor Defence"
->      | eco >= 242 && eco <= 243
->                   = "Russian Defence-Petrov"
->      | eco >= 244 && eco <= 245
->                   = "Scotch Opening"
->      | eco >= 246 && eco <= 249
->                   = "Four Knight's"
->      | eco == 250 = "Italian Opening"
->      | eco >= 251 && eco <= 252
->                   = "Evans Gambit"
->      | eco >= 253 && eco <= 254
->                   = "Italian Opening"
->      | eco >= 255 && eco <= 259
->                   = "Two Knight's Play"
->      | eco >= 260 && eco <= 299
->                   = "Ruy Lopez"
->      | eco >= 300 && eco <= 305
->                   = "Queen Pawn's Opening"
->      | eco >= 306 && eco <= 307
->                   = "Queen's Gambit"
->      | eco >= 308 && eco <= 309
->                   = "Albins Counter Gambit"
->      | eco >= 310 && eco <= 319
->                   = "Slav Defence"
->      | eco >= 320 && eco <= 329
->                   = "Queen's Gambit Accepted"
->      | eco >= 330 && eco <= 369
->                   = "Queen's Gambit"
->      | eco >= 370 && eco <= 399
->                   = "Gruenfeld Defence"
->      | eco >= 400 && eco <= 409
->                   = "Catalan"
->      | eco == 410 = "Blumenfeld Gambit"
->      | eco >= 411 && eco <= 419
->                   = "Queen's Indian"
->      | eco >= 420 && eco <= 459
->                   = "Nimzo Indian"
->      | eco >= 460 && eco <= 499
->                   = "King's Indian"
-> -}
-
-%------------------------------------------------------------------------------
-
-> data MoveNumber = MoveNumber Int Colour
-> instance Presentable MoveNumber where
->      userFormat (MoveNumber n White)  = show n ++ "."
->      userFormat (MoveNumber n Black)  = show n ++ "..."
-
-> initMoveNumber = MoveNumber 1 White
-> incMove (MoveNumber i White) = MoveNumber i Black
-> incMove (MoveNumber i Black) = MoveNumber (i+1) White
-> decMove (MoveNumber i White) = MoveNumber (i-1) Black
-> decMove (MoveNumber i Black) = MoveNumber i White
-> getMoveColour :: MoveNumber -> Colour
-> getMoveColour (MoveNumber _ c) = c
-
-%------------------------------------------------------------------------------
-
-> data Token 
-
-Both first and second level.
-
->      = StringToken   String
->      | AsterixToken
->      | LeftABToken           -- ??
->      | RightABToken          -- ??
->      | NAGToken      Int     -- `normal' NAGS
->      | NAGAnnToken   Int String
->                              -- `special' move annotating NAGS (1-6)
->      | SymbolToken   String
->      | CommentToken  [String] -- list of words
->      | LeftSBToken
->      | RightSBToken
->      | LeftRBToken
->      | RightRBToken
->      | IntToken      Int
->      | PeriodToken
-
-Second level Token, as produced by the parser.
-
->      | AnalToken     [Token]
-
-> instance Presentable Token where
->      userFormat (StringToken str) = show str
->      userFormat (IntToken n)      = show n
->      userFormat (PeriodToken)     = "."
->      userFormat (AsterixToken)    = "*"
->      userFormat (LeftSBToken)     = "["
->      userFormat (RightSBToken)    = "]"
->      userFormat (LeftRBToken)     = "("
->      userFormat (RightRBToken)    = ")"
->      userFormat (LeftABToken)     = "<"
->      userFormat (RightABToken)    = ">"
->      userFormat (NAGToken i)      = "$" ++ show i
->      userFormat (NAGAnnToken i s) = "$" ++ show i
->      userFormat (SymbolToken str) = str
->      userFormat (CommentToken str) = "{" ++ unwords str ++ "}"
->      userFormat (AnalToken toks) = "( " ++ unwords (map userFormat toks)
->                                      ++ " )"
-
-%------------------------------------------------------------------------------
-
-The Parser Emits a list of these.
-
-> data Game a = Game [TagStr] [a]
-
-> type AbsGame = Game Token
-> type RealGame = Game Quantum
-
-> instance (Presentable a) => Presentable (Game a) where
->      userFormat (Game tags toks) = 
->              unlines (map userFormat tags 
->                 ++ formatText 78 (map userFormat toks))
-
-%------------------------------------------------------------------------------
-
-Here are the moves that actually can be played,
-all in the context of a particular board.
-
-> data PlayMove
->      = PlayMove
->              Piece           -- with this
->              BoardPos        -- from here
->              BoardPos        -- to here (possibly capturing)
->              SpecialMove
-
-> mkPlayMove p f t = PlayMove p f t NothingSpecial
-
-> data SpecialMove 
->      = NothingSpecial        
->      | BigPawnMove           -- allows e.p. next move
->      | Queening Piece        -- queen with this
->      | EnPassant             -- capture e.p.
->    deriving (Eq)
-               
-> instance Presentable PlayMove where
->      userFormat (PlayMove piece pos pos' sp) = 
->              userFormat piece ++
->              userFormatBoardPos pos ++ "-" ++
->              userFormatBoardPos pos' ++ 
->              userFormat sp
-
-> instance Presentable SpecialMove where
->      userFormat (NothingSpecial) = ""
->      userFormat (BigPawnMove) = "{b.p.m.}"
->      userFormat (Queening p) = "=" ++ userFormat p
->      userFormat (EnPassant) = "e.p."
-
-> extractSrcFromPlayMove :: PlayMove -> BoardPos
-> extractSrcFromPlayMove (PlayMove _ src _ _) = src
-
-> extractDestFromPlayMove :: PlayMove -> BoardPos
-> extractDestFromPlayMove (PlayMove _ _ dest _)       = dest
-
-> extractSpecialFromPlayMove :: PlayMove -> SpecialMove
-> extractSpecialFromPlayMove (PlayMove _ _ _ sp)       = sp
-
-
-%------------------------------------------------------------------------------
-
-Now the representation of the board itself.
-
-> data BoardSquare
->      = VacantSq
->      | WhitesSq Piece
->      | BlacksSq Piece
-
-> data SquareContent
->      = Vacant
->      | Friendly
->      | Baddy
->      | OffBoard deriving (Eq)
-
-> instance Presentable SquareContent where
->      userFormat Vacant   = "."
->      userFormat Friendly = "*"
->      userFormat Baddy    = "#"
->      userFormat OffBoard = "?"
-
-
-%------------------------------------------------------------------------------
-
-A Static representation of what the current placement of pieces is.
-
-> data Board 
->      = Board (Array BoardPos BoardSquare)
->              MoveNumber              -- current player & and move
->              (Maybe ChessFile)       -- e.p. possibilties.
-
-This is Christmas for foldr/build !
-
-> displayBoard :: Colour -> Board -> [String]
-> displayBoard col (Board arr _ ep) = 
->      ([cjustify 33 (userFormat (changeColour col)),""] ++
->      [
->   concat [ (case (even x,even y) of
->      (True,True)   -> showSq (x `div` 2) (y `div` 2)
->      (False,False) -> "+"
->      (True,False)  -> "---"
->      (False,True)  -> (if x == 17 then "| " ++ show (y `div` 2) else "|"))
->              | x <- [1..17::Int]]
->              | y <- reverse [1..17::Int]] ++
->      [concat [ "  " ++ [x] ++ " " | x <- "abcdefgh" ]] ++
->      ["",cjustify 33 (userFormat col),"",
->              case ep of
->               Nothing -> ""
->               Just p -> "EnPassant:" ++ userFormatFile p ])
->    where
->      make n str = take n (str ++ repeat ' ')
->      lookupPlace :: Int -> Int -> BoardSquare
->      lookupPlace x' y' = arr ! (x',y')
-
->      bold :: String -> String
->      bold str = map toLower str
-
->      showSq x y = case lookupPlace x y of
->              VacantSq     -> [if_dot,if_dot,if_dot]
->              (WhitesSq p) -> (if_dot : userFormat p) ++ [if_dot]
->              (BlacksSq p)  -> (if_dot : bold (userFormat p)) ++ [if_dot]
->         where
->              if_dot = if (x - y) `rem` 2 == 0 then '.' else ' '
-
-> instance Presentable Board where
->   userFormat = unlines . displayBoard White
-
-> boardSize :: (BoardPos,BoardPos)
-> boardSize = ((1,1),(8,8))
-
-
-This uses forsyth notation.
-
-> buildBoard :: String -> Board
-> buildBoard str = Board brd initMoveNumber Nothing
->    where
->      brd = array boardSize (zipWith (=:) allSq (mkPieces str))
->      allSq = [ (x,y) | y <- reverse [1..8::Int],x <- [1..8::Int]]
->      mkPieces :: String -> [BoardSquare]
->      mkPieces (hd:rest) | hd `elem` "KQRNBPkqrnbp" = pc : mkPieces rest
->         where
->              pc = case hd of
->                      'K' -> WhitesSq King    
->                      'Q' -> WhitesSq Queen
->                      'R' -> WhitesSq Rook
->                      'N' -> WhitesSq Knight
->                      'B' -> WhitesSq Bishop  
->                      'P' -> WhitesSq Pawn
->                      'k' -> BlacksSq King    
->                      'q' -> BlacksSq Queen
->                      'r' -> BlacksSq Rook
->                      'n' -> BlacksSq Knight
->                      'b' -> BlacksSq Bishop  
->                      'p' -> BlacksSq Pawn
->      mkPieces ('/':rest) = mkPieces rest
->      mkPieces (c:rest) | isDigit c =
->              case span isDigit rest of
->                (cs,rest') -> take (read (c:cs)) (repeat VacantSq) 
->                                      ++ mkPieces rest'
->      mkPieces [] = []
-
-> startBoard :: Board  -- the uni before the big bang.
-> startBoard = buildBoard "rnbqkbnr/pppppppp/32/PPPPPPPP/RNBQKBNR"
-
-> lookupSquare :: Colour -> BoardSquare -> SquareContent
-> lookupSquare _      VacantSq    = Vacant
-> lookupSquare White (WhitesSq p) = Friendly
-> lookupSquare Black (WhitesSq p) = Baddy
-> lookupSquare White (BlacksSq p) = Baddy
-> lookupSquare Black (BlacksSq p) = Friendly
-
-> lookupBoard :: Board -> BoardPos -> SquareContent
-> lookupBoard (Board arr col _) pos = 
->      if inRange boardSize pos
->      then lookupSquare (getMoveColour col) (arr ! pos)
->      else OffBoard
-
-> lookupBoardSquare :: Board -> BoardPos -> BoardSquare
-> lookupBoardSquare (Board arr _ _) pos = arr ! pos
-
-> getSquarePiece :: BoardSquare -> Maybe Piece
-> getSquarePiece VacantSq    = Nothing
-> getSquarePiece (WhitesSq p) = Just p
-> getSquarePiece (BlacksSq p) = Just p
-
-> lookupBoardPiece :: Board -> BoardPos -> Maybe Piece
-> lookupBoardPiece (Board arr _ _) pos = 
->     case arr ! pos of
->      VacantSq -> Nothing
->      WhitesSq piece -> Just piece
->      BlacksSq piece -> Just piece
-
-This will improve sharing, by 
-
-> {-# INLINE mkColBoardSq #-}
-> mkColBoardSq :: Colour -> Piece -> BoardSquare
-> mkColBoardSq White p = WhitesSq p
-> mkColBoardSq Black p = BlacksSq p
-
-> getBoardColour (Board _ mv _) = getMoveColour mv
-