{-# LANGUAGE OverloadedStrings #-}

-- |
-- SPDX-License-Identifier: BSD-3-Clause
--
-- Capabilities needed to evaluate and execute programs.  Language
-- constructs or commands require certain capabilities, and in turn
-- capabilities are provided by various devices.  A robot must have an
-- appropriate device equipped in order to make use of each language
-- construct or command.
module Swarm.Language.Capability (
  Capability (..),
  capabilityName,
  constCaps,
  constByCaps,
) where

import Control.Arrow ((&&&))
import Data.Aeson (FromJSONKey, ToJSONKey)
import Data.Char (toLower)
import Data.Data (Data)
import Data.Hashable (Hashable)
import Data.List.NonEmpty qualified as NE
import Data.Map (Map)
import Data.Maybe (mapMaybe)
import Data.Text (Text)
import Data.Text qualified as T
import Data.Tuple (swap)
import Data.Yaml
import GHC.Generics (Generic)
import Swarm.Language.Syntax.Constants (Const (..), allConst)
import Swarm.Util (binTuples, failT)
import Text.Read (readMaybe)
import Witch (from)
import Prelude hiding (lookup)

-- | Various capabilities which robots can have.
data Capability
  = -- | Be powered, i.e. execute anything at all
    CPower
  | -- | Execute the 'Move' command
    CMove
  | -- | Execute the 'Backup' command
    CBackup
  | -- | Execute the 'Volume' command
    CVolume
  | -- | Execute the 'Path' command
    CPath
  | -- | Execute the 'Push' command
    CPush
  | -- | Execute the 'Stride' command
    CMovemultiple
  | -- | Execute the 'Move' command for a heavy robot
    CMoveheavy
  | -- | Execute the 'Turn' command
    --
    -- NOTE: using cardinal directions is separate 'COrient' capability
    CTurn
  | -- | Execute the 'Selfdestruct' command
    CSelfdestruct
  | -- | Execute the 'Grab' command
    CGrab
  | -- | Execute the 'Harvest' command
    CHarvest
  | -- | Execute the 'Sow' command
    CSow
  | -- | Execute the 'Ignite' command
    CIgnite
  | -- | Execute the 'Place' command
    CPlace
  | -- | Execute the 'Ping' command
    CPing
  | -- | Execute the 'Give' command
    CGive
  | -- | Execute the 'Equip' command
    CEquip
  | -- | Execute the 'Unequip' command
    CUnequip
  | -- | Execute the 'Make' command
    CMake
  | -- | Execute the 'Count' command
    CCount
  | -- | Execute the 'Scout' command. Reconnaissance along a line in a direction.
    CRecondir
  | -- | Execute the 'Build' command
    CBuild
  | -- | Execute the 'Salvage' command
    CSalvage
  | -- | Execute the 'Drill' command
    CDrill
  | -- | Execute the 'Waypoint' command
    CWaypoint
  | -- | Execute the 'Structure' and 'Floorplan' commands
    CStructure
  | -- | Execute the 'HasTag' command
    CHastag
  | -- | Execute the 'TagMembers' command
    CTagmembers
  | -- | Execute the 'Whereami' command
    CSenseloc
  | -- | Execute the 'Blocked' command
    CSensefront
  | -- | Execute the 'Ishere' and 'Isempty' commands
    CSensehere
  | -- | Execute the 'Detect' command
    CDetectloc
  | -- | Execute the 'Resonate' and 'Density' commands
    CDetectcount
  | -- | Execute the 'Sniff' command
    CDetectdistance
  | -- | Execute the 'Chirp' command
    CDetectdirection
  | -- | Execute the 'Watch' command
    CWakeself
  | -- | Execute the 'Scan' command
    CScan
  | -- | Execute the 'Random' command
    CRandom
  | -- | Execute the 'Appear' command
    CAppear
  | -- | Execute the 'Create' command
    CCreate
  | -- | Execute the 'Listen' command and passively log messages if also has 'CLog'
    CListen
  | -- | Execute the 'Log' command
    CLog
  | -- | Format values as text
    CFormat
  | -- | Split text into two pieces
    CConcat
  | -- | Join two text values into one
    CSplit
  | -- | Count the characters in a text value
    CCharcount
  | -- | Convert between characters/text and Unicode values
    CCode
  | -- | Don't drown in liquid
    CFloat
  | -- | Evaluate conditional expressions
    CCond
  | -- | Negate boolean value
    CNegation
  | -- | Evaluate comparison operations
    CCompare
  | -- | Use cardinal direction constants.
    COrient
  | -- | Evaluate arithmetic operations
    CArith
  | -- | Store and look up definitions in an environment
    CEnv
  | -- | Interpret lambda abstractions
    CLambda
  | -- | Enable recursive definitions
    CRecursion
  | -- | Execute the 'Reprogram' command
    CReprogram
  | -- | Execute the `meet` and `meetAll` commands.
    CMeet
  | -- | Capability to introspect and see its own name
    CWhoami
  | -- | Capability to set its own name
    CSetname
  | -- | Capability to move unrestricted to any place
    CTeleport
  | -- | Capability to run commands atomically
    CAtomic
  | -- | Capability to execute swap (grab and place atomically at the same time).
    CSwap
  | -- | Capability to obtain absolute time, namely via the `time` command.
    CTimeabs
  | -- | Capability to utilize relative passage of time, namely via the `wait` command.
    --   This is strictly weaker than "CTimeAbs".
    CTimerel
  | -- | Capability to execute `try`.
    CTry
  | -- | Capability for working with sum types.
    CSum
  | -- | Capability for working with product types.
    CProd
  | -- | Capability for working with record types.
    CRecord
  | -- | Debug capability.
    CDebug
  | -- | Capability to handle keyboard input.
    CHandleinput
  | -- | Capability to make other robots halt.
    CHalt
  | -- | Capability to handle recursive types.
    CRectype
  | -- | God-like capabilities.  For e.g. commands intended only for
    --   checking challenge mode win conditions, and not for use by
    --   players.
    CGod
  deriving (Capability -> Capability -> Bool
(Capability -> Capability -> Bool)
-> (Capability -> Capability -> Bool) -> Eq Capability
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Capability -> Capability -> Bool
== :: Capability -> Capability -> Bool
$c/= :: Capability -> Capability -> Bool
/= :: Capability -> Capability -> Bool
Eq, Eq Capability
Eq Capability =>
(Capability -> Capability -> Ordering)
-> (Capability -> Capability -> Bool)
-> (Capability -> Capability -> Bool)
-> (Capability -> Capability -> Bool)
-> (Capability -> Capability -> Bool)
-> (Capability -> Capability -> Capability)
-> (Capability -> Capability -> Capability)
-> Ord Capability
Capability -> Capability -> Bool
Capability -> Capability -> Ordering
Capability -> Capability -> Capability
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Capability -> Capability -> Ordering
compare :: Capability -> Capability -> Ordering
$c< :: Capability -> Capability -> Bool
< :: Capability -> Capability -> Bool
$c<= :: Capability -> Capability -> Bool
<= :: Capability -> Capability -> Bool
$c> :: Capability -> Capability -> Bool
> :: Capability -> Capability -> Bool
$c>= :: Capability -> Capability -> Bool
>= :: Capability -> Capability -> Bool
$cmax :: Capability -> Capability -> Capability
max :: Capability -> Capability -> Capability
$cmin :: Capability -> Capability -> Capability
min :: Capability -> Capability -> Capability
Ord, Int -> Capability -> ShowS
[Capability] -> ShowS
Capability -> String
(Int -> Capability -> ShowS)
-> (Capability -> String)
-> ([Capability] -> ShowS)
-> Show Capability
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Capability -> ShowS
showsPrec :: Int -> Capability -> ShowS
$cshow :: Capability -> String
show :: Capability -> String
$cshowList :: [Capability] -> ShowS
showList :: [Capability] -> ShowS
Show, ReadPrec [Capability]
ReadPrec Capability
Int -> ReadS Capability
ReadS [Capability]
(Int -> ReadS Capability)
-> ReadS [Capability]
-> ReadPrec Capability
-> ReadPrec [Capability]
-> Read Capability
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Capability
readsPrec :: Int -> ReadS Capability
$creadList :: ReadS [Capability]
readList :: ReadS [Capability]
$creadPrec :: ReadPrec Capability
readPrec :: ReadPrec Capability
$creadListPrec :: ReadPrec [Capability]
readListPrec :: ReadPrec [Capability]
Read, Int -> Capability
Capability -> Int
Capability -> [Capability]
Capability -> Capability
Capability -> Capability -> [Capability]
Capability -> Capability -> Capability -> [Capability]
(Capability -> Capability)
-> (Capability -> Capability)
-> (Int -> Capability)
-> (Capability -> Int)
-> (Capability -> [Capability])
-> (Capability -> Capability -> [Capability])
-> (Capability -> Capability -> [Capability])
-> (Capability -> Capability -> Capability -> [Capability])
-> Enum Capability
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Capability -> Capability
succ :: Capability -> Capability
$cpred :: Capability -> Capability
pred :: Capability -> Capability
$ctoEnum :: Int -> Capability
toEnum :: Int -> Capability
$cfromEnum :: Capability -> Int
fromEnum :: Capability -> Int
$cenumFrom :: Capability -> [Capability]
enumFrom :: Capability -> [Capability]
$cenumFromThen :: Capability -> Capability -> [Capability]
enumFromThen :: Capability -> Capability -> [Capability]
$cenumFromTo :: Capability -> Capability -> [Capability]
enumFromTo :: Capability -> Capability -> [Capability]
$cenumFromThenTo :: Capability -> Capability -> Capability -> [Capability]
enumFromThenTo :: Capability -> Capability -> Capability -> [Capability]
Enum, Capability
Capability -> Capability -> Bounded Capability
forall a. a -> a -> Bounded a
$cminBound :: Capability
minBound :: Capability
$cmaxBound :: Capability
maxBound :: Capability
Bounded, (forall x. Capability -> Rep Capability x)
-> (forall x. Rep Capability x -> Capability) -> Generic Capability
forall x. Rep Capability x -> Capability
forall x. Capability -> Rep Capability x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Capability -> Rep Capability x
from :: forall x. Capability -> Rep Capability x
$cto :: forall x. Rep Capability x -> Capability
to :: forall x. Rep Capability x -> Capability
Generic, Eq Capability
Eq Capability =>
(Int -> Capability -> Int)
-> (Capability -> Int) -> Hashable Capability
Int -> Capability -> Int
Capability -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> Capability -> Int
hashWithSalt :: Int -> Capability -> Int
$chash :: Capability -> Int
hash :: Capability -> Int
Hashable, Typeable Capability
Typeable Capability =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> Capability -> c Capability)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Capability)
-> (Capability -> Constr)
-> (Capability -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Capability))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c Capability))
-> ((forall b. Data b => b -> b) -> Capability -> Capability)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Capability -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Capability -> r)
-> (forall u. (forall d. Data d => d -> u) -> Capability -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> Capability -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Capability -> m Capability)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Capability -> m Capability)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Capability -> m Capability)
-> Data Capability
Capability -> Constr
Capability -> DataType
(forall b. Data b => b -> b) -> Capability -> Capability
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Capability -> u
forall u. (forall d. Data d => d -> u) -> Capability -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Capability -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Capability -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Capability -> m Capability
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Capability -> m Capability
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Capability
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Capability -> c Capability
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Capability)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Capability)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Capability -> c Capability
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Capability -> c Capability
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Capability
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Capability
$ctoConstr :: Capability -> Constr
toConstr :: Capability -> Constr
$cdataTypeOf :: Capability -> DataType
dataTypeOf :: Capability -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Capability)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Capability)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Capability)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Capability)
$cgmapT :: (forall b. Data b => b -> b) -> Capability -> Capability
gmapT :: (forall b. Data b => b -> b) -> Capability -> Capability
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Capability -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Capability -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Capability -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Capability -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Capability -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> Capability -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Capability -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Capability -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Capability -> m Capability
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Capability -> m Capability
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Capability -> m Capability
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Capability -> m Capability
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Capability -> m Capability
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Capability -> m Capability
Data, FromJSONKeyFunction [Capability]
FromJSONKeyFunction Capability
FromJSONKeyFunction Capability
-> FromJSONKeyFunction [Capability] -> FromJSONKey Capability
forall a.
FromJSONKeyFunction a -> FromJSONKeyFunction [a] -> FromJSONKey a
$cfromJSONKey :: FromJSONKeyFunction Capability
fromJSONKey :: FromJSONKeyFunction Capability
$cfromJSONKeyList :: FromJSONKeyFunction [Capability]
fromJSONKeyList :: FromJSONKeyFunction [Capability]
FromJSONKey, ToJSONKeyFunction [Capability]
ToJSONKeyFunction Capability
ToJSONKeyFunction Capability
-> ToJSONKeyFunction [Capability] -> ToJSONKey Capability
forall a.
ToJSONKeyFunction a -> ToJSONKeyFunction [a] -> ToJSONKey a
$ctoJSONKey :: ToJSONKeyFunction Capability
toJSONKey :: ToJSONKeyFunction Capability
$ctoJSONKeyList :: ToJSONKeyFunction [Capability]
toJSONKeyList :: ToJSONKeyFunction [Capability]
ToJSONKey)

capabilityName :: Capability -> Text
capabilityName :: Capability -> Text
capabilityName = forall source target. From source target => source -> target
from @String (String -> Text) -> (Capability -> String) -> Capability -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower ShowS -> (Capability -> String) -> Capability -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
forall a. Int -> [a] -> [a]
drop Int
1 ShowS -> (Capability -> String) -> Capability -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Capability -> String
forall a. Show a => a -> String
show

instance ToJSON Capability where
  toJSON :: Capability -> Value
toJSON = Text -> Value
String (Text -> Value) -> (Capability -> Text) -> Capability -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Capability -> Text
capabilityName

instance FromJSON Capability where
  parseJSON :: Value -> Parser Capability
parseJSON = String -> (Text -> Parser Capability) -> Value -> Parser Capability
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"Capability" Text -> Parser Capability
tryRead
   where
    tryRead :: Text -> Parser Capability
    tryRead :: Text -> Parser Capability
tryRead Text
t = case String -> Maybe Capability
forall a. Read a => String -> Maybe a
readMaybe (String -> Maybe Capability)
-> (Text -> String) -> Text -> Maybe Capability
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
forall source target. From source target => source -> target
from (Text -> String) -> (Text -> Text) -> Text -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Text -> Text
T.cons Char
'C' (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.toTitle (Text -> Maybe Capability) -> Text -> Maybe Capability
forall a b. (a -> b) -> a -> b
$ Text
t of
      Just Capability
c -> Capability -> Parser Capability
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return Capability
c
      Maybe Capability
Nothing -> [Text] -> Parser Capability
forall (m :: * -> *) a. MonadFail m => [Text] -> m a
failT [Text
"Unknown capability", Text
t]

-- | Capabilities needed to evaluate or execute a constant.
constCaps :: Const -> Maybe Capability
constCaps :: Const -> Maybe Capability
constCaps = \case
  -- ----------------------------------------------------------------
  -- Some built-in constants that don't require any special capability.
  Const
Noop -> Maybe Capability
forall a. Maybe a
Nothing
  Const
AppF -> Maybe Capability
forall a. Maybe a
Nothing
  Const
Force -> Maybe Capability
forall a. Maybe a
Nothing
  Const
Return -> Maybe Capability
forall a. Maybe a
Nothing
  Const
Parent -> Maybe Capability
forall a. Maybe a
Nothing
  Const
Base -> Maybe Capability
forall a. Maybe a
Nothing
  Const
Setname -> Maybe Capability
forall a. Maybe a
Nothing
  Const
Undefined -> Maybe Capability
forall a. Maybe a
Nothing
  Const
Fail -> Maybe Capability
forall a. Maybe a
Nothing
  Const
Has -> Maybe Capability
forall a. Maybe a
Nothing
  Const
Equipped -> Maybe Capability
forall a. Maybe a
Nothing
  -- speaking is natural to robots (unlike listening)
  Const
Say -> Maybe Capability
forall a. Maybe a
Nothing
  -- TODO: #495
  --   the require command will be inlined once the Issue is fixed
  --   so the capabilities of the run commands will be checked instead
  Const
Run -> Maybe Capability
forall a. Maybe a
Nothing
  -- ----------------------------------------------------------------
  -- Some straightforward ones.
  Const
Listen -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CListen
  Const
Log -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CLog
  Const
Selfdestruct -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSelfdestruct
  Const
Move -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CMove
  Const
Backup -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CBackup
  Const
Volume -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CVolume
  Const
Path -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CPath
  Const
Push -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CPush
  Const
Stride -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CMovemultiple
  Const
Turn -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CTurn
  Const
Grab -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CGrab
  Const
Harvest -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CHarvest
  Const
Sow -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSow
  Const
Ignite -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CIgnite
  Const
Place -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CPlace
  Const
Ping -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CPing
  Const
Give -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CGive
  Const
Equip -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CEquip
  Const
Unequip -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CUnequip
  Const
Make -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CMake
  Const
Count -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCount
  Const
If -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCond
  Const
Blocked -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSensefront
  Const
Scan -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CScan
  Const
Ishere -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSensehere
  Const
Isempty -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSensehere
  Const
Upload -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CScan
  Const
Build -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CBuild
  Const
Salvage -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSalvage
  Const
Reprogram -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CReprogram
  Const
Meet -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CMeet
  Const
MeetAll -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CMeet
  Const
Drill -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CDrill
  Const
Use -> Maybe Capability
forall a. Maybe a
Nothing -- Recipes alone shall dictate whether things can be "used"
  Const
Neg -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CArith
  Const
Add -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CArith
  Const
Sub -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CArith
  Const
Mul -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CArith
  Const
Div -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CArith
  Const
Exp -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CArith
  Const
Whoami -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CWhoami
  Const
Self -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CWhoami
  Const
Swap -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSwap
  Const
Atomic -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CAtomic
  Const
Instant -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CGod
  Const
Time -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CTimeabs
  Const
Wait -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CTimerel
  Const
Scout -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CRecondir
  Const
Whereami -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSenseloc
  Const
Waypoint -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CWaypoint
  Const
Structure -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CStructure
  Const
Floorplan -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CStructure
  Const
HasTag -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CHastag
  Const
TagMembers -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CTagmembers
  Const
Detect -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CDetectloc
  Const
Resonate -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CDetectcount
  Const
Density -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CDetectcount
  Const
Sniff -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CDetectdistance
  Const
Chirp -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CDetectdirection
  Const
Watch -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CWakeself
  Const
Heading -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
COrient
  Const
Key -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CHandleinput
  Const
InstallKeyHandler -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CHandleinput
  Const
Halt -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CHalt
  -- ----------------------------------------------------------------
  -- Text operations
  Const
Format -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CFormat
  Const
Concat -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CConcat
  Const
Split -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSplit
  Const
Chars -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCharcount
  Const
CharAt -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCode
  Const
ToChar -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCode
  -- ----------------------------------------------------------------
  -- Some God-like abilities.
  Const
As -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CGod
  Const
RobotNamed -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CGod
  Const
RobotNumbered -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CGod
  Const
Create -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CGod
  Const
Surveil -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CGod
  -- ----------------------------------------------------------------
  -- arithmetic
  Const
Eq -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCompare
  Const
Neq -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCompare
  Const
Lt -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCompare
  Const
Gt -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCompare
  Const
Leq -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCompare
  Const
Geq -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCompare
  -- ----------------------------------------------------------------
  -- boolean logic
  Const
And -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCond
  Const
Or -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CCond
  Const
Not -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CNegation
  -- ----------------------------------------------------------------
  -- exceptions
  Const
Try -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CTry
  -- ----------------------------------------------------------------
  -- type-level arithmetic
  Const
Inl -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSum
  Const
Inr -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSum
  Const
Case -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CSum
  Const
Fst -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CProd
  Const
Snd -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CProd
  -- TODO: #563 pair syntax (1,2,3...) should require CProd too

  -- ----------------------------------------------------------------
  -- Some additional straightforward ones, which however currently
  -- cannot be used in classic mode since there is no craftable item
  -- which conveys their capability. TODO: #26
  Const
Teleport -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CTeleport -- Some space-time machine like Tardis?
  Const
Appear -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CAppear -- paint?
  Const
Random -> Capability -> Maybe Capability
forall a. a -> Maybe a
Just Capability
CRandom -- randomness device (with bitcoins)?
  -- ----------------------------------------------------------------
  -- Some more constants which *ought* to have their own capability but
  -- currently don't.
  Const
View -> Maybe Capability
forall a. Maybe a
Nothing -- TODO: #17 should require equipping an antenna
  Const
Knows -> Maybe Capability
forall a. Maybe a
Nothing

-- | Inverts the 'constCaps' mapping.
constByCaps :: Map Capability (NE.NonEmpty Const)
constByCaps :: Map Capability (NonEmpty Const)
constByCaps =
  [(Capability, Const)] -> Map Capability (NonEmpty Const)
forall (t :: * -> *) a b.
(Foldable t, Ord a) =>
t (a, b) -> Map a (NonEmpty b)
binTuples ([(Capability, Const)] -> Map Capability (NonEmpty Const))
-> [(Capability, Const)] -> Map Capability (NonEmpty Const)
forall a b. (a -> b) -> a -> b
$
    ((Const, Capability) -> (Capability, Const))
-> [(Const, Capability)] -> [(Capability, Const)]
forall a b. (a -> b) -> [a] -> [b]
map (Const, Capability) -> (Capability, Const)
forall a b. (a, b) -> (b, a)
swap ([(Const, Capability)] -> [(Capability, Const)])
-> [(Const, Capability)] -> [(Capability, Const)]
forall a b. (a -> b) -> a -> b
$
      (Const -> Maybe (Const, Capability))
-> [Const] -> [(Const, Capability)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ((Const, Maybe Capability) -> Maybe (Const, Capability)
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
forall (f :: * -> *) a.
Applicative f =>
(Const, f a) -> f (Const, a)
sequenceA ((Const, Maybe Capability) -> Maybe (Const, Capability))
-> (Const -> (Const, Maybe Capability))
-> Const
-> Maybe (Const, Capability)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Const -> Const
forall a. a -> a
id (Const -> Const)
-> (Const -> Maybe Capability)
-> Const
-> (Const, Maybe Capability)
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& Const -> Maybe Capability
constCaps)) [Const]
allConst