    -- | Operations on the 'Actor' type, and related, that need the 'State' type,
    -- but not our custom monad types.
    module Game.LambdaHack.Common.ActorState
      ( fidActorNotProjGlobalAssocs, actorAssocs, fidActorRegularAssocs
      , fidActorRegularIds, foeRegularAssocs, foeRegularList
      , friendRegularAssocs, friendRegularList, bagAssocs, bagAssocsK
      , posToBig, posToBigAssoc, posToProjs, posToProjAssocs
      , posToAids, posToAidAssocs, calculateTotal, itemPrice, findIid, combinedItems
      , getActorBody, getActorMaxSkills, actorCurrentSkills, canTraverse
      , getCarriedAssocsAndTrunk, getContainerBag
      , getFloorBag, getEmbedBag, getBodyStoreBag, getFactionStashBag
      , mapActorItems_, getActorAssocs
      , memActor, getLocalTime, regenCalmDelta, actorInAmbient
      , dispEnemy, itemToFull, fullAssocs, kitAssocs
      , getItemKindId, getIidKindId, getItemKind, getIidKind
      , getItemKindIdServer, getIidKindIdServer, getItemKindServer, getIidKindServer
      , tileAlterable, lidFromC, posFromC, anyFoeAdj, anyHarmfulFoeAdj
      , adjacentBigAssocs, adjacentProjAssocs, armorHurtBonus, inMelee
      ) where

    import Prelude ()

    import Game.LambdaHack.Core.Prelude

    import qualified Data.EnumMap.Strict as EM
    import qualified Data.EnumSet as ES
    import           Data.Int (Int64)
    import           GHC.Exts (inline)

    import           Game.LambdaHack.Common.Actor
    import           Game.LambdaHack.Common.Faction
    import           Game.LambdaHack.Common.Item
    import           Game.LambdaHack.Common.Kind
    import           Game.LambdaHack.Common.Level
    import           Game.LambdaHack.Common.Misc
    import           Game.LambdaHack.Common.Point
    import           Game.LambdaHack.Common.State
    import qualified Game.LambdaHack.Common.Tile as Tile
    import           Game.LambdaHack.Common.Time
    import           Game.LambdaHack.Common.Types
    import           Game.LambdaHack.Common.Vector
    import qualified Game.LambdaHack.Content.ItemKind as IK
    import           Game.LambdaHack.Content.FactionKind
    import qualified Game.LambdaHack.Content.TileKind as TK
    import qualified Game.LambdaHack.Definition.Ability as Ability
    import           Game.LambdaHack.Definition.Defs

    fidActorNotProjGlobalAssocs :: FactionId -> State -> [(ActorId, Actor)]
    fidActorNotProjGlobalAssocs :: FactionId -> State -> [(ActorId, Actor)]
    fidActorNotProjGlobalAssocs FactionId
    fid State
    s =
      let f :: (ActorId, Actor) -> Bool
    f (ActorId
    _, Actor
    b) = Bool -> Bool
    not (Actor -> Bool
    bproj Actor
    b) Bool -> Bool -> Bool
    && Actor -> FactionId
    bfid Actor
    b FactionId -> FactionId -> Bool
    forall a. Eq a => a -> a -> Bool
    == FactionId
    fid
      in ((ActorId, Actor) -> Bool)
    -> [(ActorId, Actor)] -> [(ActorId, Actor)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (ActorId, Actor) -> Bool
    f ([(ActorId, Actor)] -> [(ActorId, Actor)])
    -> [(ActorId, Actor)] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ EnumMap ActorId Actor -> [(ActorId, Actor)]
    forall k a. Enum k => EnumMap k a -> [(k, a)]
    EM.assocs (EnumMap ActorId Actor -> [(ActorId, Actor)])
    -> EnumMap ActorId Actor -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ State -> EnumMap ActorId Actor
    sactorD State
    s

    actorAssocs :: (FactionId -> Bool) -> LevelId -> State
                -> [(ActorId, Actor)]
    actorAssocs :: (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)]
    actorAssocs FactionId -> Bool
    p LevelId
    lid State
    s =
      let f :: (ActorId, Actor) -> Bool
    f (ActorId
    _, Actor
    b) = Actor -> LevelId
    blid Actor
    b LevelId -> LevelId -> Bool
    forall a. Eq a => a -> a -> Bool
    == LevelId
    lid Bool -> Bool -> Bool
    && FactionId -> Bool
    p (Actor -> FactionId
    bfid Actor
    b)
      in ((ActorId, Actor) -> Bool)
    -> [(ActorId, Actor)] -> [(ActorId, Actor)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (ActorId, Actor) -> Bool
    f ([(ActorId, Actor)] -> [(ActorId, Actor)])
    -> [(ActorId, Actor)] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ EnumMap ActorId Actor -> [(ActorId, Actor)]
    forall k a. Enum k => EnumMap k a -> [(k, a)]
    EM.assocs (EnumMap ActorId Actor -> [(ActorId, Actor)])
    -> EnumMap ActorId Actor -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ State -> EnumMap ActorId Actor
    sactorD State
    s

    actorRegularAssocs :: (FactionId -> Bool) -> LevelId -> State
                       -> [(ActorId, Actor)]
    {-# INLINE actorRegularAssocs #-}
    actorRegularAssocs :: (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)]
    actorRegularAssocs FactionId -> Bool
    p LevelId
    lid State
    s =
      let f :: (ActorId, Actor) -> Bool
    f (ActorId
    _, Actor
    b) = Bool -> Bool
    not (Actor -> Bool
    bproj Actor
    b) Bool -> Bool -> Bool
    && Actor -> LevelId
    blid Actor
    b LevelId -> LevelId -> Bool
    forall a. Eq a => a -> a -> Bool
    == LevelId
    lid Bool -> Bool -> Bool
    && FactionId -> Bool
    p (Actor -> FactionId
    bfid Actor
    b) Bool -> Bool -> Bool
    && Actor -> Int64
    bhp Actor
    b Int64 -> Int64 -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int64
    0
      in ((ActorId, Actor) -> Bool)
    -> [(ActorId, Actor)] -> [(ActorId, Actor)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (ActorId, Actor) -> Bool
    f ([(ActorId, Actor)] -> [(ActorId, Actor)])
    -> [(ActorId, Actor)] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ EnumMap ActorId Actor -> [(ActorId, Actor)]
    forall k a. Enum k => EnumMap k a -> [(k, a)]
    EM.assocs (EnumMap ActorId Actor -> [(ActorId, Actor)])
    -> EnumMap ActorId Actor -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ State -> EnumMap ActorId Actor
    sactorD State
    s

    fidActorRegularAssocs :: FactionId -> LevelId -> State -> [(ActorId, Actor)]
    fidActorRegularAssocs :: FactionId -> LevelId -> State -> [(ActorId, Actor)]
    fidActorRegularAssocs FactionId
    fid = (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)]
    actorRegularAssocs (FactionId -> FactionId -> Bool
    forall a. Eq a => a -> a -> Bool
    == FactionId
    fid)

    fidActorRegularIds :: FactionId -> LevelId -> State -> [ActorId]
    fidActorRegularIds :: FactionId -> LevelId -> State -> [ActorId]
    fidActorRegularIds FactionId
    fid LevelId
    lid State
    s =
      ((ActorId, Actor) -> ActorId) -> [(ActorId, Actor)] -> [ActorId]
    forall a b. (a -> b) -> [a] -> [b]
    map (ActorId, Actor) -> ActorId
    forall a b. (a, b) -> a
    fst ([(ActorId, Actor)] -> [ActorId])
    -> [(ActorId, Actor)] -> [ActorId]
    forall a b. (a -> b) -> a -> b
    $ (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)]
    actorRegularAssocs (FactionId -> FactionId -> Bool
    forall a. Eq a => a -> a -> Bool
    == FactionId
    fid) LevelId
    lid State
    s

    foeRegularAssocs :: FactionId -> LevelId -> State -> [(ActorId, Actor)]
    foeRegularAssocs :: FactionId -> LevelId -> State -> [(ActorId, Actor)]
    foeRegularAssocs FactionId
    fid LevelId
    lid State
    s =
      let fact :: Faction
    fact = (EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! FactionId
    fid) (EnumMap FactionId Faction -> Faction)
    -> (State -> EnumMap FactionId Faction) -> State -> Faction
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> EnumMap FactionId Faction
    sfactionD (State -> Faction) -> State -> Faction
    forall a b. (a -> b) -> a -> b
    $ State
    s
      in (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)]
    actorRegularAssocs ((FactionId -> Faction -> FactionId -> Bool)
    -> FactionId -> Faction -> FactionId -> Bool
    forall a. a -> a
    inline FactionId -> Faction -> FactionId -> Bool
    isFoe FactionId
    fid Faction
    fact) LevelId
    lid State
    s

    foeRegularList :: FactionId -> LevelId -> State -> [Actor]
    foeRegularList :: FactionId -> LevelId -> State -> [Actor]
    foeRegularList FactionId
    fid LevelId
    lid State
    s =
      let fact :: Faction
    fact = (EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! FactionId
    fid) (EnumMap FactionId Faction -> Faction)
    -> (State -> EnumMap FactionId Faction) -> State -> Faction
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> EnumMap FactionId Faction
    sfactionD (State -> Faction) -> State -> Faction
    forall a b. (a -> b) -> a -> b
    $ State
    s
      in ((ActorId, Actor) -> Actor) -> [(ActorId, Actor)] -> [Actor]
    forall a b. (a -> b) -> [a] -> [b]
    map (ActorId, Actor) -> Actor
    forall a b. (a, b) -> b
    snd ([(ActorId, Actor)] -> [Actor]) -> [(ActorId, Actor)] -> [Actor]
    forall a b. (a -> b) -> a -> b
    $ (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)]
    actorRegularAssocs ((FactionId -> Faction -> FactionId -> Bool)
    -> FactionId -> Faction -> FactionId -> Bool
    forall a. a -> a
    inline FactionId -> Faction -> FactionId -> Bool
    isFoe FactionId
    fid Faction
    fact) LevelId
    lid State
    s

    friendRegularAssocs :: FactionId -> LevelId -> State -> [(ActorId, Actor)]
    friendRegularAssocs :: FactionId -> LevelId -> State -> [(ActorId, Actor)]
    friendRegularAssocs FactionId
    fid LevelId
    lid State
    s =
      let fact :: Faction
    fact = (EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! FactionId
    fid) (EnumMap FactionId Faction -> Faction)
    -> (State -> EnumMap FactionId Faction) -> State -> Faction
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> EnumMap FactionId Faction
    sfactionD (State -> Faction) -> State -> Faction
    forall a b. (a -> b) -> a -> b
    $ State
    s
      in (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)]
    actorRegularAssocs ((FactionId -> Faction -> FactionId -> Bool)
    -> FactionId -> Faction -> FactionId -> Bool
    forall a. a -> a
    inline FactionId -> Faction -> FactionId -> Bool
    isFriend FactionId
    fid Faction
    fact) LevelId
    lid State
    s

    friendRegularList :: FactionId -> LevelId -> State -> [Actor]
    friendRegularList :: FactionId -> LevelId -> State -> [Actor]
    friendRegularList FactionId
    fid LevelId
    lid State
    s =
      let fact :: Faction
    fact = (EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! FactionId
    fid) (EnumMap FactionId Faction -> Faction)
    -> (State -> EnumMap FactionId Faction) -> State -> Faction
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> EnumMap FactionId Faction
    sfactionD (State -> Faction) -> State -> Faction
    forall a b. (a -> b) -> a -> b
    $ State
    s
      in ((ActorId, Actor) -> Actor) -> [(ActorId, Actor)] -> [Actor]
    forall a b. (a -> b) -> [a] -> [b]
    map (ActorId, Actor) -> Actor
    forall a b. (a, b) -> b
    snd ([(ActorId, Actor)] -> [Actor]) -> [(ActorId, Actor)] -> [Actor]
    forall a b. (a -> b) -> a -> b
    $ (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)]
    actorRegularAssocs ((FactionId -> Faction -> FactionId -> Bool)
    -> FactionId -> Faction -> FactionId -> Bool
    forall a. a -> a
    inline FactionId -> Faction -> FactionId -> Bool
    isFriend FactionId
    fid Faction
    fact) LevelId
    lid State
    s

    bagAssocs :: State -> ItemBag -> [(ItemId, Item)]
    bagAssocs :: State -> ItemBag -> [(ItemId, Item)]
    bagAssocs State
    s ItemBag
    bag =
      let iidItem :: ItemId -> (ItemId, Item)
    iidItem ItemId
    iid = (ItemId
    iid, ItemId -> State -> Item
    getItemBody ItemId
    iid State
    s)
      in (ItemId -> (ItemId, Item)) -> [ItemId] -> [(ItemId, Item)]
    forall a b. (a -> b) -> [a] -> [b]
    map ItemId -> (ItemId, Item)
    iidItem ([ItemId] -> [(ItemId, Item)]) -> [ItemId] -> [(ItemId, Item)]
    forall a b. (a -> b) -> a -> b
    $ ItemBag -> [ItemId]
    forall k a. Enum k => EnumMap k a -> [k]
    EM.keys ItemBag
    bag

    bagAssocsK :: State -> ItemBag -> [(ItemId, (Item, ItemQuant))]
    bagAssocsK :: State -> ItemBag -> [(ItemId, (Item, ItemQuant))]
    bagAssocsK State
    s ItemBag
    bag =
      let iidItem :: (ItemId, ItemQuant) -> (ItemId, (Item, ItemQuant))
    iidItem (ItemId
    iid, ItemQuant
    kit) = (ItemId
    iid, (ItemId -> State -> Item
    getItemBody ItemId
    iid State
    s, ItemQuant
    kit))
      in ((ItemId, ItemQuant) -> (ItemId, (Item, ItemQuant)))
    -> [(ItemId, ItemQuant)] -> [(ItemId, (Item, ItemQuant))]
    forall a b. (a -> b) -> [a] -> [b]
    map (ItemId, ItemQuant) -> (ItemId, (Item, ItemQuant))
    iidItem ([(ItemId, ItemQuant)] -> [(ItemId, (Item, ItemQuant))])
    -> [(ItemId, ItemQuant)] -> [(ItemId, (Item, ItemQuant))]
    forall a b. (a -> b) -> a -> b
    $ ItemBag -> [(ItemId, ItemQuant)]
    forall k a. Enum k => EnumMap k a -> [(k, a)]
    EM.assocs ItemBag
    bag

    posToBig :: Point -> LevelId -> State -> Maybe ActorId
    posToBig :: Point -> LevelId -> State -> Maybe ActorId
    posToBig Point
    pos LevelId
    lid State
    s = Point -> Level -> Maybe ActorId
    posToBigLvl Point
    pos (Level -> Maybe ActorId) -> Level -> Maybe ActorId
    forall a b. (a -> b) -> a -> b
    $ State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! LevelId
    lid

    posToBigAssoc :: Point -> LevelId -> State -> Maybe (ActorId, Actor)
    posToBigAssoc :: Point -> LevelId -> State -> Maybe (ActorId, Actor)
    posToBigAssoc Point
    pos LevelId
    lid State
    s =
      let maid :: Maybe ActorId
    maid = Point -> Level -> Maybe ActorId
    posToBigLvl Point
    pos (Level -> Maybe ActorId) -> Level -> Maybe ActorId
    forall a b. (a -> b) -> a -> b
    $ State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! LevelId
    lid
      in (ActorId -> (ActorId, Actor))
    -> Maybe ActorId -> Maybe (ActorId, Actor)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\ActorId
    aid -> (ActorId
    aid, ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s)) Maybe ActorId
    maid

    posToProjs :: Point -> LevelId -> State -> [ActorId]
    posToProjs :: Point -> LevelId -> State -> [ActorId]
    posToProjs Point
    pos LevelId
    lid State
    s = Point -> Level -> [ActorId]
    posToProjsLvl Point
    pos (Level -> [ActorId]) -> Level -> [ActorId]
    forall a b. (a -> b) -> a -> b
    $ State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! LevelId
    lid

    posToProjAssocs :: Point -> LevelId -> State -> [(ActorId, Actor)]
    posToProjAssocs :: Point -> LevelId -> State -> [(ActorId, Actor)]
    posToProjAssocs Point
    pos LevelId
    lid State
    s =
      let l :: [ActorId]
    l = Point -> Level -> [ActorId]
    posToProjsLvl Point
    pos (Level -> [ActorId]) -> Level -> [ActorId]
    forall a b. (a -> b) -> a -> b
    $ State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! LevelId
    lid
      in (ActorId -> (ActorId, Actor)) -> [ActorId] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ActorId
    aid -> (ActorId
    aid, ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s)) [ActorId]
    l

    posToAids :: Point -> LevelId -> State -> [ActorId]
    posToAids :: Point -> LevelId -> State -> [ActorId]
    posToAids Point
    pos LevelId
    lid State
    s = Point -> Level -> [ActorId]
    posToAidsLvl Point
    pos (Level -> [ActorId]) -> Level -> [ActorId]
    forall a b. (a -> b) -> a -> b
    $ State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! LevelId
    lid

    posToAidAssocs :: Point -> LevelId -> State -> [(ActorId, Actor)]
    posToAidAssocs :: Point -> LevelId -> State -> [(ActorId, Actor)]
    posToAidAssocs Point
    pos LevelId
    lid State
    s =
      let l :: [ActorId]
    l = Point -> Level -> [ActorId]
    posToAidsLvl Point
    pos (Level -> [ActorId]) -> Level -> [ActorId]
    forall a b. (a -> b) -> a -> b
    $ State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! LevelId
    lid
      in (ActorId -> (ActorId, Actor)) -> [ActorId] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ActorId
    aid -> (ActorId
    aid, ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s)) [ActorId]
    l

    -- | Calculate loot's worth for a given faction.
    calculateTotal :: FactionId -> State -> (ItemBag, Int)
    calculateTotal :: FactionId -> State -> (ItemBag, Int)
    calculateTotal FactionId
    fid State
    s =
      let bag :: ItemBag
    bag = FactionId -> State -> ItemBag
    combinedItems FactionId
    fid State
    s
          items :: [(Item, Int)]
    items = ((ItemId, ItemQuant) -> (Item, Int))
    -> [(ItemId, ItemQuant)] -> [(Item, Int)]
    forall a b. (a -> b) -> [a] -> [b]
    map (\(ItemId
    iid, (Int
    k, ItemTimers
    _)) -> (ItemId -> State -> Item
    getItemBody ItemId
    iid State
    s, Int
    k)) ([(ItemId, ItemQuant)] -> [(Item, Int)])
    -> [(ItemId, ItemQuant)] -> [(Item, Int)]
    forall a b. (a -> b) -> a -> b
    $ ItemBag -> [(ItemId, ItemQuant)]
    forall k a. Enum k => EnumMap k a -> [(k, a)]
    EM.assocs ItemBag
    bag
          price :: (Item, Int) -> Int
    price (Item
    item, Int
    k) = Int -> ItemKind -> Int
    itemPrice Int
    k (ItemKind -> Int) -> ItemKind -> Int
    forall a b. (a -> b) -> a -> b
    $ Item -> State -> ItemKind
    getItemKind Item
    item State
    s
      in (ItemBag
    bag, [Int] -> Int
    forall a. Num a => [a] -> a
    sum ([Int] -> Int) -> [Int] -> Int
    forall a b. (a -> b) -> a -> b
    $ ((Item, Int) -> Int) -> [(Item, Int)] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    map (Item, Int) -> Int
    price [(Item, Int)]
    items)

    -- | Price an item, taking count into consideration.
    itemPrice :: Int -> IK.ItemKind -> Int
    itemPrice :: Int -> ItemKind -> Int
    itemPrice Int
    jcount ItemKind
    itemKind = case GroupName ItemKind -> [(GroupName ItemKind, Int)] -> Maybe Int
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup GroupName ItemKind
    IK.VALUABLE ([(GroupName ItemKind, Int)] -> Maybe Int)
    -> [(GroupName ItemKind, Int)] -> Maybe Int
    forall a b. (a -> b) -> a -> b
    $ ItemKind -> [(GroupName ItemKind, Int)]
    IK.ifreq ItemKind
    itemKind of
      Just Int
    k -> Int
    jcount Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    k
      Maybe Int
    Nothing -> Int
    0

    findIid :: ActorId -> FactionId -> ItemId -> State
            -> [(ActorId, (Actor, CStore))]
    findIid :: ActorId
    -> FactionId -> ItemId -> State -> [(ActorId, (Actor, CStore))]
    findIid ActorId
    leader FactionId
    fid ItemId
    iid State
    s =
      let actors :: [(ActorId, Actor)]
    actors = FactionId -> State -> [(ActorId, Actor)]
    fidActorNotProjGlobalAssocs FactionId
    fid State
    s
          itemsOfActor :: (ActorId, Actor) -> [(ItemId, (ActorId, (Actor, CStore)))]
    itemsOfActor (ActorId
    aid, Actor
    b) =
            let itemsOfCStore :: CStore -> [(ItemId, (ActorId, (Actor, CStore)))]
    itemsOfCStore CStore
    store =
                  let bag :: ItemBag
    bag = Actor -> CStore -> State -> ItemBag
    getBodyStoreBag Actor
    b CStore
    store State
    s
                  in (ItemId -> (ItemId, (ActorId, (Actor, CStore))))
    -> [ItemId] -> [(ItemId, (ActorId, (Actor, CStore)))]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ItemId
    iid2 -> (ItemId
    iid2, (ActorId
    aid, (Actor
    b, CStore
    store)))) (ItemBag -> [ItemId]
    forall k a. Enum k => EnumMap k a -> [k]
    EM.keys ItemBag
    bag)
                stores :: [CStore]
    stores = [CStore
    CEqp, CStore
    COrgan] [CStore] -> [CStore] -> [CStore]
    forall a. [a] -> [a] -> [a]
    ++ [CStore
    CStash | ActorId
    aid ActorId -> ActorId -> Bool
    forall a. Eq a => a -> a -> Bool
    == ActorId
    leader]
            in (CStore -> [(ItemId, (ActorId, (Actor, CStore)))])
    -> [CStore] -> [(ItemId, (ActorId, (Actor, CStore)))]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap CStore -> [(ItemId, (ActorId, (Actor, CStore)))]
    itemsOfCStore [CStore]
    stores
          items :: [(ItemId, (ActorId, (Actor, CStore)))]
    items = ((ActorId, Actor) -> [(ItemId, (ActorId, (Actor, CStore)))])
    -> [(ActorId, Actor)] -> [(ItemId, (ActorId, (Actor, CStore)))]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (ActorId, Actor) -> [(ItemId, (ActorId, (Actor, CStore)))]
    itemsOfActor [(ActorId, Actor)]
    actors
      in ((ItemId, (ActorId, (Actor, CStore)))
     -> (ActorId, (Actor, CStore)))
    -> [(ItemId, (ActorId, (Actor, CStore)))]
    -> [(ActorId, (Actor, CStore))]
    forall a b. (a -> b) -> [a] -> [b]
    map (ItemId, (ActorId, (Actor, CStore))) -> (ActorId, (Actor, CStore))
    forall a b. (a, b) -> b
    snd ([(ItemId, (ActorId, (Actor, CStore)))]
     -> [(ActorId, (Actor, CStore))])
    -> [(ItemId, (ActorId, (Actor, CStore)))]
    -> [(ActorId, (Actor, CStore))]
    forall a b. (a -> b) -> a -> b
    $ ((ItemId, (ActorId, (Actor, CStore))) -> Bool)
    -> [(ItemId, (ActorId, (Actor, CStore)))]
    -> [(ItemId, (ActorId, (Actor, CStore)))]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ((ItemId -> ItemId -> Bool
    forall a. Eq a => a -> a -> Bool
    == ItemId
    iid) (ItemId -> Bool)
    -> ((ItemId, (ActorId, (Actor, CStore))) -> ItemId)
    -> (ItemId, (ActorId, (Actor, CStore)))
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ItemId, (ActorId, (Actor, CStore))) -> ItemId
    forall a b. (a, b) -> a
    fst) [(ItemId, (ActorId, (Actor, CStore)))]
    items

    -- Trunk not considered (if stolen).
    combinedItems :: FactionId -> State -> ItemBag
    combinedItems :: FactionId -> State -> ItemBag
    combinedItems FactionId
    fid State
    s =
      let stashBag :: ItemBag
    stashBag = FactionId -> State -> ItemBag
    getFactionStashBag FactionId
    fid State
    s
          bs :: [Actor]
    bs = ((ActorId, Actor) -> Actor) -> [(ActorId, Actor)] -> [Actor]
    forall a b. (a -> b) -> [a] -> [b]
    map (ActorId, Actor) -> Actor
    forall a b. (a, b) -> b
    snd ([(ActorId, Actor)] -> [Actor]) -> [(ActorId, Actor)] -> [Actor]
    forall a b. (a -> b) -> a -> b
    $ (FactionId -> State -> [(ActorId, Actor)])
    -> FactionId -> State -> [(ActorId, Actor)]
    forall a. a -> a
    inline FactionId -> State -> [(ActorId, Actor)]
    fidActorNotProjGlobalAssocs FactionId
    fid State
    s
      in (ItemQuant -> ItemQuant -> ItemQuant) -> [ItemBag] -> ItemBag
    forall a k. (a -> a -> a) -> [EnumMap k a] -> EnumMap k a
    EM.unionsWith ItemQuant -> ItemQuant -> ItemQuant
    mergeItemQuant ([ItemBag] -> ItemBag) -> [ItemBag] -> ItemBag
    forall a b. (a -> b) -> a -> b
    $ (Actor -> ItemBag) -> [Actor] -> [ItemBag]
    forall a b. (a -> b) -> [a] -> [b]
    map Actor -> ItemBag
    beqp [Actor]
    bs [ItemBag] -> [ItemBag] -> [ItemBag]
    forall a. [a] -> [a] -> [a]
    ++ [ItemBag
    stashBag]

    getActorBody :: ActorId -> State -> Actor
    {-# INLINE getActorBody #-}
    getActorBody :: ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s = State -> EnumMap ActorId Actor
    sactorD State
    s EnumMap ActorId Actor -> ActorId -> Actor
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! ActorId
    aid

    -- For now, faction and doctrine skill modifiers only change
    -- the stats that affect permitted actions (@SkMove..SkApply@),
    -- so the expensive @actorCurrentSkills@ operation doesn't need to be used
    -- when checking the other skills, e.g., for FOV calculations,
    -- and the @getActorMaxSkills@ cheap operation suffices.
    -- (@ModeKind@ content is not currently validated in this respect.)
    getActorMaxSkills :: ActorId -> State -> Ability.Skills
    {-# INLINE getActorMaxSkills #-}
    getActorMaxSkills :: ActorId -> State -> Skills
    getActorMaxSkills ActorId
    aid State
    s = State -> ActorMaxSkills
    sactorMaxSkills State
    s ActorMaxSkills -> ActorId -> Skills
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! ActorId
    aid

    actorCurrentSkills :: Maybe ActorId -> ActorId -> State -> Ability.Skills
    actorCurrentSkills :: Maybe ActorId -> ActorId -> State -> Skills
    actorCurrentSkills Maybe ActorId
    mleader ActorId
    aid State
    s =
      let body :: Actor
    body = ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s
          actorMaxSk :: Skills
    actorMaxSk = ActorId -> State -> Skills
    getActorMaxSkills ActorId
    aid State
    s
          fact :: Faction
    fact = (EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! Actor -> FactionId
    bfid Actor
    body) (EnumMap FactionId Faction -> Faction)
    -> (State -> EnumMap FactionId Faction) -> State -> Faction
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> EnumMap FactionId Faction
    sfactionD (State -> Faction) -> State -> Faction
    forall a b. (a -> b) -> a -> b
    $ State
    s
          skillsFromDoctrine :: Skills
    skillsFromDoctrine = Doctrine -> Skills
    Ability.doctrineSkills (Doctrine -> Skills) -> Doctrine -> Skills
    forall a b. (a -> b) -> a -> b
    $ Faction -> Doctrine
    gdoctrine Faction
    fact
          factionSkills :: Skills
    factionSkills
            | ActorId -> Maybe ActorId
    forall a. a -> Maybe a
    Just ActorId
    aid Maybe ActorId -> Maybe ActorId -> Bool
    forall a. Eq a => a -> a -> Bool
    == Maybe ActorId
    mleader = Skills
    Ability.zeroSkills
            | Bool
    otherwise = FactionKind -> Skills
    fskillsOther (Faction -> FactionKind
    gkind Faction
    fact)
                          Skills -> Skills -> Skills
    `Ability.addSkills` Skills
    skillsFromDoctrine
      in Skills
    actorMaxSk Skills -> Skills -> Skills
    `Ability.addSkills` Skills
    factionSkills

    -- Check that the actor can move, also between levels and through doors.
    -- Otherwise, it's too awkward for human player to control, e.g.,
    -- being stuck in a room with revolving doors closing after one turn
    -- and the player needing to micromanage opening such doors with
    -- another actor all the time. Completely immovable actors
    -- e.g., an impregnable surveillance camera in a crowded corridor,
    -- are less of a problem due to micromanagment, but more due to
    -- the constant disturbing of other actor's running, etc.
    canTraverse :: ActorId -> State -> Bool
    canTraverse :: ActorId -> State -> Bool
    canTraverse ActorId
    aid State
    s =
      let actorMaxSk :: Skills
    actorMaxSk = ActorId -> State -> Skills
    getActorMaxSkills ActorId
    aid State
    s
      in Skill -> Skills -> Int
    Ability.getSk Skill
    Ability.SkMove Skills
    actorMaxSk Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    0
         Bool -> Bool -> Bool
    && Skill -> Skills -> Int
    Ability.getSk Skill
    Ability.SkAlter Skills
    actorMaxSk Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Word8 -> Int
    forall a. Enum a => a -> Int
    fromEnum Word8
    TK.talterForStairs

    getCarriedAssocsAndTrunk :: Actor -> State -> [(ItemId, Item)]
    getCarriedAssocsAndTrunk :: Actor -> State -> [(ItemId, Item)]
    getCarriedAssocsAndTrunk Actor
    b State
    s =
      -- The trunk is important for a case of spotting a caught projectile
      -- with a stolen projecting item. This actually does happen.
      let trunk :: ItemBag
    trunk = ItemId -> ItemQuant -> ItemBag
    forall k a. Enum k => k -> a -> EnumMap k a
    EM.singleton (Actor -> ItemId
    btrunk Actor
    b) ItemQuant
    quantSingle
      in State -> ItemBag -> [(ItemId, Item)]
    bagAssocs State
    s (ItemBag -> [(ItemId, Item)]) -> ItemBag -> [(ItemId, Item)]
    forall a b. (a -> b) -> a -> b
    $ (ItemQuant -> ItemQuant -> ItemQuant) -> [ItemBag] -> ItemBag
    forall a k. (a -> a -> a) -> [EnumMap k a] -> EnumMap k a
    EM.unionsWith ItemQuant -> ItemQuant -> ItemQuant
    forall a b. a -> b -> a
    const [Actor -> ItemBag
    beqp Actor
    b, Actor -> ItemBag
    borgan Actor
    b, ItemBag
    trunk]

    getContainerBag :: Container -> State -> ItemBag
    getContainerBag :: Container -> State -> ItemBag
    getContainerBag Container
    c State
    s = case Container
    c of
      CFloor LevelId
    lid Point
    p -> LevelId -> Point -> State -> ItemBag
    getFloorBag LevelId
    lid Point
    p State
    s
      CEmbed LevelId
    lid Point
    p -> LevelId -> Point -> State -> ItemBag
    getEmbedBag LevelId
    lid Point
    p State
    s
      CActor ActorId
    aid CStore
    cstore -> let b :: Actor
    b = ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s
                           in Actor -> CStore -> State -> ItemBag
    getBodyStoreBag Actor
    b CStore
    cstore State
    s
      CTrunk{} -> ItemBag
    forall k a. EnumMap k a
    EM.empty  -- for dummy/test/analytics cases

    getFloorBag :: LevelId -> Point -> State -> ItemBag
    getFloorBag :: LevelId -> Point -> State -> ItemBag
    getFloorBag LevelId
    lid Point
    p State
    s = ItemBag -> Point -> EnumMap Point ItemBag -> ItemBag
    forall k a. Enum k => a -> k -> EnumMap k a -> a
    EM.findWithDefault ItemBag
    forall k a. EnumMap k a
    EM.empty Point
    p
                          (EnumMap Point ItemBag -> ItemBag)
    -> EnumMap Point ItemBag -> ItemBag
    forall a b. (a -> b) -> a -> b
    $ Level -> EnumMap Point ItemBag
    lfloor (State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! LevelId
    lid)

    getEmbedBag :: LevelId -> Point -> State -> ItemBag
    getEmbedBag :: LevelId -> Point -> State -> ItemBag
    getEmbedBag LevelId
    lid Point
    p State
    s = ItemBag -> Point -> EnumMap Point ItemBag -> ItemBag
    forall k a. Enum k => a -> k -> EnumMap k a -> a
    EM.findWithDefault ItemBag
    forall k a. EnumMap k a
    EM.empty Point
    p
                          (EnumMap Point ItemBag -> ItemBag)
    -> EnumMap Point ItemBag -> ItemBag
    forall a b. (a -> b) -> a -> b
    $ Level -> EnumMap Point ItemBag
    lembed (State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! LevelId
    lid)

    getBodyStoreBag :: Actor -> CStore -> State -> ItemBag
    getBodyStoreBag :: Actor -> CStore -> State -> ItemBag
    getBodyStoreBag Actor
    b CStore
    cstore State
    s =
      case CStore
    cstore of
        CStore
    CGround -> LevelId -> Point -> State -> ItemBag
    getFloorBag (Actor -> LevelId
    blid Actor
    b) (Actor -> Point
    bpos Actor
    b) State
    s
        CStore
    COrgan -> Actor -> ItemBag
    borgan Actor
    b
        CStore
    CEqp -> Actor -> ItemBag
    beqp Actor
    b
        CStore
    CStash -> FactionId -> State -> ItemBag
    getFactionStashBag (Actor -> FactionId
    bfid Actor
    b) State
    s

    getFactionStashBag :: FactionId -> State -> ItemBag
    getFactionStashBag :: FactionId -> State -> ItemBag
    getFactionStashBag FactionId
    fid State
    s = case Faction -> Maybe (LevelId, Point)
    gstash (Faction -> Maybe (LevelId, Point))
    -> Faction -> Maybe (LevelId, Point)
    forall a b. (a -> b) -> a -> b
    $ State -> EnumMap FactionId Faction
    sfactionD State
    s EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! FactionId
    fid of
      Just (LevelId
    lid, Point
    pos) -> LevelId -> Point -> State -> ItemBag
    getFloorBag LevelId
    lid Point
    pos State
    s
      Maybe (LevelId, Point)
    Nothing -> ItemBag
    forall k a. EnumMap k a
    EM.empty

    mapActorItems_ :: Monad m
                   => (CStore -> ItemId -> ItemQuant -> m ()) -> Actor -> State
                   -> m ()
    mapActorItems_ :: forall (m :: * -> *).
    Monad m =>
    (CStore -> ItemId -> ItemQuant -> m ()) -> Actor -> State -> m ()
    mapActorItems_ CStore -> ItemId -> ItemQuant -> m ()
    f Actor
    b State
    s = do
      let notProcessed :: [CStore]
    notProcessed = [CStore
    CGround]
          sts :: [CStore]
    sts = [CStore
    forall a. Bounded a => a
    minBound..CStore
    forall a. Bounded a => a
    maxBound] [CStore] -> [CStore] -> [CStore]
    forall a. Eq a => [a] -> [a] -> [a]
    \\ [CStore]
    notProcessed
          g :: CStore -> m ()
    g CStore
    cstore = do
            let bag :: ItemBag
    bag = Actor -> CStore -> State -> ItemBag
    getBodyStoreBag Actor
    b CStore
    cstore State
    s
            ((ItemId, ItemQuant) -> m ()) -> [(ItemId, ItemQuant)] -> m ()
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, Monad m) =>
    (a -> m ()) -> t a -> m ()
    mapM_ ((ItemId -> ItemQuant -> m ()) -> (ItemId, ItemQuant) -> m ()
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry ((ItemId -> ItemQuant -> m ()) -> (ItemId, ItemQuant) -> m ())
    -> (ItemId -> ItemQuant -> m ()) -> (ItemId, ItemQuant) -> m ()
    forall a b. (a -> b) -> a -> b
    $ CStore -> ItemId -> ItemQuant -> m ()
    f CStore
    cstore) ([(ItemId, ItemQuant)] -> m ()) -> [(ItemId, ItemQuant)] -> m ()
    forall a b. (a -> b) -> a -> b
    $ ItemBag -> [(ItemId, ItemQuant)]
    forall k a. Enum k => EnumMap k a -> [(k, a)]
    EM.assocs ItemBag
    bag
      (CStore -> m ()) -> [CStore] -> m ()
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, Monad m) =>
    (a -> m ()) -> t a -> m ()
    mapM_ CStore -> m ()
    g [CStore]
    sts

    getActorAssocs :: ActorId -> CStore -> State -> [(ItemId, (Item, ItemQuant))]
    getActorAssocs :: ActorId -> CStore -> State -> [(ItemId, (Item, ItemQuant))]
    getActorAssocs ActorId
    aid CStore
    cstore State
    s =
      let b :: Actor
    b = ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s
      in State -> ItemBag -> [(ItemId, (Item, ItemQuant))]
    bagAssocsK State
    s (ItemBag -> [(ItemId, (Item, ItemQuant))])
    -> ItemBag -> [(ItemId, (Item, ItemQuant))]
    forall a b. (a -> b) -> a -> b
    $ Actor -> CStore -> State -> ItemBag
    getBodyStoreBag Actor
    b CStore
    cstore State
    s

    -- | Checks if the actor is present on the current level.
    -- The order of argument here and in other functions is set to allow
    --
    -- > b <- getsState (memActor a)
    memActor :: ActorId -> LevelId -> State -> Bool
    memActor :: ActorId -> LevelId -> State -> Bool
    memActor ActorId
    aid LevelId
    lid State
    s =
      Bool -> (Actor -> Bool) -> Maybe Actor -> Bool
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Bool
    False ((LevelId -> LevelId -> Bool
    forall a. Eq a => a -> a -> Bool
    == LevelId
    lid) (LevelId -> Bool) -> (Actor -> LevelId) -> Actor -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Actor -> LevelId
    blid) (Maybe Actor -> Bool) -> Maybe Actor -> Bool
    forall a b. (a -> b) -> a -> b
    $ ActorId -> EnumMap ActorId Actor -> Maybe Actor
    forall k a. Enum k => k -> EnumMap k a -> Maybe a
    EM.lookup ActorId
    aid (EnumMap ActorId Actor -> Maybe Actor)
    -> EnumMap ActorId Actor -> Maybe Actor
    forall a b. (a -> b) -> a -> b
    $ State -> EnumMap ActorId Actor
    sactorD State
    s

    -- | Get current time from the dungeon data.
    getLocalTime :: LevelId -> State -> Time
    getLocalTime :: LevelId -> State -> Time
    getLocalTime LevelId
    lid State
    s = Level -> Time
    ltime (Level -> Time) -> Level -> Time
    forall a b. (a -> b) -> a -> b
    $ State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! LevelId
    lid

    regenCalmDelta :: ActorId -> Actor -> State -> Int64
    regenCalmDelta :: ActorId -> Actor -> State -> Int64
    regenCalmDelta ActorId
    aid Actor
    body State
    s =
      let calmIncr :: Int64
    calmIncr = Int64
    oneM  -- normal rate of calm regen
          actorMaxSk :: Skills
    actorMaxSk = ActorId -> State -> Skills
    getActorMaxSkills ActorId
    aid State
    s
          maxDeltaCalm :: Int64
    maxDeltaCalm = Int -> Int64
    xM (Skill -> Skills -> Int
    Ability.getSk Skill
    Ability.SkMaxCalm Skills
    actorMaxSk)
                         Int64 -> Int64 -> Int64
    forall a. Num a => a -> a -> a
    - Actor -> Int64
    bcalm Actor
    body
          fact :: Faction
    fact = (EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! Actor -> FactionId
    bfid Actor
    body) (EnumMap FactionId Faction -> Faction)
    -> (State -> EnumMap FactionId Faction) -> State -> Faction
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> EnumMap FactionId Faction
    sfactionD (State -> Faction) -> State -> Faction
    forall a b. (a -> b) -> a -> b
    $ State
    s
          -- Worry actor by non-projectile enemies felt (even if not seen)
          -- on the level within 3 steps. Even dying, but not hiding in wait.
          isHeardFoe :: (Point, ActorId) -> Bool
    isHeardFoe (!Point
    p, ActorId
    aid2) =
            let b :: Actor
    b = ActorId -> State -> Actor
    getActorBody ActorId
    aid2 State
    s
            in (Point -> Point -> Int) -> Point -> Point -> Int
    forall a. a -> a
    inline Point -> Point -> Int
    chessDist Point
    p (Actor -> Point
    bpos Actor
    body) Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    3
               Bool -> Bool -> Bool
    && Bool -> Bool
    not (Actor -> Bool
    actorWaitsOrSleeps Actor
    b)  -- uncommon
               Bool -> Bool -> Bool
    && (FactionId -> Faction -> FactionId -> Bool)
    -> FactionId -> Faction -> FactionId -> Bool
    forall a. a -> a
    inline FactionId -> Faction -> FactionId -> Bool
    isFoe (Actor -> FactionId
    bfid Actor
    body) Faction
    fact (Actor -> FactionId
    bfid Actor
    b)  -- costly
          actorRelaxed :: Bool
    actorRelaxed = ResDelta -> Bool
    deltaBenign (ResDelta -> Bool) -> ResDelta -> Bool
    forall a b. (a -> b) -> a -> b
    $ Actor -> ResDelta
    bcalmDelta Actor
    body
          actorWasRelaxed :: Bool
    actorWasRelaxed = ResDelta -> Bool
    deltaWasBenign (ResDelta -> Bool) -> ResDelta -> Bool
    forall a b. (a -> b) -> a -> b
    $ Actor -> ResDelta
    bcalmDelta Actor
    body
      in if | Bool -> Bool
    not Bool
    actorRelaxed -> Int64
    0
                -- if no foes around, do not compensate and obscure distress,
                -- otherwise, don't increase delta further and suggest grave harm;
                -- note that in the effect, an actor that first hears distant
                -- action and then hears nearby enemy, won't notice the latter,
                -- which can be justified by distraction and is KISS and tactical
            | ((Point, ActorId) -> Bool) -> [(Point, ActorId)] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any (Point, ActorId) -> Bool
    isHeardFoe ([(Point, ActorId)] -> Bool) -> [(Point, ActorId)] -> Bool
    forall a b. (a -> b) -> a -> b
    $ EnumMap Point ActorId -> [(Point, ActorId)]
    forall k a. Enum k => EnumMap k a -> [(k, a)]
    EM.assocs (EnumMap Point ActorId -> [(Point, ActorId)])
    -> EnumMap Point ActorId -> [(Point, ActorId)]
    forall a b. (a -> b) -> a -> b
    $ Level -> EnumMap Point ActorId
    lbig (Level -> EnumMap Point ActorId) -> Level -> EnumMap Point ActorId
    forall a b. (a -> b) -> a -> b
    $ State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! Actor -> LevelId
    blid Actor
    body ->
              Int64
    minusM1  -- even if all calmness spent, keep informing the client;
                       -- from above we know delta won't get too large here
            | Bool
    actorWasRelaxed -> Int64 -> Int64 -> Int64
    forall a. Ord a => a -> a -> a
    min Int64
    calmIncr (Int64 -> Int64 -> Int64
    forall a. Ord a => a -> a -> a
    max Int64
    0 Int64
    maxDeltaCalm)
                                                 -- if Calm is over max
            | Bool
    otherwise -> Int64
    0  -- don't regenerate if shortly after stress, to make
                              -- waking up actors via bad stealth easier

    actorInAmbient :: Actor -> State -> Bool
    actorInAmbient :: Actor -> State -> Bool
    actorInAmbient Actor
    b State
    s =
      let lvl :: Level
    lvl = (Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! Actor -> LevelId
    blid Actor
    b) (Dungeon -> Level) -> (State -> Dungeon) -> State -> Level
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> Dungeon
    sdungeon (State -> Level) -> State -> Level
    forall a b. (a -> b) -> a -> b
    $ State
    s
      in TileSpeedup -> ContentId TileKind -> Bool
    Tile.isLit (COps -> TileSpeedup
    coTileSpeedup (COps -> TileSpeedup) -> COps -> TileSpeedup
    forall a b. (a -> b) -> a -> b
    $ State -> COps
    scops State
    s) (Level
    lvl Level -> Point -> ContentId TileKind
    `at` Actor -> Point
    bpos Actor
    b)

    -- Check whether an actor can displace another. We assume they are adjacent
    -- and they are foes.
    dispEnemy :: ActorId -> ActorId -> Ability.Skills -> State -> Bool
    dispEnemy :: ActorId -> ActorId -> Skills -> State -> Bool
    dispEnemy ActorId
    source ActorId
    target Skills
    actorMaxSk State
    s =
      let hasBackup :: Actor -> Bool
    hasBackup Actor
    b =
            let adjAssocs :: [(ActorId, Actor)]
    adjAssocs = Actor -> State -> [(ActorId, Actor)]
    adjacentBigAssocs Actor
    b State
    s
                fact :: Faction
    fact = State -> EnumMap FactionId Faction
    sfactionD State
    s EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! Actor -> FactionId
    bfid Actor
    b
                friend :: (ActorId, Actor) -> Bool
    friend (ActorId
    _, Actor
    b2) = FactionId -> Faction -> FactionId -> Bool
    isFriend (Actor -> FactionId
    bfid Actor
    b) Faction
    fact (Actor -> FactionId
    bfid Actor
    b2) Bool -> Bool -> Bool
    && Actor -> Int64
    bhp Actor
    b2 Int64 -> Int64 -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int64
    0
            in ((ActorId, Actor) -> Bool) -> [(ActorId, Actor)] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any (ActorId, Actor) -> Bool
    friend [(ActorId, Actor)]
    adjAssocs
          sb :: Actor
    sb = ActorId -> State -> Actor
    getActorBody ActorId
    source State
    s
          tb :: Actor
    tb = ActorId -> State -> Actor
    getActorBody ActorId
    target State
    s
          tfact :: Faction
    tfact = State -> EnumMap FactionId Faction
    sfactionD State
    s EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! Actor -> FactionId
    bfid Actor
    tb
      in Actor -> Bool
    bproj Actor
    tb
         Bool -> Bool -> Bool
    || Bool -> Bool
    not (Actor -> Bool
    actorDying Actor
    tb
                 Bool -> Bool -> Bool
    || Actor -> Bool
    actorWaits Actor
    tb
                 Bool -> Bool -> Bool
    || Skill -> Skills -> Int
    Ability.getSk Skill
    Ability.SkMove Skills
    actorMaxSk Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0
                      -- sometimes this comes from sleep, but it's transient
                      -- and if we made exception for sleep, we would displace
                      -- immobile sleeping actors
                 Bool -> Bool -> Bool
    || (LevelId, Point) -> Maybe (LevelId, Point)
    forall a. a -> Maybe a
    Just (Actor -> LevelId
    blid Actor
    tb, Actor -> Point
    bpos Actor
    tb) Maybe (LevelId, Point) -> Maybe (LevelId, Point) -> Bool
    forall a. Eq a => a -> a -> Bool
    == Faction -> Maybe (LevelId, Point)
    gstash Faction
    tfact
                 Bool -> Bool -> Bool
    || Actor -> Bool
    hasBackup Actor
    sb Bool -> Bool -> Bool
    && Actor -> Bool
    hasBackup Actor
    tb)  -- solo actors are flexible

    itemToFull :: ItemId -> State -> ItemFull
    itemToFull :: ItemId -> State -> ItemFull
    itemToFull ItemId
    iid State
    s =
      COps
    -> DiscoveryKind -> DiscoveryAspect -> ItemId -> Item -> ItemFull
    itemToFull6 (State -> COps
    scops State
    s) (State -> DiscoveryKind
    sdiscoKind State
    s) (State -> DiscoveryAspect
    sdiscoAspect State
    s) ItemId
    iid (ItemId -> State -> Item
    getItemBody ItemId
    iid State
    s)

    fullAssocs :: ActorId -> [CStore] -> State -> [(ItemId, ItemFull)]
    fullAssocs :: ActorId -> [CStore] -> State -> [(ItemId, ItemFull)]
    fullAssocs ActorId
    aid [CStore]
    cstores State
    s =
      let allAssocs :: [(ItemId, (Item, ItemQuant))]
    allAssocs = (CStore -> [(ItemId, (Item, ItemQuant))])
    -> [CStore] -> [(ItemId, (Item, ItemQuant))]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (\CStore
    cstore -> ActorId -> CStore -> State -> [(ItemId, (Item, ItemQuant))]
    getActorAssocs ActorId
    aid CStore
    cstore State
    s) [CStore]
    cstores
          iToFull :: (ItemId, (Item, ItemQuant)) -> (ItemId, ItemFull)
    iToFull (ItemId
    iid, (Item
    item, ItemQuant
    _kit)) =
            (ItemId
    iid, COps
    -> DiscoveryKind -> DiscoveryAspect -> ItemId -> Item -> ItemFull
    itemToFull6 (State -> COps
    scops State
    s) (State -> DiscoveryKind
    sdiscoKind State
    s) (State -> DiscoveryAspect
    sdiscoAspect State
    s) ItemId
    iid Item
    item)
      in ((ItemId, (Item, ItemQuant)) -> (ItemId, ItemFull))
    -> [(ItemId, (Item, ItemQuant))] -> [(ItemId, ItemFull)]
    forall a b. (a -> b) -> [a] -> [b]
    map (ItemId, (Item, ItemQuant)) -> (ItemId, ItemFull)
    iToFull [(ItemId, (Item, ItemQuant))]
    allAssocs

    kitAssocs :: ActorId -> [CStore] -> State -> [(ItemId, ItemFullKit)]
    kitAssocs :: ActorId -> [CStore] -> State -> [(ItemId, ItemFullKit)]
    kitAssocs ActorId
    aid [CStore]
    cstores State
    s =
      let allAssocs :: [(ItemId, (Item, ItemQuant))]
    allAssocs = (CStore -> [(ItemId, (Item, ItemQuant))])
    -> [CStore] -> [(ItemId, (Item, ItemQuant))]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (\CStore
    cstore -> ActorId -> CStore -> State -> [(ItemId, (Item, ItemQuant))]
    getActorAssocs ActorId
    aid CStore
    cstore State
    s) [CStore]
    cstores
          iToFull :: (ItemId, (Item, ItemQuant)) -> (ItemId, ItemFullKit)
    iToFull (ItemId
    iid, (Item
    item, ItemQuant
    kit)) =
            (ItemId
    iid, ( COps
    -> DiscoveryKind -> DiscoveryAspect -> ItemId -> Item -> ItemFull
    itemToFull6 (State -> COps
    scops State
    s) (State -> DiscoveryKind
    sdiscoKind State
    s) (State -> DiscoveryAspect
    sdiscoAspect State
    s) ItemId
    iid Item
    item
                  , ItemQuant
    kit ))
      in ((ItemId, (Item, ItemQuant)) -> (ItemId, ItemFullKit))
    -> [(ItemId, (Item, ItemQuant))] -> [(ItemId, ItemFullKit)]
    forall a b. (a -> b) -> [a] -> [b]
    map (ItemId, (Item, ItemQuant)) -> (ItemId, ItemFullKit)
    iToFull [(ItemId, (Item, ItemQuant))]
    allAssocs

    getItemKindId :: Item -> State -> ContentId IK.ItemKind
    getItemKindId :: Item -> State -> ContentId ItemKind
    getItemKindId Item
    item State
    s = case Item -> ItemIdentity
    jkind Item
    item of
      IdentityObvious ContentId ItemKind
    ik -> ContentId ItemKind
    ik
      IdentityCovered ItemKindIx
    ix ContentId ItemKind
    ik -> ContentId ItemKind
    -> Maybe (ContentId ItemKind) -> ContentId ItemKind
    forall a. a -> Maybe a -> a
    fromMaybe ContentId ItemKind
    ik (Maybe (ContentId ItemKind) -> ContentId ItemKind)
    -> Maybe (ContentId ItemKind) -> ContentId ItemKind
    forall a b. (a -> b) -> a -> b
    $ ItemKindIx -> DiscoveryKind -> Maybe (ContentId ItemKind)
    forall k a. Enum k => k -> EnumMap k a -> Maybe a
    EM.lookup ItemKindIx
    ix (DiscoveryKind -> Maybe (ContentId ItemKind))
    -> DiscoveryKind -> Maybe (ContentId ItemKind)
    forall a b. (a -> b) -> a -> b
    $ State -> DiscoveryKind
    sdiscoKind State
    s

    getIidKindId :: ItemId -> State -> ContentId IK.ItemKind
    getIidKindId :: ItemId -> State -> ContentId ItemKind
    getIidKindId ItemId
    iid State
    s = Item -> State -> ContentId ItemKind
    getItemKindId (ItemId -> State -> Item
    getItemBody ItemId
    iid State
    s) State
    s

    getItemKind :: Item -> State -> IK.ItemKind
    getItemKind :: Item -> State -> ItemKind
    getItemKind Item
    item State
    s = ContentData ItemKind -> ContentId ItemKind -> ItemKind
    forall a. ContentData a -> ContentId a -> a
    okind (COps -> ContentData ItemKind
    coitem (COps -> ContentData ItemKind) -> COps -> ContentData ItemKind
    forall a b. (a -> b) -> a -> b
    $ State -> COps
    scops State
    s) (ContentId ItemKind -> ItemKind) -> ContentId ItemKind -> ItemKind
    forall a b. (a -> b) -> a -> b
    $ Item -> State -> ContentId ItemKind
    getItemKindId Item
    item State
    s

    getIidKind :: ItemId -> State -> IK.ItemKind
    getIidKind :: ItemId -> State -> ItemKind
    getIidKind ItemId
    iid State
    s = Item -> State -> ItemKind
    getItemKind (ItemId -> State -> Item
    getItemBody ItemId
    iid State
    s) State
    s

    getItemKindIdServer :: Item -> State -> ContentId IK.ItemKind
    getItemKindIdServer :: Item -> State -> ContentId ItemKind
    getItemKindIdServer Item
    item State
    s = case Item -> ItemIdentity
    jkind Item
    item of
      IdentityObvious ContentId ItemKind
    ik -> ContentId ItemKind
    ik
      IdentityCovered ItemKindIx
    ix ContentId ItemKind
    _ik -> ContentId ItemKind
    -> Maybe (ContentId ItemKind) -> ContentId ItemKind
    forall a. a -> Maybe a -> a
    fromMaybe ([Char] -> ContentId ItemKind
    forall a. HasCallStack => [Char] -> a
    error ([Char] -> ContentId ItemKind) -> [Char] -> ContentId ItemKind
    forall a b. (a -> b) -> a -> b
    $ ItemIdentity -> [Char]
    forall a. Show a => a -> [Char]
    show (ItemIdentity -> [Char]) -> ItemIdentity -> [Char]
    forall a b. (a -> b) -> a -> b
    $ Item -> ItemIdentity
    jkind Item
    item)
                                          (ItemKindIx -> DiscoveryKind -> Maybe (ContentId ItemKind)
    forall k a. Enum k => k -> EnumMap k a -> Maybe a
    EM.lookup ItemKindIx
    ix (DiscoveryKind -> Maybe (ContentId ItemKind))
    -> DiscoveryKind -> Maybe (ContentId ItemKind)
    forall a b. (a -> b) -> a -> b
    $ State -> DiscoveryKind
    sdiscoKind State
    s)

    getIidKindIdServer :: ItemId -> State -> ContentId IK.ItemKind
    getIidKindIdServer :: ItemId -> State -> ContentId ItemKind
    getIidKindIdServer ItemId
    iid State
    s = Item -> State -> ContentId ItemKind
    getItemKindIdServer (ItemId -> State -> Item
    getItemBody ItemId
    iid State
    s) State
    s

    getItemKindServer :: Item -> State -> IK.ItemKind
    getItemKindServer :: Item -> State -> ItemKind
    getItemKindServer Item
    item State
    s = ContentData ItemKind -> ContentId ItemKind -> ItemKind
    forall a. ContentData a -> ContentId a -> a
    okind (COps -> ContentData ItemKind
    coitem (COps -> ContentData ItemKind) -> COps -> ContentData ItemKind
    forall a b. (a -> b) -> a -> b
    $ State -> COps
    scops State
    s) (ContentId ItemKind -> ItemKind) -> ContentId ItemKind -> ItemKind
    forall a b. (a -> b) -> a -> b
    $ Item -> State -> ContentId ItemKind
    getItemKindIdServer Item
    item State
    s

    getIidKindServer :: ItemId -> State -> IK.ItemKind
    getIidKindServer :: ItemId -> State -> ItemKind
    getIidKindServer ItemId
    iid State
    s = Item -> State -> ItemKind
    getItemKindServer (ItemId -> State -> Item
    getItemBody ItemId
    iid State
    s) State
    s

    tileAlterable :: LevelId -> Point -> State -> Bool
    tileAlterable :: LevelId -> Point -> State -> Bool
    tileAlterable LevelId
    lid Point
    pos State
    s =
      let COps{TileSpeedup
    coTileSpeedup :: COps -> TileSpeedup
    coTileSpeedup :: TileSpeedup
    coTileSpeedup} = State -> COps
    scops State
    s
          embeds :: ItemBag
    embeds = LevelId -> Point -> State -> ItemBag
    getEmbedBag LevelId
    lid Point
    pos State
    s
          lvl :: Level
    lvl = State -> Dungeon
    sdungeon State
    s Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! LevelId
    lid
          t :: ContentId TileKind
    t = Level
    lvl Level -> Point -> ContentId TileKind
    `at` Point
    pos
          triggerable :: Bool
    triggerable = (ItemId -> Bool) -> [ItemId] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any (\ItemId
    iid -> Bool -> Bool
    not (Bool -> Bool) -> Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ [Effect] -> Bool
    forall a. [a] -> Bool
    null ([Effect] -> Bool) -> [Effect] -> Bool
    forall a b. (a -> b) -> a -> b
    $ ItemKind -> [Effect]
    IK.ieffects (ItemKind -> [Effect]) -> ItemKind -> [Effect]
    forall a b. (a -> b) -> a -> b
    $ ItemId -> State -> ItemKind
    getIidKind ItemId
    iid State
    s)
                            (ItemBag -> [ItemId]
    forall k a. Enum k => EnumMap k a -> [k]
    EM.keys ItemBag
    embeds)
      in TileSpeedup -> ContentId TileKind -> Bool
    Tile.isModifiable TileSpeedup
    coTileSpeedup ContentId TileKind
    t Bool -> Bool -> Bool
    || Bool
    triggerable

    -- | Determine the dungeon level of the container. If the item is in
    -- the shared stash, the level depends on which actor asks, not where
    -- the stash is located physically.
    lidFromC :: Container -> State -> LevelId
    lidFromC :: Container -> State -> LevelId
    lidFromC (CFloor LevelId
    lid Point
    _) State
    _ = LevelId
    lid
    lidFromC (CEmbed LevelId
    lid Point
    _) State
    _ = LevelId
    lid
    lidFromC (CActor ActorId
    aid CStore
    _) State
    s = Actor -> LevelId
    blid (Actor -> LevelId) -> Actor -> LevelId
    forall a b. (a -> b) -> a -> b
    $ ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s
    lidFromC (CTrunk FactionId
    _ LevelId
    lid Point
    _) State
    _ = LevelId
    lid

    posFromC :: Container -> State -> Point
    posFromC :: Container -> State -> Point
    posFromC (CFloor LevelId
    _ Point
    pos) State
    _ = Point
    pos
    posFromC (CEmbed LevelId
    _ Point
    pos) State
    _ = Point
    pos
    posFromC (CActor ActorId
    aid CStore
    _) State
    s = Actor -> Point
    bpos (Actor -> Point) -> Actor -> Point
    forall a b. (a -> b) -> a -> b
    $ ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s
    posFromC c :: Container
    c@CTrunk{} State
    _ = [Char] -> Point
    forall a. HasCallStack => [Char] -> a
    error ([Char] -> Point) -> [Char] -> Point
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "" [Char] -> Container -> [Char]
    forall v. Show v => [Char] -> v -> [Char]
    `showFailure` Container
    c

    vicinityFoeAdj :: ((ActorId, Actor) -> Bool) -> ActorId -> State -> Bool
    {-# INLINE vicinityFoeAdj #-}
    vicinityFoeAdj :: ((ActorId, Actor) -> Bool) -> ActorId -> State -> Bool
    vicinityFoeAdj (ActorId, Actor) -> Bool
    predicate ActorId
    aid State
    s =
      let body :: Actor
    body = ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s
          lvl :: Level
    lvl = (Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! Actor -> LevelId
    blid Actor
    body) (Dungeon -> Level) -> (State -> Dungeon) -> State -> Level
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> Dungeon
    sdungeon (State -> Level) -> State -> Level
    forall a b. (a -> b) -> a -> b
    $ State
    s
          fact :: Faction
    fact = (EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! Actor -> FactionId
    bfid Actor
    body) (EnumMap FactionId Faction -> Faction)
    -> (State -> EnumMap FactionId Faction) -> State -> Faction
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> EnumMap FactionId Faction
    sfactionD (State -> Faction) -> State -> Faction
    forall a b. (a -> b) -> a -> b
    $ State
    s
          f :: Point -> Bool
    f !Point
    p = case Point -> Level -> Maybe ActorId
    posToBigLvl Point
    p Level
    lvl of
            Maybe ActorId
    Nothing -> Bool
    False
            Just ActorId
    aid2 -> let b2 :: Actor
    b2 = ActorId -> State -> Actor
    getActorBody ActorId
    aid2 State
    s
                         in FactionId -> Faction -> FactionId -> Bool
    isFoe (Actor -> FactionId
    bfid Actor
    body) Faction
    fact (Actor -> FactionId
    bfid Actor
    b2)
                            Bool -> Bool -> Bool
    && (ActorId, Actor) -> Bool
    predicate (ActorId
    aid2, Actor
    b2)
          h :: Point -> Bool
    h !Point
    p = case Point -> Level -> [ActorId]
    posToProjsLvl Point
    p Level
    lvl of
            [] -> Bool
    False
            ActorId
    aid2 : [ActorId]
    _ -> FactionId -> Faction -> FactionId -> Bool
    isFoe (Actor -> FactionId
    bfid Actor
    body) Faction
    fact (FactionId -> Bool) -> (Actor -> FactionId) -> Actor -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Actor -> FactionId
    bfid (Actor -> Bool) -> Actor -> Bool
    forall a b. (a -> b) -> a -> b
    $ ActorId -> State -> Actor
    getActorBody ActorId
    aid2 State
    s
      in (Point -> Bool) -> [Point] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any (\Point
    p -> Point -> Bool
    f Point
    p Bool -> Bool -> Bool
    || Point -> Bool
    h Point
    p) ([Point] -> Bool) -> [Point] -> Bool
    forall a b. (a -> b) -> a -> b
    $ Point -> [Point]
    vicinityUnsafe (Point -> [Point]) -> Point -> [Point]
    forall a b. (a -> b) -> a -> b
    $ Actor -> Point
    bpos Actor
    body

    -- | Require that any non-dying foe is adjacent. We include even
    -- projectiles that explode when stricken down, because they can be caught
    -- and then they don't explode, so it makes sense to focus on handling them.
    -- If there are many projectiles in a single adjacent position, we only test
    -- the first one, the one that would be hit in melee (this is not optimal
    -- if the actor would need to flee instead of meleeing, but fleeing
    -- with *many* projectiles adjacent is a possible waste of a move anyway).
    anyFoeAdj :: ActorId -> State -> Bool
    anyFoeAdj :: ActorId -> State -> Bool
    anyFoeAdj = ((ActorId, Actor) -> Bool) -> ActorId -> State -> Bool
    vicinityFoeAdj (Bool -> (ActorId, Actor) -> Bool
    forall a b. a -> b -> a
    const Bool
    True)

    anyHarmfulFoeAdj :: ActorMaxSkills -> ActorId -> State -> Bool
    anyHarmfulFoeAdj :: ActorMaxSkills -> ActorId -> State -> Bool
    anyHarmfulFoeAdj = ((ActorId, Actor) -> Bool) -> ActorId -> State -> Bool
    vicinityFoeAdj (((ActorId, Actor) -> Bool) -> ActorId -> State -> Bool)
    -> (ActorMaxSkills -> (ActorId, Actor) -> Bool)
    -> ActorMaxSkills
    -> ActorId
    -> State
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ActorId -> Actor -> Bool) -> (ActorId, Actor) -> Bool
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry ((ActorId -> Actor -> Bool) -> (ActorId, Actor) -> Bool)
    -> (ActorMaxSkills -> ActorId -> Actor -> Bool)
    -> ActorMaxSkills
    -> (ActorId, Actor)
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ActorMaxSkills -> ActorId -> Actor -> Bool
    actorWorthKilling

    adjacentBigAssocs :: Actor -> State -> [(ActorId, Actor)]
    {-# INLINE adjacentBigAssocs #-}
    adjacentBigAssocs :: Actor -> State -> [(ActorId, Actor)]
    adjacentBigAssocs Actor
    body State
    s =
      let lvl :: Level
    lvl = (Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! Actor -> LevelId
    blid Actor
    body) (Dungeon -> Level) -> (State -> Dungeon) -> State -> Level
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> Dungeon
    sdungeon (State -> Level) -> State -> Level
    forall a b. (a -> b) -> a -> b
    $ State
    s
          f :: Point -> Maybe ActorId
    f !Point
    p = Point -> Level -> Maybe ActorId
    posToBigLvl Point
    p Level
    lvl
          g :: ActorId -> (ActorId, Actor)
    g !ActorId
    aid = (ActorId
    aid, ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s)
      in (ActorId -> (ActorId, Actor)) -> [ActorId] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> [a] -> [b]
    map ActorId -> (ActorId, Actor)
    g ([ActorId] -> [(ActorId, Actor)])
    -> [ActorId] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ (Point -> Maybe ActorId) -> [Point] -> [ActorId]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe Point -> Maybe ActorId
    f ([Point] -> [ActorId]) -> [Point] -> [ActorId]
    forall a b. (a -> b) -> a -> b
    $ Point -> [Point]
    vicinityUnsafe (Point -> [Point]) -> Point -> [Point]
    forall a b. (a -> b) -> a -> b
    $ Actor -> Point
    bpos Actor
    body

    adjacentProjAssocs :: Actor -> State -> [(ActorId, Actor)]
    {-# INLINE adjacentProjAssocs #-}
    adjacentProjAssocs :: Actor -> State -> [(ActorId, Actor)]
    adjacentProjAssocs Actor
    body State
    s =
      let lvl :: Level
    lvl = (Dungeon -> LevelId -> Level
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! Actor -> LevelId
    blid Actor
    body) (Dungeon -> Level) -> (State -> Dungeon) -> State -> Level
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . State -> Dungeon
    sdungeon (State -> Level) -> State -> Level
    forall a b. (a -> b) -> a -> b
    $ State
    s
          f :: Point -> [ActorId]
    f !Point
    p = Point -> Level -> [ActorId]
    posToProjsLvl Point
    p Level
    lvl
          g :: ActorId -> (ActorId, Actor)
    g !ActorId
    aid = (ActorId
    aid, ActorId -> State -> Actor
    getActorBody ActorId
    aid State
    s)
      in (ActorId -> (ActorId, Actor)) -> [ActorId] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> [a] -> [b]
    map ActorId -> (ActorId, Actor)
    g ([ActorId] -> [(ActorId, Actor)])
    -> [ActorId] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ (Point -> [ActorId]) -> [Point] -> [ActorId]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Point -> [ActorId]
    f ([Point] -> [ActorId]) -> [Point] -> [ActorId]
    forall a b. (a -> b) -> a -> b
    $ Point -> [Point]
    vicinityUnsafe (Point -> [Point]) -> Point -> [Point]
    forall a b. (a -> b) -> a -> b
    $ Actor -> Point
    bpos Actor
    body

    armorHurtBonus :: ActorId -> ActorId -> State -> Int
    armorHurtBonus :: ActorId -> ActorId -> State -> Int
    armorHurtBonus ActorId
    source ActorId
    target State
    s =
      let sb :: Actor
    sb = ActorId -> State -> Actor
    getActorBody ActorId
    source State
    s
          sMaxSk :: Skills
    sMaxSk = ActorId -> State -> Skills
    getActorMaxSkills ActorId
    source State
    s
          tMaxSk :: Skills
    tMaxSk = ActorId -> State -> Skills
    getActorMaxSkills ActorId
    target State
    s
      in Bool -> Skills -> Skills -> Int
    armorHurtCalculation (Actor -> Bool
    bproj Actor
    sb) Skills
    sMaxSk Skills
    tMaxSk

    -- | Check if any non-dying foe is adjacent to any of our normal actors
    -- and either can harm them via melee or can attack from a distance.
    -- Otherwise no point meleeing him. Projectiles are ignored, because
    -- they are not actively attempted to melee, see @meleeAny@.
    -- This is regardless of whether our actor can melee or just needs to flee,
    -- in which case alert is needed so that he is not slowed down by others.
    -- However, if our actor can't move nor melee, no real combat is taking place.
    -- This is needed only by AI and computed as lazily as possible.
    inMelee :: ActorMaxSkills -> FactionId -> LevelId -> State -> Bool
    inMelee :: ActorMaxSkills -> FactionId -> LevelId -> State -> Bool
    inMelee !ActorMaxSkills
    actorMaxSkills !FactionId
    fid !LevelId
    lid State
    s =
      let fact :: Faction
    fact = State -> EnumMap FactionId Faction
    sfactionD State
    s EnumMap FactionId Faction -> FactionId -> Faction
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! FactionId
    fid
          f :: (ActorId, Actor) -> Bool
    f (!ActorId
    aid, !Actor
    b) =
            Actor -> LevelId
    blid Actor
    b LevelId -> LevelId -> Bool
    forall a. Eq a => a -> a -> Bool
    == LevelId
    lid
            Bool -> Bool -> Bool
    && Bool -> Bool
    not (Actor -> Bool
    bproj Actor
    b)
            Bool -> Bool -> Bool
    && (FactionId -> Faction -> FactionId -> Bool)
    -> FactionId -> Faction -> FactionId -> Bool
    forall a. a -> a
    inline FactionId -> Faction -> FactionId -> Bool
    isFoe FactionId
    fid Faction
    fact (Actor -> FactionId
    bfid Actor
    b)  -- costly
            Bool -> Bool -> Bool
    && ActorMaxSkills -> ActorId -> Actor -> Bool
    actorWorthKilling ActorMaxSkills
    actorMaxSkills ActorId
    aid Actor
    b
          allFoes :: [(ActorId, Actor)]
    allFoes = ((ActorId, Actor) -> Bool)
    -> [(ActorId, Actor)] -> [(ActorId, Actor)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (ActorId, Actor) -> Bool
    f ([(ActorId, Actor)] -> [(ActorId, Actor)])
    -> [(ActorId, Actor)] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ EnumMap ActorId Actor -> [(ActorId, Actor)]
    forall k a. Enum k => EnumMap k a -> [(k, a)]
    EM.assocs (EnumMap ActorId Actor -> [(ActorId, Actor)])
    -> EnumMap ActorId Actor -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ State -> EnumMap ActorId Actor
    sactorD State
    s
          g :: (ActorId, Actor) -> Bool
    g (!ActorId
    aid, !Actor
    b) = Actor -> FactionId
    bfid Actor
    b FactionId -> FactionId -> Bool
    forall a. Eq a => a -> a -> Bool
    == FactionId
    fid
                         Bool -> Bool -> Bool
    && Actor -> LevelId
    blid Actor
    b LevelId -> LevelId -> Bool
    forall a. Eq a => a -> a -> Bool
    == LevelId
    lid
                         Bool -> Bool -> Bool
    && Bool -> Bool
    not (Actor -> Bool
    bproj Actor
    b)
                         Bool -> Bool -> Bool
    && Actor -> Int64
    bhp Actor
    b Int64 -> Int64 -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int64
    0
                         Bool -> Bool -> Bool
    && let actorMaxSk :: Skills
    actorMaxSk = ActorMaxSkills
    actorMaxSkills ActorMaxSkills -> ActorId -> Skills
    forall k a. Enum k => EnumMap k a -> k -> a
    EM.! ActorId
    aid
                            in Skill -> Skills -> Int
    Ability.getSk Skill
    Ability.SkMove Skills
    actorMaxSk Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    0
                               Bool -> Bool -> Bool
    || ActorMaxSkills -> ActorId -> Actor -> Bool
    actorCanMeleeToHarm ActorMaxSkills
    actorMaxSkills ActorId
    aid Actor
    b
          allOurs :: [(ActorId, Actor)]
    allOurs = ((ActorId, Actor) -> Bool)
    -> [(ActorId, Actor)] -> [(ActorId, Actor)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (ActorId, Actor) -> Bool
    g ([(ActorId, Actor)] -> [(ActorId, Actor)])
    -> [(ActorId, Actor)] -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ EnumMap ActorId Actor -> [(ActorId, Actor)]
    forall k a. Enum k => EnumMap k a -> [(k, a)]
    EM.assocs (EnumMap ActorId Actor -> [(ActorId, Actor)])
    -> EnumMap ActorId Actor -> [(ActorId, Actor)]
    forall a b. (a -> b) -> a -> b
    $ State -> EnumMap ActorId Actor
    sactorD State
    s
          -- We assume foes are less numerous, even though they may come
          -- from multiple factions and they contain projectiles,
          -- because we see all our actors, while many foes may be hidden.
          -- Consequently, we allocate the set of foe positions
          -- and avoid allocating ours, by iterating over our actors.
          -- This in O(mn) instead of O(m+n), but it allocates
          -- less and multiplicative constants are lower.
          -- We inspect adjacent locations of foe positions, not of ours,
          -- thus increasing allocation a bit, but not by much, because
          -- the set should be rather saturated.
          -- If there are no foes in sight, we don't iterate at all.
          setFoeVicinity :: EnumSet Point
    setFoeVicinity =
            [Point] -> EnumSet Point
    forall k. Enum k => [k] -> EnumSet k
    ES.fromList ([Point] -> EnumSet Point) -> [Point] -> EnumSet Point
    forall a b. (a -> b) -> a -> b
    $ ((ActorId, Actor) -> [Point]) -> [(ActorId, Actor)] -> [Point]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (Point -> [Point]
    vicinityUnsafe (Point -> [Point])
    -> ((ActorId, Actor) -> Point) -> (ActorId, Actor) -> [Point]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Actor -> Point
    bpos (Actor -> Point)
    -> ((ActorId, Actor) -> Actor) -> (ActorId, Actor) -> Point
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ActorId, Actor) -> Actor
    forall a b. (a, b) -> b
    snd) [(ActorId, Actor)]
    allFoes
      in Bool -> Bool
    not (EnumSet Point -> Bool
    forall k. EnumSet k -> Bool
    ES.null EnumSet Point
    setFoeVicinity)  -- shortcut
         Bool -> Bool -> Bool
    && ((ActorId, Actor) -> Bool) -> [(ActorId, Actor)] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any (\(ActorId
    _, Actor
    b) -> Actor -> Point
    bpos Actor
    b Point -> EnumSet Point -> Bool
    forall k. Enum k => k -> EnumSet k -> Bool
    `ES.member` EnumSet Point
    setFoeVicinity) [(ActorId, Actor)]
    allOurs