module Game.LambdaHack.Client.AI.Preferences
( totalUsefulness, effectToBenefit
) where
import qualified Control.Monad.State as St
import qualified Data.EnumMap.Strict as EM
import Data.Maybe
import Game.LambdaHack.Common.Actor
import Game.LambdaHack.Common.ActorState
import qualified Game.LambdaHack.Common.Dice as Dice
import qualified Game.LambdaHack.Common.Effect as Effect
import Game.LambdaHack.Common.Faction
import Game.LambdaHack.Common.Item
import Game.LambdaHack.Common.ItemStrongest
import qualified Game.LambdaHack.Common.Kind as Kind
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Content.ItemKind
import Game.LambdaHack.Content.ModeKind
effectToBenefit :: Kind.COps -> Actor -> [ItemFull] -> Faction
-> Effect.Effect Int -> Int
effectToBenefit cops b activeItems fact eff =
let dungeonDweller = not $ fcanEscape $ gplayer fact
in case eff of
Effect.NoEffect _ -> 0
Effect.RefillHP p ->
let hpMax = sumSlotNoFilter Effect.EqpSlotAddMaxHP activeItems
in if p > 0
then 1 + 10 * min p (fromIntegral $ (xM hpMax bhp b) `divUp` oneM)
else max (99) (10 * p)
Effect.Hurt d -> (min 99 $ round (10 * Dice.meanDice d))
Effect.RefillCalm p ->
let calmMax = sumSlotNoFilter Effect.EqpSlotAddMaxCalm activeItems
in if p > 0
then 1 + min p (fromIntegral $ (xM calmMax bcalm b) `divUp` oneM)
else max (20) p
Effect.Dominate -> 200
Effect.Impress -> 10
Effect.CallFriend p -> 20 * p
Effect.Summon{} | dungeonDweller -> 1
Effect.Summon{} -> 0
Effect.CreateItem p -> 20 * p
Effect.ApplyPerfume -> 10
Effect.Burn p -> 15 * p
Effect.Ascend{} -> 1
Effect.Escape{} -> 10000
Effect.Paralyze p -> 20 * p
Effect.InsertMove p -> 50 * p
Effect.DropBestWeapon -> 50
Effect.DropEqp ' ' False -> 80
Effect.DropEqp ' ' True -> 100
Effect.DropEqp _ False -> 40
Effect.DropEqp _ True -> 50
Effect.SendFlying _ -> 10
Effect.PushActor _ -> 10
Effect.PullActor _ -> 10
Effect.Teleport p | p < 5 -> 5 * p
Effect.Teleport p | p < 10 -> 1
Effect.Teleport p -> 5 * p
Effect.PolyItem _ -> 0
Effect.Identify _ -> 0
Effect.ActivateInv ' ' -> 100
Effect.ActivateInv _ -> 50
Effect.Explode _ -> 10
Effect.OneOf _ -> 1
Effect.OnSmash _ -> 10
Effect.TimedAspect k asp -> k * (aspectToBenefit cops b asp) `div` 50
aspectToBenefit :: Kind.COps -> Actor -> Effect.Aspect Int -> Int
aspectToBenefit _cops _b asp =
case asp of
Effect.Periodic{} -> 0
Effect.AddMaxHP p -> p * 10
Effect.AddMaxCalm p -> p `divUp` 2
Effect.AddSpeed p -> p * 10000
Effect.AddSkills m -> 5 * sum (EM.elems m)
Effect.AddHurtMelee p -> p `divUp` 3
Effect.AddHurtRanged p -> p `divUp` 5
Effect.AddArmorMelee p -> p `divUp` 5
Effect.AddArmorRanged p -> p `divUp` 10
Effect.AddSight p -> p * 10
Effect.AddSmell p -> p * 2
Effect.AddLight p -> p * 10
totalUsefulness :: Kind.COps -> Actor -> [ItemFull] -> Faction -> ItemFull
-> Maybe (Int, (Int, Int))
totalUsefulness cops b activeItems fact itemFull =
let ben effects aspects =
let effBens = map (effectToBenefit cops b activeItems fact) effects
aspBens = map (aspectToBenefit cops b) aspects
periodicEffBens =
case strengthFromEqpSlot Effect.EqpSlotPeriodic itemFull of
Nothing -> []
Just in100 -> map (\eff -> eff * in100 `div` 5) effBens
selfBens = aspBens ++ periodicEffBens
eqpSum = if not (null selfBens) && minimum selfBens < 10
&& maximum selfBens > 10
then 0
else sum selfBens
effSum = sum effBens
isWeapon =
isJust (strengthFromEqpSlot Effect.EqpSlotWeapon itemFull)
totalSum = if goesIntoInv $ itemBase itemFull
then effSum
else if isWeapon
then effSum + eqpSum
else eqpSum
in (totalSum, (eqpSum, effSum))
in case itemDisco itemFull of
Just ItemDisco{itemAE=Just ItemAspectEffect{jaspects, jeffects}} ->
Just $ ben jeffects jaspects
Just ItemDisco{itemKind=ItemKind{iaspects, ieffects}} ->
let travA x =
St.evalState (Effect.aspectTrav x (return . round . Dice.meanDice))
()
jaspects = map travA iaspects
travE x =
St.evalState (Effect.effectTrav x (return . round . Dice.meanDice))
()
jeffects = map travE ieffects
in Just $ ben jeffects jaspects
_ -> Nothing