-- | The type of definitions of key-command mappings to be used for the UI
-- and shorthands for specifying command triples in the content files.
module Game.LambdaHack.Client.UI.Content.Input
  ( InputContentRaw(..), InputContent(..), makeData
  , evalKeyDef
  , addCmdCategory, replaceDesc, moveItemTriple, repeatTriple
  , mouseLMB, mouseMMB, mouseRMB
  , goToCmd, runToAllCmd, autoexploreCmd, autoexplore25Cmd
  , aimFlingCmd, projectI, projectA, flingTs, applyIK, applyI
  , grabItems, dropItems, descIs, descTs, defaultHeroSelect
#ifdef EXPOSE_INTERNAL
    -- * Internal operations
  , replaceCmd, projectICmd, grabCmd, dropCmd
#endif
  ) where

import Prelude ()

import Game.LambdaHack.Core.Prelude

import qualified Data.Char as Char
import qualified Data.Map.Strict as M
import qualified NLP.Miniutter.English as MU

import           Game.LambdaHack.Client.UI.HumanCmd
import qualified Game.LambdaHack.Client.UI.Key as K
import           Game.LambdaHack.Client.UI.UIOptions
import           Game.LambdaHack.Common.Misc
import           Game.LambdaHack.Definition.Defs

-- | Key-command mappings to be specified in content and used for the UI.
newtype InputContentRaw = InputContentRaw [(K.KM, CmdTriple)]

-- | Bindings and other information about human player commands.
data InputContent = InputContent
  { InputContent -> Map KM CmdTriple
bcmdMap  :: M.Map K.KM CmdTriple   -- ^ binding of keys to commands
  , InputContent -> [(KM, CmdTriple)]
bcmdList :: [(K.KM, CmdTriple)]    -- ^ the properly ordered list
                                       --   of commands for the help menu
  , InputContent -> Map HumanCmd [KM]
brevMap  :: M.Map HumanCmd [K.KM]  -- ^ and from commands to their keys
  }

-- | Create binding of keys to movement and other standard commands,
-- as well as commands defined in the config file.
makeData :: UIOptions        -- ^ UI client options
         -> InputContentRaw  -- ^ default key bindings from the content
         -> InputContent     -- ^ concrete binding
makeData :: UIOptions -> InputContentRaw -> InputContent
makeData UIOptions{[(KM, CmdTriple)]
uCommands :: UIOptions -> [(KM, CmdTriple)]
uCommands :: [(KM, CmdTriple)]
uCommands, Bool
uVi :: UIOptions -> Bool
uVi :: Bool
uVi, Bool
uLaptop :: UIOptions -> Bool
uLaptop :: Bool
uLaptop} (InputContentRaw copsClient :: [(KM, CmdTriple)]
copsClient) =
  let waitTriple :: CmdTriple
waitTriple = ([CmdCategory
CmdMove], "", HumanCmd
Wait)
      wait10Triple :: CmdTriple
wait10Triple = ([CmdCategory
CmdMove], "", HumanCmd
Wait10)
      moveXhairOr :: Int -> (Vector -> HumanCmd) -> Vector -> HumanCmd
moveXhairOr n :: Int
n cmd :: Vector -> HumanCmd
cmd v :: Vector
v = AimModeCmd -> HumanCmd
ByAimMode (AimModeCmd -> HumanCmd) -> AimModeCmd -> HumanCmd
forall a b. (a -> b) -> a -> b
$ $WAimModeCmd :: HumanCmd -> HumanCmd -> AimModeCmd
AimModeCmd { exploration :: HumanCmd
exploration = Vector -> HumanCmd
cmd Vector
v
                                                   , aiming :: HumanCmd
aiming = Vector -> Int -> HumanCmd
MoveXhair Vector
v Int
n }
      bcmdList :: [(KM, CmdTriple)]
bcmdList =
        (if | Bool
uVi -> ((KM, CmdTriple) -> Bool) -> [(KM, CmdTriple)] -> [(KM, CmdTriple)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(k :: KM
k, _) ->
              KM
k KM -> [KM] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [String -> KM
K.mkKM "period", String -> KM
K.mkKM "C-period"])
            | Bool
uLaptop -> ((KM, CmdTriple) -> Bool) -> [(KM, CmdTriple)] -> [(KM, CmdTriple)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(k :: KM
k, _) ->
              KM
k KM -> [KM] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [String -> KM
K.mkKM "i", String -> KM
K.mkKM "C-i", String -> KM
K.mkKM "I"])
            | Bool
otherwise -> [(KM, CmdTriple)] -> [(KM, CmdTriple)]
forall a. a -> a
id) [(KM, CmdTriple)]
copsClient
        [(KM, CmdTriple)] -> [(KM, CmdTriple)] -> [(KM, CmdTriple)]
forall a. [a] -> [a] -> [a]
++ [(KM, CmdTriple)]
uCommands
        [(KM, CmdTriple)] -> [(KM, CmdTriple)] -> [(KM, CmdTriple)]
forall a. [a] -> [a] -> [a]
++ [ (String -> KM
K.mkKM "KP_Begin", CmdTriple
waitTriple)
           , (String -> KM
K.mkKM "C-KP_Begin", CmdTriple
wait10Triple)
           , (String -> KM
K.mkKM "KP_5", CmdTriple
wait10Triple)
           , (String -> KM
K.mkKM "C-KP_5", CmdTriple
wait10Triple) ]
        [(KM, CmdTriple)] -> [(KM, CmdTriple)] -> [(KM, CmdTriple)]
forall a. [a] -> [a] -> [a]
++ (if | Bool
uVi ->
                 [ (String -> KM
K.mkKM "period", CmdTriple
waitTriple)
                 , (String -> KM
K.mkKM "C-period", CmdTriple
wait10Triple) ]  -- yell on % always
               | Bool
uLaptop ->
                 [ (String -> KM
K.mkKM "i", CmdTriple
waitTriple)
                 , (String -> KM
K.mkKM "C-i", CmdTriple
wait10Triple)
                 , (String -> KM
K.mkKM "I", CmdTriple
wait10Triple) ]
               | Bool
otherwise ->
                 [])
        [(KM, CmdTriple)] -> [(KM, CmdTriple)] -> [(KM, CmdTriple)]
forall a. [a] -> [a] -> [a]
++ Bool
-> Bool
-> (Vector -> CmdTriple)
-> (Vector -> CmdTriple)
-> [(KM, CmdTriple)]
forall a.
Bool -> Bool -> (Vector -> a) -> (Vector -> a) -> [(KM, a)]
K.moveBinding Bool
uVi Bool
uLaptop
             (\v :: Vector
v -> ([CmdCategory
CmdMove], "", Int -> (Vector -> HumanCmd) -> Vector -> HumanCmd
moveXhairOr 1 Vector -> HumanCmd
MoveDir Vector
v))
             (\v :: Vector
v -> ([CmdCategory
CmdMove], "", Int -> (Vector -> HumanCmd) -> Vector -> HumanCmd
moveXhairOr 10 Vector -> HumanCmd
RunDir Vector
v))
      rejectRepetitions :: a -> b -> a
rejectRepetitions t1 :: a
t1 t2 :: b
t2 = String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ "duplicate key"
                                        String -> (a, b) -> String
forall v. Show v => String -> v -> String
`showFailure` (a
t1, b
t2)
  in $WInputContent :: Map KM CmdTriple
-> [(KM, CmdTriple)] -> Map HumanCmd [KM] -> InputContent
InputContent
  { bcmdMap :: Map KM CmdTriple
bcmdMap = (CmdTriple -> CmdTriple -> CmdTriple)
-> [(KM, CmdTriple)] -> Map KM CmdTriple
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
M.fromListWith CmdTriple -> CmdTriple -> CmdTriple
forall a b a. (Show a, Show b) => a -> b -> a
rejectRepetitions
      [ (KM
k, CmdTriple
triple)
      | (k :: KM
k, triple :: CmdTriple
triple@(cats :: [CmdCategory]
cats, _, _)) <- [(KM, CmdTriple)]
bcmdList
      , (CmdCategory -> Bool) -> [CmdCategory] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (CmdCategory -> [CmdCategory] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [CmdCategory
CmdMainMenu]) [CmdCategory]
cats
      ]
  , [(KM, CmdTriple)]
bcmdList :: [(KM, CmdTriple)]
bcmdList :: [(KM, CmdTriple)]
bcmdList
  , brevMap :: Map HumanCmd [KM]
brevMap = ([KM] -> [KM] -> [KM]) -> [(HumanCmd, [KM])] -> Map HumanCmd [KM]
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
M.fromListWith (([KM] -> [KM] -> [KM]) -> [KM] -> [KM] -> [KM]
forall a b c. (a -> b -> c) -> b -> a -> c
flip [KM] -> [KM] -> [KM]
forall a. [a] -> [a] -> [a]
(++)) ([(HumanCmd, [KM])] -> Map HumanCmd [KM])
-> [(HumanCmd, [KM])] -> Map HumanCmd [KM]
forall a b. (a -> b) -> a -> b
$ [[(HumanCmd, [KM])]] -> [(HumanCmd, [KM])]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
      [ [(HumanCmd
cmd, [KM
k])]
      | (k :: KM
k, (cats :: [CmdCategory]
cats, _desc :: Text
_desc, cmd :: HumanCmd
cmd)) <- [(KM, CmdTriple)]
bcmdList
      , (CmdCategory -> Bool) -> [CmdCategory] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (CmdCategory -> [CmdCategory] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [CmdCategory
CmdMainMenu, CmdCategory
CmdDebug, CmdCategory
CmdNoHelp]) [CmdCategory]
cats
      ]
  }

evalKeyDef :: (String, CmdTriple) -> (K.KM, CmdTriple)
evalKeyDef :: (String, CmdTriple) -> (KM, CmdTriple)
evalKeyDef (t :: String
t, triple :: CmdTriple
triple@(cats :: [CmdCategory]
cats, _, _)) =
  let km :: KM
km = if CmdCategory
CmdInternal CmdCategory -> [CmdCategory] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [CmdCategory]
cats
           then Modifier -> Key -> KM
K.KM Modifier
K.NoModifier (Key -> KM) -> Key -> KM
forall a b. (a -> b) -> a -> b
$ String -> Key
K.Unknown String
t
           else String -> KM
K.mkKM String
t
  in (KM
km, CmdTriple
triple)

addCmdCategory :: CmdCategory -> CmdTriple -> CmdTriple
addCmdCategory :: CmdCategory -> CmdTriple -> CmdTriple
addCmdCategory cat :: CmdCategory
cat (cats :: [CmdCategory]
cats, desc :: Text
desc, cmd :: HumanCmd
cmd) = (CmdCategory
cat CmdCategory -> [CmdCategory] -> [CmdCategory]
forall a. a -> [a] -> [a]
: [CmdCategory]
cats, Text
desc, HumanCmd
cmd)

replaceDesc :: Text -> CmdTriple -> CmdTriple
replaceDesc :: Text -> CmdTriple -> CmdTriple
replaceDesc desc :: Text
desc (cats :: [CmdCategory]
cats, _, cmd :: HumanCmd
cmd) = ([CmdCategory]
cats, Text
desc, HumanCmd
cmd)

replaceCmd :: HumanCmd -> CmdTriple -> CmdTriple
replaceCmd :: HumanCmd -> CmdTriple -> CmdTriple
replaceCmd cmd :: HumanCmd
cmd (cats :: [CmdCategory]
cats, desc :: Text
desc, _) = ([CmdCategory]
cats, Text
desc, HumanCmd
cmd)

moveItemTriple :: [CStore] -> CStore -> MU.Part -> Bool -> CmdTriple
moveItemTriple :: [CStore] -> CStore -> Part -> Bool -> CmdTriple
moveItemTriple stores1 :: [CStore]
stores1 store2 :: CStore
store2 object :: Part
object auto :: Bool
auto =
  let verb :: Part
verb = Text -> Part
MU.Text (Text -> Part) -> Text -> Part
forall a b. (a -> b) -> a -> b
$ CStore -> Text
verbCStore CStore
store2
      desc :: Text
desc = [Part] -> Text
makePhrase [Part
verb, Part
object]
  in ([CmdCategory
CmdItemMenu], Text
desc, [CStore] -> CStore -> Maybe Part -> Bool -> HumanCmd
MoveItem [CStore]
stores1 CStore
store2 Maybe Part
forall a. Maybe a
Nothing Bool
auto)

repeatTriple :: Int -> CmdTriple
repeatTriple :: Int -> CmdTriple
repeatTriple n :: Int
n = ( [CmdCategory
CmdMeta]
                 , "voice recorded commands" Text -> Text -> Text
<+> Int -> Text
forall a. Show a => a -> Text
tshow Int
n Text -> Text -> Text
<+> "times"
                 , Int -> HumanCmd
Repeat Int
n )

-- @AimFloor@ is not there, but @AimEnemy@ and @AimItem@ almost make up for it.
mouseLMB :: HumanCmd -> Text -> CmdTriple
mouseLMB :: HumanCmd -> Text -> CmdTriple
mouseLMB goToOrRunTo :: HumanCmd
goToOrRunTo desc :: Text
desc =
  ([CmdCategory
CmdMouse], Text
desc, AimModeCmd -> HumanCmd
ByAimMode AimModeCmd
aimMode)
 where
  aimMode :: AimModeCmd
aimMode = $WAimModeCmd :: HumanCmd -> HumanCmd -> AimModeCmd
AimModeCmd
    { exploration :: HumanCmd
exploration = [(CmdArea, HumanCmd)] -> HumanCmd
ByArea ([(CmdArea, HumanCmd)] -> HumanCmd)
-> [(CmdArea, HumanCmd)] -> HumanCmd
forall a b. (a -> b) -> a -> b
$ [(CmdArea, HumanCmd)]
common [(CmdArea, HumanCmd)]
-> [(CmdArea, HumanCmd)] -> [(CmdArea, HumanCmd)]
forall a. [a] -> [a] -> [a]
++  -- exploration mode
        [ (CmdArea
CaMapLeader, HumanCmd
grabCmd)
        , (CmdArea
CaMapParty, HumanCmd
PickLeaderWithPointer)
        , (CmdArea
CaMap, HumanCmd
goToOrRunTo)
        , (CmdArea
CaArenaName, HumanCmd
Dashboard)
        , (CmdArea
CaPercentSeen, HumanCmd
autoexploreCmd) ]
    , aiming :: HumanCmd
aiming = [(CmdArea, HumanCmd)] -> HumanCmd
ByArea ([(CmdArea, HumanCmd)] -> HumanCmd)
-> [(CmdArea, HumanCmd)] -> HumanCmd
forall a b. (a -> b) -> a -> b
$ [(CmdArea, HumanCmd)]
common [(CmdArea, HumanCmd)]
-> [(CmdArea, HumanCmd)] -> [(CmdArea, HumanCmd)]
forall a. [a] -> [a] -> [a]
++  -- aiming mode
        [ (CmdArea
CaMap, HumanCmd
aimFlingCmd)
        , (CmdArea
CaArenaName, HumanCmd
Accept)
        , (CmdArea
CaPercentSeen, Bool -> HumanCmd
XhairStair Bool
True) ] }
  common :: [(CmdArea, HumanCmd)]
common =
    [ (CmdArea
CaMessage, HumanCmd -> HumanCmd
ExecuteIfClear HumanCmd
LastHistory)
    , (CmdArea
CaLevelNumber, Int -> HumanCmd
AimAscend 1)
    , (CmdArea
CaXhairDesc, HumanCmd
AimEnemy)  -- inits aiming and then cycles enemies
    , (CmdArea
CaSelected, HumanCmd
PickLeaderWithPointer)
--    , (CaCalmGauge, Macro ["KP_Begin", "C-V"])
    , (CmdArea
CaCalmValue, HumanCmd
Yell)
    , (CmdArea
CaHPGauge, [String] -> HumanCmd
Macro ["KP_Begin", "C-V"])
    , (CmdArea
CaHPValue, HumanCmd
Wait)
    , (CmdArea
CaLeaderDesc, [TriggerItem] -> HumanCmd
projectICmd [TriggerItem]
flingTs) ]

mouseMMB :: CmdTriple
mouseMMB :: CmdTriple
mouseMMB = ( [CmdCategory
CmdMouse]
           , "snap x-hair to floor under pointer"
           , HumanCmd
XhairPointerFloor )

mouseRMB :: CmdTriple
mouseRMB :: CmdTriple
mouseRMB = ( [CmdCategory
CmdMouse]
           , "start aiming at enemy under pointer"
           , AimModeCmd -> HumanCmd
ByAimMode AimModeCmd
aimMode )
 where
  aimMode :: AimModeCmd
aimMode = $WAimModeCmd :: HumanCmd -> HumanCmd -> AimModeCmd
AimModeCmd
    { exploration :: HumanCmd
exploration = [(CmdArea, HumanCmd)] -> HumanCmd
ByArea ([(CmdArea, HumanCmd)] -> HumanCmd)
-> [(CmdArea, HumanCmd)] -> HumanCmd
forall a b. (a -> b) -> a -> b
$ [(CmdArea, HumanCmd)]
common [(CmdArea, HumanCmd)]
-> [(CmdArea, HumanCmd)] -> [(CmdArea, HumanCmd)]
forall a. [a] -> [a] -> [a]
++
        [ (CmdArea
CaMapLeader, HumanCmd
dropCmd)
        , (CmdArea
CaMapParty, HumanCmd
SelectWithPointer)
        , (CmdArea
CaMap, HumanCmd
AimPointerEnemy)
        , (CmdArea
CaArenaName, HumanCmd
MainMenuAutoOff)
        , (CmdArea
CaPercentSeen, HumanCmd
autoexplore25Cmd) ]
    , aiming :: HumanCmd
aiming = [(CmdArea, HumanCmd)] -> HumanCmd
ByArea ([(CmdArea, HumanCmd)] -> HumanCmd)
-> [(CmdArea, HumanCmd)] -> HumanCmd
forall a b. (a -> b) -> a -> b
$ [(CmdArea, HumanCmd)]
common [(CmdArea, HumanCmd)]
-> [(CmdArea, HumanCmd)] -> [(CmdArea, HumanCmd)]
forall a. [a] -> [a] -> [a]
++
        [ (CmdArea
CaMap, HumanCmd
XhairPointerEnemy)  -- hack; same effect, but matches LMB
        , (CmdArea
CaArenaName, HumanCmd
Cancel)
        , (CmdArea
CaPercentSeen, Bool -> HumanCmd
XhairStair Bool
False) ] }
  common :: [(CmdArea, HumanCmd)]
common =
    [ (CmdArea
CaMessage, HumanCmd
Hint)
    , (CmdArea
CaLevelNumber, Int -> HumanCmd
AimAscend (-1))
    , (CmdArea
CaXhairDesc, HumanCmd
AimItem)
    , (CmdArea
CaSelected, HumanCmd
SelectWithPointer)
--    , (CaCalmGauge, Macro ["C-KP_Begin", "V"])
    , (CmdArea
CaCalmValue, HumanCmd
Yell)
    , (CmdArea
CaHPGauge, [String] -> HumanCmd
Macro ["C-KP_Begin", "V"])
    , (CmdArea
CaHPValue, HumanCmd
Wait10)
    , (CmdArea
CaLeaderDesc, HumanCmd -> HumanCmd -> HumanCmd
ComposeUnlessError HumanCmd
ClearTargetIfItemClear HumanCmd
ItemClear) ]

-- This is duplicated wrt content, instead of included via @semicolon@,
-- because the C- commands are less likely to be modified by the player.
goToCmd :: HumanCmd
goToCmd :: HumanCmd
goToCmd = [String] -> HumanCmd
Macro ["MiddleButtonRelease", "C-semicolon", "C-quotedbl", "C-V"]

-- This is duplicated wrt content, instead of included via @colon@,
-- because the C- commands are less likely to be modified by the player.
runToAllCmd :: HumanCmd
runToAllCmd :: HumanCmd
runToAllCmd = [String] -> HumanCmd
Macro ["MiddleButtonRelease", "C-colon", "C-quotedbl", "C-V"]

autoexploreCmd :: HumanCmd
autoexploreCmd :: HumanCmd
autoexploreCmd = [String] -> HumanCmd
Macro ["C-?", "C-quotedbl", "C-V"]

autoexplore25Cmd :: HumanCmd
autoexplore25Cmd :: HumanCmd
autoexplore25Cmd = [String] -> HumanCmd
Macro ["'", "C-?", "C-quotedbl", "'", "C-V"]

aimFlingCmd :: HumanCmd
aimFlingCmd :: HumanCmd
aimFlingCmd = HumanCmd -> HumanCmd -> HumanCmd
ComposeIfLocal HumanCmd
AimPointerEnemy ([TriggerItem] -> HumanCmd
projectICmd [TriggerItem]
flingTs)

projectICmd :: [TriggerItem] -> HumanCmd
projectICmd :: [TriggerItem] -> HumanCmd
projectICmd ts :: [TriggerItem]
ts = HumanCmd -> HumanCmd -> HumanCmd
ComposeUnlessError ([TriggerItem] -> HumanCmd
ChooseItemProject [TriggerItem]
ts) HumanCmd
Project

projectI :: [TriggerItem] -> CmdTriple
projectI :: [TriggerItem] -> CmdTriple
projectI ts :: [TriggerItem]
ts = ([], [TriggerItem] -> Text
descIs [TriggerItem]
ts, [TriggerItem] -> HumanCmd
projectICmd [TriggerItem]
ts)

projectA :: [TriggerItem] -> CmdTriple
projectA :: [TriggerItem] -> CmdTriple
projectA ts :: [TriggerItem]
ts =
  let fling :: HumanCmd
fling = HumanCmd -> HumanCmd -> HumanCmd
Compose2ndLocal HumanCmd
Project HumanCmd
ItemClear
      flingICmd :: HumanCmd
flingICmd = HumanCmd -> HumanCmd -> HumanCmd
ComposeUnlessError ([TriggerItem] -> HumanCmd
ChooseItemProject [TriggerItem]
ts) HumanCmd
fling
  in HumanCmd -> CmdTriple -> CmdTriple
replaceCmd (AimModeCmd -> HumanCmd
ByAimMode $WAimModeCmd :: HumanCmd -> HumanCmd -> AimModeCmd
AimModeCmd { exploration :: HumanCmd
exploration = HumanCmd
AimTgt
                                      , aiming :: HumanCmd
aiming = HumanCmd
flingICmd })
                ([TriggerItem] -> CmdTriple
projectI [TriggerItem]
ts)

flingTs :: [TriggerItem]
flingTs :: [TriggerItem]
flingTs = [$WTriggerItem :: Part -> Part -> String -> TriggerItem
TriggerItem { tiverb :: Part
tiverb = "fling"
                       , tiobject :: Part
tiobject = "projectile"
                       , tisymbols :: String
tisymbols = "" }]

applyIK :: [TriggerItem] -> CmdTriple
applyIK :: [TriggerItem] -> CmdTriple
applyIK ts :: [TriggerItem]
ts =
  ([], [TriggerItem] -> Text
descIs [TriggerItem]
ts, HumanCmd -> HumanCmd -> HumanCmd
ComposeUnlessError ([TriggerItem] -> HumanCmd
ChooseItemApply [TriggerItem]
ts) HumanCmd
Apply)

applyI :: [TriggerItem] -> CmdTriple
applyI :: [TriggerItem] -> CmdTriple
applyI ts :: [TriggerItem]
ts =
  let apply :: HumanCmd
apply = HumanCmd -> HumanCmd -> HumanCmd
Compose2ndLocal HumanCmd
Apply HumanCmd
ItemClear
  in ([], [TriggerItem] -> Text
descIs [TriggerItem]
ts, HumanCmd -> HumanCmd -> HumanCmd
ComposeUnlessError ([TriggerItem] -> HumanCmd
ChooseItemApply [TriggerItem]
ts) HumanCmd
apply)

grabCmd :: HumanCmd
grabCmd :: HumanCmd
grabCmd = [CStore] -> CStore -> Maybe Part -> Bool -> HumanCmd
MoveItem [CStore
CGround] CStore
CEqp (Part -> Maybe Part
forall a. a -> Maybe a
Just "grab") Bool
True
            -- @CEqp@ is the implicit default; refined in HandleHumanGlobalM

grabItems :: Text -> CmdTriple
grabItems :: Text -> CmdTriple
grabItems t :: Text
t = ([CmdCategory
CmdItemMenu], Text
t, HumanCmd
grabCmd)

dropCmd :: HumanCmd
dropCmd :: HumanCmd
dropCmd = [CStore] -> CStore -> Maybe Part -> Bool -> HumanCmd
MoveItem [CStore
CEqp, CStore
CInv, CStore
CSha] CStore
CGround Maybe Part
forall a. Maybe a
Nothing Bool
False

dropItems :: Text -> CmdTriple
dropItems :: Text -> CmdTriple
dropItems t :: Text
t = ([CmdCategory
CmdItemMenu], Text
t, HumanCmd
dropCmd)

descIs :: [TriggerItem] -> Text
descIs :: [TriggerItem] -> Text
descIs [] = "trigger an item"
descIs (t :: TriggerItem
t : _) = [Part] -> Text
makePhrase [TriggerItem -> Part
tiverb TriggerItem
t, TriggerItem -> Part
tiobject TriggerItem
t]

descTs :: [TriggerTile] -> Text
descTs :: [TriggerTile] -> Text
descTs [] = "alter a tile"
descTs (t :: TriggerTile
t : _) = [Part] -> Text
makePhrase [TriggerTile -> Part
ttverb TriggerTile
t, TriggerTile -> Part
ttobject TriggerTile
t]

defaultHeroSelect :: Int -> (String, CmdTriple)
defaultHeroSelect :: Int -> (String, CmdTriple)
defaultHeroSelect k :: Int
k = ([Int -> Char
Char.intToDigit Int
k], ([CmdCategory
CmdMeta], "", Int -> HumanCmd
PickLeader Int
k))