    {-# LANGUAGE DeriveGeneric, GeneralizedNewtypeDeriving #-}
    -- | The client UI session state.
    module Game.LambdaHack.Client.UI.SessionUI
      ( SessionUI(..), ReqDelay(..), ItemDictUI, ItemRoles(..), AimMode(..)
      , KeyMacro(..), KeyMacroFrame(..), RunParams(..), ChosenLore(..)
      , emptySessionUI, emptyMacroFrame
      , cycleMarkVision, toggleMarkSmell, cycleOverrideTut, getActorUI
      ) where

    import Prelude ()

    import Game.LambdaHack.Core.Prelude

    import           Data.Binary
    import qualified Data.EnumMap.Strict as EM
    import qualified Data.EnumSet as ES
    import qualified Data.Map.Strict as M
    import qualified Data.Set as S
    import           Data.Time.Clock.POSIX
    import           GHC.Generics (Generic)
    import qualified System.Random.SplitMix32 as SM

    import           Game.LambdaHack.Client.Request
    import           Game.LambdaHack.Client.State
    import           Game.LambdaHack.Client.UI.ActorUI
    import           Game.LambdaHack.Client.UI.ContentClientUI
    import           Game.LambdaHack.Client.UI.EffectDescription (DetailLevel (..))
    import           Game.LambdaHack.Client.UI.Frontend
    import qualified Game.LambdaHack.Client.UI.Key as K
    import           Game.LambdaHack.Client.UI.Msg
    import           Game.LambdaHack.Client.UI.PointUI
    import           Game.LambdaHack.Client.UI.UIOptions
    import           Game.LambdaHack.Common.Actor
    import           Game.LambdaHack.Common.Faction
    import           Game.LambdaHack.Common.Item
    import           Game.LambdaHack.Common.Time
    import           Game.LambdaHack.Common.Types
    import           Game.LambdaHack.Content.ModeKind (ModeKind)
    import           Game.LambdaHack.Definition.Defs

    -- | The information that is used across a human player playing session,
    -- including many consecutive games in a single session,
    -- including playing different teams. Some of it is saved, some is reset
    -- when a new playing session starts. Nothing is tied to a faction/team,
    -- but instead all to UI configuration and UI input and display history.
    -- An important component is the frontend session.
    data SessionUI = SessionUI
      { SessionUI -> Maybe RequestUI
    sreqPending    :: Maybe RequestUI
                                        -- ^ request created by a UI query
                                        --   but not yet sent to the server
      , SessionUI -> ReqDelay
    sreqDelay      :: ReqDelay      -- ^ server delayed sending query to client
                                        --   or receiving request from client
      , SessionUI -> Bool
    sreqQueried    :: Bool          -- ^ player is now queried for a command
      , SessionUI -> Bool
    sregainControl :: Bool          -- ^ player requested to regain control
                                        --   from AI ASAP
      , SessionUI -> Maybe Target
    sxhair         :: Maybe Target  -- ^ the common xhair
      , SessionUI -> Maybe Target
    sxhairGoTo     :: Maybe Target  -- ^ xhair set for last GoTo
      , SessionUI -> ActorDictUI
    sactorUI       :: ActorDictUI   -- ^ assigned actor UI presentations
      , SessionUI -> ItemDictUI
    sitemUI        :: ItemDictUI    -- ^ assigned item first seen level
      , SessionUI -> ItemRoles
    sroles         :: ItemRoles     -- ^ assignment of roles to items
      , SessionUI -> Maybe (CStore, CStore)
    slastItemMove  :: Maybe (CStore, CStore)
                                        -- ^ last item move stores
      , SessionUI -> ChanFrontend
    schanF         :: ChanFrontend  -- ^ connection with the frontend
      , SessionUI -> CCUI
    sccui          :: CCUI          -- ^ UI client content
      , SessionUI -> UIOptions
    sUIOptions     :: UIOptions     -- ^ UI options as set by the player
      , SessionUI -> Maybe AimMode
    saimMode       :: Maybe AimMode -- ^ aiming mode
      , SessionUI -> Bool
    sxhairMoused   :: Bool          -- ^ last mouse aiming not vacuus
      , SessionUI -> Maybe (ItemId, CStore, Bool)
    sitemSel       :: Maybe (ItemId, CStore, Bool)
                                        -- ^ selected item, if any, it's store and
                                        --   whether to override suitability check
      , SessionUI -> EnumSet ActorId
    sselected      :: ES.EnumSet ActorId
                                        -- ^ the set of currently selected actors
      , SessionUI -> Maybe RunParams
    srunning       :: Maybe RunParams
                                        -- ^ parameters of the current run, if any
      , SessionUI -> History
    shistory       :: History       -- ^ history of messages
      , SessionUI -> EnumMap (ContentId ModeKind) (Map Challenge Int)
    svictories     :: EM.EnumMap (ContentId ModeKind) (M.Map Challenge Int)
          -- ^ the number of games won by the UI faction per game mode
          --   and per difficulty level
      , SessionUI -> EnumSet (ContentId ModeKind)
    scampings      :: ES.EnumSet (ContentId ModeKind)  -- ^ camped games
      , SessionUI -> EnumSet (ContentId ModeKind)
    srestarts      :: ES.EnumSet (ContentId ModeKind)  -- ^ restarted games
      , SessionUI -> PointUI
    spointer       :: PointUI       -- ^ mouse pointer position
      , SessionUI -> Bool
    sautoYes       :: Bool          -- ^ whether to auto-clear prompts
      , SessionUI -> KeyMacroFrame
    smacroFrame    :: KeyMacroFrame -- ^ the head of the key macro stack
      , SessionUI -> [KeyMacroFrame]
    smacroStack    :: [KeyMacroFrame]
                                        -- ^ the tail of the key macro stack
      , SessionUI -> EnumSet ActorId
    slastLost      :: ES.EnumSet ActorId
                                        -- ^ actors that just got out of sight
      , SessionUI -> Int
    swaitTimes     :: Int           -- ^ player just waited this many times
      , SessionUI -> Bool
    swasAutomated  :: Bool          -- ^ the player just exited AI automation
      , SessionUI -> Int
    smarkVision    :: Int           -- ^ mark leader and party FOV
      , SessionUI -> Bool
    smarkSmell     :: Bool          -- ^ mark smell, if the leader can smell
      , SessionUI -> Int
    snxtScenario   :: Int           -- ^ next game scenario number
      , SessionUI -> Bool
    scurTutorial   :: Bool          -- ^ whether current game is a tutorial
      , SessionUI -> Bool
    snxtTutorial   :: Bool          -- ^ whether next game is to be tutorial
      , SessionUI -> Maybe Bool
    soverrideTut   :: Maybe Bool    -- ^ override display of tutorial hints
      , SessionUI -> Set Msg
    susedHints     :: S.Set Msg     -- ^ tutorial hints already shown this game
      , SessionUI -> Bool
    smuteMessages  :: Bool          -- ^ whether to mute all new messages
      , SessionUI -> Map String Int
    smenuIxMap     :: M.Map String Int
                                        -- ^ indices of last used menu items
      , SessionUI -> ChosenLore
    schosenLore    :: ChosenLore    -- ^ last lore chosen to display
      , SessionUI -> Bool
    sdisplayNeeded :: Bool          -- ^ current level needs displaying
      , SessionUI -> Bool
    sturnDisplayed :: Bool          -- ^ a frame was already displayed this turn
      , SessionUI -> Bool
    sreportNull    :: Bool          -- ^ whether no visible report created
                                        --   last UI faction turn or the report
                                        --   wiped out from screen since
      , SessionUI -> POSIXTime
    sstart         :: POSIXTime     -- ^ this session start time
      , SessionUI -> POSIXTime
    sgstart        :: POSIXTime     -- ^ this game start time
      , SessionUI -> Time
    sallTime       :: Time          -- ^ clips from start of session
                                        --   to current game start
      , SessionUI -> Int
    snframes       :: Int           -- ^ this game current frame count
      , SessionUI -> Int
    sallNframes    :: Int           -- ^ frame count from start of session
                                        --   to current game start
      , SessionUI -> SMGen
    srandomUI      :: SM.SMGen      -- ^ current random generator for UI
      }

    data ReqDelay = ReqDelayNot | ReqDelayHandled | ReqDelayAlarm
      deriving ReqDelay -> ReqDelay -> Bool
    (ReqDelay -> ReqDelay -> Bool)
    -> (ReqDelay -> ReqDelay -> Bool) -> Eq ReqDelay
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ReqDelay -> ReqDelay -> Bool
    == :: ReqDelay -> ReqDelay -> Bool
    $c/= :: ReqDelay -> ReqDelay -> Bool
    /= :: ReqDelay -> ReqDelay -> Bool
    Eq

    -- | Local macro buffer frame. Predefined macros have their own in-game macro
    -- buffer, allowing them to record in-game macro, queue actions and repeat
    -- the last macro's action.
    -- Running predefined macro pushes new @KeyMacroFrame@ onto the stack. We pop
    -- buffers from the stack if locally there are no actions pending to be handled.
    data KeyMacroFrame = KeyMacroFrame
      { KeyMacroFrame -> Either [KM] KeyMacro
    keyMacroBuffer :: Either [K.KM] KeyMacro -- ^ record keystrokes in Left;
                                                 --   repeat from Right
      , KeyMacroFrame -> KeyMacro
    keyPending     :: KeyMacro               -- ^ actions pending to be handled
      , KeyMacroFrame -> Maybe KM
    keyLast        :: Maybe K.KM             -- ^ last pressed key
      } deriving Int -> KeyMacroFrame -> ShowS
    [KeyMacroFrame] -> ShowS
    KeyMacroFrame -> String
    (Int -> KeyMacroFrame -> ShowS)
    -> (KeyMacroFrame -> String)
    -> ([KeyMacroFrame] -> ShowS)
    -> Show KeyMacroFrame
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> KeyMacroFrame -> ShowS
    showsPrec :: Int -> KeyMacroFrame -> ShowS
    $cshow :: KeyMacroFrame -> String
    show :: KeyMacroFrame -> String
    $cshowList :: [KeyMacroFrame] -> ShowS
    showList :: [KeyMacroFrame] -> ShowS
    Show

    -- This can stay a map forever, not a vector, because it's added to often,
    -- but never read from, except when the user requests item details.
    type ItemDictUI = EM.EnumMap ItemId LevelId

    -- | A collection of item identifier sets indicating what roles (possibly many)
    -- an item has assigned.
    newtype ItemRoles = ItemRoles (EM.EnumMap SLore (ES.EnumSet ItemId))
      deriving (Int -> ItemRoles -> ShowS
    [ItemRoles] -> ShowS
    ItemRoles -> String
    (Int -> ItemRoles -> ShowS)
    -> (ItemRoles -> String)
    -> ([ItemRoles] -> ShowS)
    -> Show ItemRoles
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ItemRoles -> ShowS
    showsPrec :: Int -> ItemRoles -> ShowS
    $cshow :: ItemRoles -> String
    show :: ItemRoles -> String
    $cshowList :: [ItemRoles] -> ShowS
    showList :: [ItemRoles] -> ShowS
    Show, Get ItemRoles
    [ItemRoles] -> Put
    ItemRoles -> Put
    (ItemRoles -> Put)
    -> Get ItemRoles -> ([ItemRoles] -> Put) -> Binary ItemRoles
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    $cput :: ItemRoles -> Put
    put :: ItemRoles -> Put
    $cget :: Get ItemRoles
    get :: Get ItemRoles
    $cputList :: [ItemRoles] -> Put
    putList :: [ItemRoles] -> Put
    Binary)

    -- | Current aiming mode of a client.
    data AimMode = AimMode
      { AimMode -> LevelId
    aimLevelId  :: LevelId
      , AimMode -> DetailLevel
    detailLevel :: DetailLevel
      }
      deriving (Int -> AimMode -> ShowS
    [AimMode] -> ShowS
    AimMode -> String
    (Int -> AimMode -> ShowS)
    -> (AimMode -> String) -> ([AimMode] -> ShowS) -> Show AimMode
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> AimMode -> ShowS
    showsPrec :: Int -> AimMode -> ShowS
    $cshow :: AimMode -> String
    show :: AimMode -> String
    $cshowList :: [AimMode] -> ShowS
    showList :: [AimMode] -> ShowS
    Show, AimMode -> AimMode -> Bool
    (AimMode -> AimMode -> Bool)
    -> (AimMode -> AimMode -> Bool) -> Eq AimMode
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: AimMode -> AimMode -> Bool
    == :: AimMode -> AimMode -> Bool
    $c/= :: AimMode -> AimMode -> Bool
    /= :: AimMode -> AimMode -> Bool
    Eq, (forall x. AimMode -> Rep AimMode x)
    -> (forall x. Rep AimMode x -> AimMode) -> Generic AimMode
    forall x. Rep AimMode x -> AimMode
    forall x. AimMode -> Rep AimMode x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. AimMode -> Rep AimMode x
    from :: forall x. AimMode -> Rep AimMode x
    $cto :: forall x. Rep AimMode x -> AimMode
    to :: forall x. Rep AimMode x -> AimMode
    Generic)

    instance Binary AimMode

    -- | In-game macros. We record menu navigation keystrokes and keystrokes
    -- bound to commands with one exception --- we exclude keys that invoke
    -- the @Record@ command, to avoid surprises.
    -- Keys are kept in the same order in which they're meant to be replayed,
    -- i.e. the first element of the list is replayed also as the first one.
    newtype KeyMacro = KeyMacro {KeyMacro -> [KM]
    unKeyMacro :: [K.KM]}
      deriving (Int -> KeyMacro -> ShowS
    [KeyMacro] -> ShowS
    KeyMacro -> String
    (Int -> KeyMacro -> ShowS)
    -> (KeyMacro -> String) -> ([KeyMacro] -> ShowS) -> Show KeyMacro
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> KeyMacro -> ShowS
    showsPrec :: Int -> KeyMacro -> ShowS
    $cshow :: KeyMacro -> String
    show :: KeyMacro -> String
    $cshowList :: [KeyMacro] -> ShowS
    showList :: [KeyMacro] -> ShowS
    Show, KeyMacro -> KeyMacro -> Bool
    (KeyMacro -> KeyMacro -> Bool)
    -> (KeyMacro -> KeyMacro -> Bool) -> Eq KeyMacro
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: KeyMacro -> KeyMacro -> Bool
    == :: KeyMacro -> KeyMacro -> Bool
    $c/= :: KeyMacro -> KeyMacro -> Bool
    /= :: KeyMacro -> KeyMacro -> Bool
    Eq, Get KeyMacro
    [KeyMacro] -> Put
    KeyMacro -> Put
    (KeyMacro -> Put)
    -> Get KeyMacro -> ([KeyMacro] -> Put) -> Binary KeyMacro
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    $cput :: KeyMacro -> Put
    put :: KeyMacro -> Put
    $cget :: Get KeyMacro
    get :: Get KeyMacro
    $cputList :: [KeyMacro] -> Put
    putList :: [KeyMacro] -> Put
    Binary, NonEmpty KeyMacro -> KeyMacro
    KeyMacro -> KeyMacro -> KeyMacro
    (KeyMacro -> KeyMacro -> KeyMacro)
    -> (NonEmpty KeyMacro -> KeyMacro)
    -> (forall b. Integral b => b -> KeyMacro -> KeyMacro)
    -> Semigroup KeyMacro
    forall b. Integral b => b -> KeyMacro -> KeyMacro
    forall a.
    (a -> a -> a)
    -> (NonEmpty a -> a)
    -> (forall b. Integral b => b -> a -> a)
    -> Semigroup a
    $c<> :: KeyMacro -> KeyMacro -> KeyMacro
    <> :: KeyMacro -> KeyMacro -> KeyMacro
    $csconcat :: NonEmpty KeyMacro -> KeyMacro
    sconcat :: NonEmpty KeyMacro -> KeyMacro
    $cstimes :: forall b. Integral b => b -> KeyMacro -> KeyMacro
    stimes :: forall b. Integral b => b -> KeyMacro -> KeyMacro
    Semigroup, Semigroup KeyMacro
    KeyMacro
    Semigroup KeyMacro =>
    KeyMacro
    -> (KeyMacro -> KeyMacro -> KeyMacro)
    -> ([KeyMacro] -> KeyMacro)
    -> Monoid KeyMacro
    [KeyMacro] -> KeyMacro
    KeyMacro -> KeyMacro -> KeyMacro
    forall a.
    Semigroup a =>
    a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
    $cmempty :: KeyMacro
    mempty :: KeyMacro
    $cmappend :: KeyMacro -> KeyMacro -> KeyMacro
    mappend :: KeyMacro -> KeyMacro -> KeyMacro
    $cmconcat :: [KeyMacro] -> KeyMacro
    mconcat :: [KeyMacro] -> KeyMacro
    Monoid)

    -- | Parameters of the current run.
    data RunParams = RunParams
      { RunParams -> ActorId
    runLeader  :: ActorId         -- ^ the original leader from run start
      , RunParams -> [ActorId]
    runMembers :: [ActorId]       -- ^ the list of actors that take part
      , RunParams -> Bool
    runInitial :: Bool            -- ^ initial run continuation by any
                                      --   run participant, including run leader
      , RunParams -> Maybe Text
    runStopMsg :: Maybe Text      -- ^ message with the next stop reason
      , RunParams -> Int
    runWaiting :: Int             -- ^ waiting for others to move out of the way
      }
      deriving Int -> RunParams -> ShowS
    [RunParams] -> ShowS
    RunParams -> String
    (Int -> RunParams -> ShowS)
    -> (RunParams -> String)
    -> ([RunParams] -> ShowS)
    -> Show RunParams
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> RunParams -> ShowS
    showsPrec :: Int -> RunParams -> ShowS
    $cshow :: RunParams -> String
    show :: RunParams -> String
    $cshowList :: [RunParams] -> ShowS
    showList :: [RunParams] -> ShowS
    Show

    -- | Last lore being aimed at.
    data ChosenLore =
        ChosenLore [(ActorId, Actor)] [(ItemId, ItemQuant)]
      | ChosenNothing

    emptySessionUI :: UIOptions -> SessionUI
    emptySessionUI :: UIOptions -> SessionUI
    emptySessionUI UIOptions
    sUIOptions =
      SessionUI
        { sreqPending :: Maybe RequestUI
    sreqPending = Maybe RequestUI
    forall a. Maybe a
    Nothing
        , sreqDelay :: ReqDelay
    sreqDelay = ReqDelay
    ReqDelayNot
        , sreqQueried :: Bool
    sreqQueried = Bool
    False
        , sregainControl :: Bool
    sregainControl = Bool
    False
        , sxhair :: Maybe Target
    sxhair = Maybe Target
    forall a. Maybe a
    Nothing
        , sxhairGoTo :: Maybe Target
    sxhairGoTo = Maybe Target
    forall a. Maybe a
    Nothing
        , sactorUI :: ActorDictUI
    sactorUI = ActorDictUI
    forall k a. EnumMap k a
    EM.empty
        , sitemUI :: ItemDictUI
    sitemUI = ItemDictUI
    forall k a. EnumMap k a
    EM.empty
        , sroles :: ItemRoles
    sroles = EnumMap SLore (EnumSet ItemId) -> ItemRoles
    ItemRoles (EnumMap SLore (EnumSet ItemId) -> ItemRoles)
    -> EnumMap SLore (EnumSet ItemId) -> ItemRoles
    forall a b. (a -> b) -> a -> b
    $ [(SLore, EnumSet ItemId)] -> EnumMap SLore (EnumSet ItemId)
    forall k a. Enum k => [(k, a)] -> EnumMap k a
    EM.fromDistinctAscList
                   ([(SLore, EnumSet ItemId)] -> EnumMap SLore (EnumSet ItemId))
    -> [(SLore, EnumSet ItemId)] -> EnumMap SLore (EnumSet ItemId)
    forall a b. (a -> b) -> a -> b
    $ [SLore] -> [EnumSet ItemId] -> [(SLore, EnumSet ItemId)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [SLore
    forall a. Bounded a => a
    minBound..SLore
    forall a. Bounded a => a
    maxBound] (EnumSet ItemId -> [EnumSet ItemId]
    forall a. a -> [a]
    repeat EnumSet ItemId
    forall k. EnumSet k
    ES.empty)
        , slastItemMove :: Maybe (CStore, CStore)
    slastItemMove = Maybe (CStore, CStore)
    forall a. Maybe a
    Nothing
        , schanF :: ChanFrontend
    schanF = (forall a. FrontReq a -> IO a) -> ChanFrontend
    ChanFrontend ((forall a. FrontReq a -> IO a) -> ChanFrontend)
    -> (forall a. FrontReq a -> IO a) -> ChanFrontend
    forall a b. (a -> b) -> a -> b
    $ IO a -> FrontReq a -> IO a
    forall a b. a -> b -> a
    const (IO a -> FrontReq a -> IO a) -> IO a -> FrontReq a -> IO a
    forall a b. (a -> b) -> a -> b
    $
            String -> IO a
    forall a. HasCallStack => String -> a
    error (String -> IO a) -> String -> IO a
    forall a b. (a -> b) -> a -> b
    $ String
    "emptySessionUI: ChanFrontend" String -> () -> String
    forall v. Show v => String -> v -> String
    `showFailure` ()
        , sccui :: CCUI
    sccui = CCUI
    emptyCCUI
        , UIOptions
    sUIOptions :: UIOptions
    sUIOptions :: UIOptions
    sUIOptions
        , saimMode :: Maybe AimMode
    saimMode = Maybe AimMode
    forall a. Maybe a
    Nothing
        , sxhairMoused :: Bool
    sxhairMoused = Bool
    True
        , sitemSel :: Maybe (ItemId, CStore, Bool)
    sitemSel = Maybe (ItemId, CStore, Bool)
    forall a. Maybe a
    Nothing
        , sselected :: EnumSet ActorId
    sselected = EnumSet ActorId
    forall k. EnumSet k
    ES.empty
        , srunning :: Maybe RunParams
    srunning = Maybe RunParams
    forall a. Maybe a
    Nothing
        , shistory :: History
    shistory = Int -> History
    emptyHistory Int
    0
        , svictories :: EnumMap (ContentId ModeKind) (Map Challenge Int)
    svictories = EnumMap (ContentId ModeKind) (Map Challenge Int)
    forall k a. EnumMap k a
    EM.empty
        , scampings :: EnumSet (ContentId ModeKind)
    scampings = EnumSet (ContentId ModeKind)
    forall k. EnumSet k
    ES.empty
        , srestarts :: EnumSet (ContentId ModeKind)
    srestarts = EnumSet (ContentId ModeKind)
    forall k. EnumSet k
    ES.empty
        , spointer :: PointUI
    spointer = Int -> Int -> PointUI
    PointUI Int
    0 Int
    0
        , sautoYes :: Bool
    sautoYes = Bool
    False
        , smacroFrame :: KeyMacroFrame
    smacroFrame = KeyMacroFrame
    emptyMacroFrame
        , smacroStack :: [KeyMacroFrame]
    smacroStack = []
        , slastLost :: EnumSet ActorId
    slastLost = EnumSet ActorId
    forall k. EnumSet k
    ES.empty
        , swaitTimes :: Int
    swaitTimes = Int
    0
        , swasAutomated :: Bool
    swasAutomated = Bool
    False
        , smarkVision :: Int
    smarkVision = Int
    1
        , smarkSmell :: Bool
    smarkSmell = Bool
    True
        , snxtScenario :: Int
    snxtScenario = Int
    0
        , scurTutorial :: Bool
    scurTutorial = Bool
    False
        , snxtTutorial :: Bool
    snxtTutorial = Bool
    True  -- matches @snxtScenario = 0@
        , soverrideTut :: Maybe Bool
    soverrideTut = Maybe Bool
    forall a. Maybe a
    Nothing
        , susedHints :: Set Msg
    susedHints = Set Msg
    forall a. Set a
    S.empty
        , smuteMessages :: Bool
    smuteMessages = Bool
    False
        , smenuIxMap :: Map String Int
    smenuIxMap = Map String Int
    forall k a. Map k a
    M.empty
        , schosenLore :: ChosenLore
    schosenLore = ChosenLore
    ChosenNothing
        , sdisplayNeeded :: Bool
    sdisplayNeeded = Bool
    False
        , sturnDisplayed :: Bool
    sturnDisplayed = Bool
    False
        , sreportNull :: Bool
    sreportNull = Bool
    True
        , sstart :: POSIXTime
    sstart = POSIXTime
    0
        , sgstart :: POSIXTime
    sgstart = POSIXTime
    0
        , sallTime :: Time
    sallTime = Time
    timeZero
        , snframes :: Int
    snframes = Int
    0
        , sallNframes :: Int
    sallNframes = Int
    0
        , srandomUI :: SMGen
    srandomUI = Word32 -> SMGen
    SM.mkSMGen Word32
    0
        }

    emptyMacroFrame :: KeyMacroFrame
    emptyMacroFrame :: KeyMacroFrame
    emptyMacroFrame = Either [KM] KeyMacro -> KeyMacro -> Maybe KM -> KeyMacroFrame
    KeyMacroFrame (KeyMacro -> Either [KM] KeyMacro
    forall a b. b -> Either a b
    Right KeyMacro
    forall a. Monoid a => a
    mempty) KeyMacro
    forall a. Monoid a => a
    mempty Maybe KM
    forall a. Maybe a
    Nothing

    cycleMarkVision :: Int -> SessionUI -> SessionUI
    cycleMarkVision :: Int -> SessionUI -> SessionUI
    cycleMarkVision Int
    delta SessionUI
    sess =
      SessionUI
    sess {smarkVision = (smarkVision sess + delta) `mod` 3}

    toggleMarkSmell :: SessionUI -> SessionUI
    toggleMarkSmell :: SessionUI -> SessionUI
    toggleMarkSmell SessionUI
    sess = SessionUI
    sess {smarkSmell = not (smarkSmell sess)}

    cycleOverrideTut :: Int -> SessionUI -> SessionUI
    cycleOverrideTut :: Int -> SessionUI -> SessionUI
    cycleOverrideTut Int
    delta SessionUI
    sess =
      let ordering :: [Maybe Bool]
    ordering = [Maybe Bool] -> [Maybe Bool]
    forall a. HasCallStack => [a] -> [a]
    cycle [Maybe Bool
    forall a. Maybe a
    Nothing, Bool -> Maybe Bool
    forall a. a -> Maybe a
    Just Bool
    False, Bool -> Maybe Bool
    forall a. a -> Maybe a
    Just Bool
    True]
      in SessionUI
    sess {soverrideTut =
        let ix = Maybe Int -> Int
    forall a. HasCallStack => Maybe a -> a
    fromJust (Maybe Int -> Int) -> Maybe Int -> Int
    forall a b. (a -> b) -> a -> b
    $ Maybe Bool -> [Maybe Bool] -> Maybe Int
    forall a. Eq a => a -> [a] -> Maybe Int
    elemIndex (SessionUI -> Maybe Bool
    soverrideTut SessionUI
    sess) [Maybe Bool]
    ordering
        in ordering !! (ix + delta)}

    getActorUI :: ActorId -> SessionUI -> ActorUI
    getActorUI :: ActorId -> SessionUI -> ActorUI
    getActorUI ActorId
    aid SessionUI
    sess =
      ActorUI -> ActorId -> ActorDictUI -> ActorUI
    forall k a. Enum k => a -> k -> EnumMap k a -> a
    EM.findWithDefault (String -> ActorUI
    forall a. HasCallStack => String -> a
    error (String -> ActorUI) -> String -> ActorUI
    forall a b. (a -> b) -> a -> b
    $ String
    "" String -> (ActorId, ActorDictUI) -> String
    forall v. Show v => String -> v -> String
    `showFailure` (ActorId
    aid, SessionUI -> ActorDictUI
    sactorUI SessionUI
    sess)) ActorId
    aid
      (ActorDictUI -> ActorUI) -> ActorDictUI -> ActorUI
    forall a b. (a -> b) -> a -> b
    $ SessionUI -> ActorDictUI
    sactorUI SessionUI
    sess

    instance Binary SessionUI where
      put :: SessionUI -> Put
    put SessionUI{Bool
    Int
    [KeyMacroFrame]
    Maybe Bool
    Maybe (CStore, CStore)
    Maybe RequestUI
    Maybe (ItemId, CStore, Bool)
    Maybe Target
    Maybe RunParams
    Maybe AimMode
    Set Msg
    Map String Int
    EnumSet (ContentId ModeKind)
    EnumSet ActorId
    EnumMap (ContentId ModeKind) (Map Challenge Int)
    ActorDictUI
    ItemDictUI
    SMGen
    POSIXTime
    Time
    PointUI
    History
    UIOptions
    ChanFrontend
    CCUI
    ChosenLore
    ItemRoles
    KeyMacroFrame
    ReqDelay
    sreqPending :: SessionUI -> Maybe RequestUI
    sreqDelay :: SessionUI -> ReqDelay
    sreqQueried :: SessionUI -> Bool
    sregainControl :: SessionUI -> Bool
    sxhair :: SessionUI -> Maybe Target
    sxhairGoTo :: SessionUI -> Maybe Target
    sactorUI :: SessionUI -> ActorDictUI
    sitemUI :: SessionUI -> ItemDictUI
    sroles :: SessionUI -> ItemRoles
    slastItemMove :: SessionUI -> Maybe (CStore, CStore)
    schanF :: SessionUI -> ChanFrontend
    sccui :: SessionUI -> CCUI
    sUIOptions :: SessionUI -> UIOptions
    saimMode :: SessionUI -> Maybe AimMode
    sxhairMoused :: SessionUI -> Bool
    sitemSel :: SessionUI -> Maybe (ItemId, CStore, Bool)
    sselected :: SessionUI -> EnumSet ActorId
    srunning :: SessionUI -> Maybe RunParams
    shistory :: SessionUI -> History
    svictories :: SessionUI -> EnumMap (ContentId ModeKind) (Map Challenge Int)
    scampings :: SessionUI -> EnumSet (ContentId ModeKind)
    srestarts :: SessionUI -> EnumSet (ContentId ModeKind)
    spointer :: SessionUI -> PointUI
    sautoYes :: SessionUI -> Bool
    smacroFrame :: SessionUI -> KeyMacroFrame
    smacroStack :: SessionUI -> [KeyMacroFrame]
    slastLost :: SessionUI -> EnumSet ActorId
    swaitTimes :: SessionUI -> Int
    swasAutomated :: SessionUI -> Bool
    smarkVision :: SessionUI -> Int
    smarkSmell :: SessionUI -> Bool
    snxtScenario :: SessionUI -> Int
    scurTutorial :: SessionUI -> Bool
    snxtTutorial :: SessionUI -> Bool
    soverrideTut :: SessionUI -> Maybe Bool
    susedHints :: SessionUI -> Set Msg
    smuteMessages :: SessionUI -> Bool
    smenuIxMap :: SessionUI -> Map String Int
    schosenLore :: SessionUI -> ChosenLore
    sdisplayNeeded :: SessionUI -> Bool
    sturnDisplayed :: SessionUI -> Bool
    sreportNull :: SessionUI -> Bool
    sstart :: SessionUI -> POSIXTime
    sgstart :: SessionUI -> POSIXTime
    sallTime :: SessionUI -> Time
    snframes :: SessionUI -> Int
    sallNframes :: SessionUI -> Int
    srandomUI :: SessionUI -> SMGen
    sreqPending :: Maybe RequestUI
    sreqDelay :: ReqDelay
    sreqQueried :: Bool
    sregainControl :: Bool
    sxhair :: Maybe Target
    sxhairGoTo :: Maybe Target
    sactorUI :: ActorDictUI
    sitemUI :: ItemDictUI
    sroles :: ItemRoles
    slastItemMove :: Maybe (CStore, CStore)
    schanF :: ChanFrontend
    sccui :: CCUI
    sUIOptions :: UIOptions
    saimMode :: Maybe AimMode
    sxhairMoused :: Bool
    sitemSel :: Maybe (ItemId, CStore, Bool)
    sselected :: EnumSet ActorId
    srunning :: Maybe RunParams
    shistory :: History
    svictories :: EnumMap (ContentId ModeKind) (Map Challenge Int)
    scampings :: EnumSet (ContentId ModeKind)
    srestarts :: EnumSet (ContentId ModeKind)
    spointer :: PointUI
    sautoYes :: Bool
    smacroFrame :: KeyMacroFrame
    smacroStack :: [KeyMacroFrame]
    slastLost :: EnumSet ActorId
    swaitTimes :: Int
    swasAutomated :: Bool
    smarkVision :: Int
    smarkSmell :: Bool
    snxtScenario :: Int
    scurTutorial :: Bool
    snxtTutorial :: Bool
    soverrideTut :: Maybe Bool
    susedHints :: Set Msg
    smuteMessages :: Bool
    smenuIxMap :: Map String Int
    schosenLore :: ChosenLore
    sdisplayNeeded :: Bool
    sturnDisplayed :: Bool
    sreportNull :: Bool
    sstart :: POSIXTime
    sgstart :: POSIXTime
    sallTime :: Time
    snframes :: Int
    sallNframes :: Int
    srandomUI :: SMGen
    ..} = do
        Maybe Target -> Put
    forall t. Binary t => t -> Put
    put Maybe Target
    sxhair
        ActorDictUI -> Put
    forall t. Binary t => t -> Put
    put ActorDictUI
    sactorUI
        ItemDictUI -> Put
    forall t. Binary t => t -> Put
    put ItemDictUI
    sitemUI
        ItemRoles -> Put
    forall t. Binary t => t -> Put
    put ItemRoles
    sroles
        UIOptions -> Put
    forall t. Binary t => t -> Put
    put UIOptions
    sUIOptions
        Maybe AimMode -> Put
    forall t. Binary t => t -> Put
    put Maybe AimMode
    saimMode
        Maybe (ItemId, CStore, Bool) -> Put
    forall t. Binary t => t -> Put
    put Maybe (ItemId, CStore, Bool)
    sitemSel
        EnumSet ActorId -> Put
    forall t. Binary t => t -> Put
    put EnumSet ActorId
    sselected
        Maybe RunParams -> Put
    forall t. Binary t => t -> Put
    put Maybe RunParams
    srunning
        History -> Put
    forall t. Binary t => t -> Put
    put (History -> Put) -> History -> Put
    forall a b. (a -> b) -> a -> b
    $ History -> History
    archiveReport History
    shistory
          -- avoid displaying ending messages again at game start
        EnumMap (ContentId ModeKind) (Map Challenge Int) -> Put
    forall t. Binary t => t -> Put
    put EnumMap (ContentId ModeKind) (Map Challenge Int)
    svictories
        EnumSet (ContentId ModeKind) -> Put
    forall t. Binary t => t -> Put
    put EnumSet (ContentId ModeKind)
    scampings
        EnumSet (ContentId ModeKind) -> Put
    forall t. Binary t => t -> Put
    put EnumSet (ContentId ModeKind)
    srestarts
        Int -> Put
    forall t. Binary t => t -> Put
    put Int
    smarkVision
        Bool -> Put
    forall t. Binary t => t -> Put
    put Bool
    smarkSmell
        Int -> Put
    forall t. Binary t => t -> Put
    put Int
    snxtScenario
        Bool -> Put
    forall t. Binary t => t -> Put
    put Bool
    scurTutorial
        Bool -> Put
    forall t. Binary t => t -> Put
    put Bool
    snxtTutorial
        Maybe Bool -> Put
    forall t. Binary t => t -> Put
    put Maybe Bool
    soverrideTut
        Set Msg -> Put
    forall t. Binary t => t -> Put
    put Set Msg
    susedHints
        String -> Put
    forall t. Binary t => t -> Put
    put (SMGen -> String
    forall a. Show a => a -> String
    show SMGen
    srandomUI)
      get :: Get SessionUI
    get = do
        sxhair <- Get (Maybe Target)
    forall t. Binary t => Get t
    get
        sactorUI <- get
        sitemUI <- get
        sroles <- get
        sUIOptions <- get  -- is overwritten ASAP, but useful for, e.g., crash debug
        saimMode <- get
        sitemSel <- get
        sselected <- get
        srunning <- get
        shistory <- get
        svictories <- get
        scampings <- get
        srestarts <- get
        smarkVision <- get
        smarkSmell <- get
        snxtScenario <- get
        scurTutorial <- get
        snxtTutorial <- get
        soverrideTut <- get
        susedHints <- get
        g <- get
        let sreqPending = Maybe a
    forall a. Maybe a
    Nothing
            sreqDelay = ReqDelay
    ReqDelayNot
            sreqQueried = Bool
    False
            sregainControl = Bool
    False
            sxhairGoTo = Maybe a
    forall a. Maybe a
    Nothing
            slastItemMove = Maybe a
    forall a. Maybe a
    Nothing
            schanF = (forall a. FrontReq a -> IO a) -> ChanFrontend
    ChanFrontend ((forall a. FrontReq a -> IO a) -> ChanFrontend)
    -> (forall a. FrontReq a -> IO a) -> ChanFrontend
    forall a b. (a -> b) -> a -> b
    $ IO a -> FrontReq a -> IO a
    forall a b. a -> b -> a
    const (IO a -> FrontReq a -> IO a) -> IO a -> FrontReq a -> IO a
    forall a b. (a -> b) -> a -> b
    $
              String -> IO a
    forall a. HasCallStack => String -> a
    error (String -> IO a) -> String -> IO a
    forall a b. (a -> b) -> a -> b
    $ String
    "Binary: ChanFrontend" String -> () -> String
    forall v. Show v => String -> v -> String
    `showFailure` ()
            sccui = CCUI
    emptyCCUI
            sxhairMoused = Bool
    True
            spointer = Int -> Int -> PointUI
    PointUI Int
    0 Int
    0
            sautoYes = Bool
    False
            smacroFrame = KeyMacroFrame
    emptyMacroFrame
            smacroStack = []
            slastLost = EnumSet k
    forall k. EnumSet k
    ES.empty
            swaitTimes = Int
    0
            swasAutomated = Bool
    False
            smuteMessages = Bool
    False
            smenuIxMap = Map k a
    forall k a. Map k a
    M.empty
            schosenLore = ChosenLore
    ChosenNothing
            sdisplayNeeded = Bool
    False  -- displayed regardless
            sturnDisplayed = Bool
    False
            sreportNull = Bool
    True
            sstart = POSIXTime
    0
            sgstart = POSIXTime
    0
            sallTime = Time
    timeZero
            snframes = Int
    0
            sallNframes = Int
    0
            srandomUI = String -> SMGen
    forall a. Read a => String -> a
    read String
    g
        return $! SessionUI{..}

    instance Binary RunParams where
      put :: RunParams -> Put
    put RunParams{Bool
    Int
    [ActorId]
    Maybe Text
    ActorId
    runLeader :: RunParams -> ActorId
    runMembers :: RunParams -> [ActorId]
    runInitial :: RunParams -> Bool
    runStopMsg :: RunParams -> Maybe Text
    runWaiting :: RunParams -> Int
    runLeader :: ActorId
    runMembers :: [ActorId]
    runInitial :: Bool
    runStopMsg :: Maybe Text
    runWaiting :: Int
    ..} = do
        ActorId -> Put
    forall t. Binary t => t -> Put
    put ActorId
    runLeader
        [ActorId] -> Put
    forall t. Binary t => t -> Put
    put [ActorId]
    runMembers
        Bool -> Put
    forall t. Binary t => t -> Put
    put Bool
    runInitial
        Maybe Text -> Put
    forall t. Binary t => t -> Put
    put Maybe Text
    runStopMsg
        Int -> Put
    forall t. Binary t => t -> Put
    put Int
    runWaiting
      get :: Get RunParams
    get = do
        runLeader <- Get ActorId
    forall t. Binary t => Get t
    get
        runMembers <- get
        runInitial <- get
        runStopMsg <- get
        runWaiting <- get
        return $! RunParams{..}