module Labyrinth.Read where import Labyrinth.Map import Labyrinth.Move import Control.Monad import Text.Parsec import Text.Parsec.Language import Text.Parsec.String (Parser) import qualified Text.Parsec.Token as T parseMove :: String -> Either String Move parseMove str = case parse moveParser "" str of Right m -> Right m Left err -> Left $ show err stringResult :: String -> a -> Parser a stringResult s v = do string s return v spaces1 :: Parser () spaces1 = skipMany1 space commaSpaces :: Parser () commaSpaces = do char ',' spaces moveParser :: Parser Move moveParser = do spaces m <- emptyMove <|> choosePosition <|> reorderCell <|> liftM Move actions <|> queriesParser <|> sayParser spaces eof return m emptyMove :: Parser Move emptyMove = do try $ string "skip" return $ Move [] choosePosition :: Parser Move choosePosition = do try $ string "choose" spaces1 pos <- positionParser return $ ChoosePosition pos reorderCell :: Parser Move reorderCell = do try $ string "reorder" spaces1 pos <- positionParser return $ ReorderCell pos positionParser :: Parser Position positionParser = do x <- integer spaces y <- integer return $ Pos x y integer :: Parser Int integer = liftM fromInteger $ T.integer (T.makeTokenParser emptyDef) actions :: Parser [Action] actions = sepBy1 action commaSpaces action :: Parser Action action = choice $ map try [ goAction , grenadeAction , shootAction , surrenderAction , conditionalAction ] goAction :: Parser Action goAction = do string "go" <|> string "move" spaces1 choice [ goNext , goDirection ] where goNext = stringResult "next" $ Go Next goDirection = do d <- direction return $ goTowards d grenadeAction :: Parser Action grenadeAction = do string "grenade" spaces1 d <- direction return $ Grenade d shootAction :: Parser Action shootAction = do string "shoot" spaces1 d <- direction return $ Shoot d surrenderAction :: Parser Action surrenderAction = stringResult "surrender" Surrender direction :: Parser Direction direction = choice [ stringResult "left" L , stringResult "right" R , stringResult "up" U , stringResult "down" D ] conditionalPart :: Parser [Action] conditionalPart = do spaces a <- sepBy action commaSpaces spaces char '}' return a conditionalAction :: Parser Action conditionalAction = do string "if" spaces ifPart <- manyTill (satisfy ('{' /=)) $ try openBracket thenPart <- conditionalPart spaces elsePart <- choice [ do string "else" openBracket conditionalPart , return [] ] return $ Conditional ifPart thenPart elsePart where openBracket = spaces >> char '{' queriesParser :: Parser Move queriesParser = do string "query" spaces1 liftM Query $ sepBy1 queryParser commaSpaces queryParser :: Parser QueryType queryParser = choice [ stringResult "bullets" BulletCount , stringResult "grenades" GrenadeCount , stringResult "health" PlayerHealth , stringResult "treasure" TreasureCarried ] sayParser :: Parser Move sayParser = do string "say" space liftM Say $ many anyChar