You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
2.5 KiB

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