packages feed

chessIO 0.9.1.0 → 0.9.2.0

raw patch · 8 files changed

+57/−390 lines, 8 filesdep −brickdep −filepathdep −rosezipperdep ~prettyprinterPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: brick, filepath, rosezipper, vty

Dependency ranges changed: prettyprinter

API changes (from Hackage documentation)

- Game.Chess.PGN: annPly :: forall a_a19E0 a_a19Ns. Lens (Annotated a_a19E0) (Annotated a_a19Ns) a_a19E0 a_a19Ns
+ Game.Chess.PGN: annPly :: forall a_a19M8 a_a19VA. Lens (Annotated a_a19M8) (Annotated a_a19VA) a_a19M8 a_a19VA
- Game.Chess.PGN: annPrefixNAG :: forall a_a19E0. Lens' (Annotated a_a19E0) [Int]
+ Game.Chess.PGN: annPrefixNAG :: forall a_a19M8. Lens' (Annotated a_a19M8) [Int]
- Game.Chess.PGN: annSuffixNAG :: forall a_a19E0. Lens' (Annotated a_a19E0) [Int]
+ Game.Chess.PGN: annSuffixNAG :: forall a_a19M8. Lens' (Annotated a_a19M8) [Int]
- Game.Chess.Polyglot: beKey :: forall a_a1hNp. Lens' (BookEntry a_a1hNp) Word64
+ Game.Chess.Polyglot: beKey :: forall a_a1hXq. Lens' (BookEntry a_a1hXq) Word64
- Game.Chess.Polyglot: beLearn :: forall a_a1hNp. Lens' (BookEntry a_a1hNp) Word32
+ Game.Chess.Polyglot: beLearn :: forall a_a1hXq. Lens' (BookEntry a_a1hXq) Word32
- Game.Chess.Polyglot: bePly :: forall a_a1hNp a_a1ico. Lens (BookEntry a_a1hNp) (BookEntry a_a1ico) a_a1hNp a_a1ico
+ Game.Chess.Polyglot: bePly :: forall a_a1hXq a_a1imE. Lens (BookEntry a_a1hXq) (BookEntry a_a1imE) a_a1hXq a_a1imE
- Game.Chess.Polyglot: beWeight :: forall a_a1hNp. Lens' (BookEntry a_a1hNp) Word16
+ Game.Chess.Polyglot: beWeight :: forall a_a1hXq. Lens' (BookEntry a_a1hXq) Word16

Files

ChangeLog.md view
@@ -1,5 +1,10 @@ # Releases +## chessIO 0.9.2.0++- Move `cbookview` into a separate repository, removing the build-dep on brick+- Update internal book+ ## chessIO 0.9.1.0  - Add a Binary instance for Square
README.md view
@@ -30,49 +30,3 @@  To launch a chess engine, simply pass its executable name and arguments to cboard. For instance, `cboard stockfish`.--## Opening book explorer--`cbookview` is a terminal application to explore commonly played openings.-Passing a polyglot opening book file (with extension `.bin`) on the command line-will allow you to explore the plies contained in that book file interactively.-You can also open a PGN file (extension `.pgn`) which will be presented like-it was an opening book.  In other words, all the moves played in that PGN file will-be merged into a single forest of plies.  When exporing PGN files, no-particular order of plies is imposed.  When exploring a polyglot file-the most popular moves will always come first.--For example, lets assume you want to examine blacks replies to-the [Ruy lopez](https://en.wikipedia.org/wiki/Ruy_Lopez).  Use the cursor keys-to navigate to the move after bishop b5.-Here is what the interface will show:--```-a6         ┌─────────────────┐-Nf6       1│ R +   K Q B N R │        1.e4 e5 2.Nf3 Nc6 3.Bb5 a6-g6        2│ P P P   P P P P │-f5        3│   + N +   +   + │-Nge7      4│ +   + P +   +   │-Bc5       5│   +   p   + B + │-d6        6│ +   +   + n + p │-Nd4       7│ p p p + p p p + │-Bb4       8│ r n b k q b + r │-Bd6        └─────────────────┘-Qf6          h g f e d c b a-f6----Up/Down (kj) = change ply, Left/Right (hl) = back/forward                 ESC = Quit-```--Moving the cursor down the list of book moves will also update the-position and game history.  As already mentioned, the moves in polyglot book files-are ordered according to popularity.  So pawn to a6 is actually the-most popular line of the Ruy Lopez.--### The easteregg: Poor mans chessboard--If you press `a` (for "All moves") cbookview will switch to the tree-of all possible moves.  This is a poor mans way for following-games and abusing cbookview as a two-player board.
− app/cbookview.hs
@@ -1,246 +0,0 @@-{-# LANGUAGE LambdaCase        #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards   #-}-{-# LANGUAGE TemplateHaskell   #-}-{-# LANGUAGE ViewPatterns      #-}-import           Brick.AttrMap        (AttrName, attrMap)-import qualified Brick.Focus          as F-import           Brick.Main           (App (..), continue, defaultMain, halt)-import           Brick.Types          (BrickEvent (VtyEvent), EventM,-                                       Location (Location), Next, Widget)-import           Brick.Util           (on)-import           Brick.Widgets.Border (border, borderWithLabel)-import           Brick.Widgets.Center (hCenter)-import           Brick.Widgets.Core   (hBox, hLimit, showCursor, str, strWrap,-                                       txt, txtWrap, vBox, vLimit, withAttr,-                                       (<+>), (<=>))-import qualified Brick.Widgets.List   as L-import           Control.Lens         (makeLenses, over, view, (&), (.~), (^.))-import           Control.Monad        (void)-import           Data.Foldable        (foldl', toList)-import           Data.Ix-import           Data.List            (elemIndex, intersperse)-import           Data.List.Extra      (chunksOf)-import           Data.List.NonEmpty   (NonEmpty)-import qualified Data.List.NonEmpty   as NonEmpty-import           Data.Map             (Map)-import qualified Data.Map             as Map-import           Data.Maybe           (fromJust, fromMaybe)-import           Data.Tree            (Tree (..), foldTree)-import           Data.Tree.Zipper     (Full, TreePos, fromForest, label,-                                       nextTree)-import qualified Data.Tree.Zipper     as TreePos-import qualified Data.Vector          as Vector-import           Game.Chess           (Color (..), PieceType (..), Ply,-                                       Position, Square (A1, H8), color, doPly,-                                       isDark, pieceAt, plyTarget, startpos,-                                       toFEN)-import           Game.Chess.ECO       (Opening (..), defaultECO)-import qualified Game.Chess.ECO       as ECO-import           Game.Chess.PGN       (pgnForest, readPGNFile)-import           Game.Chess.Polyglot  (bookForest, defaultBook,-                                       readPolyglotFile)-import           Game.Chess.SAN       (toSAN, varToSAN)-import           Game.Chess.Tree      (plyForest)-import qualified Graphics.Vty         as V-import           System.Environment   (getArgs)-import           System.FilePath--data Name = List | Board | BoardStyle deriving (Show, Ord, Eq)--type Style a = Position -> Square -> Widget a--data St = St { _initialPosition :: Position-             , _treePos         :: TreePos Full (NonEmpty Ply)-             , _boardStyle      :: L.List Name (String, Style Name)-             , _focusRing       :: F.FocusRing Name-             }--makeLenses ''St--initialState :: St-initialState = St { .. } where-  _initialPosition = startpos-  _treePos = fromJust . nextTree . fromForest-           $ pathTree <$> bookForest defaultBook _initialPosition-  _boardStyle = L.list BoardStyle (Vector.fromList styles) 1-  _focusRing = F.focusRing [List, Board, BoardStyle]--position, previousPosition :: St -> Position-position st = foldl' doPly (st^.initialPosition) (st^.treePos & label)-previousPosition st = foldl' doPly (st^.initialPosition) (st^.treePos & label & NonEmpty.init)--targetSquare :: St -> Square-targetSquare = plyTarget . NonEmpty.last . label . view treePos--elemList :: Eq a => n -> a -> [a] -> L.List n a-elemList n x xs = L.list n (Vector.fromList xs) 1 & L.listSelectedL .~ i where-  i = x `elemIndex` xs--plyList :: St -> L.List Name Ply-plyList (_treePos -> tp) = elemList List ply plies where-  ply = NonEmpty.last . TreePos.label $ tp-  plies = fmap (NonEmpty.last . rootLabel) . TreePos.forest $ tp--selectedAttr :: AttrName-selectedAttr = "selected"--renderPosition :: Position -> Color -> Maybe Square -> Style Name -> Widget Name-renderPosition pos persp tgt sty = ranks <+> border board <=> files where-  rev :: [a] -> [a]-  rev = if persp == Black then reverse else id-  ranks = vBox (str " " : map (str . show) (rev [8 :: Int, 7..1]) <> [str " "])-  files = str $ rev "   a b c d e f g h   "-  board = hLimit 17 . vLimit 8 . vBox $ map (hBox . spacer . map pc) squares-  squares = reverse $ chunksOf 8 $ rev [A1 .. H8]-  pc sq = putCursorIf (tgt == Just sq) Board (0,0) $ sty pos sq-  spacer = (str " " :) . (<> [str " "]) . intersperse (str " ")--allPieces :: ((Color, PieceType), (Color, PieceType))-allPieces = ((Black, Pawn), (White, King))--english :: Style a-english pos sq = case pieceAt pos sq of-  Just piece           -> str . pure $ "pnbrqkPNBRQK" !! index allPieces piece-  Nothing | isDark sq  -> str "+"-          | otherwise  -> str " "--styles :: [(String, Style a)]-styles = [ ("English",  english)-         , ("Deutsch",  german)-         , ("Figurine", figurine)-         ]- where-  german pos sq = case pieceAt pos sq of-    Just piece           -> str . pure $ "bsltdkBSLTDK" !! index allPieces piece-    Nothing | isDark sq  -> str "+"-            | otherwise  -> str " "-  figurine pos sq = case pieceAt pos sq of-    Just piece           -> str . pure $ "♟♞♝♜♛♚♙♘♗♖♕♔" !! index allPieces piece-    Nothing | isDark sq  -> str "+"-            | otherwise  -> str " "--putCursorIf :: Bool -> n -> (Int, Int) -> Widget n -> Widget n-putCursorIf True n loc = showCursor n $ Location loc-putCursorIf False _ _  = id--withAttrIf :: Bool -> AttrName -> Widget n -> Widget n-withAttrIf True attr = withAttr attr-withAttrIf False _   = id--type Command = St -> EventM Name (Next St)--next, prev, firstChild, parent, root, firstLeaf :: Command-next       = continue . over treePos (fromMaybe <*> TreePos.next)-prev       = continue . over treePos (fromMaybe <*> TreePos.prev)-firstChild = continue . over treePos (fromMaybe <*> TreePos.firstChild)-parent     = continue . over treePos (fromMaybe <*> TreePos.parent)-root       = continue . over treePos TreePos.root-firstLeaf  = continue . over treePos go where-  go tp = maybe tp go $ TreePos.firstChild tp--nextCursor, prevCursor :: Command-nextCursor = continue . over focusRing F.focusNext-prevCursor = continue . over focusRing F.focusPrev--allPlies, internalBook :: Command-allPlies     = continue . (fromMaybe <*> loadForest plyForest startpos)-internalBook = continue . (fromMaybe <*> loadForest (bookForest defaultBook) startpos)--nextStyle, prevStyle :: Command-nextStyle = continue . over boardStyle L.listMoveDown-prevStyle = continue . over boardStyle L.listMoveUp--keyMap :: Map V.Event Command-keyMap = Map.fromList $ cursor <> vi <> common where-  cursor =-    [ (V.EvKey V.KDown [],       next)-    , (V.EvKey V.KUp [],         prev)-    , (V.EvKey V.KRight [],      firstChild)-    , (V.EvKey V.KLeft [],       parent)-    , (V.EvKey V.KHome [],       root)-    , (V.EvKey V.KEnd [],        firstLeaf)-    ]-  common =-    [ (V.EvKey (V.KChar '\t') [],        nextCursor)-    , (V.EvKey (V.KChar '\t') [V.MMeta], prevCursor)-    , (V.EvKey (V.KChar 'a') [],         allPlies)-    , (V.EvKey (V.KChar 'd') [],         internalBook)-    , (V.EvKey (V.KChar '+') [],         nextStyle)-    , (V.EvKey (V.KChar '-') [],         prevStyle)-    , (V.EvKey V.KEsc [],                halt)-    , (V.EvKey (V.KChar 'q') [],         halt)-    ]-  vi =-    [ (V.EvKey (V.KChar 'j') [], next)-    , (V.EvKey (V.KChar 'k') [], prev)-    , (V.EvKey (V.KChar 'l') [], firstChild)-    , (V.EvKey (V.KChar 'h') [], parent)-    ]--cbookview :: App St e Name-cbookview = App { .. } where-  appStartEvent = pure-  appDraw st = [ui] where-    ui = hBox [ hLimit 9 list-              , hLimit 23 $ hCenter board <=> str " " <=> eco-              , hCenter . hLimit 40 $ str " " <=> var-              ]-      <=> str " "-      <=> (str "FEN: " <+> fen)-      <=> str " "-      <=> hBox [str "Board style (+/- to change): ", style]-      <=> hBox [str "Up/Down (kj) = change ply, Left/Right (hl) = back/forward"-               , hCenter $ str " "-               , str "ESC (q) = Quit"-               ]-    eco = maybe (str " ") drawECO (ECO.lookup (position st) defaultECO)-    drawECO co = borderWithLabel (str "ECO " <+> txt (coCode co)) $-      case coVariation co of-        Nothing        -> txtWrap (coName co)-        Just variation -> txtWrap (coName co) <=> txtWrap variation-    style = vLimit 1 $ L.renderList drawStyle True (st^.boardStyle)-    drawStyle foc (n, _) = putCursorIf foc BoardStyle (0,0) $ str n-    selectedStyle = maybe english (snd . snd) $-      st^.boardStyle & L.listSelectedElement-    list = L.renderList (drawPly (previousPosition st)) True (plyList st)-    drawPly p foc = putCursorIf foc List (0,0)-                  . withAttrIf foc selectedAttr-                  . str . toSAN p-    board = renderPosition (position st) (color (previousPosition st)) (Just . targetSquare $ st) selectedStyle-    var = strWrap . varToSAN (st^.initialPosition) $ st^.treePos & TreePos.label & toList-    fen = str . toFEN $ position st-  appHandleEvent st (VtyEvent e) = fromMaybe continue (Map.lookup e keyMap) st-  appHandleEvent st _            = continue st-  appAttrMap = const $ attrMap V.defAttr-             [(selectedAttr, V.white `on` V.green)-             ]-  appChooseCursor = F.focusRingCursor (view focusRing)--loadForest :: (Position -> [Tree Ply]) -> Position -> St -> Maybe St-loadForest f p st = case f p of-  [] -> Nothing-  ts -> Just $ st & initialPosition .~ p & treePos .~ tp where-    tp = fromJust . nextTree . fromForest $ pathTree <$> ts--pathTree :: Tree a -> Tree (NonEmpty a)-pathTree = foldTree $ \a -> Node (pure a) . (fmap . fmap) (NonEmpty.cons a)--main :: IO ()-main = do-  as <- getArgs-  case as of-    [] -> void $ defaultMain cbookview initialState-    [fp] -> case takeExtension fp of-      ".bin" -> do-        book <- readPolyglotFile fp-        case loadForest (bookForest book) startpos initialState of-          Just st -> void $ defaultMain cbookview st-          Nothing -> putStrLn "No moves found in book"-      ".pgn" -> readPGNFile fp >>= \case-        Right pgn -> case loadForest (const $ pgnForest pgn) startpos initialState of-          Just st -> void $ defaultMain cbookview st-          Nothing -> putStrLn "No moves found in PGN"-        Left err -> putStrLn err-      ext -> putStrLn $ "Unknown extension " <> ext <> ", only .bin (polyglot) and .pgn is supposed"-    _ -> putStrLn "Too many arguments."
app/polyplay.hs view
@@ -13,8 +13,7 @@ import           Data.IORef import           Data.List import           Data.String-import           Data.Text.Encoding                    (decodeUtf8)-import           Data.Text.Prettyprint.Doc.Render.Text+import           Data.Text.Encoding        (decodeUtf8) import           Data.Time.Clock import           Data.Tree import           Game.Chess@@ -23,7 +22,8 @@ import           Game.Chess.SAN import           Game.Chess.UCI import           Options.Applicative-import           System.IO                             (hPutStrLn, stderr)+import           Prettyprinter.Render.Text+import           System.IO                 (hPutStrLn, stderr) import           Time.Units  data Clock = Clock !Color !NominalDiffTime !NominalDiffTime !UTCTime
book/twic-9g.bin view

file too large to diff

chessIO.cabal view
@@ -5,9 +5,9 @@ -- see: https://github.com/sol/hpack  name:           chessIO-version:        0.9.1.0+version:        0.9.2.0 synopsis:       Basic chess library-description:    A simple and fast library for generating legal chess moves. Also includes a module for communication with external processes that speak the UCI (Universal Chess Interface) protocol, a PGN parser/pretty printer, and Polyglot opening book support. On top of that, provides a console frontend program (cboard) that can be used to interactively play against UCI engines, and a terminal program (cbookview) to explore commonly played chess openings.+description:    A simple and fast library for generating legal chess moves. Also includes a module for communication with external processes that speak the UCI (Universal Chess Interface) protocol, a PGN parser/pretty printer, and Polyglot opening book support. On top of that, provides a console frontend program (cboard) that can be used to interactively play against UCI engines. category:       Game homepage:       https://github.com/mlang/chessIO#readme bug-reports:    https://github.com/mlang/chessIO/issues@@ -66,7 +66,7 @@     , megaparsec >=9.0     , mono-traversable     , o-clock-    , prettyprinter+    , prettyprinter >=1.7.0     , process     , random     , stm@@ -105,7 +105,7 @@     , mono-traversable     , mtl     , o-clock-    , prettyprinter+    , prettyprinter >=1.7.0     , process     , random     , stm@@ -119,47 +119,6 @@     , vector-instances   default-language: Haskell2010 -executable cbookview-  main-is: cbookview.hs-  other-modules:-      Paths_chessIO-  hs-source-dirs:-      app-  ghc-options: -O2 -threaded-  build-depends:-      MonadRandom-    , attoparsec-    , base >=4.10 && <5-    , binary-    , brick-    , bytestring-    , chessIO-    , containers-    , deepseq-    , extra-    , file-embed-    , filepath-    , hashable-    , lens-    , megaparsec >=9.0-    , mono-traversable-    , o-clock-    , prettyprinter-    , process-    , random-    , rosezipper-    , stm-    , template-haskell >=2.9.0.0-    , text-    , th-compat >=0.1.2-    , th-lift-instances-    , unordered-containers-    , vector-    , vector-binary-instances-    , vector-instances-    , vty-  default-language: Haskell2010- executable polyplay   main-is: polyplay.hs   other-modules:@@ -184,7 +143,7 @@     , mono-traversable     , o-clock     , optparse-applicative-    , prettyprinter+    , prettyprinter >=1.7.0     , process     , random     , stm@@ -225,7 +184,7 @@     , mono-traversable     , o-clock     , parallel-    , prettyprinter+    , prettyprinter >=1.7.0     , process     , random     , stm@@ -265,7 +224,7 @@     , megaparsec >=9.0     , mono-traversable     , o-clock-    , prettyprinter+    , prettyprinter >=1.7.0     , process     , random     , stm
src/Game/Chess/Internal.hs view
@@ -524,7 +524,7 @@       forBits singlePushTargets $ \dst ->         pawn (dst - 8) dst       forBits doublePushTargets $ \dst ->-        pawn (dst - 16) dst+        add $ move (Sq $ dst - 16) (Sq dst)        piecePlies (QBB.wKnights qbb)                  (QBB.wBishops qbb)@@ -567,7 +567,7 @@       forBits singlePushTargets $ \dst ->         pawn (dst + 8) dst       forBits doublePushTargets $ \dst ->-        pawn (dst + 16) dst+        add $ move (Sq $ dst + 16) (Sq dst)        piecePlies (QBB.bKnights qbb)                  (QBB.bBishops qbb)
src/Game/Chess/PGN.hs view
@@ -36,51 +36,46 @@ , weightedForest ) where -import           Control.Lens                          (makeLenses, makePrisms,-                                                        makeWrapped)-import           Control.Monad                         (void)-import           Control.Monad.IO.Class                (MonadIO (..))-import           Data.Bifunctor                        (Bifunctor (first))-import           Data.ByteString.Char8                 (ByteString)-import qualified Data.ByteString.Char8                 as BS-import           Data.Char                             (chr, ord)-import           Data.Foldable                         (for_)-import           Data.Functor                          (($>))-import           Data.Hashable                         (Hashable (..))-import           Data.List                             (partition, sortOn)-import           Data.Maybe                            (fromJust, isNothing)-import           Data.Ord                              (Down (Down))-import           Data.Ratio                            ((%))-import           Data.Text                             (Text)-import qualified Data.Text                             as T-import           Data.Text.Encoding                    as T (decodeUtf8)-import           Data.Text.Prettyprint.Doc             (Doc,-                                                        FusionDepth (Shallow),-                                                        Pretty (pretty),-                                                        brackets, dquotes,-                                                        fillSep, fuse, line,-                                                        parens, vsep, (<+>))-import           Data.Text.Prettyprint.Doc.Render.Text (hPutDoc)-import           Data.Tree                             (Tree (..), foldTree)-import           Data.Void                             (Void)-import           Data.Word                             (Word8)-import           GHC.Generics                          (Generic)-import           Game.Chess.Internal                   (Color (..), Ply,-                                                        Position (color, moveNumber),-                                                        fromFEN, startpos,-                                                        unsafeDoPly)-import           Game.Chess.SAN                        (relaxedSAN, unsafeToSAN)-import           Language.Haskell.TH.Syntax            (Lift)-import           System.IO                             (Handle, hPutStrLn)-import           Text.Megaparsec                       (MonadParsec (eof),-                                                        Parsec, anySingleBut,-                                                        errorBundlePretty, many,-                                                        match, oneOf, optional,-                                                        parse, single, (<?>),-                                                        (<|>))-import           Text.Megaparsec.Byte                  (alphaNumChar, space,-                                                        space1, string)-import qualified Text.Megaparsec.Byte.Lexer            as L+import           Control.Lens               (makeLenses, makePrisms,+                                             makeWrapped)+import           Control.Monad              (void)+import           Control.Monad.IO.Class     (MonadIO (..))+import           Data.Bifunctor             (Bifunctor (first))+import           Data.ByteString.Char8      (ByteString)+import qualified Data.ByteString.Char8      as BS+import           Data.Char                  (chr, ord)+import           Data.Foldable              (for_)+import           Data.Functor               (($>))+import           Data.Hashable              (Hashable (..))+import           Data.List                  (partition, sortOn)+import           Data.Maybe                 (fromJust, isNothing)+import           Data.Ord                   (Down (Down))+import           Data.Ratio                 ((%))+import           Data.Text                  (Text)+import qualified Data.Text                  as T+import           Data.Text.Encoding         as T (decodeUtf8)+import           Data.Tree                  (Tree (..), foldTree)+import           Data.Void                  (Void)+import           Data.Word                  (Word8)+import           GHC.Generics               (Generic)+import           Game.Chess.Internal        (Color (..), Ply,+                                             Position (color, moveNumber),+                                             fromFEN, startpos, unsafeDoPly)+import           Game.Chess.SAN             (relaxedSAN, unsafeToSAN)+import           Language.Haskell.TH.Syntax (Lift)+import           Prettyprinter                (Doc, FusionDepth (Shallow),+                                             Pretty (pretty), brackets, dquotes,+                                             fillSep, fuse, line, parens, vsep,+                                             (<+>))+import           Prettyprinter.Render.Text    (hPutDoc)+import           System.IO                  (Handle, hPutStrLn)+import           Text.Megaparsec            (MonadParsec (eof), Parsec,+                                             anySingleBut, errorBundlePretty,+                                             many, match, oneOf, optional,+                                             parse, single, (<?>), (<|>))+import           Text.Megaparsec.Byte       (alphaNumChar, space, space1,+                                             string)+import qualified Text.Megaparsec.Byte.Lexer as L  data Annotated a = Ann {   _annPrefixNAG :: ![Int]