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