{-# LANGUAGE OverloadedStrings #-}

-- |
-- SPDX-License-Identifier: BSD-3-Clause
--
-- The main TUI update logic that is called from other controller parts.
module Swarm.TUI.Controller.UpdateUI (
  updateUI,
  updateAndRedrawUI,
  updateRobotDetailsPane,
) where

-- See Note [liftA2 re-export from Prelude]

import Brick hiding (Direction, Location, on)
import Brick.Focus
import Brick.Widgets.List qualified as BL
import Control.Lens as Lens
import Control.Monad (forM_, unless, when)
import Control.Monad.IO.Class (liftIO)
import Data.Foldable (toList)
import Data.List.Extra (enumerate)
import Data.Map.Strict qualified as M
import Data.Maybe (fromMaybe, isNothing)
import Data.Set (Set)
import Data.Set qualified as S
import Data.String (fromString)
import Data.Text qualified as T
import Data.Vector qualified as V
import Swarm.Game.Entity hiding (empty)
import Swarm.Game.Popup (Popup (..), addPopup)
import Swarm.Game.Robot
import Swarm.Game.Robot.Activity
import Swarm.Game.Robot.Concrete
import Swarm.Game.State
import Swarm.Game.State.Landscape
import Swarm.Game.State.Substate
import Swarm.Language.Typed (Typed (..))
import Swarm.Language.Types
import Swarm.Language.Value (Value (VExc, VUnit), emptyEnv, envTydefs, prettyValue)
import Swarm.Pretty
import Swarm.TUI.Controller.SaveScenario (saveScenarioInfoOnFinishNocheat)
import Swarm.TUI.Controller.Util
import Swarm.TUI.Model
import Swarm.TUI.Model.DebugOption (DebugOption (..))
import Swarm.TUI.Model.Dialog.Goal
import Swarm.TUI.Model.Menu
import Swarm.TUI.Model.Name
import Swarm.TUI.Model.Repl
import Swarm.TUI.Model.UI
import Swarm.TUI.Model.UI.Gameplay
import Swarm.TUI.View.Objective qualified as GR
import Swarm.TUI.View.Robot
import Swarm.TUI.View.Robot.Type
import Witch (into)

-- | Update the UI and redraw if needed.
--
-- This function is used after running the game for some number of ticks.
updateAndRedrawUI :: Bool -> EventM Name AppState ()
updateAndRedrawUI :: Bool -> EventM Name AppState ()
updateAndRedrawUI Bool
forceRedraw = do
  Bool
redraw <- EventM Name AppState Bool
updateUI
  Bool -> EventM Name AppState () -> EventM Name AppState ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Bool
forceRedraw Bool -> Bool -> Bool
|| Bool
redraw) EventM Name AppState ()
forall n s. EventM n s ()
continueWithoutRedraw

checkInventoryUpdated :: Maybe Robot -> EventM Name ScenarioState Bool
checkInventoryUpdated :: Maybe Robot -> EventM Name ScenarioState Bool
checkInventoryUpdated Maybe Robot
fr = do
  -- The hash of the robot whose inventory is currently displayed (if any)
  Maybe Int
listRobotHash <- ((Int, List Name InventoryListEntry) -> Int)
-> Maybe (Int, List Name InventoryListEntry) -> Maybe Int
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int, List Name InventoryListEntry) -> Int
forall a b. (a, b) -> a
fst (Maybe (Int, List Name InventoryListEntry) -> Maybe Int)
-> EventM
     Name ScenarioState (Maybe (Int, List Name InventoryListEntry))
-> EventM Name ScenarioState (Maybe Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Getting
  (Maybe (Int, List Name InventoryListEntry))
  ScenarioState
  (Maybe (Int, List Name InventoryListEntry))
-> EventM
     Name ScenarioState (Maybe (Int, List Name InventoryListEntry))
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((UIGameplay
 -> Const (Maybe (Int, List Name InventoryListEntry)) UIGameplay)
-> ScenarioState
-> Const (Maybe (Int, List Name InventoryListEntry)) ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay
  -> Const (Maybe (Int, List Name InventoryListEntry)) UIGameplay)
 -> ScenarioState
 -> Const (Maybe (Int, List Name InventoryListEntry)) ScenarioState)
-> ((Maybe (Int, List Name InventoryListEntry)
     -> Const
          (Maybe (Int, List Name InventoryListEntry))
          (Maybe (Int, List Name InventoryListEntry)))
    -> UIGameplay
    -> Const (Maybe (Int, List Name InventoryListEntry)) UIGameplay)
-> Getting
     (Maybe (Int, List Name InventoryListEntry))
     ScenarioState
     (Maybe (Int, List Name InventoryListEntry))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIInventory
 -> Const (Maybe (Int, List Name InventoryListEntry)) UIInventory)
-> UIGameplay
-> Const (Maybe (Int, List Name InventoryListEntry)) UIGameplay
Lens' UIGameplay UIInventory
uiInventory ((UIInventory
  -> Const (Maybe (Int, List Name InventoryListEntry)) UIInventory)
 -> UIGameplay
 -> Const (Maybe (Int, List Name InventoryListEntry)) UIGameplay)
-> ((Maybe (Int, List Name InventoryListEntry)
     -> Const
          (Maybe (Int, List Name InventoryListEntry))
          (Maybe (Int, List Name InventoryListEntry)))
    -> UIInventory
    -> Const (Maybe (Int, List Name InventoryListEntry)) UIInventory)
-> (Maybe (Int, List Name InventoryListEntry)
    -> Const
         (Maybe (Int, List Name InventoryListEntry))
         (Maybe (Int, List Name InventoryListEntry)))
-> UIGameplay
-> Const (Maybe (Int, List Name InventoryListEntry)) UIGameplay
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe (Int, List Name InventoryListEntry)
 -> Const
      (Maybe (Int, List Name InventoryListEntry))
      (Maybe (Int, List Name InventoryListEntry)))
-> UIInventory
-> Const (Maybe (Int, List Name InventoryListEntry)) UIInventory
Lens' UIInventory (Maybe (Int, List Name InventoryListEntry))
uiInventoryList)

  -- The hash of the focused robot (if any)
  let focusedRobotHash :: Maybe Int
focusedRobotHash = Getting Int Robot Int -> Robot -> Int
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Int Robot Int
Getter Robot Int
inventoryHash (Robot -> Int) -> Maybe Robot -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Robot
fr

  -- Check if the inventory list needs to be updated.
  Bool
shouldUpdate <- Getting Bool ScenarioState Bool -> EventM Name ScenarioState Bool
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((UIGameplay -> Const Bool UIGameplay)
-> ScenarioState -> Const Bool ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Const Bool UIGameplay)
 -> ScenarioState -> Const Bool ScenarioState)
-> ((Bool -> Const Bool Bool)
    -> UIGameplay -> Const Bool UIGameplay)
-> Getting Bool ScenarioState Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIInventory -> Const Bool UIInventory)
-> UIGameplay -> Const Bool UIGameplay
Lens' UIGameplay UIInventory
uiInventory ((UIInventory -> Const Bool UIInventory)
 -> UIGameplay -> Const Bool UIGameplay)
-> ((Bool -> Const Bool Bool)
    -> UIInventory -> Const Bool UIInventory)
-> (Bool -> Const Bool Bool)
-> UIGameplay
-> Const Bool UIGameplay
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Const Bool Bool) -> UIInventory -> Const Bool UIInventory
Lens' UIInventory Bool
uiInventoryShouldUpdate)

  -- Whether the focused robot is too far away to sense, & whether
  -- that has recently changed
  Maybe RobotRange
dist <- Getting (Maybe RobotRange) ScenarioState (Maybe RobotRange)
-> EventM Name ScenarioState (Maybe RobotRange)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((GameState -> Const (Maybe RobotRange) GameState)
-> ScenarioState -> Const (Maybe RobotRange) ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const (Maybe RobotRange) GameState)
 -> ScenarioState -> Const (Maybe RobotRange) ScenarioState)
-> ((Maybe RobotRange
     -> Const (Maybe RobotRange) (Maybe RobotRange))
    -> GameState -> Const (Maybe RobotRange) GameState)
-> Getting (Maybe RobotRange) ScenarioState (Maybe RobotRange)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameState -> Maybe RobotRange)
-> (Maybe RobotRange
    -> Const (Maybe RobotRange) (Maybe RobotRange))
-> GameState
-> Const (Maybe RobotRange) GameState
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to GameState -> Maybe RobotRange
focusedRange)
  Bool
farOK <- (Bool -> Bool -> Bool)
-> EventM Name ScenarioState Bool
-> EventM Name ScenarioState Bool
-> EventM Name ScenarioState Bool
forall a b c.
(a -> b -> c)
-> EventM Name ScenarioState a
-> EventM Name ScenarioState b
-> EventM Name ScenarioState c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Bool -> Bool -> Bool
(||) (Getting Bool ScenarioState Bool -> EventM Name ScenarioState Bool
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((GameState -> Const Bool GameState)
-> ScenarioState -> Const Bool ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const Bool GameState)
 -> ScenarioState -> Const Bool ScenarioState)
-> ((Bool -> Const Bool Bool) -> GameState -> Const Bool GameState)
-> Getting Bool ScenarioState Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Const Bool Bool) -> GameState -> Const Bool GameState
Lens' GameState Bool
creativeMode)) (Getting Bool ScenarioState Bool -> EventM Name ScenarioState Bool
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((GameState -> Const Bool GameState)
-> ScenarioState -> Const Bool ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const Bool GameState)
 -> ScenarioState -> Const Bool ScenarioState)
-> ((Bool -> Const Bool Bool) -> GameState -> Const Bool GameState)
-> Getting Bool ScenarioState Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Landscape -> Const Bool Landscape)
-> GameState -> Const Bool GameState
Lens' GameState Landscape
landscape ((Landscape -> Const Bool Landscape)
 -> GameState -> Const Bool GameState)
-> ((Bool -> Const Bool Bool) -> Landscape -> Const Bool Landscape)
-> (Bool -> Const Bool Bool)
-> GameState
-> Const Bool GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Const Bool Bool) -> Landscape -> Const Bool Landscape
Lens' Landscape Bool
worldScrollable))
  let tooFar :: Bool
tooFar = Bool -> Bool
not Bool
farOK Bool -> Bool -> Bool
&& Maybe RobotRange
dist Maybe RobotRange -> Maybe RobotRange -> Bool
forall a. Eq a => a -> a -> Bool
== RobotRange -> Maybe RobotRange
forall a. a -> Maybe a
Just RobotRange
Far
      farChanged :: Bool
farChanged = Bool
tooFar Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Int -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Int
listRobotHash

  -- If the robot moved in or out of range, or hashes don't match
  -- (either because which robot (or whether any robot) is focused
  -- changed, or the focused robot's inventory changed), or the
  -- inventory was flagged to be updated, regenerate the inventory list.
  let shouldRegenerateInventory :: Bool
shouldRegenerateInventory = Bool
farChanged Bool -> Bool -> Bool
|| Maybe Int
listRobotHash Maybe Int -> Maybe Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Int
focusedRobotHash Bool -> Bool -> Bool
|| Bool
shouldUpdate
  Bool
-> EventM Name ScenarioState () -> EventM Name ScenarioState ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
shouldRegenerateInventory (EventM Name ScenarioState () -> EventM Name ScenarioState ())
-> EventM Name ScenarioState () -> EventM Name ScenarioState ()
forall a b. (a -> b) -> a -> b
$
    LensLike'
  (Zoomed (EventM Name UIInventory) ()) ScenarioState UIInventory
-> EventM Name UIInventory () -> EventM Name ScenarioState ()
forall c.
LensLike'
  (Zoomed (EventM Name UIInventory) c) ScenarioState UIInventory
-> EventM Name UIInventory c -> EventM Name ScenarioState c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom ((UIGameplay -> Zoomed (EventM Name UIInventory) () UIGameplay)
-> ScenarioState
-> Zoomed (EventM Name UIInventory) () ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Zoomed (EventM Name UIInventory) () UIGameplay)
 -> ScenarioState
 -> Zoomed (EventM Name UIInventory) () ScenarioState)
-> ((UIInventory
     -> Zoomed (EventM Name UIInventory) () UIInventory)
    -> UIGameplay -> Zoomed (EventM Name UIInventory) () UIGameplay)
-> LensLike'
     (Zoomed (EventM Name UIInventory) ()) ScenarioState UIInventory
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIInventory -> Zoomed (EventM Name UIInventory) () UIInventory)
-> UIGameplay -> Zoomed (EventM Name UIInventory) () UIGameplay
Lens' UIGameplay UIInventory
uiInventory) (EventM Name UIInventory () -> EventM Name ScenarioState ())
-> EventM Name UIInventory () -> EventM Name ScenarioState ()
forall a b. (a -> b) -> a -> b
$ do
      Maybe Robot -> EventM Name UIInventory ()
forall (m :: * -> *).
MonadState UIInventory m =>
Maybe Robot -> m ()
populateInventoryList (Maybe Robot -> EventM Name UIInventory ())
-> Maybe Robot -> EventM Name UIInventory ()
forall a b. (a -> b) -> a -> b
$ if Bool
tooFar then Maybe Robot
forall a. Maybe a
Nothing else Maybe Robot
fr
      (Bool -> Identity Bool) -> UIInventory -> Identity UIInventory
Lens' UIInventory Bool
uiInventoryShouldUpdate ((Bool -> Identity Bool) -> UIInventory -> Identity UIInventory)
-> Bool -> EventM Name UIInventory ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
False
  Bool -> EventM Name ScenarioState Bool
forall a. a -> EventM Name ScenarioState a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
shouldRegenerateInventory

checkReplUpdated :: GameState -> EventM Name ScenarioState Bool
checkReplUpdated :: GameState -> EventM Name ScenarioState Bool
checkReplUpdated GameState
g = case GameState
g GameState -> Getting REPLStatus GameState REPLStatus -> REPLStatus
forall s a. s -> Getting a s a -> a
^. (GameControls -> Const REPLStatus GameControls)
-> GameState -> Const REPLStatus GameState
Lens' GameState GameControls
gameControls ((GameControls -> Const REPLStatus GameControls)
 -> GameState -> Const REPLStatus GameState)
-> ((REPLStatus -> Const REPLStatus REPLStatus)
    -> GameControls -> Const REPLStatus GameControls)
-> Getting REPLStatus GameState REPLStatus
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (REPLStatus -> Const REPLStatus REPLStatus)
-> GameControls -> Const REPLStatus GameControls
Lens' GameControls REPLStatus
replStatus of
  -- Now check if the base finished running a program entered at the REPL.
  REPLWorking Polytype
pty (Just Value
v)
    -- It did, and the result was the unit value or an exception.  Just reset replStatus.
    | Value
v Value -> [Value] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Value
VUnit, Value
VExc] -> do
        Text -> IO ()
listener <- Getting (Text -> IO ()) ScenarioState (Text -> IO ())
-> EventM Name ScenarioState (Text -> IO ())
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting (Text -> IO ()) ScenarioState (Text -> IO ())
 -> EventM Name ScenarioState (Text -> IO ()))
-> Getting (Text -> IO ()) ScenarioState (Text -> IO ())
-> EventM Name ScenarioState (Text -> IO ())
forall a b. (a -> b) -> a -> b
$ (GameState -> Const (Text -> IO ()) GameState)
-> ScenarioState -> Const (Text -> IO ()) ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const (Text -> IO ()) GameState)
 -> ScenarioState -> Const (Text -> IO ()) ScenarioState)
-> (((Text -> IO ()) -> Const (Text -> IO ()) (Text -> IO ()))
    -> GameState -> Const (Text -> IO ()) GameState)
-> Getting (Text -> IO ()) ScenarioState (Text -> IO ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameControls -> Const (Text -> IO ()) GameControls)
-> GameState -> Const (Text -> IO ()) GameState
Lens' GameState GameControls
gameControls ((GameControls -> Const (Text -> IO ()) GameControls)
 -> GameState -> Const (Text -> IO ()) GameState)
-> (((Text -> IO ()) -> Const (Text -> IO ()) (Text -> IO ()))
    -> GameControls -> Const (Text -> IO ()) GameControls)
-> ((Text -> IO ()) -> Const (Text -> IO ()) (Text -> IO ()))
-> GameState
-> Const (Text -> IO ()) GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Text -> IO ()) -> Const (Text -> IO ()) (Text -> IO ()))
-> GameControls -> Const (Text -> IO ()) GameControls
Lens' GameControls (Text -> IO ())
replListener
        IO () -> EventM Name ScenarioState ()
forall a. IO a -> EventM Name ScenarioState a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> EventM Name ScenarioState ())
-> IO () -> EventM Name ScenarioState ()
forall a b. (a -> b) -> a -> b
$ Text -> IO ()
listener Text
""
        (GameState -> Identity GameState)
-> ScenarioState -> Identity ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Identity GameState)
 -> ScenarioState -> Identity ScenarioState)
-> ((REPLStatus -> Identity REPLStatus)
    -> GameState -> Identity GameState)
-> (REPLStatus -> Identity REPLStatus)
-> ScenarioState
-> Identity ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameControls -> Identity GameControls)
-> GameState -> Identity GameState
Lens' GameState GameControls
gameControls ((GameControls -> Identity GameControls)
 -> GameState -> Identity GameState)
-> ((REPLStatus -> Identity REPLStatus)
    -> GameControls -> Identity GameControls)
-> (REPLStatus -> Identity REPLStatus)
-> GameState
-> Identity GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (REPLStatus -> Identity REPLStatus)
-> GameControls -> Identity GameControls
Lens' GameControls REPLStatus
replStatus ((REPLStatus -> Identity REPLStatus)
 -> ScenarioState -> Identity ScenarioState)
-> REPLStatus -> EventM Name ScenarioState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Maybe (Polytype, Value) -> REPLStatus
REPLDone ((Polytype, Value) -> Maybe (Polytype, Value)
forall a. a -> Maybe a
Just (Polytype
pty, Value
v))
        Bool -> EventM Name ScenarioState Bool
forall a. a -> EventM Name ScenarioState a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True

    -- It did, and returned some other value.  Create new 'it'
    -- variables, pretty-print the result as a REPL output, with its
    -- type, and reset the replStatus.
    | Bool
otherwise -> do
        Integer
itIx <- Getting Integer ScenarioState Integer
-> EventM Name ScenarioState Integer
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((GameState -> Const Integer GameState)
-> ScenarioState -> Const Integer ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const Integer GameState)
 -> ScenarioState -> Const Integer ScenarioState)
-> ((Integer -> Const Integer Integer)
    -> GameState -> Const Integer GameState)
-> Getting Integer ScenarioState Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameControls -> Const Integer GameControls)
-> GameState -> Const Integer GameState
Lens' GameState GameControls
gameControls ((GameControls -> Const Integer GameControls)
 -> GameState -> Const Integer GameState)
-> ((Integer -> Const Integer Integer)
    -> GameControls -> Const Integer GameControls)
-> (Integer -> Const Integer Integer)
-> GameState
-> Const Integer GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Const Integer Integer)
-> GameControls -> Const Integer GameControls
Lens' GameControls Integer
replNextValueIndex)
        Env
env <- Env -> Maybe Env -> Env
forall a. a -> Maybe a -> a
fromMaybe Env
emptyEnv (Maybe Env -> Env)
-> EventM Name ScenarioState (Maybe Env)
-> EventM Name ScenarioState Env
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Getting (First Env) ScenarioState Env
-> EventM Name ScenarioState (Maybe Env)
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse ((GameState -> Const (First Env) GameState)
-> ScenarioState -> Const (First Env) ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const (First Env) GameState)
 -> ScenarioState -> Const (First Env) ScenarioState)
-> ((Env -> Const (First Env) Env)
    -> GameState -> Const (First Env) GameState)
-> Getting (First Env) ScenarioState Env
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Env -> Const (First Env) Env)
-> GameState -> Const (First Env) GameState
Traversal' GameState Env
baseEnv)
        let finalType :: Polytype
finalType = TDCtx -> Polytype -> Polytype
stripCmd (Env
env Env -> Getting TDCtx Env TDCtx -> TDCtx
forall s a. s -> Getting a s a -> a
^. Getting TDCtx Env TDCtx
Lens' Env TDCtx
envTydefs) Polytype
pty
            itName :: Text
itName = [Char] -> Text
forall a. IsString a => [Char] -> a
fromString ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ [Char]
"it" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Integer -> [Char]
forall a. Show a => a -> [Char]
show Integer
itIx
            out :: Text
out = Text -> [Text] -> Text
T.intercalate Text
" " [Text
itName, Text
":", Polytype -> Text
forall a. PrettyPrec a => a -> Text
prettyText Polytype
finalType, Text
"=", Text -> Text
forall target source. From source target => source -> target
into (Value -> Text
prettyValue Value
v)]
        REPLHistItemType -> Text -> EventM Name ScenarioState ()
forall (m :: * -> *).
MonadState ScenarioState m =>
REPLHistItemType -> Text -> m ()
addREPLHistItem REPLHistItemType
REPLOutput Text
out
        Text -> IO ()
listener <- Getting (Text -> IO ()) ScenarioState (Text -> IO ())
-> EventM Name ScenarioState (Text -> IO ())
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting (Text -> IO ()) ScenarioState (Text -> IO ())
 -> EventM Name ScenarioState (Text -> IO ()))
-> Getting (Text -> IO ()) ScenarioState (Text -> IO ())
-> EventM Name ScenarioState (Text -> IO ())
forall a b. (a -> b) -> a -> b
$ (GameState -> Const (Text -> IO ()) GameState)
-> ScenarioState -> Const (Text -> IO ()) ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const (Text -> IO ()) GameState)
 -> ScenarioState -> Const (Text -> IO ()) ScenarioState)
-> (((Text -> IO ()) -> Const (Text -> IO ()) (Text -> IO ()))
    -> GameState -> Const (Text -> IO ()) GameState)
-> Getting (Text -> IO ()) ScenarioState (Text -> IO ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameControls -> Const (Text -> IO ()) GameControls)
-> GameState -> Const (Text -> IO ()) GameState
Lens' GameState GameControls
gameControls ((GameControls -> Const (Text -> IO ()) GameControls)
 -> GameState -> Const (Text -> IO ()) GameState)
-> (((Text -> IO ()) -> Const (Text -> IO ()) (Text -> IO ()))
    -> GameControls -> Const (Text -> IO ()) GameControls)
-> ((Text -> IO ()) -> Const (Text -> IO ()) (Text -> IO ()))
-> GameState
-> Const (Text -> IO ()) GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Text -> IO ()) -> Const (Text -> IO ()) (Text -> IO ()))
-> GameControls -> Const (Text -> IO ()) GameControls
Lens' GameControls (Text -> IO ())
replListener
        IO () -> EventM Name ScenarioState ()
forall a. IO a -> EventM Name ScenarioState a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> EventM Name ScenarioState ())
-> IO () -> EventM Name ScenarioState ()
forall a b. (a -> b) -> a -> b
$ Text -> IO ()
listener Text
out
        Name -> EventM Name ScenarioState ()
forall n s. Ord n => n -> EventM n s ()
invalidateCacheEntry Name
REPLHistoryCache
        ViewportScroll Name -> forall s. EventM Name s ()
forall n. ViewportScroll n -> forall s. EventM n s ()
vScrollToEnd ViewportScroll Name
replScroll

        LensLike'
  (Zoomed (EventM Name GameState) ()) ScenarioState GameState
-> EventM Name GameState () -> EventM Name ScenarioState ()
forall c.
LensLike'
  (Zoomed (EventM Name GameState) c) ScenarioState GameState
-> EventM Name GameState c -> EventM Name ScenarioState c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom LensLike'
  (Zoomed (EventM Name GameState) ()) ScenarioState GameState
Lens' ScenarioState GameState
gameState (EventM Name GameState () -> EventM Name ScenarioState ())
-> EventM Name GameState () -> EventM Name ScenarioState ()
forall a b. (a -> b) -> a -> b
$ do
          (GameControls -> Identity GameControls)
-> GameState -> Identity GameState
Lens' GameState GameControls
gameControls ((GameControls -> Identity GameControls)
 -> GameState -> Identity GameState)
-> ((REPLStatus -> Identity REPLStatus)
    -> GameControls -> Identity GameControls)
-> (REPLStatus -> Identity REPLStatus)
-> GameState
-> Identity GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (REPLStatus -> Identity REPLStatus)
-> GameControls -> Identity GameControls
Lens' GameControls REPLStatus
replStatus ((REPLStatus -> Identity REPLStatus)
 -> GameState -> Identity GameState)
-> REPLStatus -> EventM Name GameState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Maybe (Polytype, Value) -> REPLStatus
REPLDone ((Polytype, Value) -> Maybe (Polytype, Value)
forall a. a -> Maybe a
Just (Polytype
finalType, Value
v))
          (Env -> Identity Env) -> GameState -> Identity GameState
Traversal' GameState Env
baseEnv ((Env -> Identity Env) -> GameState -> Identity GameState)
-> ((Maybe (Typed Value) -> Identity (Maybe (Typed Value)))
    -> Env -> Identity Env)
-> (Maybe (Typed Value) -> Identity (Maybe (Typed Value)))
-> GameState
-> Identity GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index Env -> Lens' Env (Maybe (IxValue Env))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at Text
Index Env
itName ((Maybe (Typed Value) -> Identity (Maybe (Typed Value)))
 -> GameState -> Identity GameState)
-> Maybe (Typed Value) -> EventM Name GameState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Typed Value -> Maybe (Typed Value)
forall a. a -> Maybe a
Just (Value -> Polytype -> Requirements -> Typed Value
forall v. v -> Polytype -> Requirements -> Typed v
Typed Value
v Polytype
finalType Requirements
forall a. Monoid a => a
mempty)
          (Env -> Identity Env) -> GameState -> Identity GameState
Traversal' GameState Env
baseEnv ((Env -> Identity Env) -> GameState -> Identity GameState)
-> ((Maybe (Typed Value) -> Identity (Maybe (Typed Value)))
    -> Env -> Identity Env)
-> (Maybe (Typed Value) -> Identity (Maybe (Typed Value)))
-> GameState
-> Identity GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index Env -> Lens' Env (Maybe (IxValue Env))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at Text
Index Env
"it" ((Maybe (Typed Value) -> Identity (Maybe (Typed Value)))
 -> GameState -> Identity GameState)
-> Maybe (Typed Value) -> EventM Name GameState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Typed Value -> Maybe (Typed Value)
forall a. a -> Maybe a
Just (Value -> Polytype -> Requirements -> Typed Value
forall v. v -> Polytype -> Requirements -> Typed v
Typed Value
v Polytype
finalType Requirements
forall a. Monoid a => a
mempty)
          (GameControls -> Identity GameControls)
-> GameState -> Identity GameState
Lens' GameState GameControls
gameControls ((GameControls -> Identity GameControls)
 -> GameState -> Identity GameState)
-> ((Integer -> Identity Integer)
    -> GameControls -> Identity GameControls)
-> (Integer -> Identity Integer)
-> GameState
-> Identity GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Identity Integer)
-> GameControls -> Identity GameControls
Lens' GameControls Integer
replNextValueIndex ((Integer -> Identity Integer) -> GameState -> Identity GameState)
-> (Integer -> Integer) -> EventM Name GameState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1)
        Bool -> EventM Name ScenarioState Bool
forall a. a -> EventM Name ScenarioState a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True

  -- Otherwise, do nothing.
  REPLStatus
_ -> Bool -> EventM Name ScenarioState Bool
forall a. a -> EventM Name ScenarioState a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False

checkLogUpdated :: Maybe Robot -> EventM Name ScenarioState Bool
checkLogUpdated :: Maybe Robot -> EventM Name ScenarioState Bool
checkLogUpdated Maybe Robot
fr = do
  -- If the inventory or info panels are currently focused, it would
  -- be rude to update them right under the user's nose, so consider
  -- them "sticky".  They will be updated as soon as the player moves
  -- the focus away.
  FocusRing Name
fring <- Getting (FocusRing Name) ScenarioState (FocusRing Name)
-> EventM Name ScenarioState (FocusRing Name)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting (FocusRing Name) ScenarioState (FocusRing Name)
 -> EventM Name ScenarioState (FocusRing Name))
-> Getting (FocusRing Name) ScenarioState (FocusRing Name)
-> EventM Name ScenarioState (FocusRing Name)
forall a b. (a -> b) -> a -> b
$ (UIGameplay -> Const (FocusRing Name) UIGameplay)
-> ScenarioState -> Const (FocusRing Name) ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Const (FocusRing Name) UIGameplay)
 -> ScenarioState -> Const (FocusRing Name) ScenarioState)
-> ((FocusRing Name -> Const (FocusRing Name) (FocusRing Name))
    -> UIGameplay -> Const (FocusRing Name) UIGameplay)
-> Getting (FocusRing Name) ScenarioState (FocusRing Name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FocusRing Name -> Const (FocusRing Name) (FocusRing Name))
-> UIGameplay -> Const (FocusRing Name) UIGameplay
Lens' UIGameplay (FocusRing Name)
uiFocusRing
  let sticky :: Bool
sticky = FocusRing Name -> Maybe Name
forall n. FocusRing n -> Maybe n
focusGetCurrent FocusRing Name
fring Maybe Name -> [Maybe Name] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (FocusablePanel -> Maybe Name) -> [FocusablePanel] -> [Maybe Name]
forall a b. (a -> b) -> [a] -> [b]
map (Name -> Maybe Name
forall a. a -> Maybe a
Just (Name -> Maybe Name)
-> (FocusablePanel -> Name) -> FocusablePanel -> Maybe Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FocusablePanel -> Name
FocusablePanel) [FocusablePanel
RobotPanel, FocusablePanel
InfoPanel]

  -- Check if the robot log was updated and we are allowed to change
  -- the inventory+info panels.
  case Bool -> (Robot -> Bool) -> Maybe Robot -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Getting Bool Robot Bool -> Robot -> Bool
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Bool Robot Bool
Lens' Robot Bool
robotLogUpdated) Maybe Robot
fr Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
sticky of
    Bool
False -> Bool -> EventM Name ScenarioState Bool
forall a. a -> EventM Name ScenarioState a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
    Bool
True -> do
      -- Reset the log updated flag
      StateC GameState (TimeIOC (LiftC IO)) ()
-> EventM Name ScenarioState ()
forall (m :: * -> *) a.
(MonadState ScenarioState m, MonadIO m) =>
StateC GameState (TimeIOC (LiftC IO)) a -> m a
zoomGameStateFromScenarioState (StateC GameState (TimeIOC (LiftC IO)) ()
 -> EventM Name ScenarioState ())
-> StateC GameState (TimeIOC (LiftC IO)) ()
-> EventM Name ScenarioState ()
forall a b. (a -> b) -> a -> b
$ StateC Robots Identity ()
-> StateC GameState (TimeIOC (LiftC IO)) ()
forall (sig :: (* -> *) -> * -> *) (m :: * -> *) b.
Has (State GameState) sig m =>
StateC Robots Identity b -> m b
zoomRobots StateC Robots Identity ()
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (State Robots) sig m =>
m ()
clearFocusedRobotLogUpdated

      -- Find and focus an equipped "logger" device in the inventory list.
      let isLogger :: InventoryListEntry -> Bool
isLogger (EquippedEntry Entity
e) = Entity
e Entity -> Getting Text Entity Text -> Text
forall s a. s -> Getting a s a -> a
^. Getting Text Entity Text
Lens' Entity Text
entityName Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"logger"
          isLogger InventoryListEntry
_ = Bool
False
          focusLogger :: GenericList n Vector InventoryListEntry
-> GenericList n Vector InventoryListEntry
focusLogger = (InventoryListEntry -> Bool)
-> GenericList n Vector InventoryListEntry
-> GenericList n Vector InventoryListEntry
forall (t :: * -> *) e n.
(Foldable t, Splittable t) =>
(e -> Bool) -> GenericList n t e -> GenericList n t e
BL.listFindBy InventoryListEntry -> Bool
isLogger

      (UIGameplay -> Identity UIGameplay)
-> ScenarioState -> Identity ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Identity UIGameplay)
 -> ScenarioState -> Identity ScenarioState)
-> ((List Name InventoryListEntry
     -> Identity (List Name InventoryListEntry))
    -> UIGameplay -> Identity UIGameplay)
-> (List Name InventoryListEntry
    -> Identity (List Name InventoryListEntry))
-> ScenarioState
-> Identity ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIInventory -> Identity UIInventory)
-> UIGameplay -> Identity UIGameplay
Lens' UIGameplay UIInventory
uiInventory ((UIInventory -> Identity UIInventory)
 -> UIGameplay -> Identity UIGameplay)
-> ((List Name InventoryListEntry
     -> Identity (List Name InventoryListEntry))
    -> UIInventory -> Identity UIInventory)
-> (List Name InventoryListEntry
    -> Identity (List Name InventoryListEntry))
-> UIGameplay
-> Identity UIGameplay
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe (Int, List Name InventoryListEntry)
 -> Identity (Maybe (Int, List Name InventoryListEntry)))
-> UIInventory -> Identity UIInventory
Lens' UIInventory (Maybe (Int, List Name InventoryListEntry))
uiInventoryList ((Maybe (Int, List Name InventoryListEntry)
  -> Identity (Maybe (Int, List Name InventoryListEntry)))
 -> UIInventory -> Identity UIInventory)
-> ((List Name InventoryListEntry
     -> Identity (List Name InventoryListEntry))
    -> Maybe (Int, List Name InventoryListEntry)
    -> Identity (Maybe (Int, List Name InventoryListEntry)))
-> (List Name InventoryListEntry
    -> Identity (List Name InventoryListEntry))
-> UIInventory
-> Identity UIInventory
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, List Name InventoryListEntry)
 -> Identity (Int, List Name InventoryListEntry))
-> Maybe (Int, List Name InventoryListEntry)
-> Identity (Maybe (Int, List Name InventoryListEntry))
forall a b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Maybe a) (f (Maybe b))
_Just (((Int, List Name InventoryListEntry)
  -> Identity (Int, List Name InventoryListEntry))
 -> Maybe (Int, List Name InventoryListEntry)
 -> Identity (Maybe (Int, List Name InventoryListEntry)))
-> ((List Name InventoryListEntry
     -> Identity (List Name InventoryListEntry))
    -> (Int, List Name InventoryListEntry)
    -> Identity (Int, List Name InventoryListEntry))
-> (List Name InventoryListEntry
    -> Identity (List Name InventoryListEntry))
-> Maybe (Int, List Name InventoryListEntry)
-> Identity (Maybe (Int, List Name InventoryListEntry))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (List Name InventoryListEntry
 -> Identity (List Name InventoryListEntry))
-> (Int, List Name InventoryListEntry)
-> Identity (Int, List Name InventoryListEntry)
forall s t a b. Field2 s t a b => Lens s t a b
Lens
  (Int, List Name InventoryListEntry)
  (Int, List Name InventoryListEntry)
  (List Name InventoryListEntry)
  (List Name InventoryListEntry)
_2 ((List Name InventoryListEntry
  -> Identity (List Name InventoryListEntry))
 -> ScenarioState -> Identity ScenarioState)
-> (List Name InventoryListEntry -> List Name InventoryListEntry)
-> EventM Name ScenarioState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= List Name InventoryListEntry -> List Name InventoryListEntry
forall {n}.
GenericList n Vector InventoryListEntry
-> GenericList n Vector InventoryListEntry
focusLogger

      -- Now inform the UI that it should scroll the info panel to
      -- the very end.
      (UIGameplay -> Identity UIGameplay)
-> ScenarioState -> Identity ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Identity UIGameplay)
 -> ScenarioState -> Identity ScenarioState)
-> ((Bool -> Identity Bool) -> UIGameplay -> Identity UIGameplay)
-> (Bool -> Identity Bool)
-> ScenarioState
-> Identity ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Identity Bool) -> UIGameplay -> Identity UIGameplay
Lens' UIGameplay Bool
uiScrollToEnd ((Bool -> Identity Bool)
 -> ScenarioState -> Identity ScenarioState)
-> Bool -> EventM Name ScenarioState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
True
      Bool -> EventM Name ScenarioState Bool
forall a. a -> EventM Name ScenarioState a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True

-- | Update the UI.  This function is used after running the
--   game for some number of ticks.
updateUI :: EventM Name AppState Bool
updateUI :: EventM Name AppState Bool
updateUI = do
  GameState
g <- Getting GameState AppState GameState
-> EventM Name AppState GameState
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting GameState AppState GameState
 -> EventM Name AppState GameState)
-> Getting GameState AppState GameState
-> EventM Name AppState GameState
forall a b. (a -> b) -> a -> b
$ (PlayState -> Const GameState PlayState)
-> AppState -> Const GameState AppState
Lens' AppState PlayState
playState ((PlayState -> Const GameState PlayState)
 -> AppState -> Const GameState AppState)
-> ((GameState -> Const GameState GameState)
    -> PlayState -> Const GameState PlayState)
-> Getting GameState AppState GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ScenarioState -> Const GameState ScenarioState)
-> PlayState -> Const GameState PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState -> Const GameState ScenarioState)
 -> PlayState -> Const GameState PlayState)
-> ((GameState -> Const GameState GameState)
    -> ScenarioState -> Const GameState ScenarioState)
-> (GameState -> Const GameState GameState)
-> PlayState
-> Const GameState PlayState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameState -> Const GameState GameState)
-> ScenarioState -> Const GameState ScenarioState
Lens' ScenarioState GameState
gameState

  LensLike' (Zoomed (EventM Name GameState) ()) AppState GameState
-> EventM Name GameState () -> EventM Name AppState ()
forall c.
LensLike' (Zoomed (EventM Name GameState) c) AppState GameState
-> EventM Name GameState c -> EventM Name AppState c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom ((PlayState -> Focusing (StateT (EventState Name) IO) () PlayState)
-> AppState -> Focusing (StateT (EventState Name) IO) () AppState
Lens' AppState PlayState
playState ((PlayState -> Focusing (StateT (EventState Name) IO) () PlayState)
 -> AppState -> Focusing (StateT (EventState Name) IO) () AppState)
-> ((GameState
     -> Focusing (StateT (EventState Name) IO) () GameState)
    -> PlayState
    -> Focusing (StateT (EventState Name) IO) () PlayState)
-> (GameState
    -> Focusing (StateT (EventState Name) IO) () GameState)
-> AppState
-> Focusing (StateT (EventState Name) IO) () AppState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ScenarioState
 -> Focusing (StateT (EventState Name) IO) () ScenarioState)
-> PlayState -> Focusing (StateT (EventState Name) IO) () PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState
  -> Focusing (StateT (EventState Name) IO) () ScenarioState)
 -> PlayState
 -> Focusing (StateT (EventState Name) IO) () PlayState)
-> ((GameState
     -> Focusing (StateT (EventState Name) IO) () GameState)
    -> ScenarioState
    -> Focusing (StateT (EventState Name) IO) () ScenarioState)
-> (GameState
    -> Focusing (StateT (EventState Name) IO) () GameState)
-> PlayState
-> Focusing (StateT (EventState Name) IO) () PlayState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameState -> Focusing (StateT (EventState Name) IO) () GameState)
-> ScenarioState
-> Focusing (StateT (EventState Name) IO) () ScenarioState
Lens' ScenarioState GameState
gameState) EventM Name GameState ()
loadVisibleRegion

  -- If the game state indicates a redraw is needed, invalidate the
  -- world cache so it will be redrawn.
  Bool -> EventM Name AppState () -> EventM Name AppState ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (GameState
g GameState
-> ((Bool -> Const Bool Bool) -> GameState -> Const Bool GameState)
-> Bool
forall s a. s -> Getting a s a -> a
^. (Bool -> Const Bool Bool) -> GameState -> Const Bool GameState
Lens' GameState Bool
needsRedraw) (EventM Name AppState () -> EventM Name AppState ())
-> EventM Name AppState () -> EventM Name AppState ()
forall a b. (a -> b) -> a -> b
$ Name -> EventM Name AppState ()
forall n s. Ord n => n -> EventM n s ()
invalidateCacheEntry Name
WorldCache

  let fr :: Maybe Robot
fr = GameState
g GameState
-> Getting (Maybe Robot) GameState (Maybe Robot) -> Maybe Robot
forall s a. s -> Getting a s a -> a
^. (GameState -> Maybe Robot)
-> Getting (Maybe Robot) GameState (Maybe Robot)
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to GameState -> Maybe Robot
focusedRobot
  Bool
inventoryUpdated <- LensLike'
  (Zoomed (EventM Name ScenarioState) Bool) AppState ScenarioState
-> EventM Name ScenarioState Bool -> EventM Name AppState Bool
forall c.
LensLike'
  (Zoomed (EventM Name ScenarioState) c) AppState ScenarioState
-> EventM Name ScenarioState c -> EventM Name AppState c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom ((PlayState
 -> Focusing (StateT (EventState Name) IO) Bool PlayState)
-> AppState -> Focusing (StateT (EventState Name) IO) Bool AppState
Lens' AppState PlayState
playState ((PlayState
  -> Focusing (StateT (EventState Name) IO) Bool PlayState)
 -> AppState
 -> Focusing (StateT (EventState Name) IO) Bool AppState)
-> ((ScenarioState
     -> Focusing (StateT (EventState Name) IO) Bool ScenarioState)
    -> PlayState
    -> Focusing (StateT (EventState Name) IO) Bool PlayState)
-> (ScenarioState
    -> Focusing (StateT (EventState Name) IO) Bool ScenarioState)
-> AppState
-> Focusing (StateT (EventState Name) IO) Bool AppState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ScenarioState
 -> Focusing (StateT (EventState Name) IO) Bool ScenarioState)
-> PlayState
-> Focusing (StateT (EventState Name) IO) Bool PlayState
Lens' PlayState ScenarioState
scenarioState) (EventM Name ScenarioState Bool -> EventM Name AppState Bool)
-> EventM Name ScenarioState Bool -> EventM Name AppState Bool
forall a b. (a -> b) -> a -> b
$ Maybe Robot -> EventM Name ScenarioState Bool
checkInventoryUpdated Maybe Robot
fr

  -- Now check if the base finished running a program entered at the REPL.
  Bool
replUpdated <- LensLike'
  (Zoomed (EventM Name ScenarioState) Bool) AppState ScenarioState
-> EventM Name ScenarioState Bool -> EventM Name AppState Bool
forall c.
LensLike'
  (Zoomed (EventM Name ScenarioState) c) AppState ScenarioState
-> EventM Name ScenarioState c -> EventM Name AppState c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom ((PlayState
 -> Focusing (StateT (EventState Name) IO) Bool PlayState)
-> AppState -> Focusing (StateT (EventState Name) IO) Bool AppState
Lens' AppState PlayState
playState ((PlayState
  -> Focusing (StateT (EventState Name) IO) Bool PlayState)
 -> AppState
 -> Focusing (StateT (EventState Name) IO) Bool AppState)
-> ((ScenarioState
     -> Focusing (StateT (EventState Name) IO) Bool ScenarioState)
    -> PlayState
    -> Focusing (StateT (EventState Name) IO) Bool PlayState)
-> (ScenarioState
    -> Focusing (StateT (EventState Name) IO) Bool ScenarioState)
-> AppState
-> Focusing (StateT (EventState Name) IO) Bool AppState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ScenarioState
 -> Focusing (StateT (EventState Name) IO) Bool ScenarioState)
-> PlayState
-> Focusing (StateT (EventState Name) IO) Bool PlayState
Lens' PlayState ScenarioState
scenarioState) (EventM Name ScenarioState Bool -> EventM Name AppState Bool)
-> EventM Name ScenarioState Bool -> EventM Name AppState Bool
forall a b. (a -> b) -> a -> b
$ GameState -> EventM Name ScenarioState Bool
checkReplUpdated GameState
g

  -- If the focused robot's log has been updated and the UI focus
  -- isn't currently on the inventory or info panels, attempt to
  -- automatically switch to the logger and scroll all the way down so
  -- the new message can be seen.
  (PlayState -> Identity PlayState) -> AppState -> Identity AppState
Lens' AppState PlayState
playState ((PlayState -> Identity PlayState)
 -> AppState -> Identity AppState)
-> ((Bool -> Identity Bool) -> PlayState -> Identity PlayState)
-> (Bool -> Identity Bool)
-> AppState
-> Identity AppState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ScenarioState -> Identity ScenarioState)
-> PlayState -> Identity PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState -> Identity ScenarioState)
 -> PlayState -> Identity PlayState)
-> ((Bool -> Identity Bool)
    -> ScenarioState -> Identity ScenarioState)
-> (Bool -> Identity Bool)
-> PlayState
-> Identity PlayState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIGameplay -> Identity UIGameplay)
-> ScenarioState -> Identity ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Identity UIGameplay)
 -> ScenarioState -> Identity ScenarioState)
-> ((Bool -> Identity Bool) -> UIGameplay -> Identity UIGameplay)
-> (Bool -> Identity Bool)
-> ScenarioState
-> Identity ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Identity Bool) -> UIGameplay -> Identity UIGameplay
Lens' UIGameplay Bool
uiScrollToEnd ((Bool -> Identity Bool) -> AppState -> Identity AppState)
-> Bool -> EventM Name AppState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
False
  Bool
logUpdated <- LensLike'
  (Zoomed (EventM Name ScenarioState) Bool) AppState ScenarioState
-> EventM Name ScenarioState Bool -> EventM Name AppState Bool
forall c.
LensLike'
  (Zoomed (EventM Name ScenarioState) c) AppState ScenarioState
-> EventM Name ScenarioState c -> EventM Name AppState c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom ((PlayState
 -> Focusing (StateT (EventState Name) IO) Bool PlayState)
-> AppState -> Focusing (StateT (EventState Name) IO) Bool AppState
Lens' AppState PlayState
playState ((PlayState
  -> Focusing (StateT (EventState Name) IO) Bool PlayState)
 -> AppState
 -> Focusing (StateT (EventState Name) IO) Bool AppState)
-> ((ScenarioState
     -> Focusing (StateT (EventState Name) IO) Bool ScenarioState)
    -> PlayState
    -> Focusing (StateT (EventState Name) IO) Bool PlayState)
-> (ScenarioState
    -> Focusing (StateT (EventState Name) IO) Bool ScenarioState)
-> AppState
-> Focusing (StateT (EventState Name) IO) Bool AppState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ScenarioState
 -> Focusing (StateT (EventState Name) IO) Bool ScenarioState)
-> PlayState
-> Focusing (StateT (EventState Name) IO) Bool PlayState
Lens' PlayState ScenarioState
scenarioState) (EventM Name ScenarioState Bool -> EventM Name AppState Bool)
-> EventM Name ScenarioState Bool -> EventM Name AppState Bool
forall a b. (a -> b) -> a -> b
$ Maybe Robot -> EventM Name ScenarioState Bool
checkLogUpdated Maybe Robot
fr

  Menu
menu <- Getting Menu AppState Menu -> EventM Name AppState Menu
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting Menu AppState Menu -> EventM Name AppState Menu)
-> Getting Menu AppState Menu -> EventM Name AppState Menu
forall a b. (a -> b) -> a -> b
$ (UIState -> Const Menu UIState) -> AppState -> Const Menu AppState
Lens' AppState UIState
uiState ((UIState -> Const Menu UIState)
 -> AppState -> Const Menu AppState)
-> ((Menu -> Const Menu Menu) -> UIState -> Const Menu UIState)
-> Getting Menu AppState Menu
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Menu -> Const Menu Menu) -> UIState -> Const Menu UIState
Lens' UIState Menu
uiMenu
  Set DebugOption
dOps <- Getting (Set DebugOption) AppState (Set DebugOption)
-> EventM Name AppState (Set DebugOption)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting (Set DebugOption) AppState (Set DebugOption)
 -> EventM Name AppState (Set DebugOption))
-> Getting (Set DebugOption) AppState (Set DebugOption)
-> EventM Name AppState (Set DebugOption)
forall a b. (a -> b) -> a -> b
$ (UIState -> Const (Set DebugOption) UIState)
-> AppState -> Const (Set DebugOption) AppState
Lens' AppState UIState
uiState ((UIState -> Const (Set DebugOption) UIState)
 -> AppState -> Const (Set DebugOption) AppState)
-> ((Set DebugOption -> Const (Set DebugOption) (Set DebugOption))
    -> UIState -> Const (Set DebugOption) UIState)
-> Getting (Set DebugOption) AppState (Set DebugOption)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Set DebugOption -> Const (Set DebugOption) (Set DebugOption))
-> UIState -> Const (Set DebugOption) UIState
Lens' UIState (Set DebugOption)
uiDebugOptions
  Bool
goalOrWinUpdated <- LensLike' (Zoomed (EventM Name PlayState) Bool) AppState PlayState
-> EventM Name PlayState Bool -> EventM Name AppState Bool
forall c.
LensLike' (Zoomed (EventM Name PlayState) c) AppState PlayState
-> EventM Name PlayState c -> EventM Name AppState c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom (PlayState
 -> Focusing (StateT (EventState Name) IO) Bool PlayState)
-> AppState -> Focusing (StateT (EventState Name) IO) Bool AppState
LensLike' (Zoomed (EventM Name PlayState) Bool) AppState PlayState
Lens' AppState PlayState
playState (EventM Name PlayState Bool -> EventM Name AppState Bool)
-> EventM Name PlayState Bool -> EventM Name AppState Bool
forall a b. (a -> b) -> a -> b
$ Set DebugOption -> Menu -> EventM Name PlayState Bool
doGoalUpdates Set DebugOption
dOps Menu
menu

  Bool
newPopups <- LensLike' (Zoomed (EventM Name PlayState) Bool) AppState PlayState
-> EventM Name PlayState Bool -> EventM Name AppState Bool
forall c.
LensLike' (Zoomed (EventM Name PlayState) c) AppState PlayState
-> EventM Name PlayState c -> EventM Name AppState c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom (PlayState
 -> Focusing (StateT (EventState Name) IO) Bool PlayState)
-> AppState -> Focusing (StateT (EventState Name) IO) Bool AppState
LensLike' (Zoomed (EventM Name PlayState) Bool) AppState PlayState
Lens' AppState PlayState
playState EventM Name PlayState Bool
generateNotificationPopups

  -- Update the robots modal only when it is enabled.  See #2370.
  Maybe Modal
curModal <- Getting (Maybe Modal) AppState (Maybe Modal)
-> EventM Name AppState (Maybe Modal)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting (Maybe Modal) AppState (Maybe Modal)
 -> EventM Name AppState (Maybe Modal))
-> Getting (Maybe Modal) AppState (Maybe Modal)
-> EventM Name AppState (Maybe Modal)
forall a b. (a -> b) -> a -> b
$ (PlayState -> Const (Maybe Modal) PlayState)
-> AppState -> Const (Maybe Modal) AppState
Lens' AppState PlayState
playState ((PlayState -> Const (Maybe Modal) PlayState)
 -> AppState -> Const (Maybe Modal) AppState)
-> ((Maybe Modal -> Const (Maybe Modal) (Maybe Modal))
    -> PlayState -> Const (Maybe Modal) PlayState)
-> Getting (Maybe Modal) AppState (Maybe Modal)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ScenarioState -> Const (Maybe Modal) ScenarioState)
-> PlayState -> Const (Maybe Modal) PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState -> Const (Maybe Modal) ScenarioState)
 -> PlayState -> Const (Maybe Modal) PlayState)
-> ((Maybe Modal -> Const (Maybe Modal) (Maybe Modal))
    -> ScenarioState -> Const (Maybe Modal) ScenarioState)
-> (Maybe Modal -> Const (Maybe Modal) (Maybe Modal))
-> PlayState
-> Const (Maybe Modal) PlayState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIGameplay -> Const (Maybe Modal) UIGameplay)
-> ScenarioState -> Const (Maybe Modal) ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Const (Maybe Modal) UIGameplay)
 -> ScenarioState -> Const (Maybe Modal) ScenarioState)
-> ((Maybe Modal -> Const (Maybe Modal) (Maybe Modal))
    -> UIGameplay -> Const (Maybe Modal) UIGameplay)
-> (Maybe Modal -> Const (Maybe Modal) (Maybe Modal))
-> ScenarioState
-> Const (Maybe Modal) ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIDialogs -> Const (Maybe Modal) UIDialogs)
-> UIGameplay -> Const (Maybe Modal) UIGameplay
Lens' UIGameplay UIDialogs
uiDialogs ((UIDialogs -> Const (Maybe Modal) UIDialogs)
 -> UIGameplay -> Const (Maybe Modal) UIGameplay)
-> ((Maybe Modal -> Const (Maybe Modal) (Maybe Modal))
    -> UIDialogs -> Const (Maybe Modal) UIDialogs)
-> (Maybe Modal -> Const (Maybe Modal) (Maybe Modal))
-> UIGameplay
-> Const (Maybe Modal) UIGameplay
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Modal -> Const (Maybe Modal) (Maybe Modal))
-> UIDialogs -> Const (Maybe Modal) UIDialogs
Lens' UIDialogs (Maybe Modal)
uiModal
  Bool -> EventM Name AppState () -> EventM Name AppState ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ((Getting ModalType Modal ModalType -> Modal -> ModalType
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting ModalType Modal ModalType
Lens' Modal ModalType
modalType (Modal -> ModalType) -> Maybe Modal -> Maybe ModalType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Modal
curModal) Maybe ModalType -> Maybe ModalType -> Bool
forall a. Eq a => a -> a -> Bool
== ModalType -> Maybe ModalType
forall a. a -> Maybe a
Just (MidScenarioModalType -> ModalType
MidScenarioModal MidScenarioModalType
RobotsModal)) (EventM Name AppState () -> EventM Name AppState ())
-> EventM Name AppState () -> EventM Name AppState ()
forall a b. (a -> b) -> a -> b
$
    LensLike'
  (Zoomed (EventM Name RobotDisplay) ()) AppState RobotDisplay
-> EventM Name RobotDisplay () -> EventM Name AppState ()
forall c.
LensLike'
  (Zoomed (EventM Name RobotDisplay) c) AppState RobotDisplay
-> EventM Name RobotDisplay c -> EventM Name AppState c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom ((PlayState -> Focusing (StateT (EventState Name) IO) () PlayState)
-> AppState -> Focusing (StateT (EventState Name) IO) () AppState
Lens' AppState PlayState
playState ((PlayState -> Focusing (StateT (EventState Name) IO) () PlayState)
 -> AppState -> Focusing (StateT (EventState Name) IO) () AppState)
-> ((RobotDisplay
     -> Focusing (StateT (EventState Name) IO) () RobotDisplay)
    -> PlayState
    -> Focusing (StateT (EventState Name) IO) () PlayState)
-> (RobotDisplay
    -> Focusing (StateT (EventState Name) IO) () RobotDisplay)
-> AppState
-> Focusing (StateT (EventState Name) IO) () AppState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ScenarioState
 -> Focusing (StateT (EventState Name) IO) () ScenarioState)
-> PlayState -> Focusing (StateT (EventState Name) IO) () PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState
  -> Focusing (StateT (EventState Name) IO) () ScenarioState)
 -> PlayState
 -> Focusing (StateT (EventState Name) IO) () PlayState)
-> ((RobotDisplay
     -> Focusing (StateT (EventState Name) IO) () RobotDisplay)
    -> ScenarioState
    -> Focusing (StateT (EventState Name) IO) () ScenarioState)
-> (RobotDisplay
    -> Focusing (StateT (EventState Name) IO) () RobotDisplay)
-> PlayState
-> Focusing (StateT (EventState Name) IO) () PlayState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIGameplay
 -> Focusing (StateT (EventState Name) IO) () UIGameplay)
-> ScenarioState
-> Focusing (StateT (EventState Name) IO) () ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay
  -> Focusing (StateT (EventState Name) IO) () UIGameplay)
 -> ScenarioState
 -> Focusing (StateT (EventState Name) IO) () ScenarioState)
-> ((RobotDisplay
     -> Focusing (StateT (EventState Name) IO) () RobotDisplay)
    -> UIGameplay
    -> Focusing (StateT (EventState Name) IO) () UIGameplay)
-> (RobotDisplay
    -> Focusing (StateT (EventState Name) IO) () RobotDisplay)
-> ScenarioState
-> Focusing (StateT (EventState Name) IO) () ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIDialogs -> Focusing (StateT (EventState Name) IO) () UIDialogs)
-> UIGameplay
-> Focusing (StateT (EventState Name) IO) () UIGameplay
Lens' UIGameplay UIDialogs
uiDialogs ((UIDialogs -> Focusing (StateT (EventState Name) IO) () UIDialogs)
 -> UIGameplay
 -> Focusing (StateT (EventState Name) IO) () UIGameplay)
-> ((RobotDisplay
     -> Focusing (StateT (EventState Name) IO) () RobotDisplay)
    -> UIDialogs
    -> Focusing (StateT (EventState Name) IO) () UIDialogs)
-> (RobotDisplay
    -> Focusing (StateT (EventState Name) IO) () RobotDisplay)
-> UIGameplay
-> Focusing (StateT (EventState Name) IO) () UIGameplay
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (RobotDisplay
 -> Focusing (StateT (EventState Name) IO) () RobotDisplay)
-> UIDialogs -> Focusing (StateT (EventState Name) IO) () UIDialogs
Lens' UIDialogs RobotDisplay
uiRobot) (EventM Name RobotDisplay () -> EventM Name AppState ())
-> EventM Name RobotDisplay () -> EventM Name AppState ()
forall a b. (a -> b) -> a -> b
$
      Set DebugOption -> GameState -> EventM Name RobotDisplay ()
doRobotListUpdate Set DebugOption
dOps GameState
g

  let redraw :: Bool
redraw =
        GameState
g GameState
-> ((Bool -> Const Bool Bool) -> GameState -> Const Bool GameState)
-> Bool
forall s a. s -> Getting a s a -> a
^. (Bool -> Const Bool Bool) -> GameState -> Const Bool GameState
Lens' GameState Bool
needsRedraw
          Bool -> Bool -> Bool
|| Bool
inventoryUpdated
          Bool -> Bool -> Bool
|| Bool
replUpdated
          Bool -> Bool -> Bool
|| Bool
logUpdated
          Bool -> Bool -> Bool
|| Bool
goalOrWinUpdated
          Bool -> Bool -> Bool
|| Bool
newPopups
  Bool -> EventM Name AppState Bool
forall a. a -> EventM Name AppState a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
redraw

doRobotListUpdate :: Set DebugOption -> GameState -> EventM Name RobotDisplay ()
doRobotListUpdate :: Set DebugOption -> GameState -> EventM Name RobotDisplay ()
doRobotListUpdate Set DebugOption
dOps GameState
g = do
  (GridTabularList Name Int -> Identity (GridTabularList Name Int))
-> RobotDisplay -> Identity RobotDisplay
Lens' RobotDisplay (GridTabularList Name Int)
robotsGridList ((GridTabularList Name Int -> Identity (GridTabularList Name Int))
 -> RobotDisplay -> Identity RobotDisplay)
-> (GridTabularList Name Int -> GridTabularList Name Int)
-> EventM Name RobotDisplay ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= Set DebugOption
-> GameState
-> GridTabularList Name Int
-> GridTabularList Name Int
updateRobotList Set DebugOption
dOps GameState
g
  GridTabularList Name Int
rList <- Getting
  (GridTabularList Name Int) RobotDisplay (GridTabularList Name Int)
-> EventM Name RobotDisplay (GridTabularList Name Int)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting
  (GridTabularList Name Int) RobotDisplay (GridTabularList Name Int)
Lens' RobotDisplay (GridTabularList Name Int)
robotsGridList
  let mRob :: Maybe Robot
mRob = GameState -> GridTabularList Name Int -> Maybe Robot
getSelectedRobot GameState
g GridTabularList Name Int
rList
  Maybe Robot
-> (Robot -> EventM Name RobotDisplay ())
-> EventM Name RobotDisplay ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe Robot
mRob ((Robot -> EventM Name RobotDisplay ())
 -> EventM Name RobotDisplay ())
-> (Robot -> EventM Name RobotDisplay ())
-> EventM Name RobotDisplay ()
forall a b. (a -> b) -> a -> b
$ \Robot
r -> do
    LensLike'
  (Zoomed (EventM Name RobotDetailsPaneState) ())
  RobotDisplay
  RobotDetailsPaneState
-> EventM Name RobotDetailsPaneState ()
-> EventM Name RobotDisplay ()
forall c.
LensLike'
  (Zoomed (EventM Name RobotDetailsPaneState) c)
  RobotDisplay
  RobotDetailsPaneState
-> EventM Name RobotDetailsPaneState c
-> EventM Name RobotDisplay c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom (RobotDetailsPaneState
 -> Focusing (StateT (EventState Name) IO) () RobotDetailsPaneState)
-> RobotDisplay
-> Focusing (StateT (EventState Name) IO) () RobotDisplay
LensLike'
  (Zoomed (EventM Name RobotDetailsPaneState) ())
  RobotDisplay
  RobotDetailsPaneState
Lens' RobotDisplay RobotDetailsPaneState
robotDetailsPaneState (EventM Name RobotDetailsPaneState ()
 -> EventM Name RobotDisplay ())
-> EventM Name RobotDetailsPaneState ()
-> EventM Name RobotDisplay ()
forall a b. (a -> b) -> a -> b
$ Robot -> EventM Name RobotDetailsPaneState ()
updateRobotDetailsPane Robot
r

updateRobotDetailsPane :: Robot -> EventM Name RobotDetailsPaneState ()
updateRobotDetailsPane :: Robot -> EventM Name RobotDetailsPaneState ()
updateRobotDetailsPane Robot
rob = do
  (List Name (Const, Int) -> Identity (List Name (Const, Int)))
-> RobotDetailsPaneState -> Identity RobotDetailsPaneState
Lens' RobotDetailsPaneState (List Name (Const, Int))
cmdHistogramList ((List Name (Const, Int) -> Identity (List Name (Const, Int)))
 -> RobotDetailsPaneState -> Identity RobotDetailsPaneState)
-> ((Vector (Const, Int) -> Identity (Vector (Const, Int)))
    -> List Name (Const, Int) -> Identity (List Name (Const, Int)))
-> (Vector (Const, Int) -> Identity (Vector (Const, Int)))
-> RobotDetailsPaneState
-> Identity RobotDetailsPaneState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Vector (Const, Int) -> Identity (Vector (Const, Int)))
-> List Name (Const, Int) -> Identity (List Name (Const, Int))
forall n (t1 :: * -> *) e1 (t2 :: * -> *) e2 (f :: * -> *).
Functor f =>
(t1 e1 -> f (t2 e2))
-> GenericList n t1 e1 -> f (GenericList n t2 e2)
BL.listElementsL ((Vector (Const, Int) -> Identity (Vector (Const, Int)))
 -> RobotDetailsPaneState -> Identity RobotDetailsPaneState)
-> Vector (Const, Int) -> EventM Name RobotDetailsPaneState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [(Const, Int)] -> Vector (Const, Int)
forall a. [a] -> Vector a
V.fromList (Map Const Int -> [(Const, Int)]
forall k a. Map k a -> [(k, a)]
M.toList (Robot
rob Robot
-> Getting (Map Const Int) Robot (Map Const Int) -> Map Const Int
forall s a. s -> Getting a s a -> a
^. (ActivityCounts -> Const (Map Const Int) ActivityCounts)
-> Robot -> Const (Map Const Int) Robot
Lens' Robot ActivityCounts
activityCounts ((ActivityCounts -> Const (Map Const Int) ActivityCounts)
 -> Robot -> Const (Map Const Int) Robot)
-> ((Map Const Int -> Const (Map Const Int) (Map Const Int))
    -> ActivityCounts -> Const (Map Const Int) ActivityCounts)
-> Getting (Map Const Int) Robot (Map Const Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Const Int -> Const (Map Const Int) (Map Const Int))
-> ActivityCounts -> Const (Map Const Int) ActivityCounts
Lens' ActivityCounts (Map Const Int)
commandsHistogram))
  (GenericList Name Seq LogEntry
 -> Identity (GenericList Name Seq LogEntry))
-> RobotDetailsPaneState -> Identity RobotDetailsPaneState
Lens' RobotDetailsPaneState (GenericList Name Seq LogEntry)
logsList ((GenericList Name Seq LogEntry
  -> Identity (GenericList Name Seq LogEntry))
 -> RobotDetailsPaneState -> Identity RobotDetailsPaneState)
-> ((Seq LogEntry -> Identity (Seq LogEntry))
    -> GenericList Name Seq LogEntry
    -> Identity (GenericList Name Seq LogEntry))
-> (Seq LogEntry -> Identity (Seq LogEntry))
-> RobotDetailsPaneState
-> Identity RobotDetailsPaneState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Seq LogEntry -> Identity (Seq LogEntry))
-> GenericList Name Seq LogEntry
-> Identity (GenericList Name Seq LogEntry)
forall n (t1 :: * -> *) e1 (t2 :: * -> *) e2 (f :: * -> *).
Functor f =>
(t1 e1 -> f (t2 e2))
-> GenericList n t1 e1 -> f (GenericList n t2 e2)
BL.listElementsL ((Seq LogEntry -> Identity (Seq LogEntry))
 -> RobotDetailsPaneState -> Identity RobotDetailsPaneState)
-> Seq LogEntry -> EventM Name RobotDetailsPaneState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= (Robot
rob Robot
-> Getting (Seq LogEntry) Robot (Seq LogEntry) -> Seq LogEntry
forall s a. s -> Getting a s a -> a
^. Getting (Seq LogEntry) Robot (Seq LogEntry)
Lens' Robot (Seq LogEntry)
robotLog)

-- | Either pops up the updated Goals modal
-- or pops up the Congratulations (Win) modal, or pops
-- up the Condolences (Lose) modal.
-- The Win modal will take precedence if the player
-- has met the necessary conditions to win the game.
--
-- If the player chooses to "Keep Playing" from the Win modal, the
-- updated Goals will then immediately appear.
-- This is desirable for:
-- * feedback as to the final goal the player accomplished,
-- * as a summary of all of the goals of the game
-- * shows the player more "optional" goals they can continue to pursue
doGoalUpdates :: Set DebugOption -> Menu -> EventM Name PlayState Bool
doGoalUpdates :: Set DebugOption -> Menu -> EventM Name PlayState Bool
doGoalUpdates Set DebugOption
dOpts Menu
menu = do
  GoalTracking
curGoal <- Getting GoalTracking PlayState GoalTracking
-> EventM Name PlayState GoalTracking
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ScenarioState -> Const GoalTracking ScenarioState)
-> PlayState -> Const GoalTracking PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState -> Const GoalTracking ScenarioState)
 -> PlayState -> Const GoalTracking PlayState)
-> ((GoalTracking -> Const GoalTracking GoalTracking)
    -> ScenarioState -> Const GoalTracking ScenarioState)
-> Getting GoalTracking PlayState GoalTracking
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIGameplay -> Const GoalTracking UIGameplay)
-> ScenarioState -> Const GoalTracking ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Const GoalTracking UIGameplay)
 -> ScenarioState -> Const GoalTracking ScenarioState)
-> ((GoalTracking -> Const GoalTracking GoalTracking)
    -> UIGameplay -> Const GoalTracking UIGameplay)
-> (GoalTracking -> Const GoalTracking GoalTracking)
-> ScenarioState
-> Const GoalTracking ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIDialogs -> Const GoalTracking UIDialogs)
-> UIGameplay -> Const GoalTracking UIGameplay
Lens' UIGameplay UIDialogs
uiDialogs ((UIDialogs -> Const GoalTracking UIDialogs)
 -> UIGameplay -> Const GoalTracking UIGameplay)
-> ((GoalTracking -> Const GoalTracking GoalTracking)
    -> UIDialogs -> Const GoalTracking UIDialogs)
-> (GoalTracking -> Const GoalTracking GoalTracking)
-> UIGameplay
-> Const GoalTracking UIGameplay
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GoalDisplay -> Const GoalTracking GoalDisplay)
-> UIDialogs -> Const GoalTracking UIDialogs
Lens' UIDialogs GoalDisplay
uiGoal ((GoalDisplay -> Const GoalTracking GoalDisplay)
 -> UIDialogs -> Const GoalTracking UIDialogs)
-> ((GoalTracking -> Const GoalTracking GoalTracking)
    -> GoalDisplay -> Const GoalTracking GoalDisplay)
-> (GoalTracking -> Const GoalTracking GoalTracking)
-> UIDialogs
-> Const GoalTracking UIDialogs
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GoalTracking -> Const GoalTracking GoalTracking)
-> GoalDisplay -> Const GoalTracking GoalDisplay
Lens' GoalDisplay GoalTracking
goalsContent)
  WinCondition
curWinCondition <- Getting WinCondition PlayState WinCondition
-> EventM Name PlayState WinCondition
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ScenarioState -> Const WinCondition ScenarioState)
-> PlayState -> Const WinCondition PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState -> Const WinCondition ScenarioState)
 -> PlayState -> Const WinCondition PlayState)
-> ((WinCondition -> Const WinCondition WinCondition)
    -> ScenarioState -> Const WinCondition ScenarioState)
-> Getting WinCondition PlayState WinCondition
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameState -> Const WinCondition GameState)
-> ScenarioState -> Const WinCondition ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const WinCondition GameState)
 -> ScenarioState -> Const WinCondition ScenarioState)
-> ((WinCondition -> Const WinCondition WinCondition)
    -> GameState -> Const WinCondition GameState)
-> (WinCondition -> Const WinCondition WinCondition)
-> ScenarioState
-> Const WinCondition ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (WinCondition -> Const WinCondition WinCondition)
-> GameState -> Const WinCondition GameState
Lens' GameState WinCondition
winCondition)
  [Announcement]
announcementsList <- Getting [Announcement] PlayState [Announcement]
-> EventM Name PlayState [Announcement]
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ScenarioState -> Const [Announcement] ScenarioState)
-> PlayState -> Const [Announcement] PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState -> Const [Announcement] ScenarioState)
 -> PlayState -> Const [Announcement] PlayState)
-> (([Announcement] -> Const [Announcement] [Announcement])
    -> ScenarioState -> Const [Announcement] ScenarioState)
-> Getting [Announcement] PlayState [Announcement]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameState -> Const [Announcement] GameState)
-> ScenarioState -> Const [Announcement] ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const [Announcement] GameState)
 -> ScenarioState -> Const [Announcement] ScenarioState)
-> (([Announcement] -> Const [Announcement] [Announcement])
    -> GameState -> Const [Announcement] GameState)
-> ([Announcement] -> Const [Announcement] [Announcement])
-> ScenarioState
-> Const [Announcement] ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Messages -> Const [Announcement] Messages)
-> GameState -> Const [Announcement] GameState
Lens' GameState Messages
messageInfo ((Messages -> Const [Announcement] Messages)
 -> GameState -> Const [Announcement] GameState)
-> (([Announcement] -> Const [Announcement] [Announcement])
    -> Messages -> Const [Announcement] Messages)
-> ([Announcement] -> Const [Announcement] [Announcement])
-> GameState
-> Const [Announcement] GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Seq Announcement -> Const [Announcement] (Seq Announcement))
-> Messages -> Const [Announcement] Messages
Lens' Messages (Seq Announcement)
announcementQueue ((Seq Announcement -> Const [Announcement] (Seq Announcement))
 -> Messages -> Const [Announcement] Messages)
-> (([Announcement] -> Const [Announcement] [Announcement])
    -> Seq Announcement -> Const [Announcement] (Seq Announcement))
-> ([Announcement] -> Const [Announcement] [Announcement])
-> Messages
-> Const [Announcement] Messages
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Seq Announcement -> [Announcement])
-> ([Announcement] -> Const [Announcement] [Announcement])
-> Seq Announcement
-> Const [Announcement] (Seq Announcement)
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to Seq Announcement -> [Announcement]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList)
  let showHiddenGoals :: Bool
showHiddenGoals = DebugOption
ShowHiddenGoals DebugOption -> Set DebugOption -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.member` Set DebugOption
dOpts

  -- Decide whether we need to update the current goal text and pop
  -- up a modal dialog.
  case WinCondition
curWinCondition of
    WinCondition
NoWinCondition -> Bool -> EventM Name PlayState Bool
forall a. a -> EventM Name PlayState a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
    WinConditions (Unwinnable Bool
False) ObjectiveCompletion
x ->
      ScenarioOutcome
-> WinStatus -> ObjectiveCompletion -> EventM Name PlayState Bool
setFinishState ScenarioOutcome
LoseModal (Bool -> WinStatus
Unwinnable Bool
True) ObjectiveCompletion
x
    WinConditions (Won Bool
False TickNumber
ts) ObjectiveCompletion
x -> do
      ScenarioOutcome
-> WinStatus -> ObjectiveCompletion -> EventM Name PlayState Bool
setFinishState ScenarioOutcome
WinModal (Bool -> TickNumber -> WinStatus
Won Bool
True TickNumber
ts) ObjectiveCompletion
x
    WinConditions WinStatus
_ ObjectiveCompletion
oc -> LensLike'
  (Zoomed (EventM Name ScenarioState) Bool) PlayState ScenarioState
-> EventM Name ScenarioState Bool -> EventM Name PlayState Bool
forall c.
LensLike'
  (Zoomed (EventM Name ScenarioState) c) PlayState ScenarioState
-> EventM Name ScenarioState c -> EventM Name PlayState c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
Brick.zoom (ScenarioState
 -> Focusing (StateT (EventState Name) IO) Bool ScenarioState)
-> PlayState
-> Focusing (StateT (EventState Name) IO) Bool PlayState
LensLike'
  (Zoomed (EventM Name ScenarioState) Bool) PlayState ScenarioState
Lens' PlayState ScenarioState
scenarioState (EventM Name ScenarioState Bool -> EventM Name PlayState Bool)
-> EventM Name ScenarioState Bool -> EventM Name PlayState Bool
forall a b. (a -> b) -> a -> b
$ do
      Maybe ModalType
currentModal <- Getting (First ModalType) ScenarioState ModalType
-> EventM Name ScenarioState (Maybe ModalType)
forall s (m :: * -> *) a.
MonadState s m =>
Getting (First a) s a -> m (Maybe a)
preuse (Getting (First ModalType) ScenarioState ModalType
 -> EventM Name ScenarioState (Maybe ModalType))
-> Getting (First ModalType) ScenarioState ModalType
-> EventM Name ScenarioState (Maybe ModalType)
forall a b. (a -> b) -> a -> b
$ (UIGameplay -> Const (First ModalType) UIGameplay)
-> ScenarioState -> Const (First ModalType) ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Const (First ModalType) UIGameplay)
 -> ScenarioState -> Const (First ModalType) ScenarioState)
-> ((ModalType -> Const (First ModalType) ModalType)
    -> UIGameplay -> Const (First ModalType) UIGameplay)
-> Getting (First ModalType) ScenarioState ModalType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIDialogs -> Const (First ModalType) UIDialogs)
-> UIGameplay -> Const (First ModalType) UIGameplay
Lens' UIGameplay UIDialogs
uiDialogs ((UIDialogs -> Const (First ModalType) UIDialogs)
 -> UIGameplay -> Const (First ModalType) UIGameplay)
-> ((ModalType -> Const (First ModalType) ModalType)
    -> UIDialogs -> Const (First ModalType) UIDialogs)
-> (ModalType -> Const (First ModalType) ModalType)
-> UIGameplay
-> Const (First ModalType) UIGameplay
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Modal -> Const (First ModalType) (Maybe Modal))
-> UIDialogs -> Const (First ModalType) UIDialogs
Lens' UIDialogs (Maybe Modal)
uiModal ((Maybe Modal -> Const (First ModalType) (Maybe Modal))
 -> UIDialogs -> Const (First ModalType) UIDialogs)
-> ((ModalType -> Const (First ModalType) ModalType)
    -> Maybe Modal -> Const (First ModalType) (Maybe Modal))
-> (ModalType -> Const (First ModalType) ModalType)
-> UIDialogs
-> Const (First ModalType) UIDialogs
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Modal -> Const (First ModalType) Modal)
-> Maybe Modal -> Const (First ModalType) (Maybe Modal)
forall a b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Maybe a) (f (Maybe b))
_Just ((Modal -> Const (First ModalType) Modal)
 -> Maybe Modal -> Const (First ModalType) (Maybe Modal))
-> ((ModalType -> Const (First ModalType) ModalType)
    -> Modal -> Const (First ModalType) Modal)
-> (ModalType -> Const (First ModalType) ModalType)
-> Maybe Modal
-> Const (First ModalType) (Maybe Modal)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ModalType -> Const (First ModalType) ModalType)
-> Modal -> Const (First ModalType) Modal
Lens' Modal ModalType
modalType
      let newGoalTracking :: GoalTracking
newGoalTracking = [Announcement] -> CategorizedGoals -> GoalTracking
GoalTracking [Announcement]
announcementsList (CategorizedGoals -> GoalTracking)
-> CategorizedGoals -> GoalTracking
forall a b. (a -> b) -> a -> b
$ Bool -> ObjectiveCompletion -> CategorizedGoals
constructGoalMap Bool
showHiddenGoals ObjectiveCompletion
oc
          -- The "uiGoal" field is initialized with empty members, so we know that
          -- this will be the first time showing it if it will be nonempty after previously
          -- being empty.
          isFirstGoalDisplay :: Bool
isFirstGoalDisplay = GoalTracking -> Bool
hasAnythingToShow GoalTracking
newGoalTracking Bool -> Bool -> Bool
&& Bool -> Bool
not (GoalTracking -> Bool
hasAnythingToShow GoalTracking
curGoal)
          goalWasUpdated :: Bool
goalWasUpdated = Bool
isFirstGoalDisplay Bool -> Bool -> Bool
|| Bool -> Bool
not ([Announcement] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Announcement]
announcementsList)
          isEnding :: Bool
isEnding = Bool -> (ModalType -> Bool) -> Maybe ModalType -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False ModalType -> Bool
isEndingModal Maybe ModalType
currentModal

      -- Decide whether to show a pop-up modal congratulating the user on
      -- successfully completing the current challenge.
      Bool
-> EventM Name ScenarioState () -> EventM Name ScenarioState ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
goalWasUpdated Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
isEnding) (EventM Name ScenarioState () -> EventM Name ScenarioState ())
-> EventM Name ScenarioState () -> EventM Name ScenarioState ()
forall a b. (a -> b) -> a -> b
$ do
        -- The "uiGoal" field is necessary at least to "persist" the data that is needed
        -- if the player chooses to later "recall" the goals dialog with CTRL+g.
        (UIGameplay -> Identity UIGameplay)
-> ScenarioState -> Identity ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Identity UIGameplay)
 -> ScenarioState -> Identity ScenarioState)
-> ((GoalDisplay -> Identity GoalDisplay)
    -> UIGameplay -> Identity UIGameplay)
-> (GoalDisplay -> Identity GoalDisplay)
-> ScenarioState
-> Identity ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UIDialogs -> Identity UIDialogs)
-> UIGameplay -> Identity UIGameplay
Lens' UIGameplay UIDialogs
uiDialogs ((UIDialogs -> Identity UIDialogs)
 -> UIGameplay -> Identity UIGameplay)
-> ((GoalDisplay -> Identity GoalDisplay)
    -> UIDialogs -> Identity UIDialogs)
-> (GoalDisplay -> Identity GoalDisplay)
-> UIGameplay
-> Identity UIGameplay
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GoalDisplay -> Identity GoalDisplay)
-> UIDialogs -> Identity UIDialogs
Lens' UIDialogs GoalDisplay
uiGoal ((GoalDisplay -> Identity GoalDisplay)
 -> ScenarioState -> Identity ScenarioState)
-> GoalDisplay -> EventM Name ScenarioState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= GoalTracking -> GoalDisplay
goalDisplay GoalTracking
newGoalTracking

        -- This clears the "flag" that indicate that the goals dialog needs to be
        -- automatically popped up.
        (GameState -> Identity GameState)
-> ScenarioState -> Identity ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Identity GameState)
 -> ScenarioState -> Identity ScenarioState)
-> ((Seq Announcement -> Identity (Seq Announcement))
    -> GameState -> Identity GameState)
-> (Seq Announcement -> Identity (Seq Announcement))
-> ScenarioState
-> Identity ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Messages -> Identity Messages) -> GameState -> Identity GameState
Lens' GameState Messages
messageInfo ((Messages -> Identity Messages)
 -> GameState -> Identity GameState)
-> ((Seq Announcement -> Identity (Seq Announcement))
    -> Messages -> Identity Messages)
-> (Seq Announcement -> Identity (Seq Announcement))
-> GameState
-> Identity GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Seq Announcement -> Identity (Seq Announcement))
-> Messages -> Identity Messages
Lens' Messages (Seq Announcement)
announcementQueue ((Seq Announcement -> Identity (Seq Announcement))
 -> ScenarioState -> Identity ScenarioState)
-> Seq Announcement -> EventM Name ScenarioState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Seq Announcement
forall a. Monoid a => a
mempty

        Bool
showObjectives <- Getting Bool ScenarioState Bool -> EventM Name ScenarioState Bool
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting Bool ScenarioState Bool -> EventM Name ScenarioState Bool)
-> Getting Bool ScenarioState Bool
-> EventM Name ScenarioState Bool
forall a b. (a -> b) -> a -> b
$ (UIGameplay -> Const Bool UIGameplay)
-> ScenarioState -> Const Bool ScenarioState
Lens' ScenarioState UIGameplay
uiGameplay ((UIGameplay -> Const Bool UIGameplay)
 -> ScenarioState -> Const Bool ScenarioState)
-> ((Bool -> Const Bool Bool)
    -> UIGameplay -> Const Bool UIGameplay)
-> Getting Bool ScenarioState Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Const Bool Bool) -> UIGameplay -> Const Bool UIGameplay
Lens' UIGameplay Bool
uiAutoShowObjectives
        Bool
-> EventM Name ScenarioState () -> EventM Name ScenarioState ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
showObjectives (EventM Name ScenarioState () -> EventM Name ScenarioState ())
-> EventM Name ScenarioState () -> EventM Name ScenarioState ()
forall a b. (a -> b) -> a -> b
$ MidScenarioModalType -> EventM Name ScenarioState ()
openMidScenarioModal MidScenarioModalType
GoalModal

      Bool -> EventM Name ScenarioState Bool
forall a. a -> EventM Name ScenarioState a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
goalWasUpdated
 where
  setFinishState :: ScenarioOutcome -> WinStatus -> ObjectiveCompletion -> EventM Name PlayState Bool
  setFinishState :: ScenarioOutcome
-> WinStatus -> ObjectiveCompletion -> EventM Name PlayState Bool
setFinishState ScenarioOutcome
m WinStatus
result ObjectiveCompletion
x = do
    -- This clears the "flag" that the Lose dialog needs to pop up
    (ScenarioState -> Identity ScenarioState)
-> PlayState -> Identity PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState -> Identity ScenarioState)
 -> PlayState -> Identity PlayState)
-> ((WinCondition -> Identity WinCondition)
    -> ScenarioState -> Identity ScenarioState)
-> (WinCondition -> Identity WinCondition)
-> PlayState
-> Identity PlayState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameState -> Identity GameState)
-> ScenarioState -> Identity ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Identity GameState)
 -> ScenarioState -> Identity ScenarioState)
-> ((WinCondition -> Identity WinCondition)
    -> GameState -> Identity GameState)
-> (WinCondition -> Identity WinCondition)
-> ScenarioState
-> Identity ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (WinCondition -> Identity WinCondition)
-> GameState -> Identity GameState
Lens' GameState WinCondition
winCondition ((WinCondition -> Identity WinCondition)
 -> PlayState -> Identity PlayState)
-> WinCondition -> EventM Name PlayState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= WinStatus -> ObjectiveCompletion -> WinCondition
WinConditions WinStatus
result ObjectiveCompletion
x
    Menu -> EndScenarioModalType -> EventM Name PlayState ()
openEndScenarioModal Menu
menu (EndScenarioModalType -> EventM Name PlayState ())
-> EndScenarioModalType -> EventM Name PlayState ()
forall a b. (a -> b) -> a -> b
$ ScenarioOutcome -> EndScenarioModalType
ScenarioFinishModal ScenarioOutcome
m

    Set DebugOption -> EventM Name PlayState ()
forall n. Set DebugOption -> EventM n PlayState ()
saveScenarioInfoOnFinishNocheat Set DebugOption
dOpts

    -- We do NOT advance the New Game menu to the next item here (we
    -- used to!), because we do not know if the user is going to
    -- select 'keep playing' or 'next challenge'.  We maintain the
    -- invariant that the current menu item is always the same as
    -- the scenario currently being played.  If the user either (1)
    -- quits to the menu or (2) selects 'next challenge' we will
    -- advance the menu at that point.
    Bool -> EventM Name PlayState Bool
forall a. a -> EventM Name PlayState a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True

  goalDisplay :: GoalTracking -> GoalDisplay
  goalDisplay :: GoalTracking -> GoalDisplay
goalDisplay GoalTracking
newGoalTracking =
    let multiple :: Bool
multiple = GoalTracking -> Bool
hasMultipleGoals GoalTracking
newGoalTracking
     in GoalTracking
-> List Name GoalEntry -> FocusRing Name -> GoalDisplay
GoalDisplay
          GoalTracking
newGoalTracking
          (GoalTracking -> List Name GoalEntry
GR.makeListWidget GoalTracking
newGoalTracking)
          (Name -> FocusRing Name -> FocusRing Name
forall n. Eq n => n -> FocusRing n -> FocusRing n
focusSetCurrent (GoalWidget -> Name
GoalWidgets (GoalWidget -> Name) -> GoalWidget -> Name
forall a b. (a -> b) -> a -> b
$ Bool -> GoalWidget
goalFocus Bool
multiple) (Bool -> FocusRing Name
goalFocusRing Bool
multiple))

  goalFocus :: Bool -> GoalWidget
  goalFocus :: Bool -> GoalWidget
goalFocus Bool
hasMultiple = if Bool
hasMultiple then GoalWidget
ObjectivesList else GoalWidget
GoalSummary

  goalFocusRing :: Bool -> FocusRing Name
  goalFocusRing :: Bool -> FocusRing Name
goalFocusRing Bool
hasMultiple = [Name] -> FocusRing Name
forall n. [n] -> FocusRing n
focusRing ([Name] -> FocusRing Name) -> [Name] -> FocusRing Name
forall a b. (a -> b) -> a -> b
$ GoalWidget -> Name
GoalWidgets (GoalWidget -> Name) -> [GoalWidget] -> [Name]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> if Bool
hasMultiple then [GoalWidget]
forall a. (Enum a, Bounded a) => [a]
enumerate else [GoalWidget
GoalSummary]

  isEndingModal :: ModalType -> Bool
  isEndingModal :: ModalType -> Bool
isEndingModal = \case
    EndScenarioModal EndScenarioModalType
_ -> Bool
True
    ModalType
_ -> Bool
False

-- | Pops up notifications when new recipes or commands are unlocked.
generateNotificationPopups :: EventM Name PlayState Bool
generateNotificationPopups :: EventM Name PlayState Bool
generateNotificationPopups = do
  Notifications (Recipe Entity)
rs <- Getting
  (Notifications (Recipe Entity))
  PlayState
  (Notifications (Recipe Entity))
-> EventM Name PlayState (Notifications (Recipe Entity))
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting
   (Notifications (Recipe Entity))
   PlayState
   (Notifications (Recipe Entity))
 -> EventM Name PlayState (Notifications (Recipe Entity)))
-> Getting
     (Notifications (Recipe Entity))
     PlayState
     (Notifications (Recipe Entity))
-> EventM Name PlayState (Notifications (Recipe Entity))
forall a b. (a -> b) -> a -> b
$ (ScenarioState
 -> Const (Notifications (Recipe Entity)) ScenarioState)
-> PlayState -> Const (Notifications (Recipe Entity)) PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState
  -> Const (Notifications (Recipe Entity)) ScenarioState)
 -> PlayState -> Const (Notifications (Recipe Entity)) PlayState)
-> ((Notifications (Recipe Entity)
     -> Const
          (Notifications (Recipe Entity)) (Notifications (Recipe Entity)))
    -> ScenarioState
    -> Const (Notifications (Recipe Entity)) ScenarioState)
-> Getting
     (Notifications (Recipe Entity))
     PlayState
     (Notifications (Recipe Entity))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameState -> Const (Notifications (Recipe Entity)) GameState)
-> ScenarioState
-> Const (Notifications (Recipe Entity)) ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const (Notifications (Recipe Entity)) GameState)
 -> ScenarioState
 -> Const (Notifications (Recipe Entity)) ScenarioState)
-> ((Notifications (Recipe Entity)
     -> Const
          (Notifications (Recipe Entity)) (Notifications (Recipe Entity)))
    -> GameState -> Const (Notifications (Recipe Entity)) GameState)
-> (Notifications (Recipe Entity)
    -> Const
         (Notifications (Recipe Entity)) (Notifications (Recipe Entity)))
-> ScenarioState
-> Const (Notifications (Recipe Entity)) ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Discovery -> Const (Notifications (Recipe Entity)) Discovery)
-> GameState -> Const (Notifications (Recipe Entity)) GameState
Lens' GameState Discovery
discovery ((Discovery -> Const (Notifications (Recipe Entity)) Discovery)
 -> GameState -> Const (Notifications (Recipe Entity)) GameState)
-> ((Notifications (Recipe Entity)
     -> Const
          (Notifications (Recipe Entity)) (Notifications (Recipe Entity)))
    -> Discovery -> Const (Notifications (Recipe Entity)) Discovery)
-> (Notifications (Recipe Entity)
    -> Const
         (Notifications (Recipe Entity)) (Notifications (Recipe Entity)))
-> GameState
-> Const (Notifications (Recipe Entity)) GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Notifications (Recipe Entity)
 -> Const
      (Notifications (Recipe Entity)) (Notifications (Recipe Entity)))
-> Discovery -> Const (Notifications (Recipe Entity)) Discovery
Lens' Discovery (Notifications (Recipe Entity))
availableRecipes
  let newRecipes :: Bool
newRecipes = Notifications (Recipe Entity)
rs Notifications (Recipe Entity)
-> Getting Bool (Notifications (Recipe Entity)) Bool -> Bool
forall s a. s -> Getting a s a -> a
^. Getting Bool (Notifications (Recipe Entity)) Bool
forall a (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> Notifications a -> f (Notifications a)
notificationsShouldAlert
  Bool -> EventM Name PlayState () -> EventM Name PlayState ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
newRecipes (EventM Name PlayState () -> EventM Name PlayState ())
-> EventM Name PlayState () -> EventM Name PlayState ()
forall a b. (a -> b) -> a -> b
$ do
    (ProgressionState -> Identity ProgressionState)
-> PlayState -> Identity PlayState
Lens' PlayState ProgressionState
progression ((ProgressionState -> Identity ProgressionState)
 -> PlayState -> Identity PlayState)
-> ((PopupState -> Identity PopupState)
    -> ProgressionState -> Identity ProgressionState)
-> (PopupState -> Identity PopupState)
-> PlayState
-> Identity PlayState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PopupState -> Identity PopupState)
-> ProgressionState -> Identity ProgressionState
Lens' ProgressionState PopupState
uiPopups ((PopupState -> Identity PopupState)
 -> PlayState -> Identity PlayState)
-> (PopupState -> PopupState) -> EventM Name PlayState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= Popup -> PopupState -> PopupState
addPopup Popup
RecipesPopup
    (ScenarioState -> Identity ScenarioState)
-> PlayState -> Identity PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState -> Identity ScenarioState)
 -> PlayState -> Identity PlayState)
-> ((Bool -> Identity Bool)
    -> ScenarioState -> Identity ScenarioState)
-> (Bool -> Identity Bool)
-> PlayState
-> Identity PlayState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameState -> Identity GameState)
-> ScenarioState -> Identity ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Identity GameState)
 -> ScenarioState -> Identity ScenarioState)
-> ((Bool -> Identity Bool) -> GameState -> Identity GameState)
-> (Bool -> Identity Bool)
-> ScenarioState
-> Identity ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Discovery -> Identity Discovery)
-> GameState -> Identity GameState
Lens' GameState Discovery
discovery ((Discovery -> Identity Discovery)
 -> GameState -> Identity GameState)
-> ((Bool -> Identity Bool) -> Discovery -> Identity Discovery)
-> (Bool -> Identity Bool)
-> GameState
-> Identity GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Notifications (Recipe Entity)
 -> Identity (Notifications (Recipe Entity)))
-> Discovery -> Identity Discovery
Lens' Discovery (Notifications (Recipe Entity))
availableRecipes ((Notifications (Recipe Entity)
  -> Identity (Notifications (Recipe Entity)))
 -> Discovery -> Identity Discovery)
-> ((Bool -> Identity Bool)
    -> Notifications (Recipe Entity)
    -> Identity (Notifications (Recipe Entity)))
-> (Bool -> Identity Bool)
-> Discovery
-> Identity Discovery
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Identity Bool)
-> Notifications (Recipe Entity)
-> Identity (Notifications (Recipe Entity))
forall a (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> Notifications a -> f (Notifications a)
notificationsShouldAlert ((Bool -> Identity Bool) -> PlayState -> Identity PlayState)
-> Bool -> EventM Name PlayState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
False

  Notifications Const
cs <- Getting (Notifications Const) PlayState (Notifications Const)
-> EventM Name PlayState (Notifications Const)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting (Notifications Const) PlayState (Notifications Const)
 -> EventM Name PlayState (Notifications Const))
-> Getting (Notifications Const) PlayState (Notifications Const)
-> EventM Name PlayState (Notifications Const)
forall a b. (a -> b) -> a -> b
$ (ScenarioState -> Const (Notifications Const) ScenarioState)
-> PlayState -> Const (Notifications Const) PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState -> Const (Notifications Const) ScenarioState)
 -> PlayState -> Const (Notifications Const) PlayState)
-> ((Notifications Const
     -> Const (Notifications Const) (Notifications Const))
    -> ScenarioState -> Const (Notifications Const) ScenarioState)
-> Getting (Notifications Const) PlayState (Notifications Const)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameState -> Const (Notifications Const) GameState)
-> ScenarioState -> Const (Notifications Const) ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Const (Notifications Const) GameState)
 -> ScenarioState -> Const (Notifications Const) ScenarioState)
-> ((Notifications Const
     -> Const (Notifications Const) (Notifications Const))
    -> GameState -> Const (Notifications Const) GameState)
-> (Notifications Const
    -> Const (Notifications Const) (Notifications Const))
-> ScenarioState
-> Const (Notifications Const) ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Discovery -> Const (Notifications Const) Discovery)
-> GameState -> Const (Notifications Const) GameState
Lens' GameState Discovery
discovery ((Discovery -> Const (Notifications Const) Discovery)
 -> GameState -> Const (Notifications Const) GameState)
-> ((Notifications Const
     -> Const (Notifications Const) (Notifications Const))
    -> Discovery -> Const (Notifications Const) Discovery)
-> (Notifications Const
    -> Const (Notifications Const) (Notifications Const))
-> GameState
-> Const (Notifications Const) GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Notifications Const
 -> Const (Notifications Const) (Notifications Const))
-> Discovery -> Const (Notifications Const) Discovery
Lens' Discovery (Notifications Const)
availableCommands
  let alertCommands :: Bool
alertCommands = Notifications Const
cs Notifications Const
-> Getting Bool (Notifications Const) Bool -> Bool
forall s a. s -> Getting a s a -> a
^. Getting Bool (Notifications Const) Bool
forall a (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> Notifications a -> f (Notifications a)
notificationsShouldAlert
  Bool -> EventM Name PlayState () -> EventM Name PlayState ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
alertCommands (EventM Name PlayState () -> EventM Name PlayState ())
-> EventM Name PlayState () -> EventM Name PlayState ()
forall a b. (a -> b) -> a -> b
$ do
    let newCommands :: [Const]
newCommands = Int -> [Const] -> [Const]
forall a. Int -> [a] -> [a]
take (Notifications Const
cs Notifications Const -> Getting Int (Notifications Const) Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int (Notifications Const) Int
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Notifications a -> f (Notifications a)
notificationsCount) (Notifications Const
cs Notifications Const
-> Getting [Const] (Notifications Const) [Const] -> [Const]
forall s a. s -> Getting a s a -> a
^. Getting [Const] (Notifications Const) [Const]
forall a1 a2 (f :: * -> *).
Functor f =>
([a1] -> f [a2]) -> Notifications a1 -> f (Notifications a2)
notificationsContent)
    (ProgressionState -> Identity ProgressionState)
-> PlayState -> Identity PlayState
Lens' PlayState ProgressionState
progression ((ProgressionState -> Identity ProgressionState)
 -> PlayState -> Identity PlayState)
-> ((PopupState -> Identity PopupState)
    -> ProgressionState -> Identity ProgressionState)
-> (PopupState -> Identity PopupState)
-> PlayState
-> Identity PlayState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PopupState -> Identity PopupState)
-> ProgressionState -> Identity ProgressionState
Lens' ProgressionState PopupState
uiPopups ((PopupState -> Identity PopupState)
 -> PlayState -> Identity PlayState)
-> (PopupState -> PopupState) -> EventM Name PlayState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= Popup -> PopupState -> PopupState
addPopup ([Const] -> Popup
CommandsPopup [Const]
newCommands)
    (ScenarioState -> Identity ScenarioState)
-> PlayState -> Identity PlayState
Lens' PlayState ScenarioState
scenarioState ((ScenarioState -> Identity ScenarioState)
 -> PlayState -> Identity PlayState)
-> ((Bool -> Identity Bool)
    -> ScenarioState -> Identity ScenarioState)
-> (Bool -> Identity Bool)
-> PlayState
-> Identity PlayState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GameState -> Identity GameState)
-> ScenarioState -> Identity ScenarioState
Lens' ScenarioState GameState
gameState ((GameState -> Identity GameState)
 -> ScenarioState -> Identity ScenarioState)
-> ((Bool -> Identity Bool) -> GameState -> Identity GameState)
-> (Bool -> Identity Bool)
-> ScenarioState
-> Identity ScenarioState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Discovery -> Identity Discovery)
-> GameState -> Identity GameState
Lens' GameState Discovery
discovery ((Discovery -> Identity Discovery)
 -> GameState -> Identity GameState)
-> ((Bool -> Identity Bool) -> Discovery -> Identity Discovery)
-> (Bool -> Identity Bool)
-> GameState
-> Identity GameState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Notifications Const -> Identity (Notifications Const))
-> Discovery -> Identity Discovery
Lens' Discovery (Notifications Const)
availableCommands ((Notifications Const -> Identity (Notifications Const))
 -> Discovery -> Identity Discovery)
-> ((Bool -> Identity Bool)
    -> Notifications Const -> Identity (Notifications Const))
-> (Bool -> Identity Bool)
-> Discovery
-> Identity Discovery
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Identity Bool)
-> Notifications Const -> Identity (Notifications Const)
forall a (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> Notifications a -> f (Notifications a)
notificationsShouldAlert ((Bool -> Identity Bool) -> PlayState -> Identity PlayState)
-> Bool -> EventM Name PlayState ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
False

  Bool -> EventM Name PlayState Bool
forall a. a -> EventM Name PlayState a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> EventM Name PlayState Bool)
-> Bool -> EventM Name PlayState Bool
forall a b. (a -> b) -> a -> b
$ Bool
newRecipes Bool -> Bool -> Bool
|| Bool
alertCommands

-- | Strips the top-level @Cmd@ from a type, if any (to compute the
--   result type of a REPL command evaluation).
stripCmd :: TDCtx -> Polytype -> Polytype
stripCmd :: TDCtx -> Polytype -> Polytype
stripCmd TDCtx
tdCtx = (Type -> Type) -> Polytype -> Polytype
forall a b. (a -> b) -> Poly 'Quantified a -> Poly 'Quantified b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Type -> Type) -> Polytype -> Polytype)
-> (Type -> Type) -> Polytype -> Polytype
forall a b. (a -> b) -> a -> b
$ \Type
ty -> case TDCtx -> Type -> Type
whnfType TDCtx
tdCtx Type
ty of
  TyCmd Type
resTy -> Type
resTy
  Type
_ -> Type
ty