module Datatypes.Game (Game(..), Command(..), completed, new, cacheToScore, updateCache, powerPhrases, phraseConverter) where -- FIXME exports
|
|
|
|
import Data.Hashable (hash)
|
|
import qualified Data.List as List
|
|
import Data.Map.Strict (Map)
|
|
import qualified Data.Map.Strict as Map
|
|
import Data.Set (Set)
|
|
import qualified Data.Set as Set
|
|
|
|
import Datatypes.Board (Board)
|
|
import Datatypes.Unit (Unit)
|
|
import qualified Datatypes.Unit as Unit
|
|
|
|
data Command = MoveW
|
|
| MoveE
|
|
| MoveSW
|
|
| MoveSE
|
|
| RotateClockwise
|
|
| RotateCounterclockwise
|
|
deriving (Show,Eq,Ord)
|
|
|
|
type UnitHash = Int
|
|
|
|
type PhrasesCache = Map [Command] Int
|
|
|
|
data Game = Game {
|
|
board :: Board,
|
|
units :: [Unit],
|
|
visitedUnits :: Set UnitHash,
|
|
oldLines :: Int,
|
|
score :: Int,
|
|
history :: [Command],
|
|
phrasesCache :: PhrasesCache
|
|
}
|
|
deriving Show
|
|
|
|
completed :: Game -> Bool
|
|
completed game = null $ units game
|
|
|
|
new :: Board -> [Unit] -> Game
|
|
new b us = Game {
|
|
board = b,
|
|
units = (c:cs),
|
|
visitedUnits = Set.singleton (hash c),
|
|
oldLines = 0,
|
|
score = 0,
|
|
history = [],
|
|
phrasesCache = Map.empty
|
|
} where (c:cs) = map (flip Unit.centeredIn b) us
|
|
|
|
phraseConverter :: [Command] -> String
|
|
phraseConverter s = if s == reverse [MoveE, MoveSW, MoveW]
|
|
then "ei!"
|
|
else if s == reverse [MoveSW, MoveSW, MoveW, MoveSE, MoveSW, MoveSW, MoveW]
|
|
then "ia ! ia!"
|
|
else "PUPPA"
|
|
|
|
powerPhrases :: [[Command]]
|
|
powerPhrases = [
|
|
reverse [MoveE, MoveSW, MoveW],
|
|
reverse [MoveSW, MoveSW, MoveW, MoveSE, MoveSW, MoveSW, MoveW]
|
|
]
|
|
|
|
updateCache :: PhrasesCache -> [Command] -> PhrasesCache
|
|
updateCache cache history = innerUpdate cache history powerPhrases where
|
|
innerUpdate cache _ [] = cache
|
|
innerUpdate cache history (p:ps) = innerUpdate (updatedCache cache history p) history ps
|
|
updatedCache c h p | p `List.isPrefixOf` h = if Map.member p c
|
|
then Map.update (\a -> Just $ a + 1) p c
|
|
else Map.insert p 1 c
|
|
updatedCache c _ _ = c
|
|
|
|
cacheToScore :: PhrasesCache -> Int
|
|
cacheToScore items = sum $ map evalScore (Map.toAscList items) where
|
|
evalScore (phrase, count) = 2 * (length phrase) * count + if count > 0 then 300 else 0
|