-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | A scrabble library capturing the core game logic of scrabble.
--
-- A scrabble library which enforces legal transitions between moves.
-- Intended to facilitate the development of a playable game.
@package haskellscrabble
@version 1.1
module Wordify.Rules.Tile
-- | A tile is a letter with a value, or a Blank tile which may have been
-- given a letter. Blank tiles always have the value '0'.
data Tile
Letter :: Char -> Int -> Tile
Blank :: (Maybe Char) -> Tile
tileValue :: Tile -> Int
-- | isPlayble, applied to a played tile and compared against a tile
-- returns true if a player returned a letter tile on their rack, or if
-- the player played a Blank that has been given a letter
isPlayable :: Tile -> Tile -> Bool
tileLetter :: Tile -> Maybe Char
-- | Prints a letter in the style found on a scoresheet. E.g. blank letters
-- are printed in lowercase.
printLetter :: Tile -> Maybe Char
instance GHC.Classes.Ord Wordify.Rules.Tile.Tile
instance GHC.Classes.Eq Wordify.Rules.Tile.Tile
instance GHC.Show.Show Wordify.Rules.Tile.Tile
module Wordify.Rules.LetterBag.Internal
data LetterBag
LetterBag :: [Tile] -> Int -> StdGen -> LetterBag
[tiles] :: LetterBag -> [Tile]
[bagSize] :: LetterBag -> Int
[generator] :: LetterBag -> StdGen
instance GHC.Show.Show Wordify.Rules.LetterBag.Internal.LetterBag
instance GHC.Classes.Eq Wordify.Rules.LetterBag.Internal.LetterBag
module Wordify.Rules.Square
data Square
Normal :: (Maybe Tile) -> Square
DoubleLetter :: (Maybe Tile) -> Square
TripleLetter :: (Maybe Tile) -> Square
DoubleWord :: (Maybe Tile) -> Square
TripleWord :: (Maybe Tile) -> Square
isOccupied :: Square -> Bool
-- | Calculates the score of one played word.
--
-- The first list contains squares that are already on the board (and
-- thus are not subject to bonuses).
--
-- The second list contains squares that are newly occupied.
scoreSquares :: Seq Square -> Seq Square -> Int
squareIfOccupied :: Square -> Maybe Square
putTileOn :: Square -> Tile -> Square
tileIfOccupied :: Square -> Maybe Tile
instance GHC.Classes.Ord Wordify.Rules.Square.Square
instance GHC.Classes.Eq Wordify.Rules.Square.Square
instance GHC.Show.Show Wordify.Rules.Square.Square
module Wordify.Rules.Player
data Player
data LetterRack
makePlayer :: String -> Player
name :: Player -> Name
rack :: Player -> LetterRack
tilesOnRack :: Player -> [Tile]
score :: Player -> Score
increaseScore :: Player -> Int -> Player
giveTiles :: Player -> [Tile] -> Player
-- | Removes played tiles from the player's tile rack, if it was possible
-- for the player to play those tiles in the first place. A player may
-- play a tile on his rack, unless it is a blank, which must first be
-- assigned a letter.
removePlayedTiles :: Player -> [Tile] -> Maybe Player
removeTiles :: Player -> [Tile] -> Player
hasEmptyRack :: Player -> Bool
tileValues :: Player -> Int
reduceScore :: Player -> Int -> Player
exchange :: Player -> [Tile] -> [Tile] -> Maybe Player
instance GHC.Classes.Eq Wordify.Rules.Player.Player
instance GHC.Show.Show Wordify.Rules.Player.Player
instance GHC.Classes.Eq Wordify.Rules.Player.LetterRack
instance GHC.Show.Show Wordify.Rules.Player.LetterRack
module Wordify.Rules.Pos.Internal
data Pos
Pos :: !Int -> !Int -> !String -> Pos
instance GHC.Classes.Ord Wordify.Rules.Pos.Internal.Pos
instance GHC.Show.Show Wordify.Rules.Pos.Internal.Pos
instance GHC.Classes.Eq Wordify.Rules.Pos.Internal.Pos
module Wordify.Rules.Pos
data Pos
posAt :: (Int, Int) -> Maybe Pos
-- | The position above the given position, if it exists.
above :: Pos -> Maybe Pos
-- | The position below the given position, if it exists.
below :: Pos -> Maybe Pos
-- | The position to the left of the given position, if it exists.
left :: Pos -> Maybe Pos
-- | The position to the right of the given position, if it exists.
right :: Pos -> Maybe Pos
xPos :: Pos -> Int
yPos :: Pos -> Int
gridValue :: Pos -> String
-- | The position of the star square
starPos :: Pos
posMin :: Int
posMax :: Int
module Wordify.Rules.ScrabbleError
data ScrabbleError
-- | The caller has supplied an invalid path to a letter bag file, or the
-- file is not openable
LetterBagFileNotOpenable :: String -> ScrabbleError
-- | The letter bag file is marformed, so could not be parsed.
MalformedLetterBagFile :: FilePath -> ScrabbleError
-- | The path given to a dictionary file was invalid.
DictionaryFileNotFound :: FilePath -> ScrabbleError
-- | The dictionary file could not be parsed as it was malformed.
MalformedDictionaryFile :: String -> ScrabbleError
-- | A letter bag with insufficient tiles was used to create a game.
NotEnoughLettersInStartingBag :: Int -> ScrabbleError
-- | The player has made an illegal tile placement. Tiles placed must form
-- a line of tiles.
MisplacedLetter :: Pos -> ScrabbleError
-- | The tiles the player placed do not connect with any word (applies
-- after the first move on the board)
DoesNotConnectWithWord :: ScrabbleError
-- | The client put the player in the situation to be able to place no
-- tiles.
NoTilesPlaced :: ScrabbleError
-- | The first move on the board does not cover the star.
DoesNotCoverTheStarTile :: ScrabbleError
-- | The client allowed the player to place tiles on a square that is
-- already occupied with tiles.
PlacedTileOnOccupiedSquare :: Pos -> Tile -> ScrabbleError
-- | A blank tile must be labeled with a letter before being placed.
CannotPlaceBlankWithoutLetter :: Pos -> ScrabbleError
-- | The tiles the player placed formed one or more words which are not in
-- the dictionary.
WordsNotInDictionary :: [String] -> ScrabbleError
-- | The caller allowed the client to place tiles on the board which were
-- not in their rack.
PlayerCannotPlace :: LetterRack -> [Tile] -> ScrabbleError
-- | The caller allowed the player to attempt to exchange when no letters
-- were left in the bag.
CannotExchangeWhenNoLettersInBag :: ScrabbleError
-- | The caller allowed the player to attempt to exchange tiles that they
-- do not have.
PlayerCannotExchange :: LetterRack -> [Tile] -> ScrabbleError
-- | The caller allowed a move to be made when the game is finished.
GameNotInProgress :: ScrabbleError
MiscError :: String -> ScrabbleError
instance GHC.Classes.Eq Wordify.Rules.ScrabbleError.ScrabbleError
instance GHC.Show.Show Wordify.Rules.ScrabbleError.ScrabbleError
module Wordify.Rules.LetterBag
data LetterBag
-- | 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.
--
-- If successful, the letter bag is shuffled before it is returned.
makeBag :: FilePath -> IO (Either ScrabbleError LetterBag)
tiles :: LetterBag -> [Tile]
-- | Creates a letter bag from a list of tiles. The order of the tiles is
-- retained in the resulting letter bag.
--
-- This function is effectful as it is necessary to create a stdGen for
-- list to allow it to be shuffled using this generator in the future.
bagFromTiles :: [Tile] -> IO LetterBag
-- | Creates a letter bag using a list of tiles, and a generator which
-- should be used when shuffling the bag. This function allows a game to
-- be stepped through from the beginning where the moves and original
-- generator were recorded, with any shuffling yielding the same bag as
-- in the original game.
makeBagUsingGenerator :: [Tile] -> StdGen -> LetterBag
-- | Takes n numbers from a letter bag, yielding Nothing if
-- there is not enough tiles left in the bag or a Just tuple where
-- the left value is the taken tiles, and the right value is the new bag.
takeLetters :: LetterBag -> Int -> Maybe ([Tile], LetterBag)
-- | Exchanges given tiles for the same number of tiles from the bag. The
-- exchanged letters are added to the bag, the bag is then shuffled, and
-- then the same number of tiles as exchanged are drawn from the bag.
--
-- Returns Nothing if there are not enough letters in the bag to
-- exchange the given tiles for. Otherwise returns Just with a
-- tuple with the tiles given, and the new letterbag.
exchangeLetters :: LetterBag -> [Tile] -> (Maybe ([Tile], LetterBag))
-- | Shuffles the contents of a letter bag. The bag is shuffled using the
-- random generator which was created while constructing the bag.
--
-- This function should not be used when creating an additional game with
-- a new letter bag as the same seed value will be shared across games
-- (meaning tiles will come out of the bag in the same order.) When
-- constructing an additional game, use shuffleWithNewGenerator.
shuffleBag :: LetterBag -> LetterBag
-- | Shuffles a letter bag using a new random generator. This function
-- should be used when spawning a new game using a letter bag with all
-- the tiles remaining so that letter bags are unique between game
-- instances.
shuffleWithNewGenerator :: LetterBag -> IO LetterBag
bagSize :: LetterBag -> Int
-- | Get the letter bag's current generator, which will be used to shuffle
-- the contents of the bag in the next exchange or shuffle. If taken at
-- the start of the game, with the original list of tiles in the bag in
-- order, the game moves may be replayed in order with the original
-- results of any shuffle retained.
getGenerator :: LetterBag -> StdGen
module Wordify.Rules.Dictionary
data Dictionary
-- | 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)
dictionaryFromWords :: [String] -> Dictionary
isValidWord :: Dictionary -> String -> Bool
-- | Returns the list of words which are not present in the given
-- dictionary from a list of input words.
invalidWords :: Dictionary -> [String] -> [String]
instance GHC.Show.Show Wordify.Rules.Dictionary.Dictionary
module Wordify.Rules.Board.Internal
data Board
Board :: (Map Pos Square) -> Board
instance GHC.Classes.Eq Wordify.Rules.Board.Internal.Board
module Wordify.Rules.Board
data Board
-- | Creates an empty board.
emptyBoard :: Board
-- | Returns all the squares on the board, ordered by column then row.
allSquares :: Board -> [(Pos, Square)]
-- | Places a tile on a square and yields the new board, if the target
-- square is empty. Otherwise yields Nothing.
placeTile :: Board -> Tile -> Pos -> Maybe Board
-- | Returns the square at a given position if it is occupied by a tile.
-- Otherwise returns Nothing.
occupiedSquareAt :: Board -> Pos -> Maybe Square
-- | All letters immediately above a given square until a non-occupied
-- square
lettersAbove :: Board -> Pos -> Seq (Pos, Square)
-- | All letters immediately below a given square until a non-occupied
-- square
lettersBelow :: Board -> Pos -> Seq (Pos, Square)
-- | All letters immediately left of a given square until a non-occupied
-- square
lettersLeft :: Board -> Pos -> Seq (Pos, Square)
-- | All letters immediately right of a given square until a non-occupied
-- square
lettersRight :: Board -> Pos -> Seq (Pos, Square)
-- | Returns the square at a given position if it is not occupied by a
-- tile. Otherwise returns Nothing.
unoccupiedSquareAt :: Board -> Pos -> Maybe Square
-- | Pretty prints a board to a human readable string representation.
-- Helpful for development.
prettyPrint :: Board -> String
instance GHC.Show.Show Wordify.Rules.Board.Internal.Board
module Wordify.Rules.Game
data Game
-- | Starts a new game.
--
-- A game has at least 2 players, and 2 optional players (player 3 and
-- 4.) The players should be newly created, as tiles from the letter bag
-- will be distributed to each player.
--
-- Takes a letter bag and dictionary, which should be localised to the
-- same language.
--
-- Yields a tuple with the first player and the initial game state.
-- Returns a Left if there are not enough tiles in the letter bag
-- to distribute to the players.
makeGame :: (Player, Player, Maybe (Player, Maybe Player)) -> LetterBag -> Dictionary -> Either ScrabbleError Game
-- | Returns a history of the moves made in the game.
movesMade :: Game -> [Move]
gameStatus :: Game -> GameStatus
board :: Game -> Board
bag :: Game -> LetterBag
dictionary :: Game -> Dictionary
moveNumber :: Game -> Int
player1 :: Game -> Player
player2 :: Game -> Player
optionalPlayers :: Game -> Maybe (Player, Maybe Player)
currentPlayer :: Game -> Player
playerNumber :: Game -> Int
data GameStatus
InProgress :: GameStatus
Finished :: GameStatus
players :: Game -> [Player]
passes :: Game -> Int
numberOfPlayers :: Game -> Int
history :: Game -> History
data History
History :: LetterBag -> (Seq Move) -> History
module Wordify.Rules.FormedWord
data FormedWords
type FormedWord = Seq (Pos, Square)
type PlacedSquares = Map Pos Square
-- | All the words formed by a play.
allWords :: FormedWords -> [FormedWord]
-- | Returns the main word formed by the played tiles. The main word is the
-- linear stretch of tiles formed by the tiles placed.
mainWord :: FormedWords -> FormedWord
-- | Returns the list of words which were adjacent to the main word formed.
adjacentWords :: FormedWords -> [FormedWord]
-- | Returns the list of positions mapped to the squares that the player
-- placed their tiles on.
playerPlaced :: FormedWords -> [(Pos, Square)]
playerPlacedMap :: FormedWords -> Map Pos Square
-- | Scores an individual word.
--
-- Note: overallscore should be used to obtain the overall score as it
-- takes into account any bingo bonuses.
scoreWord :: PlacedSquares -> FormedWord -> Int
-- | Calculates the overall score of the play.
--
-- If a player managed to place all 7 of their letters, then they receive
-- a bingo bonus of 50 points.
overallScore :: FormedWords -> Int
-- | Returns true if the player placed all 7 of their letters while forming
-- these words, incurring a + 50 score bonus.
bingoBonusApplied :: FormedWords -> Bool
-- | Pretty prints the places a given formed word intersects with letters
-- that were already on the board using brackets. E.g. T(HI)S would
-- denote that the player placed a T and an S on to the
-- board, using the already placed word HI to form the new word
-- THIS.
prettyPrintIntersections :: PlacedSquares -> FormedWord -> String
makeString :: FormedWord -> String
-- | Returns the words formed by the play as strings.
wordStrings :: FormedWords -> [String]
-- | Scores the words formed by the tiles placed. The first item in the
-- tuple is the overall score, while the second item is the list of
-- scores for all the words formed.
wordsWithScores :: FormedWords -> (Int, [(String, Int)])
-- | Returns the words formed by the tiles played on the board. A played
-- word must be connected to a tile already on the board (or intersect
-- tiles on the board), and be formed linearly. Any blank tiles must be
-- labeled.
wordsFormedMidGame :: Board -> Map Pos Tile -> Either ScrabbleError FormedWords
-- | Returns the word formed by the first move on the board. The word must
-- cover the star tile, and be linear. Any blank tiles must be labeled.
wordFormedFirstMove :: Board -> Map Pos Tile -> Either ScrabbleError FormedWords
instance GHC.Classes.Eq Wordify.Rules.FormedWord.Direction
instance GHC.Classes.Eq Wordify.Rules.FormedWord.FormedWords
instance GHC.Show.Show Wordify.Rules.FormedWord.FormedWords
module Wordify.Rules.Move
data Move
PlaceTiles :: (Map Pos Tile) -> Move
Exchange :: [Tile] -> Move
Pass :: Move
data GameTransition
-- | The new player (with their updated letter rack and score), new game
-- state, and the words formed by the move
MoveTransition :: Player -> Game -> FormedWords -> GameTransition
-- | The new game state, and the player with their rack before and after
-- the exchange respectively.
ExchangeTransition :: Game -> Player -> Player -> GameTransition
-- | The new game state with the opportunity to play passed on to the next
-- player.
PassTransition :: Game -> GameTransition
-- | The game has finished. The final game state, and the final words
-- formed (if the game was ended by a player placing their final tiles.)
-- The players before their scores were increased or decreased is also
-- given.
GameFinished :: Game -> (Maybe FormedWords) -> [Player] -> GameTransition
-- | Transitiions the game to the next state. If the move places tiles, the
-- player must have the tiles to place and place the tiles legally. If
-- the move exchanges tiles, the bag must not be empty and the player
-- must have the tiles to exchange. A ScrabbleError is returned if these
-- condtions are not the case.
makeMove :: Game -> Move -> Either ScrabbleError GameTransition
newGame :: GameTransition -> Game
-- | Restores a game from a list of moves. The game must be set up in the
-- way the original game was set up (including the letter bag constructed
-- with the same tiles and random generator, dictionary and the list of
-- players in the original order.)
--
-- If the game is not set up as it was originally, this function will
-- return a scrabble error with the move which was invalid with the given
-- state. For example, if the original players are not ordered in the
-- correct way then the player will not have the required tiles to make
-- the move.
restoreGame :: Game -> NonEmpty Move -> Either ScrabbleError (NonEmpty GameTransition)
-- | Maps each move to a resulting game transition, if the move is legal.
-- Has the same semantics as restoreGame but returns a list of
-- Either so that laziness can be maintained, meaning all the game
-- transitions dont have to be buffered before they can be consumed.
restoreGameLazy :: Game -> NonEmpty Move -> NonEmpty (Either ScrabbleError GameTransition)