{-# LANGUAGE OverloadedStrings #-}
module Swarm.TUI.View (
drawUI,
drawTPS,
drawDialog,
generateModal,
chooseCursor,
drawKeyMenu,
drawModalMenu,
drawKeyCmd,
drawWorld,
drawRobotPanel,
drawItem,
drawLabelledEntityName,
drawInfoPanel,
explainFocusedItem,
drawREPL,
) where
import Brick hiding (Direction, Location)
import Brick.Focus
import Brick.Forms
import Brick.Widgets.Border (hBorder, hBorderWithLabel, joinableBorder, vBorder)
import Brick.Widgets.Center (center, centerLayer, hCenter)
import Brick.Widgets.Dialog
import Brick.Widgets.Edit (getEditContents, renderEditor)
import Brick.Widgets.List qualified as BL
import Brick.Widgets.Table qualified as BT
import Control.Lens hiding (Const, from)
import Control.Monad (guard)
import Data.Array (range)
import Data.Bits (shiftL, shiftR, (.&.))
import Data.Foldable qualified as F
import Data.Functor (($>))
import Data.IntMap qualified as IM
import Data.List (intersperse)
import Data.List qualified as L
import Data.List.NonEmpty (NonEmpty (..))
import Data.List.NonEmpty qualified as NE
import Data.List.Split (chunksOf)
import Data.Map qualified as M
import Data.Maybe (catMaybes, fromMaybe, mapMaybe, maybeToList)
import Data.Semigroup (sconcat)
import Data.Sequence qualified as Seq
import Data.Set qualified as Set (toList)
import Data.Text (Text)
import Data.Text qualified as T
import Data.Time (NominalDiffTime, defaultTimeLocale, formatTime)
import Linear
import Linear.Affine (Point)
import Network.Wai.Handler.Warp (Port)
import Swarm.Game.CESK (CESK (..))
import Swarm.Game.Display
import Swarm.Game.Entity as E
import Swarm.Game.Recipe
import Swarm.Game.Robot
import Swarm.Game.Scenario (scenarioAuthor, scenarioDescription, scenarioName, scenarioObjectives)
import Swarm.Game.Scenario.Objective.Presentation.Model (goalsContent, hasAnythingToShow)
import Swarm.Game.Scenario.Objective.Presentation.Render qualified as GR
import Swarm.Game.ScenarioInfo (
ScenarioItem (..),
ScenarioStatus (..),
scenarioBestTicks,
scenarioBestTime,
scenarioItemName,
scenarioStatus,
)
import Swarm.Game.State
import Swarm.Game.World qualified as W
import Swarm.Language.Capability (constCaps)
import Swarm.Language.Pretty (prettyText)
import Swarm.Language.Syntax
import Swarm.Language.Typecheck (inferConst)
import Swarm.TUI.Attr
import Swarm.TUI.Border
import Swarm.TUI.Inventory.Sorting (renderSortMethod)
import Swarm.TUI.Model
import Swarm.TUI.Model.Repl
import Swarm.TUI.Model.UI
import Swarm.TUI.Panel
import Swarm.TUI.View.Achievement
import Swarm.TUI.View.CellDisplay
import Swarm.TUI.View.Util
import Swarm.Util
import Swarm.Util.Location
import Swarm.Version (NewReleaseFailure (..))
import System.Clock (TimeSpec (..))
import Text.Printf
import Text.Wrap
import Witch (from, into)
drawUI :: AppState -> [Widget Name]
drawUI :: AppState -> [Widget Name]
drawUI AppState
s
| AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Bool
uiPlaying = AppState -> [Widget Name]
drawGameUI AppState
s
| Bool
otherwise = case AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Menu
uiMenu of
Menu
NoMenu -> [AppState -> List Name MainMenuEntry -> Widget Name
drawMainMenuUI AppState
s (MainMenuEntry -> List Name MainMenuEntry
mainMenu MainMenuEntry
NewGame)]
MainMenu List Name MainMenuEntry
l -> [AppState -> List Name MainMenuEntry -> Widget Name
drawMainMenuUI AppState
s List Name MainMenuEntry
l]
NewGameMenu NonEmpty (List Name ScenarioItem)
stk -> [NonEmpty (List Name ScenarioItem) -> Widget Name
drawNewGameMenuUI NonEmpty (List Name ScenarioItem)
stk]
AchievementsMenu List Name CategorizedAchievement
l -> [AppState -> List Name CategorizedAchievement -> Widget Name
drawAchievementsMenuUI AppState
s List Name CategorizedAchievement
l]
Menu
MessagesMenu -> [AppState -> Widget Name
drawMainMessages AppState
s]
Menu
AboutMenu -> [Maybe Text -> Widget Name
drawAboutMenuUI (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (Map Text Text)
appData forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at Text
"about")]
drawMainMessages :: AppState -> Widget Name
drawMainMessages :: AppState -> Widget Name
drawMainMessages AppState
s = forall n a. Ord n => Dialog a n -> Widget n -> Widget n
renderDialog forall {a}. Dialog a Name
dial forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Padding -> Widget n -> Widget n
padBottom Padding
Max forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {n}. [Widget n] -> Widget n
scrollList forall a b. (a -> b) -> a -> b
$ forall {a}. [LogEntry] -> [Widget a]
drawLogs [LogEntry]
ls
where
ls :: [LogEntry]
ls = forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState RuntimeState
runtimeState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' RuntimeState (Notifications LogEntry)
eventLog forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a1 a2. Lens (Notifications a1) (Notifications a2) [a1] [a2]
notificationsContent
dial :: Dialog a Name
dial = forall n a.
Eq n =>
Maybe (Widget n)
-> Maybe (n, [(String, n, a)]) -> Count -> Dialog a n
dialog (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall n. String -> Widget n
str String
"Messages") forall a. Maybe a
Nothing Count
maxModalWindowWidth
scrollList :: [Widget n] -> Widget n
scrollList = forall n. VScrollBarOrientation -> Widget n -> Widget n
withVScrollBars VScrollBarOrientation
OnRight forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {n}. [Widget n] -> Widget n
vBox
drawLogs :: [LogEntry] -> [Widget a]
drawLogs = forall a b. (a -> b) -> [a] -> [b]
map (forall a. Bool -> LogEntry -> Widget a
drawLogEntry Bool
True)
drawMainMenuUI :: AppState -> BL.List Name MainMenuEntry -> Widget Name
drawMainMenuUI :: AppState -> List Name MainMenuEntry -> Widget Name
drawMainMenuUI AppState
s List Name MainMenuEntry
l =
forall {n}. [Widget n] -> Widget n
vBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [Maybe a] -> [a]
catMaybes forall a b. (a -> b) -> a -> b
$
[ Text -> Widget Name
drawLogo forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Text
logo
, forall n. Widget n -> Widget n
hCenter forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Count -> Widget n -> Widget n
padTopBottom Count
2 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall n. Either NewReleaseFailure String -> Maybe (Widget n)
newVersionWidget Either NewReleaseFailure String
version
, forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Widget n -> Widget n
centerLayer forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Count -> Widget n -> Widget n
vLimit Count
6 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Count -> Widget n -> Widget n
hLimit Count
20 forall a b. (a -> b) -> a -> b
$
forall (t :: * -> *) n e.
(Traversable t, Splittable t, Ord n, Show n) =>
(Bool -> e -> Widget n) -> Bool -> GenericList n t e -> Widget n
BL.renderList (forall a b. a -> b -> a
const (forall n. Widget n -> Widget n
hCenter forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppState -> MainMenuEntry -> Widget Name
drawMainMenuEntry AppState
s)) Bool
True List Name MainMenuEntry
l
]
where
logo :: Maybe Text
logo = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (Map Text Text)
appData forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at Text
"logo"
version :: Either NewReleaseFailure String
version = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState RuntimeState
runtimeState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' RuntimeState (Either NewReleaseFailure String)
upstreamRelease
newVersionWidget :: Either NewReleaseFailure String -> Maybe (Widget n)
newVersionWidget :: forall n. Either NewReleaseFailure String -> Maybe (Widget n)
newVersionWidget = \case
Right String
ver -> forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"New version " forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
ver forall a. Semigroup a => a -> a -> a
<> Text
" is available!"
Left (OnDevelopmentBranch String
_b) -> forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"Good luck developing!"
Left (FailedReleaseQuery String
_f) -> forall a. Maybe a
Nothing
Left (NoMainUpstreamRelease [String]
_fails) -> forall a. Maybe a
Nothing
Left (OldUpstreamRelease Version
_up Version
_my) -> forall a. Maybe a
Nothing
drawLogo :: Text -> Widget Name
drawLogo :: Text -> Widget Name
drawLogo = forall n. Widget n -> Widget n
centerLayer forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {n}. [Widget n] -> Widget n
vBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall {n}. [Widget n] -> Widget n
hBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (Char -> a -> a) -> a -> Text -> a
T.foldr (\Char
c [Widget Name]
ws -> Char -> Widget Name
drawThing Char
c forall a. a -> [a] -> [a]
: [Widget Name]
ws) []) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.lines
where
drawThing :: Char -> Widget Name
drawThing :: Char -> Widget Name
drawThing Char
c = forall n. AttrName -> Widget n -> Widget n
withAttr (Char -> AttrName
attrFor Char
c) forall a b. (a -> b) -> a -> b
$ forall n. String -> Widget n
str [Char
c]
attrFor :: Char -> AttrName
attrFor :: Char -> AttrName
attrFor Char
c
| Char
c forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (String
"<>v^" :: String) = AttrName
robotAttr
attrFor Char
'T' = AttrName
plantAttr
attrFor Char
'@' = AttrName
rockAttr
attrFor Char
'~' = AttrName
waterAttr
attrFor Char
'▒' = AttrName
dirtAttr
attrFor Char
_ = AttrName
defAttr
drawNewGameMenuUI :: NonEmpty (BL.List Name ScenarioItem) -> Widget Name
(List Name ScenarioItem
l :| [List Name ScenarioItem]
ls) =
forall n. Count -> Widget n -> Widget n
padLeftRight Count
20
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Widget n -> Widget n
centerLayer
forall a b. (a -> b) -> a -> b
$ forall {n}. [Widget n] -> Widget n
hBox
[ forall {n}. [Widget n] -> Widget n
vBox
[ forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
boldAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ [List Name ScenarioItem] -> Text
breadcrumbs [List Name ScenarioItem]
ls
, forall n. Text -> Widget n
txt Text
" "
, forall n. Count -> Widget n -> Widget n
vLimit Count
20
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Count -> Widget n -> Widget n
hLimit Count
35
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) n e.
(Traversable t, Splittable t, Ord n, Show n) =>
(Bool -> e -> Widget n) -> Bool -> GenericList n t e -> Widget n
BL.renderList (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall n. Padding -> Widget n -> Widget n
padRight Padding
Max forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {n}. ScenarioItem -> Widget n
drawScenarioItem) Bool
True
forall a b. (a -> b) -> a -> b
$ List Name ScenarioItem
l
]
, forall n. Padding -> Widget n -> Widget n
padLeft (Count -> Padding
Pad Count
5) (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall n. Text -> Widget n
txt Text
"") (ScenarioItem -> Widget Name
drawDescription forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) (forall (t :: * -> *) e n.
(Splittable t, Traversable t, Semigroup (t e)) =>
GenericList n t e -> Maybe (Count, e)
BL.listSelectedElement List Name ScenarioItem
l))
]
where
drawScenarioItem :: ScenarioItem -> Widget n
drawScenarioItem (SISingle (Scenario
s, ScenarioInfo
si)) = forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad Count
1) (forall {n}. Scenario -> ScenarioInfo -> Widget n
drawStatusInfo Scenario
s ScenarioInfo
si) forall n. Widget n -> Widget n -> Widget n
<+> forall n. Text -> Widget n
txt (Scenario
s forall s a. s -> Getting a s a -> a
^. Lens' Scenario Text
scenarioName)
drawScenarioItem (SICollection Text
nm ScenarioCollection
_) = forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad Count
1) (forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
boldAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
" > ") forall n. Widget n -> Widget n -> Widget n
<+> forall n. Text -> Widget n
txt Text
nm
drawStatusInfo :: Scenario -> ScenarioInfo -> Widget n
drawStatusInfo Scenario
s ScenarioInfo
si = case ScenarioInfo
si forall s a. s -> Getting a s a -> a
^. Lens' ScenarioInfo ScenarioStatus
scenarioBestTime of
ScenarioStatus
NotStarted -> forall n. Text -> Widget n
txt Text
" ○ "
InProgress {} -> case Scenario
s forall s a. s -> Getting a s a -> a
^. Lens' Scenario [Objective]
scenarioObjectives of
[] -> forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
cyanAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
" ◉ "
[Objective]
_ -> forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
yellowAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
" ◎ "
Complete {} -> forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
greenAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
" ● "
describeStatus :: ScenarioStatus -> Widget n
describeStatus = \case
ScenarioStatus
NotStarted -> forall n. Text -> Widget n
txt Text
"none"
InProgress ZonedTime
_s NominalDiffTime
e Integer
_t ->
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
yellowAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {n}. [Widget n] -> Widget n
vBox forall a b. (a -> b) -> a -> b
$
[ forall n. Text -> Widget n
txt Text
"in progress"
, forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"(played for " forall a. Semigroup a => a -> a -> a
<> NominalDiffTime -> Text
formatTimeDiff NominalDiffTime
e forall a. Semigroup a => a -> a -> a
<> Text
")"
]
Complete ZonedTime
_s NominalDiffTime
e Integer
t ->
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
greenAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {n}. [Widget n] -> Widget n
vBox forall a b. (a -> b) -> a -> b
$
[ forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"completed in " forall a. Semigroup a => a -> a -> a
<> NominalDiffTime -> Text
formatTimeDiff NominalDiffTime
e
, forall {n}. [Widget n] -> Widget n
hBox
[ forall n. Text -> Widget n
txt Text
"("
, forall n. Integer -> Bool -> Widget n
drawTime Integer
t Bool
True
, forall n. Text -> Widget n
txt Text
" ticks)"
]
]
formatTimeDiff :: NominalDiffTime -> Text
formatTimeDiff :: NominalDiffTime -> Text
formatTimeDiff = String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%hh %Mm %Ss"
breadcrumbs :: [BL.List Name ScenarioItem] -> Text
breadcrumbs :: [List Name ScenarioItem] -> Text
breadcrumbs =
Text -> [Text] -> Text
T.intercalate Text
" > "
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
"Scenarios" forall a. a -> [a] -> [a]
:)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ScenarioItem -> Text
scenarioItemName forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) e n.
(Splittable t, Traversable t, Semigroup (t e)) =>
GenericList n t e -> Maybe (Count, e)
BL.listSelectedElement)
drawDescription :: ScenarioItem -> Widget Name
drawDescription :: ScenarioItem -> Widget Name
drawDescription (SICollection Text
_ ScenarioCollection
_) = forall n. Text -> Widget n
txtWrap Text
" "
drawDescription (SISingle (Scenario
s, ScenarioInfo
si)) = do
let oneBest :: Bool
oneBest = ScenarioInfo
si forall s a. s -> Getting a s a -> a
^. Lens' ScenarioInfo ScenarioStatus
scenarioBestTime forall a. Eq a => a -> a -> Bool
== ScenarioInfo
si forall s a. s -> Getting a s a -> a
^. Lens' ScenarioInfo ScenarioStatus
scenarioBestTicks
let bestRealTime :: Text
bestRealTime = if Bool
oneBest then Text
"best:" else Text
"best real time:"
let noSame :: a -> Maybe a
noSame = if Bool
oneBest then forall a b. a -> b -> a
const forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just
let lastText :: Widget n
lastText = let la :: Text
la = Text
"last:" in forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad forall a b. (a -> b) -> a -> b
$ Text -> Count
T.length Text
bestRealTime forall a. Num a => a -> a -> a
- Text -> Count
T.length Text
la) (forall n. Text -> Widget n
txt Text
la)
forall {n}. [Widget n] -> Widget n
vBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [Maybe a] -> [a]
catMaybes forall a b. (a -> b) -> a -> b
$
[ forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txtWrap (forall {a}. (Eq a, IsString a) => a -> a
nonBlank (Scenario
s forall s a. s -> Getting a s a -> a
^. Lens' Scenario Text
scenarioDescription))
, forall n. Padding -> Widget n -> Widget n
padTop (Count -> Padding
Pad Count
1)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
dimAttr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall n. Text -> Widget n
txt Text
"Author: " forall n. Widget n -> Widget n -> Widget n
<+>)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Scenario
s forall s a. s -> Getting a s a -> a
^. Lens' Scenario (Maybe Text)
scenarioAuthor)
, forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$
forall n. Padding -> Widget n -> Widget n
padTop (Count -> Padding
Pad Count
3) forall a b. (a -> b) -> a -> b
$
forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad Count
1) (forall n. Text -> Widget n
txt Text
bestRealTime) forall n. Widget n -> Widget n -> Widget n
<+> forall {n}. ScenarioStatus -> Widget n
describeStatus (ScenarioInfo
si forall s a. s -> Getting a s a -> a
^. Lens' ScenarioInfo ScenarioStatus
scenarioBestTime)
, forall a. a -> Maybe a
noSame forall a b. (a -> b) -> a -> b
$
forall n. Padding -> Widget n -> Widget n
padTop (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$
forall n. Text -> Widget n
txt Text
"best game time: " forall n. Widget n -> Widget n -> Widget n
<+> forall {n}. ScenarioStatus -> Widget n
describeStatus (ScenarioInfo
si forall s a. s -> Getting a s a -> a
^. Lens' ScenarioInfo ScenarioStatus
scenarioBestTicks)
, forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$
forall n. Padding -> Widget n -> Widget n
padTop (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$
forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad Count
1) forall {n}. Widget n
lastText forall n. Widget n -> Widget n -> Widget n
<+> forall {n}. ScenarioStatus -> Widget n
describeStatus (ScenarioInfo
si forall s a. s -> Getting a s a -> a
^. Lens' ScenarioInfo ScenarioStatus
scenarioStatus)
]
nonBlank :: a -> a
nonBlank a
"" = a
" "
nonBlank a
t = a
t
drawMainMenuEntry :: AppState -> MainMenuEntry -> Widget Name
drawMainMenuEntry :: AppState -> MainMenuEntry -> Widget Name
drawMainMenuEntry AppState
s = \case
MainMenuEntry
NewGame -> forall n. Text -> Widget n
txt Text
"New game"
MainMenuEntry
Tutorial -> forall n. Text -> Widget n
txt Text
"Tutorial"
MainMenuEntry
Achievements -> forall n. Text -> Widget n
txt Text
"Achievements"
MainMenuEntry
About -> forall n. Text -> Widget n
txt Text
"About"
MainMenuEntry
Messages -> forall n. Widget n -> Widget n
highlightMessages forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
"Messages"
MainMenuEntry
Quit -> forall n. Text -> Widget n
txt Text
"Quit"
where
highlightMessages :: Widget n -> Widget n
highlightMessages =
if AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState RuntimeState
runtimeState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' RuntimeState (Notifications LogEntry)
eventLog forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Lens' (Notifications a) Count
notificationsCount forall a. Ord a => a -> a -> Bool
> Count
0
then forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
notifAttr
else forall a. a -> a
id
drawAboutMenuUI :: Maybe Text -> Widget Name
Maybe Text
Nothing = forall n. Widget n -> Widget n
centerLayer forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
"About swarm!"
drawAboutMenuUI (Just Text
t) = forall n. Widget n -> Widget n
centerLayer forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {n}. [Widget n] -> Widget n
vBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall n. Widget n -> Widget n
hCenter forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}. (Eq a, IsString a) => a -> a
nonblank) forall a b. (a -> b) -> a -> b
$ Text -> [Text]
T.lines Text
t
where
nonblank :: a -> a
nonblank a
"" = a
" "
nonblank a
s = a
s
drawGameUI :: AppState -> [Widget Name]
drawGameUI :: AppState -> [Widget Name]
drawGameUI AppState
s =
[ forall n. Widget n -> Widget n
joinBorders forall a b. (a -> b) -> a -> b
$ AppState -> Widget Name
drawDialog AppState
s
, forall n. Widget n -> Widget n
joinBorders forall a b. (a -> b) -> a -> b
$
forall {n}. [Widget n] -> Widget n
hBox
[ forall n. Count -> Widget n -> Widget n
hLimitPercent Count
25 forall a b. (a -> b) -> a -> b
$
forall {n}. [Widget n] -> Widget n
vBox
[ forall n. Count -> Widget n -> Widget n
vLimitPercent Count
50 forall a b. (a -> b) -> a -> b
$ forall n.
Eq n =>
AttrName
-> FocusRing n -> n -> BorderLabels n -> Widget n -> Widget n
panel AttrName
highlightAttr FocusRing Name
fr (FocusablePanel -> Name
FocusablePanel FocusablePanel
RobotPanel) forall n. BorderLabels n
plainBorder forall a b. (a -> b) -> a -> b
$ AppState -> Widget Name
drawRobotPanel AppState
s
, forall n.
Eq n =>
AttrName
-> FocusRing n -> n -> BorderLabels n -> Widget n -> Widget n
panel
AttrName
highlightAttr
FocusRing Name
fr
(FocusablePanel -> Name
FocusablePanel FocusablePanel
InfoPanel)
( forall n. BorderLabels n
plainBorder
forall a b. a -> (a -> b) -> b
& forall n. Lens' (BorderLabels n) (HBorderLabels n)
topLabels forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Lens' (HBorderLabels n) (Maybe (Widget n))
centerLabel
forall s t a b. ASetter s t a b -> b -> s -> t
.~ (if Bool
moreTop then forall a. a -> Maybe a
Just (forall n. Text -> Widget n
txt Text
" · · · ") else forall a. Maybe a
Nothing)
forall a b. a -> (a -> b) -> b
& forall n. Lens' (BorderLabels n) (HBorderLabels n)
bottomLabels forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Lens' (HBorderLabels n) (Maybe (Widget n))
centerLabel
forall s t a b. ASetter s t a b -> b -> s -> t
.~ (if Bool
moreBot then forall a. a -> Maybe a
Just (forall n. Text -> Widget n
txt Text
" · · · ") else forall a. Maybe a
Nothing)
)
forall a b. (a -> b) -> a -> b
$ AppState -> Widget Name
drawInfoPanel AppState
s
]
, forall {n}. [Widget n] -> Widget n
vBox
[ forall n.
Eq n =>
AttrName
-> FocusRing n -> n -> BorderLabels n -> Widget n -> Widget n
panel
AttrName
highlightAttr
FocusRing Name
fr
(FocusablePanel -> Name
FocusablePanel FocusablePanel
WorldPanel)
( forall n. BorderLabels n
plainBorder
forall a b. a -> (a -> b) -> b
& forall n. Lens' (BorderLabels n) (HBorderLabels n)
bottomLabels forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Lens' (HBorderLabels n) (Maybe (Widget n))
rightLabel forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ forall n. Count -> Widget n -> Widget n
padLeftRight Count
1 (AppState -> Widget Name
drawTPS AppState
s)
forall a b. a -> (a -> b) -> b
& forall n. Lens' (BorderLabels n) (HBorderLabels n)
topLabels forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Lens' (HBorderLabels n) (Maybe (Widget n))
leftLabel forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ AppState -> Widget Name
drawModalMenu AppState
s
forall a b. a -> (a -> b) -> b
& BorderLabels Name -> BorderLabels Name
addCursorPos
forall a b. a -> (a -> b) -> b
& forall {n}. BorderLabels n -> BorderLabels n
addClock
)
(Bool -> GameState -> Widget Name
drawWorld (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getter UIState Bool
uiShowRobots) (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState))
, AppState -> Widget Name
drawKeyMenu AppState
s
, forall n. Ord n => n -> Widget n -> Widget n
clickable (FocusablePanel -> Name
FocusablePanel FocusablePanel
REPLPanel) forall a b. (a -> b) -> a -> b
$
forall n.
Eq n =>
AttrName
-> FocusRing n -> n -> BorderLabels n -> Widget n -> Widget n
panel
AttrName
highlightAttr
FocusRing Name
fr
(FocusablePanel -> Name
FocusablePanel FocusablePanel
REPLPanel)
( forall n. BorderLabels n
plainBorder
forall a b. a -> (a -> b) -> b
& forall n. Lens' (BorderLabels n) (HBorderLabels n)
topLabels forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Lens' (HBorderLabels n) (Maybe (Widget n))
rightLabel forall s t a b. ASetter s t a b -> b -> s -> t
.~ (Polytype -> Widget Name
drawType forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState REPLState
uiREPL forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' REPLState (Maybe Polytype)
replType))
)
( forall n. Count -> Widget n -> Widget n
vLimit Count
replHeight
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Padding -> Widget n -> Widget n
padBottom Padding
Max
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Count -> Widget n -> Widget n
padLeftRight Count
1
forall a b. (a -> b) -> a -> b
$ AppState -> Widget Name
drawREPL AppState
s
)
]
]
]
where
addCursorPos :: BorderLabels Name -> BorderLabels Name
addCursorPos = case AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (Maybe Coords)
uiWorldCursor of
Maybe Coords
Nothing -> forall a. a -> a
id
Just Coords
coord ->
let worldCursorInfo :: Widget Name
worldCursorInfo = GameState -> Coords -> Widget Name
drawWorldCursorInfo (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState) Coords
coord
in forall n. Lens' (BorderLabels n) (HBorderLabels n)
bottomLabels forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Lens' (HBorderLabels n) (Maybe (Widget n))
leftLabel forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ forall n. Count -> Widget n -> Widget n
padLeftRight Count
1 Widget Name
worldCursorInfo
addClock :: BorderLabels n -> BorderLabels n
addClock = forall n. Lens' (BorderLabels n) (HBorderLabels n)
topLabels forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Lens' (HBorderLabels n) (Maybe (Widget n))
rightLabel forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ forall n. Count -> Widget n -> Widget n
padLeftRight Count
1 (forall n. GameState -> Widget n
drawClockDisplay forall a b. (a -> b) -> a -> b
$ AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState)
fr :: FocusRing Name
fr = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (FocusRing Name)
uiFocusRing
moreTop :: Bool
moreTop = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Bool
uiMoreInfoTop
moreBot :: Bool
moreBot = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Bool
uiMoreInfoBot
drawWorldCursorInfo :: GameState -> W.Coords -> Widget Name
drawWorldCursorInfo :: GameState -> Coords -> Widget Name
drawWorldCursorInfo GameState
g coords :: Coords
coords@(W.Coords (Int32
y, Int32
x)) =
forall {n}. [Widget n] -> Widget n
hBox forall a b. (a -> b) -> a -> b
$ forall {n}. [Widget n]
tileMemberWidgets forall a. [a] -> [a] -> [a]
++ [forall {n}. Widget n
coordsWidget]
where
coordsWidget :: Widget n
coordsWidget =
forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$
[Text] -> Text
T.unwords
[ forall source target. From source target => source -> target
from forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Int32
x
, forall source target. From source target => source -> target
from forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ Int32
y forall a. Num a => a -> a -> a
* (-Int32
1)
]
tileMembers :: [Display]
tileMembers = Display
terrain forall a. a -> [a] -> [a]
: forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe [Display] -> Maybe Display
merge [[Display]
entity, [Display]
robot]
tileMemberWidgets :: [Widget n]
tileMemberWidgets =
forall a b. (a -> b) -> [a] -> [b]
map (forall n. Padding -> Widget n -> Widget n
padRight forall a b. (a -> b) -> a -> b
$ Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall a b. (a -> b) -> a -> b
$
forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall {n}. Display -> Text -> [Widget n]
f [Display]
tileMembers [Text
"at", Text
"on", Text
"with"]
where
f :: Display -> Text -> [Widget n]
f Display
cell Text
preposition = [forall n. Display -> Widget n
renderDisplay Display
cell, forall n. Text -> Widget n
txt Text
preposition]
terrain :: Display
terrain = GameState -> Coords -> Display
displayTerrainCell GameState
g Coords
coords
entity :: [Display]
entity = GameState -> Coords -> [Display]
displayEntityCell GameState
g Coords
coords
robot :: [Display]
robot = GameState -> Coords -> [Display]
displayRobotCell GameState
g Coords
coords
merge :: [Display] -> Maybe Display
merge = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Semigroup a => NonEmpty a -> a
sconcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall s a. s -> Getting a s a -> a
^. Lens' Display Bool
invisible))
drawClockDisplay :: GameState -> Widget n
drawClockDisplay :: forall n. GameState -> Widget n
drawClockDisplay GameState
gs = forall {n}. [Widget n] -> Widget n
hBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> [a] -> [a]
intersperse (forall n. Text -> Widget n
txt Text
" ") forall a b. (a -> b) -> a -> b
$ forall a. [Maybe a] -> [a]
catMaybes [forall {n}. Maybe (Widget n)
clockWidget, forall {n}. Maybe (Widget n)
pauseWidget]
where
clockWidget :: Maybe (Widget n)
clockWidget = forall n. Integer -> Bool -> GameState -> Maybe (Widget n)
maybeDrawTime (GameState
gs forall s a. s -> Getting a s a -> a
^. Lens' GameState Integer
ticks) (GameState
gs forall s a. s -> Getting a s a -> a
^. Getter GameState Bool
paused) GameState
gs
pauseWidget :: Maybe (Widget n)
pauseWidget = forall (f :: * -> *). Alternative f => Bool -> f ()
guard (GameState
gs forall s a. s -> Getting a s a -> a
^. Getter GameState Bool
paused) forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> forall n. Text -> Widget n
txt Text
"(PAUSED)"
clockEquipped :: GameState -> Bool
clockEquipped :: GameState -> Bool
clockEquipped GameState
gs = case GameState -> Maybe Robot
focusedRobot GameState
gs of
Maybe Robot
Nothing -> Bool
False
Just Robot
r
| Text -> Inventory -> Count
countByName Text
"clock" (Robot
r forall s a. s -> Getting a s a -> a
^. Lens' Robot Inventory
equippedDevices) forall a. Ord a => a -> a -> Bool
> Count
0 -> Bool
True
| Bool
otherwise -> Bool
False
drawTime :: Integer -> Bool -> Widget n
drawTime :: forall n. Integer -> Bool -> Widget n
drawTime Integer
t Bool
showTicks =
forall n. String -> Widget n
str forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Monoid a => [a] -> a
mconcat forall a b. (a -> b) -> a -> b
$
[ forall r. PrintfType r => String -> r
printf String
"%x" (Integer
t forall a. Bits a => a -> Count -> a
`shiftR` Count
20)
, String
":"
, forall r. PrintfType r => String -> r
printf String
"%02x" ((Integer
t forall a. Bits a => a -> Count -> a
`shiftR` Count
12) forall a. Bits a => a -> a -> a
.&. ((Integer
1 forall a. Bits a => a -> Count -> a
`shiftL` Count
8) forall a. Num a => a -> a -> a
- Integer
1))
, String
":"
, forall r. PrintfType r => String -> r
printf String
"%02x" ((Integer
t forall a. Bits a => a -> Count -> a
`shiftR` Count
4) forall a. Bits a => a -> a -> a
.&. ((Integer
1 forall a. Bits a => a -> Count -> a
`shiftL` Count
8) forall a. Num a => a -> a -> a
- Integer
1))
]
forall a. [a] -> [a] -> [a]
++ if Bool
showTicks then [String
".", forall r. PrintfType r => String -> r
printf String
"%x" (Integer
t forall a. Bits a => a -> a -> a
.&. ((Integer
1 forall a. Bits a => a -> Count -> a
`shiftL` Count
4) forall a. Num a => a -> a -> a
- Integer
1))] else []
maybeDrawTime :: Integer -> Bool -> GameState -> Maybe (Widget n)
maybeDrawTime :: forall n. Integer -> Bool -> GameState -> Maybe (Widget n)
maybeDrawTime Integer
t Bool
showTicks GameState
gs = forall (f :: * -> *). Alternative f => Bool -> f ()
guard (GameState -> Bool
clockEquipped GameState
gs) forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> forall n. Integer -> Bool -> Widget n
drawTime Integer
t Bool
showTicks
drawTPS :: AppState -> Widget Name
drawTPS :: AppState -> Widget Name
drawTPS AppState
s = forall {n}. [Widget n] -> Widget n
hBox (forall {n}. Widget n
tpsInfo forall a. a -> [a] -> [a]
: forall {n}. [Widget n]
rateInfo)
where
tpsInfo :: Widget n
tpsInfo
| Count
l forall a. Ord a => a -> a -> Bool
>= Count
0 = forall {n}. [Widget n] -> Widget n
hBox [forall n. String -> Widget n
str (forall a. Show a => a -> String
show Count
n), forall n. Text -> Widget n
txt Text
" ", forall n. Text -> Widget n
txt (Count -> Text -> Text
number Count
n Text
"tick"), forall n. Text -> Widget n
txt Text
" / s"]
| Bool
otherwise = forall {n}. [Widget n] -> Widget n
hBox [forall n. Text -> Widget n
txt Text
"1 tick / ", forall n. String -> Widget n
str (forall a. Show a => a -> String
show Count
n), forall n. Text -> Widget n
txt Text
" s"]
rateInfo :: [Widget n]
rateInfo
| AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Bool
uiShowFPS =
[ forall n. Text -> Widget n
txt Text
" ("
, forall n. String -> Widget n
str (forall r. PrintfType r => String -> r
printf String
"%0.1f" (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Double
uiTPF))
, forall n. Text -> Widget n
txt Text
" tpf, "
, forall n. String -> Widget n
str (forall r. PrintfType r => String -> r
printf String
"%0.1f" (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Double
uiFPS))
, forall n. Text -> Widget n
txt Text
" fps)"
]
| Bool
otherwise = []
l :: Count
l = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Count
lgTicksPerSecond
n :: Count
n = Count
2 forall a b. (Num a, Integral b) => a -> b -> a
^ forall a. Num a => a -> a
abs Count
l
replHeight :: Int
replHeight :: Count
replHeight = Count
10
chooseCursor :: AppState -> [CursorLocation n] -> Maybe (CursorLocation n)
chooseCursor :: forall n.
AppState -> [CursorLocation n] -> Maybe (CursorLocation n)
chooseCursor AppState
s [CursorLocation n]
locs = case AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (Maybe Modal)
uiModal of
Maybe Modal
Nothing -> forall s n. s -> [CursorLocation n] -> Maybe (CursorLocation n)
showFirstCursor AppState
s [CursorLocation n]
locs
Just Modal
_ -> forall a. Maybe a
Nothing
renderErrorDialog :: Text -> Widget Name
renderErrorDialog :: Text -> Widget Name
renderErrorDialog Text
err = forall n a. Ord n => Dialog a n -> Widget n -> Widget n
renderDialog (forall n a.
Eq n =>
Maybe (Widget n)
-> Maybe (n, [(String, n, a)]) -> Count -> Dialog a n
dialog (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall n. String -> Widget n
str String
"Error") forall a. Maybe a
Nothing (Count
maxModalWindowWidth forall a. Ord a => a -> a -> a
`min` Count
requiredWidth)) forall {n}. Widget n
errContent
where
errContent :: Widget n
errContent = forall n. WrapSettings -> Text -> Widget n
txtWrapWith WrapSettings
indent2 {preserveIndentation :: Bool
preserveIndentation = Bool
True} Text
err
requiredWidth :: Count
requiredWidth = Count
2 forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (forall a. TextWidth a => a -> Count
textWidth forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> [Text]
T.lines Text
err)
drawDialog :: AppState -> Widget Name
drawDialog :: AppState -> Widget Name
drawDialog AppState
s = case AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (Maybe Modal)
uiModal of
Just (Modal ModalType
mt Dialog ButtonAction Name
d) -> forall n a. Ord n => Dialog a n -> Widget n -> Widget n
renderDialog Dialog ButtonAction Name
d forall a b. (a -> b) -> a -> b
$ case ModalType
mt of
ModalType
GoalModal -> AppState -> ModalType -> Widget Name
drawModal AppState
s ModalType
mt
ModalType
_ -> forall n. (Ord n, Show n) => n -> Widget n -> Widget n
maybeScroll Name
ModalViewport forall a b. (a -> b) -> a -> b
$ AppState -> ModalType -> Widget Name
drawModal AppState
s ModalType
mt
Maybe Modal
Nothing -> forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall {n}. Widget n
emptyWidget Text -> Widget Name
renderErrorDialog (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (Maybe Text)
uiError)
drawModal :: AppState -> ModalType -> Widget Name
drawModal :: AppState -> ModalType -> Widget Name
drawModal AppState
s = \case
ModalType
HelpModal -> Count -> Maybe Count -> Widget Name
helpWidget (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' GameState Count
seed) (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState RuntimeState
runtimeState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' RuntimeState (Maybe Count)
webPort)
ModalType
RobotsModal -> AppState -> Widget Name
robotsListWidget AppState
s
ModalType
RecipesModal -> GameState -> NotificationList -> Widget Name
availableListWidget (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState) NotificationList
RecipeList
ModalType
CommandsModal -> GameState -> Widget Name
commandsListWidget (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState)
ModalType
MessagesModal -> GameState -> NotificationList -> Widget Name
availableListWidget (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState) NotificationList
MessageList
ModalType
WinModal -> forall n. Padding -> Widget n -> Widget n
padBottom (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$ forall n. Widget n -> Widget n
hCenter forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
"Congratulations!"
ModalType
LoseModal ->
forall n. Padding -> Widget n -> Widget n
padBottom (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$
forall {n}. [Widget n] -> Widget n
vBox forall a b. (a -> b) -> a -> b
$
forall a b. (a -> b) -> [a] -> [b]
map
(forall n. Widget n -> Widget n
hCenter forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt)
[ Text
"Condolences!"
, Text
"This scenario is no longer winnable."
]
DescriptionModal Entity
e -> AppState -> Entity -> Widget Name
descriptionWidget AppState
s Entity
e
ModalType
QuitModal -> forall n. Padding -> Widget n -> Widget n
padBottom (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$ forall n. Widget n -> Widget n
hCenter forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt (Menu -> Text
quitMsg (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Menu
uiMenu))
ModalType
GoalModal -> GoalDisplay -> Widget Name
GR.renderGoalsDisplay (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState GoalDisplay
uiGoal)
ModalType
KeepPlayingModal -> forall n. Count -> Widget n -> Widget n
padLeftRight Count
1 ([Text] -> Widget Name
displayParagraphs [Text
"Have fun! Hit Ctrl-Q whenever you're ready to proceed to the next challenge or return to the menu."])
robotsListWidget :: AppState -> Widget Name
robotsListWidget :: AppState -> Widget Name
robotsListWidget AppState
s = forall n. Widget n -> Widget n
hCenter Widget Name
table
where
table :: Widget Name
table =
forall n. Table n -> Widget n
BT.renderTable
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Bool -> Table n -> Table n
BT.columnBorders Bool
False
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. ColumnAlignment -> Table n -> Table n
BT.setDefaultColAlignment ColumnAlignment
BT.AlignCenter
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Count -> Table n -> Table n
BT.alignRight Count
4
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. [[Widget n]] -> Table n
BT.table
forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall n. Count -> Widget n -> Widget n
padLeftRight Count
1) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall {n}. [Widget n]
headers forall a. a -> [a] -> [a]
: [[Widget Name]]
robotsTable)
headers :: [Widget n]
headers =
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
robotAttr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ forall n. Text -> Widget n
txt Text
"Name"
, forall n. Text -> Widget n
txt Text
"Age"
, forall n. Text -> Widget n
txt Text
"Position"
, forall n. Text -> Widget n
txt Text
"Inventory"
, forall n. Text -> Widget n
txt Text
"Status"
, forall n. Text -> Widget n
txt Text
"Log"
]
robotsTable :: [[Widget Name]]
robotsTable = Robot -> [Widget Name]
mkRobotRow forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Robot]
robots
mkRobotRow :: Robot -> [Widget Name]
mkRobotRow Robot
robot =
[ forall {n}. Widget n
nameWidget
, forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ forall source target. From source target => source -> target
from String
ageStr
, Widget Name
locWidget
, forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad Count
1) (forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ forall source target. From source target => source -> target
from forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Count
rInvCount)
, forall {n}. Widget n
statusWidget
, forall n. Text -> Widget n
txt Text
rLog
]
where
nameWidget :: Widget n
nameWidget = forall {n}. [Widget n] -> Widget n
hBox [forall n. Display -> Widget n
renderDisplay (Robot
robot forall s a. s -> Getting a s a -> a
^. Lens' Robot Display
robotDisplay), forall n. Widget n -> Widget n
higlightSystem forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
" " forall a. Semigroup a => a -> a -> a
<> Robot
robot forall s a. s -> Getting a s a -> a
^. Lens' Robot Text
robotName]
higlightSystem :: Widget n -> Widget n
higlightSystem = if Robot
robot forall s a. s -> Getting a s a -> a
^. Lens' Robot Bool
systemRobot then forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
highlightAttr else forall a. a -> a
id
ageStr :: String
ageStr
| Int64
age forall a. Ord a => a -> a -> Bool
< Int64
60 = forall a. Show a => a -> String
show Int64
age forall a. Semigroup a => a -> a -> a
<> String
"sec"
| Int64
age forall a. Ord a => a -> a -> Bool
< Int64
3600 = forall a. Show a => a -> String
show (Int64
age forall a. Integral a => a -> a -> a
`div` Int64
60) forall a. Semigroup a => a -> a -> a
<> String
"min"
| Int64
age forall a. Ord a => a -> a -> Bool
< Int64
3600 forall a. Num a => a -> a -> a
* Int64
24 = forall a. Show a => a -> String
show (Int64
age forall a. Integral a => a -> a -> a
`div` Int64
3600) forall a. Semigroup a => a -> a -> a
<> String
"hour"
| Bool
otherwise = forall a. Show a => a -> String
show (Int64
age forall a. Integral a => a -> a -> a
`div` Int64
3600 forall a. Num a => a -> a -> a
* Int64
24) forall a. Semigroup a => a -> a -> a
<> String
"day"
where
TimeSpec Int64
createdAtSec Int64
_ = Robot
robot forall s a. s -> Getting a s a -> a
^. Lens' Robot TimeSpec
robotCreatedAt
TimeSpec Int64
nowSec Int64
_ = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState TimeSpec
lastFrameTime
age :: Int64
age = Int64
nowSec forall a. Num a => a -> a -> a
- Int64
createdAtSec
rInvCount :: Count
rInvCount = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. Inventory -> [(Count, Entity)]
E.elems forall a b. (a -> b) -> a -> b
$ Robot
robot forall s a. s -> Getting a s a -> a
^. forall (phase :: RobotPhase). Lens' (RobotR phase) Entity
robotEntity forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' Entity Inventory
entityInventory
rLog :: Text
rLog
| Robot
robot forall s a. s -> Getting a s a -> a
^. Lens' Robot Bool
robotLogUpdated = Text
"x"
| Bool
otherwise = Text
" "
locWidget :: Widget Name
locWidget = forall {n}. [Widget n] -> Widget n
hBox [Widget Name
worldCell, forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
" " forall a. Semigroup a => a -> a -> a
<> Text
locStr]
where
rloc :: Point V2 Int32
rloc@(Location Int32
x Int32
y) = Robot
robot forall s a. s -> Getting a s a -> a
^. Getter Robot (Point V2 Int32)
robotLocation
worldCell :: Widget Name
worldCell = Bool -> GameState -> Coords -> Widget Name
drawLoc (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getter UIState Bool
uiShowRobots) GameState
g (Point V2 Int32 -> Coords
W.locToCoords Point V2 Int32
rloc)
locStr :: Text
locStr = forall source target. From source target => source -> target
from (forall a. Show a => a -> String
show Int32
x) forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<> forall source target. From source target => source -> target
from (forall a. Show a => a -> String
show Int32
y)
statusWidget :: Widget n
statusWidget = case Robot
robot forall s a. s -> Getting a s a -> a
^. Lens' Robot CESK
machine of
Waiting {} -> forall n. Text -> Widget n
txt Text
"waiting"
CESK
_
| Robot -> Bool
isActive Robot
robot -> forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
notifAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
"busy"
| Bool
otherwise -> forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
greenAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
"idle"
basePos :: Point V2 Double
basePos :: Point V2 Double
basePos = forall a b. (Real a, Fractional b) => a -> b
realToFrac forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. a -> Maybe a -> a
fromMaybe forall (f :: * -> *) a. (Additive f, Num a) => Point f a
origin (GameState
g forall s a. s -> Getting (First a) s a -> Maybe a
^? Traversal' GameState Robot
baseRobot forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getter Robot (Point V2 Int32)
robotLocation)
isRelevant :: Robot -> Bool
isRelevant Robot
robot = Robot
robot forall s a. s -> Getting a s a -> a
^. Getter Robot Count
robotID forall a. Eq a => a -> a -> Bool
== Count
0 Bool -> Bool -> Bool
|| Bool -> Bool
not (Robot
robot forall s a. s -> Getting a s a -> a
^. Lens' Robot Bool
systemRobot)
isNear :: Robot -> Bool
isNear Robot
robot = Bool
creative Bool -> Bool -> Bool
|| forall (f :: * -> *) a. (Metric f, Floating a) => f a -> f a -> a
distance (forall a b. (Real a, Fractional b) => a -> b
realToFrac forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Robot
robot forall s a. s -> Getting a s a -> a
^. Getter Robot (Point V2 Int32)
robotLocation) Point V2 Double
basePos forall a. Ord a => a -> a -> Bool
< Double
32
robots :: [Robot]
robots :: [Robot]
robots =
forall a. (a -> Bool) -> [a] -> [a]
filter (\Robot
robot -> Bool
debugging Bool -> Bool -> Bool
|| (Robot -> Bool
isRelevant Robot
robot Bool -> Bool -> Bool
&& Robot -> Bool
isNear Robot
robot))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IntMap a -> [a]
IM.elems
forall a b. (a -> b) -> a -> b
$ GameState
g forall s a. s -> Getting a s a -> a
^. Lens' GameState (IntMap Robot)
robotMap
creative :: Bool
creative = GameState
g forall s a. s -> Getting a s a -> a
^. Lens' GameState Bool
creativeMode
cheat :: Bool
cheat = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Bool
uiCheatMode
debugging :: Bool
debugging = Bool
creative Bool -> Bool -> Bool
&& Bool
cheat
g :: GameState
g = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState
helpWidget :: Seed -> Maybe Port -> Widget Name
helpWidget :: Count -> Maybe Count -> Widget Name
helpWidget Count
theSeed Maybe Count
mport =
forall n. Padding -> Widget n -> Widget n
padTop (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$
(forall {n}. [Widget n] -> Widget n
hBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall n. Count -> Widget n -> Widget n
padLeftRight Count
2) forall a b. (a -> b) -> a -> b
$ [forall {n}. Widget n
helpKeys, forall {n}. Widget n
info])
forall n. Widget n -> Widget n -> Widget n
<=> forall n. Padding -> Widget n -> Widget n
padTop (Count -> Padding
Pad Count
1) (forall n. Widget n -> Widget n
hCenter forall {n}. Widget n
tips)
where
tips :: Widget n
tips =
forall {n}. [Widget n] -> Widget n
vBox
[ forall n. Text -> Widget n
txt Text
"Have questions? Want some tips? Check out:"
, forall n. Text -> Widget n
txt Text
" "
, forall n. Text -> Widget n
txt Text
" - The Swarm wiki, https://github.com/swarm-game/swarm/wiki"
, forall n. Text -> Widget n
txt Text
" - The #swarm IRC channel on Libera.Chat"
]
info :: Widget n
info =
forall {n}. [Widget n] -> Widget n
vBox
[ forall n. Text -> Widget n
txt Text
"Configuration"
, forall n. Text -> Widget n
txt Text
" "
, forall n. Text -> Widget n
txt (Text
"Seed: " forall a. Semigroup a => a -> a -> a
<> forall target source. From source target => source -> target
into @Text (forall a. Show a => a -> String
show Count
theSeed))
, forall n. Text -> Widget n
txt (Text
"Web server port: " forall a. Semigroup a => a -> a -> a
<> forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"none" (forall target source. From source target => source -> target
into @Text forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show) Maybe Count
mport)
]
helpKeys :: Widget n
helpKeys =
forall {n}. [Widget n] -> Widget n
vBox
[ forall n. Text -> Widget n
txt Text
"Keybindings"
, forall n. Text -> Widget n
txt Text
" "
, forall {n}. [(Text, Text)] -> Widget n
mkTable [(Text, Text)]
glKeyBindings
]
mkTable :: [(Text, Text)] -> Widget n
mkTable =
forall n. Table n -> Widget n
BT.renderTable
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Bool -> Table n -> Table n
BT.surroundingBorder Bool
False
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Bool -> Table n -> Table n
BT.rowBorders Bool
False
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. [[Widget n]] -> Table n
BT.table
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall {n}. (Text, Text) -> [Widget n]
toRow
toRow :: (Text, Text) -> [Widget n]
toRow (Text
k, Text
v) = [forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
k, forall n. Padding -> Widget n -> Widget n
padLeft (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
v]
glKeyBindings :: [(Text, Text)]
glKeyBindings =
[ (Text
"F1", Text
"Help")
, (Text
"F2", Text
"Robots list")
, (Text
"F3", Text
"Available recipes")
, (Text
"F4", Text
"Available commands")
, (Text
"F5", Text
"Messages")
, (Text
"Ctrl-g", Text
"show goal")
, (Text
"Ctrl-p", Text
"pause")
, (Text
"Ctrl-o", Text
"single step")
, (Text
"Ctrl-z", Text
"decrease speed")
, (Text
"Ctrl-w", Text
"increase speed")
, (Text
"Ctrl-q", Text
"quit the current scenario")
, (Text
"Meta-h", Text
"hide robots for 2s")
, (Text
"Meta-w", Text
"focus on the world map")
, (Text
"Meta-e", Text
"focus on the robot inventory")
, (Text
"Meta-r", Text
"focus on the REPL")
, (Text
"Meta-t", Text
"focus on the info panel")
]
data NotificationList = RecipeList | MessageList
availableListWidget :: GameState -> NotificationList -> Widget Name
availableListWidget :: GameState -> NotificationList -> Widget Name
availableListWidget GameState
gs NotificationList
nl = forall n. Padding -> Widget n -> Widget n
padTop (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$ forall {n}. [Widget n] -> Widget n
vBox [Widget Name]
widgetList
where
widgetList :: [Widget Name]
widgetList = case NotificationList
nl of
NotificationList
RecipeList -> forall a.
GameState
-> Lens' GameState (Notifications a)
-> (a -> Widget Name)
-> [Widget Name]
mkAvailableList GameState
gs Lens' GameState (Notifications (Recipe Entity))
availableRecipes Recipe Entity -> Widget Name
renderRecipe
NotificationList
MessageList -> GameState -> [Widget Name]
messagesWidget GameState
gs
renderRecipe :: Recipe Entity -> Widget Name
renderRecipe = forall n. Count -> Widget n -> Widget n
padLeftRight Count
18 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Entity -> Inventory -> Recipe Entity -> Widget Name
drawRecipe forall a. Maybe a
Nothing (forall a. a -> Maybe a -> a
fromMaybe Inventory
E.empty Maybe Inventory
inv)
inv :: Maybe Inventory
inv = GameState
gs forall s a. s -> Getting (First a) s a -> Maybe a
^? forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to GameState -> Maybe Robot
focusedRobot forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Prism (Maybe a) (Maybe b) a b
_Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' Robot Inventory
robotInventory
mkAvailableList :: GameState -> Lens' GameState (Notifications a) -> (a -> Widget Name) -> [Widget Name]
mkAvailableList :: forall a.
GameState
-> Lens' GameState (Notifications a)
-> (a -> Widget Name)
-> [Widget Name]
mkAvailableList GameState
gs Lens' GameState (Notifications a)
notifLens a -> Widget Name
notifRender = forall a b. (a -> b) -> [a] -> [b]
map a -> Widget Name
padRender [a]
news forall a. Semigroup a => a -> a -> a
<> forall {n}. [Widget n]
notifSep forall a. Semigroup a => a -> a -> a
<> forall a b. (a -> b) -> [a] -> [b]
map a -> Widget Name
padRender [a]
knowns
where
padRender :: a -> Widget Name
padRender = forall n. Padding -> Widget n -> Widget n
padBottom (Count -> Padding
Pad Count
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Widget Name
notifRender
count :: Count
count = GameState
gs forall s a. s -> Getting a s a -> a
^. Lens' GameState (Notifications a)
notifLens forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Lens' (Notifications a) Count
notificationsCount
([a]
news, [a]
knowns) = forall a. Count -> [a] -> ([a], [a])
splitAt Count
count (GameState
gs forall s a. s -> Getting a s a -> a
^. Lens' GameState (Notifications a)
notifLens forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a1 a2. Lens (Notifications a1) (Notifications a2) [a1] [a2]
notificationsContent)
notifSep :: [Widget n]
notifSep
| Count
count forall a. Ord a => a -> a -> Bool
> Count
0 Bool -> Bool -> Bool
&& Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [a]
knowns) =
[ forall n. Padding -> Widget n -> Widget n
padBottom (Count -> Padding
Pad Count
1) (forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
redAttr forall a b. (a -> b) -> a -> b
$ forall n. Widget n -> Widget n
hBorderWithLabel (forall n. Count -> Widget n -> Widget n
padLeftRight Count
1 (forall n. Text -> Widget n
txt Text
"new↑")))
]
| Bool
otherwise = []
commandsListWidget :: GameState -> Widget Name
commandsListWidget :: GameState -> Widget Name
commandsListWidget GameState
gs =
forall n. Widget n -> Widget n
hCenter forall a b. (a -> b) -> a -> b
$
forall {n}. [Widget n] -> Widget n
vBox
[ Widget Name
table
, forall n. Padding -> Widget n -> Widget n
padTop (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
"For the full list of available commands see the Wiki at:"
, forall n. Text -> Widget n
txt Text
"https://github.com/swarm-game/swarm/wiki/Commands-Cheat-Sheet"
]
where
commands :: [Const]
commands = GameState
gs forall s a. s -> Getting a s a -> a
^. Lens' GameState (Notifications Const)
availableCommands forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a1 a2. Lens (Notifications a1) (Notifications a2) [a1] [a2]
notificationsContent
table :: Widget Name
table =
forall n. Table n -> Widget n
BT.renderTable
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Bool -> Table n -> Table n
BT.surroundingBorder Bool
False
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Bool -> Table n -> Table n
BT.columnBorders Bool
False
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Bool -> Table n -> Table n
BT.rowBorders Bool
False
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. ColumnAlignment -> Table n -> Table n
BT.setDefaultColAlignment ColumnAlignment
BT.AlignLeft
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Count -> Table n -> Table n
BT.alignRight Count
0
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. [[Widget n]] -> Table n
BT.table
forall a b. (a -> b) -> a -> b
$ forall {n}. [Widget n]
headers forall a. a -> [a] -> [a]
: [[Widget Name]]
commandsTable
headers :: [Widget n]
headers =
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
robotAttr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ forall n. Text -> Widget n
txt Text
"command name"
, forall n. Text -> Widget n
txt Text
" : type"
, forall n. Text -> Widget n
txt Text
"Enabled by"
]
commandsTable :: [[Widget Name]]
commandsTable = Const -> [Widget Name]
mkCmdRow forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Const]
commands
mkCmdRow :: Const -> [Widget Name]
mkCmdRow Const
cmd =
forall a b. (a -> b) -> [a] -> [b]
map
(forall n. Padding -> Widget n -> Widget n
padTop forall a b. (a -> b) -> a -> b
$ Count -> Padding
Pad Count
1)
[ forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ ConstInfo -> Text
syntax forall a b. (a -> b) -> a -> b
$ Const -> ConstInfo
constInfo Const
cmd
, forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad Count
2) forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
" : " forall a. Semigroup a => a -> a -> a
<> forall a. PrettyPrec a => a -> Text
prettyText (Const -> Polytype
inferConst Const
cmd)
, Const -> Widget Name
listDevices Const
cmd
]
base :: Maybe Robot
base = GameState
gs forall s a. s -> Getting (First a) s a -> Maybe a
^? Traversal' GameState Robot
baseRobot
entsByCap :: Map Capability [Entity]
entsByCap = case Maybe Robot
base of
Just Robot
r ->
forall a b k. (a -> b) -> Map k a -> Map k b
M.map forall a. NonEmpty a -> [a]
NE.toList forall a b. (a -> b) -> a -> b
$
Inventory -> Map Capability (NonEmpty Entity)
entitiesByCapability forall a b. (a -> b) -> a -> b
$
(Robot
r forall s a. s -> Getting a s a -> a
^. Lens' Robot Inventory
equippedDevices) Inventory -> Inventory -> Inventory
`union` (Robot
r forall s a. s -> Getting a s a -> a
^. Lens' Robot Inventory
robotInventory)
Maybe Robot
Nothing -> forall a. Monoid a => a
mempty
listDevices :: Const -> Widget Name
listDevices Const
cmd = forall {n}. [Widget n] -> Widget n
vBox forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Entity -> Widget Name
drawLabelledEntityName [Entity]
providerDevices
where
providerDevices :: [Entity]
providerDevices =
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault []) Map Capability [Entity]
entsByCap) forall a b. (a -> b) -> a -> b
$
forall a. Maybe a -> [a]
maybeToList forall a b. (a -> b) -> a -> b
$
Const -> Maybe Capability
constCaps Const
cmd
descriptionWidget :: AppState -> Entity -> Widget Name
descriptionWidget :: AppState -> Entity -> Widget Name
descriptionWidget AppState
s Entity
e = forall n. Count -> Widget n -> Widget n
padLeftRight Count
1 (AppState -> Entity -> Widget Name
explainEntry AppState
s Entity
e)
messagesWidget :: GameState -> [Widget Name]
messagesWidget :: GameState -> [Widget Name]
messagesWidget GameState
gs = [Widget Name]
widgetList
where
widgetList :: [Widget Name]
widgetList = [Widget Name] -> [Widget Name]
focusNewest forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall {n}. LogEntry -> Widget n
drawLogEntry' forall a b. (a -> b) -> a -> b
$ GameState
gs forall s a. s -> Getting a s a -> a
^. Getter GameState (Notifications LogEntry)
messageNotifications forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a1 a2. Lens (Notifications a1) (Notifications a2) [a1] [a2]
notificationsContent
focusNewest :: [Widget Name] -> [Widget Name]
focusNewest = if GameState
gs forall s a. s -> Getting a s a -> a
^. Getter GameState Bool
paused then forall a. a -> a
id else forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over forall s a. Snoc s s a a => Traversal' s a
_last forall n. Widget n -> Widget n
visible
drawLogEntry' :: LogEntry -> Widget n
drawLogEntry' LogEntry
e =
forall n. AttrName -> Widget n -> Widget n
withAttr (LogEntry -> AttrName
colorLogs LogEntry
e) forall a b. (a -> b) -> a -> b
$
forall {n}. [Widget n] -> Widget n
hBox
[ forall a. a -> Maybe a -> a
fromMaybe (forall n. Text -> Widget n
txt Text
"") forall a b. (a -> b) -> a -> b
$ forall n. Integer -> Bool -> GameState -> Maybe (Widget n)
maybeDrawTime (LogEntry
e forall s a. s -> Getting a s a -> a
^. Lens' LogEntry Integer
leTime) Bool
True GameState
gs
, forall n. Padding -> Widget n -> Widget n
padLeft (Count -> Padding
Pad Count
2) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"[" forall a. Semigroup a => a -> a -> a
<> LogEntry
e forall s a. s -> Getting a s a -> a
^. Lens' LogEntry Text
leRobotName forall a. Semigroup a => a -> a -> a
<> Text
"]"
, forall n. Padding -> Widget n -> Widget n
padLeft (Count -> Padding
Pad Count
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt2 forall a b. (a -> b) -> a -> b
$ LogEntry
e forall s a. s -> Getting a s a -> a
^. Lens' LogEntry Text
leText
]
txt2 :: Text -> Widget n
txt2 = forall n. WrapSettings -> Text -> Widget n
txtWrapWith WrapSettings
indent2
colorLogs :: LogEntry -> AttrName
colorLogs :: LogEntry -> AttrName
colorLogs LogEntry
e = case LogEntry
e forall s a. s -> Getting a s a -> a
^. Lens' LogEntry LogSource
leSource of
LogSource
Said -> Count -> AttrName
robotColor (LogEntry
e forall s a. s -> Getting a s a -> a
^. Lens' LogEntry Count
leRobotID)
LogSource
Logged -> AttrName
notifAttr
ErrorTrace ErrorLevel
l -> case ErrorLevel
l of
ErrorLevel
Debug -> AttrName
dimAttr
ErrorLevel
Warning -> AttrName
yellowAttr
ErrorLevel
Error -> AttrName
redAttr
ErrorLevel
Critical -> AttrName
redAttr
where
robotColor :: Count -> AttrName
robotColor Count
rid = [AttrName]
fgCols forall a. [a] -> Count -> a
!! (Count
rid forall a. Integral a => a -> a -> a
`mod` Count
fgColLen)
fgCols :: [AttrName]
fgCols = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(AttrName, Attr)]
worldAttributes
fgColLen :: Count
fgColLen = forall (t :: * -> *) a. Foldable t => t a -> Count
length [AttrName]
fgCols
drawModalMenu :: AppState -> Widget Name
AppState
s = forall n. Count -> Widget n -> Widget n
vLimit Count
1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {n}. [Widget n] -> Widget n
hBox forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall n. Count -> Widget n -> Widget n
padLeftRight Count
1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. (KeyHighlight, Text, Text) -> Widget Name
drawKeyCmd) [(KeyHighlight, Text, Text)]
globalKeyCmds
where
notificationKey :: Getter GameState (Notifications a) -> Text -> Text -> Maybe (KeyHighlight, Text, Text)
notificationKey :: forall a.
Getter GameState (Notifications a)
-> Text -> Text -> Maybe (KeyHighlight, Text, Text)
notificationKey Getter GameState (Notifications a)
notifLens Text
key Text
name
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getter GameState (Notifications a)
notifLens forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a1 a2. Lens (Notifications a1) (Notifications a2) [a1] [a2]
notificationsContent) = forall a. Maybe a
Nothing
| Bool
otherwise =
let highlight :: KeyHighlight
highlight
| AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getter GameState (Notifications a)
notifLens forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Lens' (Notifications a) Count
notificationsCount forall a. Ord a => a -> a -> Bool
> Count
0 = KeyHighlight
Alert
| Bool
otherwise = KeyHighlight
NoHighlight
in forall a. a -> Maybe a
Just (KeyHighlight
highlight, Text
key, Text
name)
globalKeyCmds :: [(KeyHighlight, Text, Text)]
globalKeyCmds =
forall a. [Maybe a] -> [a]
catMaybes
[ forall a. a -> Maybe a
Just (KeyHighlight
NoHighlight, Text
"F1", Text
"Help")
, forall a. a -> Maybe a
Just (KeyHighlight
NoHighlight, Text
"F2", Text
"Robots")
, forall a.
Getter GameState (Notifications a)
-> Text -> Text -> Maybe (KeyHighlight, Text, Text)
notificationKey Lens' GameState (Notifications (Recipe Entity))
availableRecipes Text
"F3" Text
"Recipes"
, forall a.
Getter GameState (Notifications a)
-> Text -> Text -> Maybe (KeyHighlight, Text, Text)
notificationKey Lens' GameState (Notifications Const)
availableCommands Text
"F4" Text
"Commands"
, forall a.
Getter GameState (Notifications a)
-> Text -> Text -> Maybe (KeyHighlight, Text, Text)
notificationKey Getter GameState (Notifications LogEntry)
messageNotifications Text
"F5" Text
"Messages"
]
drawKeyMenu :: AppState -> Widget Name
AppState
s =
forall n. Count -> Widget n -> Widget n
vLimit Count
2 forall a b. (a -> b) -> a -> b
$
forall {n}. [Widget n] -> Widget n
hBox
[ forall {n}. [Widget n] -> Widget n
vBox
[ [(KeyHighlight, Text, Text)] -> Widget Name
mkCmdRow [(KeyHighlight, Text, Text)]
globalKeyCmds
, forall n. Padding -> Widget n -> Widget n
padLeft (Count -> Padding
Pad Count
2) forall a b. (a -> b) -> a -> b
$ [(KeyHighlight, Text, Text)] -> Widget Name
mkCmdRow [(KeyHighlight, Text, Text)]
focusedPanelCmds
]
, forall {n}. Widget n
gameModeWidget
]
where
mkCmdRow :: [(KeyHighlight, Text, Text)] -> Widget Name
mkCmdRow = forall {n}. [Widget n] -> Widget n
hBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (KeyHighlight, Text, Text) -> Widget Name
drawPaddedCmd
drawPaddedCmd :: (KeyHighlight, Text, Text) -> Widget Name
drawPaddedCmd = forall n. Count -> Widget n -> Widget n
padLeftRight Count
1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. (KeyHighlight, Text, Text) -> Widget Name
drawKeyCmd
focusedPanelCmds :: [(KeyHighlight, Text, Text)]
focusedPanelCmds =
forall a b. (a -> b) -> [a] -> [b]
map forall {a} {t}.
(Eq a, IsString a) =>
(t, a) -> (KeyHighlight, t, a)
highlightKeyCmds forall a b. (a -> b) -> a -> b
$
forall {a}. IsString a => Maybe Name -> [(a, Text)]
keyCmdsFor forall a b. (a -> b) -> a -> b
$
forall n. FocusRing n -> Maybe n
focusGetCurrent forall a b. (a -> b) -> a -> b
$
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (FocusRing Name)
uiFocusRing) AppState
s
isReplWorking :: Bool
isReplWorking = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getter GameState Bool
replWorking
isPaused :: Bool
isPaused = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getter GameState Bool
paused
viewingBase :: Bool
viewingBase = (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' GameState ViewCenterRule
viewCenterRule) forall a. Eq a => a -> a -> Bool
== Count -> ViewCenterRule
VCRobot Count
0
creative :: Bool
creative = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' GameState Bool
creativeMode
cheat :: Bool
cheat = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Bool
uiCheatMode
goal :: Bool
goal = GoalTracking -> Bool
hasAnythingToShow forall a b. (a -> b) -> a -> b
$ AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState GoalDisplay
uiGoal forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' GoalDisplay GoalTracking
goalsContent
showZero :: Bool
showZero = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Bool
uiShowZero
inventorySort :: InventorySortOptions
inventorySort = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState InventorySortOptions
uiInventorySort
ctrlMode :: ReplControlMode
ctrlMode = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState REPLState
uiREPL forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' REPLState ReplControlMode
replControlMode
renderControlModeSwitch :: ReplControlMode -> T.Text
renderControlModeSwitch :: ReplControlMode -> Text
renderControlModeSwitch = \case
ReplControlMode
Piloting -> Text
"REPL"
ReplControlMode
Typing -> Text
"pilot"
gameModeWidget :: Widget n
gameModeWidget =
forall n. Padding -> Widget n -> Widget n
padLeft Padding
Max
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Count -> Widget n -> Widget n
padLeftRight Count
1
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Semigroup a => a -> a -> a
<> Text
" mode")
forall a b. (a -> b) -> a -> b
$ case Bool
creative of
Bool
False -> Text
"Classic"
Bool
True -> Text
"Creative"
globalKeyCmds :: [(KeyHighlight, Text, Text)]
globalKeyCmds =
forall a. [Maybe a] -> [a]
catMaybes
[ forall {a}. Bool -> a -> Maybe a
may Bool
goal (KeyHighlight
NoHighlight, Text
"^g", Text
"goal")
, forall {a}. Bool -> a -> Maybe a
may Bool
cheat (KeyHighlight
NoHighlight, Text
"^v", Text
"creative")
, forall a. a -> Maybe a
Just (KeyHighlight
NoHighlight, Text
"^p", if Bool
isPaused then Text
"unpause" else Text
"pause")
, forall a. a -> Maybe a
Just (KeyHighlight
NoHighlight, Text
"^o", Text
"step")
, forall a. a -> Maybe a
Just (KeyHighlight
NoHighlight, Text
"^zx", Text
"speed")
, forall a. a -> Maybe a
Just (if AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getter UIState Bool
uiShowRobots then KeyHighlight
NoHighlight else KeyHighlight
Alert, Text
"M-h", Text
"hide robots")
]
may :: Bool -> a -> Maybe a
may Bool
b = if Bool
b then forall a. a -> Maybe a
Just else forall a b. a -> b -> a
const forall a. Maybe a
Nothing
highlightKeyCmds :: (t, a) -> (KeyHighlight, t, a)
highlightKeyCmds (t
k, a
n) = (,t
k,a
n) forall a b. (a -> b) -> a -> b
$ case a
n of
a
"pop out" | (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Bool
uiMoreInfoBot) Bool -> Bool -> Bool
|| (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Bool
uiMoreInfoTop) -> KeyHighlight
Alert
a
_ -> KeyHighlight
PanelSpecific
keyCmdsFor :: Maybe Name -> [(a, Text)]
keyCmdsFor (Just (FocusablePanel FocusablePanel
REPLPanel)) =
[ (a
"↓↑", Text
"history")
]
forall a. [a] -> [a] -> [a]
++ [(a
"Enter", Text
"execute") | Bool -> Bool
not Bool
isReplWorking]
forall a. [a] -> [a] -> [a]
++ [(a
"^c", Text
"cancel") | Bool
isReplWorking]
forall a. [a] -> [a] -> [a]
++ [(a
"M-p", ReplControlMode -> Text
renderControlModeSwitch ReplControlMode
ctrlMode) | Bool
creative]
keyCmdsFor (Just (FocusablePanel FocusablePanel
WorldPanel)) =
[ (a
"←↓↑→ / hjkl", Text
"scroll") | Bool
creative
]
forall a. [a] -> [a] -> [a]
++ [(a
"c", Text
"recenter") | Bool -> Bool
not Bool
viewingBase]
forall a. [a] -> [a] -> [a]
++ [(a
"f", Text
"FPS")]
keyCmdsFor (Just (FocusablePanel FocusablePanel
RobotPanel)) =
[ (a
"Enter", Text
"pop out")
, (a
"m", Text
"make")
, (a
"0", (if Bool
showZero then Text
"hide" else Text
"show") forall a. Semigroup a => a -> a -> a
<> Text
" 0")
, (a
":/;", [Text] -> Text
T.unwords [Text
"Sort:", InventorySortOptions -> Text
renderSortMethod InventorySortOptions
inventorySort])
]
keyCmdsFor (Just (FocusablePanel FocusablePanel
InfoPanel)) = []
keyCmdsFor Maybe Name
_ = []
data KeyHighlight = NoHighlight | Alert | PanelSpecific
drawKeyCmd :: (KeyHighlight, Text, Text) -> Widget Name
drawKeyCmd :: (KeyHighlight, Text, Text) -> Widget Name
drawKeyCmd (KeyHighlight
h, Text
key, Text
cmd) =
forall {n}. [Widget n] -> Widget n
hBox
[ forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
attr (forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ [Text] -> Text
T.concat [Text
"[", Text
key, Text
"] "])
, forall n. Text -> Widget n
txt Text
cmd
]
where
attr :: AttrName
attr = case KeyHighlight
h of
KeyHighlight
NoHighlight -> AttrName
defAttr
KeyHighlight
Alert -> AttrName
notifAttr
KeyHighlight
PanelSpecific -> AttrName
highlightAttr
drawWorld :: Bool -> GameState -> Widget Name
drawWorld :: Bool -> GameState -> Widget Name
drawWorld Bool
showRobots GameState
g =
forall n. Widget n -> Widget n
center
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Ord n => n -> Widget n -> Widget n
cached Name
WorldCache
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Ord n => n -> Widget n -> Widget n
reportExtent Name
WorldExtent
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Ord n => n -> Widget n -> Widget n
clickable (FocusablePanel -> Name
FocusablePanel FocusablePanel
WorldPanel)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Size -> Size -> RenderM n (Result n) -> Widget n
Widget Size
Fixed Size
Fixed
forall a b. (a -> b) -> a -> b
$ do
Context Name
ctx <- forall n. RenderM n (Context n)
getContext
let w :: Count
w = Context Name
ctx forall s a. s -> Getting a s a -> a
^. forall n. Lens' (Context n) Count
availWidthL
h :: Count
h = Context Name
ctx forall s a. s -> Getting a s a -> a
^. forall n. Lens' (Context n) Count
availHeightL
ixs :: [Coords]
ixs = forall a. Ix a => (a, a) -> [a]
range (GameState -> (Int32, Int32) -> (Coords, Coords)
viewingRegion GameState
g (forall a b. (Integral a, Num b) => a -> b
fromIntegral Count
w, forall a b. (Integral a, Num b) => a -> b
fromIntegral Count
h))
forall n. Widget n -> RenderM n (Result n)
render forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {n}. [Widget n] -> Widget n
vBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall {n}. [Widget n] -> Widget n
hBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e. Count -> [e] -> [[e]]
chunksOf Count
w forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (Bool -> GameState -> Coords -> Widget Name
drawLoc Bool
showRobots GameState
g) forall a b. (a -> b) -> a -> b
$ [Coords]
ixs
drawRobotPanel :: AppState -> Widget Name
drawRobotPanel :: AppState -> Widget Name
drawRobotPanel AppState
s = case (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to GameState -> Maybe Robot
focusedRobot, AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (Maybe (Count, List Name InventoryListEntry))
uiInventory) of
(Just Robot
r, Just (Count
_, List Name InventoryListEntry
lst)) ->
let Location Int32
x Int32
y = Robot
r forall s a. s -> Getting a s a -> a
^. Getter Robot (Point V2 Int32)
robotLocation
drawClickableItem :: Count -> Bool -> InventoryListEntry -> Widget Name
drawClickableItem Count
pos Bool
selb = forall n. Ord n => n -> Widget n -> Widget n
clickable (Count -> Name
InventoryListItem Count
pos) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Count -> Count -> Bool -> InventoryListEntry -> Widget Name
drawItem (List Name InventoryListEntry
lst forall s a. s -> Getting a s a -> a
^. forall n (t :: * -> *) e. Lens' (GenericList n t e) (Maybe Count)
BL.listSelectedL) Count
pos Bool
selb
in forall n. Padding -> Widget n -> Widget n
padBottom Padding
Max forall a b. (a -> b) -> a -> b
$
forall {n}. [Widget n] -> Widget n
vBox
[ forall n. Widget n -> Widget n
hCenter forall a b. (a -> b) -> a -> b
$
forall {n}. [Widget n] -> Widget n
hBox
[ forall n. Text -> Widget n
txt (Robot
r forall s a. s -> Getting a s a -> a
^. Lens' Robot Text
robotName)
, forall n. Padding -> Widget n -> Widget n
padLeft (Count -> Padding
Pad Count
2) forall a b. (a -> b) -> a -> b
$ forall n. String -> Widget n
str (forall r. PrintfType r => String -> r
printf String
"(%d, %d)" Int32
x Int32
y)
, forall n. Padding -> Widget n -> Widget n
padLeft (Count -> Padding
Pad Count
2) forall a b. (a -> b) -> a -> b
$ forall n. Display -> Widget n
renderDisplay (Robot
r forall s a. s -> Getting a s a -> a
^. Lens' Robot Display
robotDisplay)
]
, forall n. Count -> Widget n -> Widget n
padAll Count
1 (forall (t :: * -> *) n e.
(Traversable t, Splittable t, Ord n, Show n) =>
(Count -> Bool -> e -> Widget n)
-> Bool -> GenericList n t e -> Widget n
BL.renderListWithIndex Count -> Bool -> InventoryListEntry -> Widget Name
drawClickableItem Bool
True List Name InventoryListEntry
lst)
]
(Maybe Robot, Maybe (Count, List Name InventoryListEntry))
_ -> forall n. Padding -> Widget n -> Widget n
padRight Padding
Max forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Padding -> Widget n -> Widget n
padBottom Padding
Max forall a b. (a -> b) -> a -> b
$ forall n. String -> Widget n
str String
" "
drawItem ::
Maybe Int ->
Int ->
Bool ->
InventoryListEntry ->
Widget Name
drawItem :: Maybe Count -> Count -> Bool -> InventoryListEntry -> Widget Name
drawItem Maybe Count
sel Count
i Bool
_ (Separator Text
l) =
(if Maybe Count
sel forall a. Eq a => a -> a -> Bool
== forall a. a -> Maybe a
Just (Count
i forall a. Num a => a -> a -> a
+ Count
1) then forall n. Widget n -> Widget n
visible else forall a. a -> a
id) forall a b. (a -> b) -> a -> b
$ forall n. Widget n -> Widget n
hBorderWithLabel (forall n. Text -> Widget n
txt Text
l)
drawItem Maybe Count
_ Count
_ Bool
_ (InventoryEntry Count
n Entity
e) = Entity -> Widget Name
drawLabelledEntityName Entity
e forall n. Widget n -> Widget n -> Widget n
<+> forall {n}. Count -> Widget n
showCount Count
n
where
showCount :: Count -> Widget n
showCount = forall n. Padding -> Widget n -> Widget n
padLeft Padding
Max forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. String -> Widget n
str forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show
drawItem Maybe Count
_ Count
_ Bool
_ (EquippedEntry Entity
e) = Entity -> Widget Name
drawLabelledEntityName Entity
e forall n. Widget n -> Widget n -> Widget n
<+> forall n. Padding -> Widget n -> Widget n
padLeft Padding
Max (forall n. String -> Widget n
str String
" ")
drawLabelledEntityName :: Entity -> Widget Name
drawLabelledEntityName :: Entity -> Widget Name
drawLabelledEntityName Entity
e =
forall {n}. [Widget n] -> Widget n
hBox
[ forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad Count
2) (forall n. Display -> Widget n
renderDisplay (Entity
e forall s a. s -> Getting a s a -> a
^. Lens' Entity Display
entityDisplay))
, forall n. Text -> Widget n
txt (Entity
e forall s a. s -> Getting a s a -> a
^. Lens' Entity Text
entityName)
]
drawInfoPanel :: AppState -> Widget Name
drawInfoPanel :: AppState -> Widget Name
drawInfoPanel AppState
s =
forall n.
(Ord n, Show n) =>
n -> ViewportType -> Widget n -> Widget n
viewport Name
InfoViewport ViewportType
Vertical
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Count -> Widget n -> Widget n
padLeftRight Count
1
forall a b. (a -> b) -> a -> b
$ AppState -> Widget Name
explainFocusedItem AppState
s
explainFocusedItem :: AppState -> Widget Name
explainFocusedItem :: AppState -> Widget Name
explainFocusedItem AppState
s = case AppState -> Maybe InventoryListEntry
focusedItem AppState
s of
Just (InventoryEntry Count
_ Entity
e) -> AppState -> Entity -> Widget Name
explainEntry AppState
s Entity
e
Just (EquippedEntry Entity
e) ->
AppState -> Entity -> Widget Name
explainEntry AppState
s Entity
e
forall n. Widget n -> Widget n -> Widget n
<=> if Entity
e forall s a. s -> Getting a s a -> a
^. Lens' Entity Text
entityName forall a. Eq a => a -> a -> Bool
== Text
"logger" then AppState -> Widget Name
drawRobotLog AppState
s else forall {n}. Widget n
emptyWidget
Maybe InventoryListEntry
_ -> forall n. Text -> Widget n
txt Text
" "
explainEntry :: AppState -> Entity -> Widget Name
explainEntry :: AppState -> Entity -> Widget Name
explainEntry AppState
s Entity
e =
forall {n}. [Widget n] -> Widget n
vBox
[ [EntityProperty] -> Widget Name
displayProperties forall a b. (a -> b) -> a -> b
$ forall a. Set a -> [a]
Set.toList (Entity
e forall s a. s -> Getting a s a -> a
^. Lens' Entity (Set EntityProperty)
entityProperties)
, [Text] -> Widget Name
displayParagraphs (Entity
e forall s a. s -> Getting a s a -> a
^. Lens' Entity [Text]
entityDescription)
, AppState -> Entity -> Widget Name
explainRecipes AppState
s Entity
e
]
displayProperties :: [EntityProperty] -> Widget Name
displayProperties :: [EntityProperty] -> Widget Name
displayProperties = forall {n}. [Text] -> Widget n
displayList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe forall {a}. IsString a => EntityProperty -> Maybe a
showProperty
where
showProperty :: EntityProperty -> Maybe a
showProperty EntityProperty
Growable = forall a. a -> Maybe a
Just a
"growing"
showProperty EntityProperty
Infinite = forall a. a -> Maybe a
Just a
"infinite"
showProperty EntityProperty
Liquid = forall a. a -> Maybe a
Just a
"liquid"
showProperty EntityProperty
Unwalkable = forall a. a -> Maybe a
Just a
"blocking"
showProperty EntityProperty
Portable = forall a. Maybe a
Nothing
showProperty EntityProperty
Known = forall a. Maybe a
Nothing
displayList :: [Text] -> Widget n
displayList [] = forall {n}. Widget n
emptyWidget
displayList [Text]
ps =
forall {n}. [Widget n] -> Widget n
vBox
[ forall {n}. [Widget n] -> Widget n
hBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> [a] -> [a]
L.intersperse (forall n. Text -> Widget n
txt Text
", ") forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
robotAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Text -> Widget n
txt) forall a b. (a -> b) -> a -> b
$ [Text]
ps
, forall n. Text -> Widget n
txt Text
" "
]
explainRecipes :: AppState -> Entity -> Widget Name
explainRecipes :: AppState -> Entity -> Widget Name
explainRecipes AppState
s Entity
e
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Recipe Entity]
recipes = forall {n}. Widget n
emptyWidget
| Bool
otherwise =
forall {n}. [Widget n] -> Widget n
vBox
[ forall n. Padding -> Widget n -> Widget n
padBottom (Count -> Padding
Pad Count
1) (forall n. Widget n -> Widget n
hBorderWithLabel (forall n. Text -> Widget n
txt Text
"Recipes"))
, forall n. Count -> Widget n -> Widget n
padLeftRight Count
2 forall a b. (a -> b) -> a -> b
$
forall n. Widget n -> Widget n
hCenter forall a b. (a -> b) -> a -> b
$
forall {n}. [Widget n] -> Widget n
vBox forall a b. (a -> b) -> a -> b
$
forall a b. (a -> b) -> [a] -> [b]
map (forall n. Count -> Widget n -> Widget n
hLimit Count
widthLimit forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Padding -> Widget n -> Widget n
padBottom (Count -> Padding
Pad Count
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Entity -> Inventory -> Recipe Entity -> Widget Name
drawRecipe (forall a. a -> Maybe a
Just Entity
e) Inventory
inv) [Recipe Entity]
recipes
]
where
recipes :: [Recipe Entity]
recipes = AppState -> Entity -> [Recipe Entity]
recipesWith AppState
s Entity
e
inv :: Inventory
inv = forall a. a -> Maybe a -> a
fromMaybe Inventory
E.empty forall a b. (a -> b) -> a -> b
$ AppState
s forall s a. s -> Getting (First a) s a -> Maybe a
^? Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to GameState -> Maybe Robot
focusedRobot forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Prism (Maybe a) (Maybe b) a b
_Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' Robot Inventory
robotInventory
width :: (a, Entity) -> Count
width (a
n, Entity
ingr) =
forall (t :: * -> *) a. Foldable t => t a -> Count
length (forall a. Show a => a -> String
show a
n) forall a. Num a => a -> a -> a
+ Count
1 forall a. Num a => a -> a -> a
+ forall a. (Num a, Ord a) => [a] -> a
maximum0 (forall a b. (a -> b) -> [a] -> [b]
map Text -> Count
T.length forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.words forall a b. (a -> b) -> a -> b
$ Entity
ingr forall s a. s -> Getting a s a -> a
^. Lens' Entity Text
entityName)
maxInputWidth :: Count
maxInputWidth =
forall a. a -> Maybe a -> a
fromMaybe Count
0 forall a b. (a -> b) -> a -> b
$
forall a s.
Ord a =>
Getting (Endo (Endo (Maybe a))) s a -> s -> Maybe a
maximumOf (forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e. Lens' (Recipe e) (IngredientList e)
recipeInputs forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall {a}. Show a => (a, Entity) -> Count
width) [Recipe Entity]
recipes
maxOutputWidth :: Count
maxOutputWidth =
forall a. a -> Maybe a -> a
fromMaybe Count
0 forall a b. (a -> b) -> a -> b
$
forall a s.
Ord a =>
Getting (Endo (Endo (Maybe a))) s a -> s -> Maybe a
maximumOf (forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e. Lens' (Recipe e) (IngredientList e)
recipeOutputs forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall {a}. Show a => (a, Entity) -> Count
width) [Recipe Entity]
recipes
widthLimit :: Count
widthLimit = Count
2 forall a. Num a => a -> a -> a
* forall a. Ord a => a -> a -> a
max Count
maxInputWidth Count
maxOutputWidth forall a. Num a => a -> a -> a
+ Count
11
recipesWith :: AppState -> Entity -> [Recipe Entity]
recipesWith :: AppState -> Entity -> [Recipe Entity]
recipesWith AppState
s Entity
e =
let getRecipes :: ((IntMap [Recipe Entity]
-> Const (IntMap [Recipe Entity]) (IntMap [Recipe Entity]))
-> GameState -> Const (IntMap [Recipe Entity]) GameState)
-> [Recipe Entity]
getRecipes (IntMap [Recipe Entity]
-> Const (IntMap [Recipe Entity]) (IntMap [Recipe Entity]))
-> GameState -> Const (IntMap [Recipe Entity]) GameState
select = IntMap [Recipe Entity] -> Entity -> [Recipe Entity]
recipesFor (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. (IntMap [Recipe Entity]
-> Const (IntMap [Recipe Entity]) (IntMap [Recipe Entity]))
-> GameState -> Const (IntMap [Recipe Entity]) GameState
select) Entity
e
in
forall a. Eq a => [a] -> [a]
L.nub forall a b. (a -> b) -> a -> b
$ ((IntMap [Recipe Entity]
-> Const (IntMap [Recipe Entity]) (IntMap [Recipe Entity]))
-> GameState -> Const (IntMap [Recipe Entity]) GameState)
-> [Recipe Entity]
getRecipes Lens' GameState (IntMap [Recipe Entity])
recipesIn forall a. [a] -> [a] -> [a]
++ ((IntMap [Recipe Entity]
-> Const (IntMap [Recipe Entity]) (IntMap [Recipe Entity]))
-> GameState -> Const (IntMap [Recipe Entity]) GameState)
-> [Recipe Entity]
getRecipes Lens' GameState (IntMap [Recipe Entity])
recipesReq forall a. [a] -> [a] -> [a]
++ ((IntMap [Recipe Entity]
-> Const (IntMap [Recipe Entity]) (IntMap [Recipe Entity]))
-> GameState -> Const (IntMap [Recipe Entity]) GameState)
-> [Recipe Entity]
getRecipes Lens' GameState (IntMap [Recipe Entity])
recipesOut
drawRecipe :: Maybe Entity -> Inventory -> Recipe Entity -> Widget Name
drawRecipe :: Maybe Entity -> Inventory -> Recipe Entity -> Widget Name
drawRecipe Maybe Entity
me Inventory
inv (Recipe [(Count, Entity)]
ins [(Count, Entity)]
outs [(Count, Entity)]
reqs Integer
time Integer
_weight) =
forall {n}. [Widget n] -> Widget n
vBox
[ forall n. Widget n -> Widget n
hCenter forall a b. (a -> b) -> a -> b
$ [(Count, Entity)] -> Widget Name
drawReqs [(Count, Entity)]
reqs
,
forall {n}. [Widget n] -> Widget n
hBox
[ forall {n}. [Widget n] -> Widget n
vBox (forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Count -> (Count, Entity) -> Widget Name
drawIn [Count
0 ..] ([(Count, Entity)]
ins forall a. Semigroup a => a -> a -> a
<> [(Count, Entity)]
times))
, forall {n}. Widget n
connector
, forall {n}. [Widget n] -> Widget n
vBox (forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Count -> (Count, Entity) -> Widget Name
drawOut [Count
0 ..] [(Count, Entity)]
outs)
]
]
where
connector :: Widget n
connector
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Count, Entity)]
reqs = forall n. Count -> Widget n -> Widget n
hLimit Count
5 forall {n}. Widget n
hBorder
| Bool
otherwise =
forall {n}. [Widget n] -> Widget n
hBox
[ forall n. Count -> Widget n -> Widget n
hLimit Count
2 forall {n}. Widget n
hBorder
, forall n. Edges Bool -> Widget n
joinableBorder (forall a. a -> a -> a -> a -> Edges a
Edges Bool
True Bool
False Bool
True Bool
True)
, forall n. Count -> Widget n -> Widget n
hLimit Count
2 forall {n}. Widget n
hBorder
]
inLen :: Count
inLen = forall (t :: * -> *) a. Foldable t => t a -> Count
length [(Count, Entity)]
ins forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. Foldable t => t a -> Count
length [(Count, Entity)]
times
outLen :: Count
outLen = forall (t :: * -> *) a. Foldable t => t a -> Count
length [(Count, Entity)]
outs
times :: [(Count, Entity)]
times = [(forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
time, Entity
timeE) | Integer
time forall a. Eq a => a -> a -> Bool
/= Integer
1]
drawIn, drawOut :: Int -> (Count, Entity) -> Widget Name
drawIn :: Count -> (Count, Entity) -> Widget Name
drawIn Count
i (Count
n, Entity
ingr) =
forall {n}. [Widget n] -> Widget n
hBox
[ forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$ forall n. String -> Widget n
str (forall a. Show a => a -> String
show Count
n)
, forall {n}. Bool -> Entity -> Widget n
fmtEntityName Bool
missing Entity
ingr
, forall n. Padding -> Widget n -> Widget n
padLeft (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$
forall {n}. Widget n
hBorder
forall n. Widget n -> Widget n -> Widget n
<+> ( forall n. Edges Bool -> Widget n
joinableBorder (forall a. a -> a -> a -> a -> Edges a
Edges (Count
i forall a. Eq a => a -> a -> Bool
/= Count
0) (Count
i forall a. Eq a => a -> a -> Bool
/= Count
inLen forall a. Num a => a -> a -> a
- Count
1) Bool
True Bool
False)
forall n. Widget n -> Widget n -> Widget n
<=> if Count
i forall a. Eq a => a -> a -> Bool
/= Count
inLen forall a. Num a => a -> a -> a
- Count
1
then forall n. Count -> Widget n -> Widget n
vLimit (forall a. Num a => a -> a -> a
subtract Count
1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Count
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.words forall a b. (a -> b) -> a -> b
$ Entity
ingr forall s a. s -> Getting a s a -> a
^. Lens' Entity Text
entityName) forall {n}. Widget n
vBorder
else forall {n}. Widget n
emptyWidget
)
]
where
missing :: Bool
missing = Entity -> Inventory -> Count
E.lookup Entity
ingr Inventory
inv forall a. Ord a => a -> a -> Bool
< Count
n
drawOut :: Count -> (Count, Entity) -> Widget Name
drawOut Count
i (Count
n, Entity
ingr) =
forall {n}. [Widget n] -> Widget n
hBox
[ forall n. Padding -> Widget n -> Widget n
padRight (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$
( forall n. Edges Bool -> Widget n
joinableBorder (forall a. a -> a -> a -> a -> Edges a
Edges (Count
i forall a. Eq a => a -> a -> Bool
/= Count
0) (Count
i forall a. Eq a => a -> a -> Bool
/= Count
outLen forall a. Num a => a -> a -> a
- Count
1) Bool
False Bool
True)
forall n. Widget n -> Widget n -> Widget n
<=> if Count
i forall a. Eq a => a -> a -> Bool
/= Count
outLen forall a. Num a => a -> a -> a
- Count
1
then forall n. Count -> Widget n -> Widget n
vLimit (forall a. Num a => a -> a -> a
subtract Count
1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Count
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.words forall a b. (a -> b) -> a -> b
$ Entity
ingr forall s a. s -> Getting a s a -> a
^. Lens' Entity Text
entityName) forall {n}. Widget n
vBorder
else forall {n}. Widget n
emptyWidget
)
forall n. Widget n -> Widget n -> Widget n
<+> forall {n}. Widget n
hBorder
, forall {n}. Bool -> Entity -> Widget n
fmtEntityName Bool
False Entity
ingr
, forall n. Padding -> Widget n -> Widget n
padLeft (Count -> Padding
Pad Count
1) forall a b. (a -> b) -> a -> b
$ forall n. String -> Widget n
str (forall a. Show a => a -> String
show Count
n)
]
fmtEntityName :: Bool -> Entity -> Widget n
fmtEntityName Bool
missing Entity
ingr
| forall a. a -> Maybe a
Just Entity
ingr forall a. Eq a => a -> a -> Bool
== Maybe Entity
me = forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
highlightAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txtLines Text
nm
| Entity
ingr forall a. Eq a => a -> a -> Bool
== Entity
timeE = forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
yellowAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txtLines Text
nm
| Bool
missing = forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
invalidFormInputAttr forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txtLines Text
nm
| Bool
otherwise = forall n. Text -> Widget n
txtLines Text
nm
where
nm :: Text
nm = Entity
ingr forall s a. s -> Getting a s a -> a
^. Lens' Entity Text
entityName
txtLines :: Text -> Widget n
txtLines = forall {n}. [Widget n] -> Widget n
vBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall n. Text -> Widget n
txt forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.words
timeE :: Entity
timeE :: Entity
timeE = Display
-> Text -> [Text] -> [EntityProperty] -> [Capability] -> Entity
mkEntity (Char -> Display
defaultEntityDisplay Char
'.') Text
"ticks" [] [] []
drawReqs :: IngredientList Entity -> Widget Name
drawReqs :: [(Count, Entity)] -> Widget Name
drawReqs = forall {n}. [Widget n] -> Widget n
vBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall n. Widget n -> Widget n
hCenter forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a} {n}. (Eq a, Num a, Show a) => (a, Entity) -> Widget n
drawReq)
where
drawReq :: (a, Entity) -> Widget n
drawReq (a
1, Entity
e) = forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Entity
e forall s a. s -> Getting a s a -> a
^. Lens' Entity Text
entityName
drawReq (a
n, Entity
e) = forall n. String -> Widget n
str (forall a. Show a => a -> String
show a
n) forall n. Widget n -> Widget n -> Widget n
<+> forall n. Text -> Widget n
txt Text
" " forall n. Widget n -> Widget n -> Widget n
<+> forall n. Text -> Widget n
txt (Entity
e forall s a. s -> Getting a s a -> a
^. Lens' Entity Text
entityName)
indent2 :: WrapSettings
indent2 :: WrapSettings
indent2 = WrapSettings
defaultWrapSettings {fillStrategy :: FillStrategy
fillStrategy = Count -> FillStrategy
FillIndent Count
2}
drawRobotLog :: AppState -> Widget Name
drawRobotLog :: AppState -> Widget Name
drawRobotLog AppState
s =
forall {n}. [Widget n] -> Widget n
vBox
[ forall n. Padding -> Widget n -> Widget n
padBottom (Count -> Padding
Pad Count
1) (forall n. Widget n -> Widget n
hBorderWithLabel (forall n. Text -> Widget n
txt Text
"Log"))
, forall {n}. [Widget n] -> Widget n
vBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i (f :: * -> *) a b.
FunctorWithIndex i f =>
(i -> a -> b) -> f a -> f b
imap forall {n}. Count -> LogEntry -> Widget n
drawEntry forall a b. (a -> b) -> a -> b
$ Seq LogEntry
logEntries
]
where
logEntries :: Seq LogEntry
logEntries = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to GameState -> Maybe Robot
focusedRobot forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Prism (Maybe a) (Maybe b) a b
_Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' Robot (Seq LogEntry)
robotLog
rn :: Maybe Text
rn = AppState
s forall s a. s -> Getting (First a) s a -> Maybe a
^? Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to GameState -> Maybe Robot
focusedRobot forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Prism (Maybe a) (Maybe b) a b
_Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' Robot Text
robotName
n :: Count
n = forall a. Seq a -> Count
Seq.length Seq LogEntry
logEntries
allMe :: Bool
allMe = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ((forall a. Eq a => a -> a -> Bool
== Maybe Text
rn) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Lens' LogEntry Text
leRobotName) Seq LogEntry
logEntries
drawEntry :: Count -> LogEntry -> Widget n
drawEntry Count
i LogEntry
e =
(if Count
i forall a. Eq a => a -> a -> Bool
== Count
n forall a. Num a => a -> a -> a
- Count
1 Bool -> Bool -> Bool
&& AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState Bool
uiScrollToEnd then forall n. Widget n -> Widget n
visible else forall a. a -> a
id) forall a b. (a -> b) -> a -> b
$
forall a. Bool -> LogEntry -> Widget a
drawLogEntry (Bool -> Bool
not Bool
allMe) LogEntry
e
drawLogEntry :: Bool -> LogEntry -> Widget a
drawLogEntry :: forall a. Bool -> LogEntry -> Widget a
drawLogEntry Bool
addName LogEntry
e = forall n. AttrName -> Widget n -> Widget n
withAttr (LogEntry -> AttrName
colorLogs LogEntry
e) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. WrapSettings -> Text -> Widget n
txtWrapWith WrapSettings
indent2 forall a b. (a -> b) -> a -> b
$ if Bool
addName then Text
name else Text
t
where
t :: Text
t = LogEntry
e forall s a. s -> Getting a s a -> a
^. Lens' LogEntry Text
leText
name :: Text
name = Text
"[" forall a. Semigroup a => a -> a -> a
<> forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Lens' LogEntry Text
leRobotName LogEntry
e forall a. Semigroup a => a -> a -> a
<> Text
"] " forall a. Semigroup a => a -> a -> a
<> (if LogEntry
e forall s a. s -> Getting a s a -> a
^. Lens' LogEntry LogSource
leSource forall a. Eq a => a -> a -> Bool
== LogSource
Said then Text
"said " forall a. Semigroup a => a -> a -> a
<> Text -> Text
quote Text
t else Text
t)
replPromptAsWidget :: Text -> REPLPrompt -> Widget Name
replPromptAsWidget :: Text -> REPLPrompt -> Widget Name
replPromptAsWidget Text
_ (CmdPrompt [Text]
_) = forall n. Text -> Widget n
txt Text
"> "
replPromptAsWidget Text
t (SearchPrompt REPLHistory
rh) =
case Text -> REPLHistory -> Maybe Text
lastEntry Text
t REPLHistory
rh of
Maybe Text
Nothing -> forall n. Text -> Widget n
txt Text
"[nothing found] "
Just Text
lastentry
| Text -> Bool
T.null Text
t -> forall n. Text -> Widget n
txt Text
"[find] "
| Bool
otherwise -> forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"[found: \"" forall a. Semigroup a => a -> a -> a
<> Text
lastentry forall a. Semigroup a => a -> a -> a
<> Text
"\"] "
renderREPLPrompt :: FocusRing Name -> REPLState -> Widget Name
renderREPLPrompt :: FocusRing Name -> REPLState -> Widget Name
renderREPLPrompt FocusRing Name
focus REPLState
repl = Widget Name
ps1 forall n. Widget n -> Widget n -> Widget n
<+> Widget Name
replE
where
prompt :: REPLPrompt
prompt = REPLState
repl forall s a. s -> Getting a s a -> a
^. Lens' REPLState REPLPrompt
replPromptType
replEditor :: Editor Text Name
replEditor = REPLState
repl forall s a. s -> Getting a s a -> a
^. Lens' REPLState (Editor Text Name)
replPromptEditor
color :: Widget n -> Widget n
color = if REPLState
repl forall s a. s -> Getting a s a -> a
^. Lens' REPLState Bool
replValid then forall a. a -> a
id else forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
redAttr
ps1 :: Widget Name
ps1 = Text -> REPLPrompt -> Widget Name
replPromptAsWidget ([Text] -> Text
T.concat forall a b. (a -> b) -> a -> b
$ forall t n. Monoid t => Editor t n -> [t]
getEditContents Editor Text Name
replEditor) REPLPrompt
prompt
replE :: Widget Name
replE =
forall n t.
(Ord n, Show n, Monoid t, TextWidth t, GenericTextZipper t) =>
([t] -> Widget n) -> Bool -> Editor t n -> Widget n
renderEditor
(forall n. Widget n -> Widget n
color forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {n}. [Widget n] -> Widget n
vBox forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall n. Text -> Widget n
txt)
(forall n. FocusRing n -> Maybe n
focusGetCurrent FocusRing Name
focus forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [forall a. Maybe a
Nothing, forall a. a -> Maybe a
Just (FocusablePanel -> Name
FocusablePanel FocusablePanel
REPLPanel), forall a. a -> Maybe a
Just Name
REPLInput])
Editor Text Name
replEditor
drawREPL :: AppState -> Widget Name
drawREPL :: AppState -> Widget Name
drawREPL AppState
s = forall {n}. [Widget n] -> Widget n
vBox forall a b. (a -> b) -> a -> b
$ forall {n}. [Widget n]
latestHistory forall a. Semigroup a => a -> a -> a
<> [Widget Name
currentPrompt]
where
latestHistory :: [Widget n]
latestHistory :: forall {n}. [Widget n]
latestHistory = forall a b. (a -> b) -> [a] -> [b]
map forall {n}. REPLHistItem -> Widget n
fmt (Count -> REPLHistory -> [REPLHistItem]
getLatestREPLHistoryItems (Count
replHeight forall a. Num a => a -> a -> a
- Count
inputLines) (REPLState
repl forall s a. s -> Getting a s a -> a
^. Lens' REPLState REPLHistory
replHistory))
currentPrompt :: Widget Name
currentPrompt :: Widget Name
currentPrompt = case Robot -> Bool
isActive forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Robot
base of
Just Bool
False -> FocusRing Name -> REPLState -> Widget Name
renderREPLPrompt (AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState (FocusRing Name)
uiFocusRing) REPLState
repl
Maybe Bool
_running -> forall n. Padding -> Widget n -> Widget n
padRight Padding
Max forall a b. (a -> b) -> a -> b
$ forall n. Text -> Widget n
txt Text
"..."
inputLines :: Count
inputLines = Count
1
repl :: REPLState
repl = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState UIState
uiState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' UIState REPLState
uiREPL
base :: Maybe Robot
base = AppState
s forall s a. s -> Getting a s a -> a
^. Lens' AppState GameState
gameState forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' GameState (IntMap Robot)
robotMap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at Count
0
fmt :: REPLHistItem -> Widget n
fmt (REPLEntry Text
e) = forall n. Text -> Widget n
txt forall a b. (a -> b) -> a -> b
$ Text
"> " forall a. Semigroup a => a -> a -> a
<> Text
e
fmt (REPLOutput Text
t) = forall n. Text -> Widget n
txt Text
t