module Game.LambdaHack.Common.Faction
( FactionId, FactionDict, Faction(..), Diplomacy(..), Outcome(..), Status(..)
, isHeroFact, isCivilianFact, isHorrorFact, isSpawnFact, isSummonFact
, isAllMoveFact, keepArenaFact, isAtWar, isAllied
, difficultyBound, difficultyDefault, difficultyCoeff
) where
import Data.Binary
import qualified Data.EnumMap.Strict as EM
import Data.Text (Text)
import qualified Game.LambdaHack.Common.Ability as Ability
import Game.LambdaHack.Common.Actor
import qualified Game.LambdaHack.Common.Color as Color
import Game.LambdaHack.Common.Item
import qualified Game.LambdaHack.Common.Kind as Kind
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Content.FactionKind
import Game.LambdaHack.Content.ItemKind
import Game.LambdaHack.Content.ModeKind
type FactionDict = EM.EnumMap FactionId Faction
data Faction = Faction
{ gkind :: !(Kind.Id FactionKind)
, gname :: !Text
, gcolor :: !Color.Color
, gplayer :: !Player
, gdipl :: !Dipl
, gquit :: !(Maybe Status)
, gleader :: !(Maybe ActorId)
, gsha :: !ItemBag
, gvictims :: !(EM.EnumMap (Kind.Id ItemKind) Int)
}
deriving (Show, Eq)
data Diplomacy =
Unknown
| Neutral
| Alliance
| War
deriving (Show, Eq, Ord, Enum)
type Dipl = EM.EnumMap FactionId Diplomacy
data Outcome =
Killed
| Defeated
| Camping
| Conquer
| Escape
| Restart
deriving (Show, Eq, Ord, Enum)
data Status = Status
{ stOutcome :: !Outcome
, stDepth :: !Int
, stInfo :: !Text
}
deriving (Show, Eq, Ord)
isHeroFact :: Faction -> Bool
isHeroFact fact = playerIsHero (gplayer fact)
isCivilianFact :: Kind.COps -> Faction -> Bool
isCivilianFact Kind.COps{cofaction=Kind.Ops{okind}} fact =
let kind = okind (gkind fact)
in maybe False (> 0) $ lookup "civilian" $ ffreq kind
isHorrorFact :: Kind.COps -> Faction -> Bool
isHorrorFact Kind.COps{cofaction=Kind.Ops{okind}} fact =
let kind = okind (gkind fact)
in maybe False (> 0) $ lookup "horror" $ ffreq kind
isSpawnFact :: Faction -> Bool
isSpawnFact fact = playerIsSpawn (gplayer fact)
isSummonFact :: Kind.COps -> Faction -> Bool
isSummonFact Kind.COps{cofaction=Kind.Ops{okind}} fact =
let kind = okind (gkind fact)
in maybe False (> 0) $ lookup "summon" $ ffreq kind
isAllMoveFact :: Kind.COps -> Faction -> Bool
isAllMoveFact Kind.COps{cofaction=Kind.Ops{okind}} fact =
let kind = okind (gkind fact)
skillsLeader = fSkillsLeader kind
skillsOther = fSkillsOther kind
in EM.findWithDefault 0 Ability.AbMove skillsLeader > 0
&& EM.findWithDefault 0 Ability.AbMove skillsOther > 0
keepArenaFact :: Faction -> Bool
keepArenaFact fact = playerLeader (gplayer fact) && not (isSpawnFact fact)
isAtWar :: Faction -> FactionId -> Bool
isAtWar fact fid = War == EM.findWithDefault Unknown fid (gdipl fact)
isAllied :: Faction -> FactionId -> Bool
isAllied fact fid = Alliance == EM.findWithDefault Unknown fid (gdipl fact)
difficultyBound :: Int
difficultyBound = 9
difficultyDefault :: Int
difficultyDefault = (1 + difficultyBound) `div` 2
difficultyCoeff :: Int -> Int
difficultyCoeff n = difficultyDefault n
instance Binary Faction where
put Faction{..} = do
put gkind
put gname
put gcolor
put gplayer
put gdipl
put gquit
put gleader
put gsha
put gvictims
get = do
gkind <- get
gname <- get
gcolor <- get
gplayer <- get
gdipl <- get
gquit <- get
gleader <- get
gsha <- get
gvictims <- get
return $! Faction{..}
instance Binary Diplomacy where
put = putWord8 . toEnum . fromEnum
get = fmap (toEnum . fromEnum) getWord8
instance Binary Outcome where
put = putWord8 . toEnum . fromEnum
get = fmap (toEnum . fromEnum) getWord8
instance Binary Status where
put Status{..} = do
put stOutcome
put stDepth
put stInfo
get = do
stOutcome <- get
stDepth <- get
stInfo <- get
return $! Status{..}