packages feed

macbeth-lib-0.0.12: src/Macbeth/Fics/Parsers/MoveParser.hs

{-# LANGUAGE OverloadedStrings #-}

module Macbeth.Fics.Parsers.MoveParser (
  move,
  moveOnly,
  pieceHolding,
  pieceHoldingOnly,
  verboseMove'
) where

import Macbeth.Fics.Api.Api
import Macbeth.Fics.FicsMessage hiding (move, Observing)
import Macbeth.Fics.Parsers.PositionParser
import Macbeth.Fics.Api.Move hiding (relation)

import Control.Applicative
import Data.Attoparsec.ByteString.Char8 hiding (D)
import Data.Maybe
import qualified Data.Attoparsec.ByteString.Char8 as A (take)
import qualified Data.ByteString.Char8 as BS

--test = BS.pack "<12> --kr-bnr ppp-pppp --nqb--- ---p---- ---P-B-- --NQ---P PPP-PPP- R---KBNR W -1 1 1 0 0 1 345 GuestTVTH GuestPYFX -1 5 0 39 39 282 288 6 o-o-o (0:03) O-O-O 1 1 0"
--test2 = BS.pack "<12> --kr-bnr ppp-pppp --nqb--- ---p---- ---P-B-- --NQ---P PPP-PPP- R---KBNR W -1 1 1 0 0 1 345 GuestTVTH GuestPYFX -1 5 0 39 39 282 288 6 o-o (0:03) O-O-O 1 1 0"
--test3 = BS.pack "<12> r--k-b-n ppp-pppP --bpp-b- ---pp--N -------- --P--PB- PPP-pPPP R---R-K- W -1 0 0 0 0 0 408 CarlosFenix mandevil 0 2 0 43 28 48 31 27 B/@@-g6 (0:25) B@g6 0 1 0\n"

move :: Parser Move
move = "<12>" *> moveOnly

moveOnly :: Parser Move
moveOnly = do
  pos <- BS.unpack `fmap` (space *> A.take 71)
  Move
    <$> pure pos
    <*> pure (parsePosition pos)
    <*> (space *> ("B" *> pure Black <|> "W" *> pure White)) -- turn
    <*> (space *> ("-1" *> pure Nothing <|> Just `fmap` column)) -- doublePawnPush
    <*> (catMaybes <$> sequence [ castle WhiteShort, castle WhiteLong, castle BlackShort, castle BlackLong])
    <*> (space *> decimal) -- the number of moves made since the last irreversible move, halfmove clock
    <*> (space *> decimal) -- gameId
    <*> (space *> manyTill anyChar space) -- nameW
    <*> manyTill anyChar space -- nameB
    <*> relation
    <*> (space *> decimal) --initialTime
    <*> (space *> decimal) --inc per move
    <*> (space *> decimal) -- whiteRelStrength
    <*> (space *> decimal) -- blackRelStrength
    <*> (space *> (decimal <|> ("-" *> (decimal >>= pure . negate)))) -- remTimeWhite
    <*> (space *> (decimal <|> ("-" *> (decimal >>= pure . negate)))) -- remTimeBlack
    <*> (space *> decimal) -- moveNumber
    <*> (space *> verboseMove') -- moveVerbose
    <*> (space *> manyTill anyChar space) -- timeTaken
    <*> ("none" *> pure Nothing <|> Just `fmap` manyTill anyChar space) -- movePretty


verboseMove' :: Parser (Maybe MoveDetailed)
verboseMove' = ("none" *> pure Nothing) <|> Just <$> (
  (Simple <$> (anyChar *> "/" *> square) <*> ("-" *> square <* takeTill (== ' '))) <|>
  (Drop <$> (anyChar *> "/@@-" *> square <* takeTill (== ' '))) <|>
  ("o-o-o" *> pure CastleLong) <|>
  ("o-o" *> pure CastleShort))


castle :: Castling -> Parser (Maybe Castling)
castle c = space *> ("0" *> pure Nothing <|> "1" *> pure (Just c))


square :: Parser Square
square = Square <$> columnAH <*> row


columnAH :: Parser Column
columnAH =
  "a" *> pure A <|> "b" *> pure B <|> "c" *> pure C <|> "d" *> pure D <|>
  "e" *> pure E <|> "f" *> pure F <|> "g" *> pure G <|> "h" *> pure H


row :: Parser Row
row =
  "1" *> pure One <|> "2" *> pure Two <|> "3" *> pure Three <|> "4" *> pure Four <|>
  "5" *> pure Five <|> "6" *> pure Six <|> "7" *> pure Seven <|> "8" *> pure Eight


relation =
  "-3" *> pure IsolatedPosition <|> "-2" *> pure ObservingExaminedGame <|> "2"  *> pure Examiner <|>
  "-1" *> pure OponentsMove <|> "1"  *> pure MyMove <|> "0"  *> pure Observing


column :: Parser Column
column =
  "0" *> pure A <|> "1" *> pure B <|>  "2" *> pure C <|> "3" *> pure D <|>
  "4" *> pure E <|> "5" *> pure F <|> "6" *> pure G <|> "7" *> pure H


-- <b1> game 455 white [PP] black []

pieceHolding :: Parser FicsMessage
pieceHolding = "<b1>" *> pieceHoldingOnly

pieceHoldingOnly :: Parser FicsMessage
pieceHoldingOnly = PieceHolding
  <$> (" game " *> decimal <* " ")
  <*> ("white [" *> many' dropablePiece <* "] ")
  <*> ("black [" *> many' dropablePiece <* "]" <* option "" " <-")


dropablePiece :: Parser PType
dropablePiece =
  "P" *> pure Pawn <|> "R" *> pure Rook <|> "N" *> pure Knight <|>
  "B" *> pure Bishop <|> "Q" *> pure Queen