haskellscrabble 0.1.0.2 → 1.0
raw patch · 6 files changed
+42/−43 lines, 6 filesdep +arrowsdep ~basedep ~errorsPVP ok
version bump matches the API change (PVP)
Dependencies added: arrows
Dependency ranges changed: base, errors
API changes (from Hackage documentation)
- Wordify.Rules.Board: instance Show Board
- Wordify.Rules.Board.Internal: instance Eq Board
- Wordify.Rules.Dictionary: instance Show Dictionary
- Wordify.Rules.FormedWord: instance Eq Direction
- Wordify.Rules.FormedWord: instance Eq FormedWords
- Wordify.Rules.FormedWord: instance Show FormedWords
- Wordify.Rules.LetterBag.Internal: bagSize :: LetterBag -> Int
- Wordify.Rules.LetterBag.Internal: generator :: LetterBag -> StdGen
- Wordify.Rules.LetterBag.Internal: instance Eq LetterBag
- Wordify.Rules.LetterBag.Internal: instance Show LetterBag
- Wordify.Rules.LetterBag.Internal: tiles :: LetterBag -> [Tile]
- Wordify.Rules.Player: instance Eq LetterRack
- Wordify.Rules.Player: instance Eq Player
- Wordify.Rules.Player: instance Show LetterRack
- Wordify.Rules.Player: instance Show Player
- Wordify.Rules.Pos.Internal: instance Eq Pos
- Wordify.Rules.Pos.Internal: instance Ord Pos
- Wordify.Rules.Pos.Internal: instance Show Pos
- Wordify.Rules.ScrabbleError: instance Eq ScrabbleError
- Wordify.Rules.ScrabbleError: instance Show ScrabbleError
- Wordify.Rules.Square: instance Eq Square
- Wordify.Rules.Square: instance Ord Square
- Wordify.Rules.Square: instance Show Square
- Wordify.Rules.Tile: instance Eq Tile
- Wordify.Rules.Tile: instance Ord Tile
- Wordify.Rules.Tile: instance Show Tile
+ Wordify.Rules.Board: instance GHC.Show.Show Wordify.Rules.Board.Internal.Board
+ Wordify.Rules.Board.Internal: instance GHC.Classes.Eq Wordify.Rules.Board.Internal.Board
+ Wordify.Rules.Dictionary: instance GHC.Show.Show Wordify.Rules.Dictionary.Dictionary
+ Wordify.Rules.FormedWord: instance GHC.Classes.Eq Wordify.Rules.FormedWord.Direction
+ Wordify.Rules.FormedWord: instance GHC.Classes.Eq Wordify.Rules.FormedWord.FormedWords
+ Wordify.Rules.FormedWord: instance GHC.Show.Show Wordify.Rules.FormedWord.FormedWords
+ Wordify.Rules.LetterBag.Internal: [bagSize] :: LetterBag -> Int
+ Wordify.Rules.LetterBag.Internal: [generator] :: LetterBag -> StdGen
+ Wordify.Rules.LetterBag.Internal: [tiles] :: LetterBag -> [Tile]
+ Wordify.Rules.LetterBag.Internal: instance GHC.Classes.Eq Wordify.Rules.LetterBag.Internal.LetterBag
+ Wordify.Rules.LetterBag.Internal: instance GHC.Show.Show Wordify.Rules.LetterBag.Internal.LetterBag
+ Wordify.Rules.Player: instance GHC.Classes.Eq Wordify.Rules.Player.LetterRack
+ Wordify.Rules.Player: instance GHC.Classes.Eq Wordify.Rules.Player.Player
+ Wordify.Rules.Player: instance GHC.Show.Show Wordify.Rules.Player.LetterRack
+ Wordify.Rules.Player: instance GHC.Show.Show Wordify.Rules.Player.Player
+ Wordify.Rules.Pos.Internal: instance GHC.Classes.Eq Wordify.Rules.Pos.Internal.Pos
+ Wordify.Rules.Pos.Internal: instance GHC.Classes.Ord Wordify.Rules.Pos.Internal.Pos
+ Wordify.Rules.Pos.Internal: instance GHC.Show.Show Wordify.Rules.Pos.Internal.Pos
+ Wordify.Rules.ScrabbleError: instance GHC.Classes.Eq Wordify.Rules.ScrabbleError.ScrabbleError
+ Wordify.Rules.ScrabbleError: instance GHC.Show.Show Wordify.Rules.ScrabbleError.ScrabbleError
+ Wordify.Rules.Square: instance GHC.Classes.Eq Wordify.Rules.Square.Square
+ Wordify.Rules.Square: instance GHC.Classes.Ord Wordify.Rules.Square.Square
+ Wordify.Rules.Square: instance GHC.Show.Show Wordify.Rules.Square.Square
+ Wordify.Rules.Tile: instance GHC.Classes.Eq Wordify.Rules.Tile.Tile
+ Wordify.Rules.Tile: instance GHC.Classes.Ord Wordify.Rules.Tile.Tile
+ Wordify.Rules.Tile: instance GHC.Show.Show Wordify.Rules.Tile.Tile
- Wordify.Rules.ScrabbleError: MalformedDictionaryFile :: FilePath -> ScrabbleError
+ Wordify.Rules.ScrabbleError: MalformedDictionaryFile :: String -> ScrabbleError
Files
- haskellscrabble.cabal +4/−4
- src/Wordify/Rules/Dictionary.hs +26/−25
- src/Wordify/Rules/FormedWord.hs +5/−7
- src/Wordify/Rules/LetterBag.hs +2/−0
- src/Wordify/Rules/Move.hs +3/−5
- src/Wordify/Rules/ScrabbleError.hs +2/−2
haskellscrabble.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: haskellscrabble-version: 0.1.0.2+version: 1.0 synopsis: A scrabble library capturing the core game logic of scrabble. description: A scrabble library which enforces legal transitions between moves. Intended to facilitate the development of a playable game. homepage: http://www.github.com/happy0/haskellscrabble@@ -34,8 +34,8 @@ other-modules: Wordify.Rules.Game.Internal - build-depends: base < 4.8, containers, array, random, mtl, transformers, QuickCheck, - parsec, unordered-containers, semigroups, errors, safe, split+ build-depends: base < 5, containers, array, random, mtl, transformers, QuickCheck, + parsec, unordered-containers, semigroups, errors < 2.0, safe, split, arrows hs-source-dirs: src test-suite tests@@ -45,7 +45,7 @@ build-depends: haskellscrabble,- base < 4.8,+ base < 5, QuickCheck, HUnit, test-framework,
src/Wordify/Rules/Dictionary.hs view
@@ -4,8 +4,10 @@ import Wordify.Rules.ScrabbleError import qualified Control.Exception as Exc import Text.ParserCombinators.Parsec+ import Text.Parsec.Prim import Data.Char import Control.Monad+ import Control.Arrow data Dictionary = Dictionary (HashSet.HashSet String) deriving Show @@ -23,38 +25,37 @@ isValidWord (Dictionary dictionaryWords) = flip HashSet.member dictionaryWords dictionaryFromWords :: [String] -> Dictionary- dictionaryFromWords wordList = Dictionary $ HashSet.fromList upperCaseWords- where- upperCaseWords = (map . map) toUpper wordList+ dictionaryFromWords = Dictionary . HashSet.fromList . upperCaseWords {- | Creates a dictionary from a file containing a list of valid words, each word being seperated by a newline. -} makeDictionary :: FilePath -> IO (Either ScrabbleError Dictionary)- makeDictionary filePath = - do- fileContents <- Exc.try (readFile filePath) :: IO (Either Exc.IOException String)- case fileContents of - Left _ -> return $ Left (DictionaryFileNotFound filePath)- Right dictContents -> - let dictWords = parseFile dictContents- in case dictWords of - Left _ -> return $ Left (MalformedDictionaryFile filePath)- Right wordList -> return $ Right (Dictionary $ HashSet.fromList wordList)+ makeDictionary filePath = join . fmap parseDictionary <$> readDictionaryFile filePath + readDictionaryFile :: FilePath -> IO (Either ScrabbleError String)+ readDictionaryFile filePath = convertFileError <$> (Exc.try (readFile filePath) :: (IO (Either Exc.IOException String))) where- toUpperCase = (map . map) toUpper - parseFile contents = liftM toUpperCase $ parse dictionaryFile "Malformed dictionary file " contents+ convertFileError = left (\_ -> DictionaryFileNotFound filePath) - dictionaryFile = - do- dictWords <- many word- _ <- eof- return dictWords+ parseDictionary :: String -> Either ScrabbleError Dictionary+ parseDictionary = either (Left . MalformedDictionaryFile . show) (Right . dictionaryFromWords) . parseFile+ where+ parseFile = parse dictionaryFile "" - word = - do- entry <- many letter- _ <- newline- return entry+ dictionaryFile = + do+ dictWords <- many word+ _ <- eof+ return dictWords++ word = + do+ entry <- many letter :: Parser String+ _ <- newline+ return entry+ + upperCaseWords :: [String] -> [String]+ upperCaseWords = (map . map) toUpper+
src/Wordify/Rules/FormedWord.hs view
@@ -38,11 +38,9 @@ the star tile, and be linear. Any blank tiles must be labeled. -} wordFormedFirstMove :: Board -> Map Pos Tile -> Either ScrabbleError FormedWords- wordFormedFirstMove board tiles = - if starPos `Map.notMember` tiles- then Left DoesNotCoverTheStarTile- else placedSquares board tiles >>= - \squares -> (FirstWord . main) <$> wordsFormed board squares+ wordFormedFirstMove board tiles+ | starPos `Map.notMember` tiles = Left DoesNotCoverTheStarTile+ | otherwise = placedSquares board tiles >>= fmap (FirstWord . main) . wordsFormed board {- | Returns the words formed by the tiles played on the board. A played word@@ -122,7 +120,7 @@ makeString word = M.mapMaybe (\(_, sq) -> tileIfOccupied sq >>= tileLetter) $ Foldable.toList word {-- Checks that the tiles can be placed, and if so turns a map of the squares at the placed positions.+ Checks that the tiles can be placed, and if so returns a map of the squares at the placed positions. A tile may be placed if the square is not already occupied, and if it is not an unlabeled blank tile. -} placedSquares :: Board -> Map Pos Tile -> Either ScrabbleError (Map Pos Square)@@ -166,7 +164,7 @@ middleFirstWord direction = case placedList of - x:[] -> Right (Seq.singleton x, minPos)+ [x] -> Right (Seq.singleton x, minPos) (x:xs) -> foldM (\(word, lastPos) (pos, square) -> if not $ stillOnPath lastPos pos direction
src/Wordify/Rules/LetterBag.hs view
@@ -24,6 +24,8 @@ import Control.Monad.ST import Data.STRef ++ {- | Creates a letter bag from a file where each line contains a space delimited letter character, letter value, and letter distribution. A blank letter is represented by a '_' character and has a disribution, but no value.
src/Wordify/Rules/Move.hs view
@@ -50,7 +50,7 @@ gameTransition = case move of PlaceTiles placed -> makeBoardMove game placed Exchange exchanged -> exchangeMove game exchanged- Pass -> passMove game+ Pass -> (Right . passMove) game makeBoardMove :: Game -> M.Map Pos Tile -> Either ScrabbleError GameTransition makeBoardMove game placed =@@ -86,7 +86,6 @@ PlaceTiles _ -> True _ -> False - exchangeMove :: Game -> [Tile] -> Either ScrabbleError GameTransition exchangeMove game exchangedTiles = let exchangeOutcome = exchangeLetters (bag game) exchangedTiles@@ -100,11 +99,10 @@ where player = currentPlayer game - passMove :: Game -> Either ScrabbleError GameTransition+ passMove :: Game -> GameTransition passMove game = let gameState = pass game - in - Right $ + in if gameFinished then GameFinished (finaliseGame gameState) Nothing (players gameState) else PassTransition gameState
src/Wordify/Rules/ScrabbleError.hs view
@@ -16,7 +16,7 @@ -- | The path given to a dictionary file was invalid. | DictionaryFileNotFound FilePath -- | The dictionary file could not be parsed as it was malformed.- | MalformedDictionaryFile FilePath+ | MalformedDictionaryFile String -- | A letter bag with insufficient tiles was used to create a game. | NotEnoughLettersInStartingBag Int -- | The player has made an illegal tile placement. Tiles placed must form a line of tiles.@@ -45,7 +45,7 @@ instance Show ScrabbleError where- show (MalformedDictionaryFile path) = "Dictionary file " ++ path ++ " was malformed."+ show (MalformedDictionaryFile reason) = "Dictionary file could not be parsed for the following reason: " ++ reason show (MalformedLetterBagFile path) = "Letter bag file " ++ path ++ " was malformed." show (DictionaryFileNotFound path) = "Dictionary file " ++ path ++ " was not found." show (LetterBagFileNotOpenable path) = "Letter bag file " ++ path ++ " was not openable"