-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | 2D resource gathering game with programmable robots
--
-- Swarm is a 2D programming and resource gathering game. Program your
-- robots to explore the world and collect resources, which in turn
-- allows you to build upgraded robots that can run more interesting and
-- complex programs. See the README for more information and instructions
-- on how to play or contribute!
@package swarm
@version 0.4
-- | A carrier for Accum effects. This carrier performs its append
-- operations strictly and thus avoids the space leaks inherent in lazy
-- writer monads. These appends are left-associative; as such,
-- [] is a poor choice of monoid for computations that entail
-- many calls to tell. The Seq or DList monoids
-- may be a superior choice.
module Control.Carrier.Accum.FixedStrict
-- | Run an Accum effect with a Monoidal log, applying a
-- continuation to the final log and result.
--
--
-- runAccum w0 (pure a) = pure (w0, a)
--
--
--
-- runAccum w0 (add w) = pure (w0 <> w, ())
--
--
--
-- runAccum w0 (add w >> look) = pure (w0 <> w, w0 <> w)
--
runAccum :: w -> AccumC w m a -> m (w, a)
-- | Run a Accum effect (typically with a Monoidal log),
-- producing the final log and discarding the result value.
--
--
-- execAccum w = fmap fst . runAccum w
--
execAccum :: Functor m => w -> AccumC w m a -> m w
-- | Run a Accum effect (typically with a Monoidal log),
-- producing the result value and discarding the final log.
--
--
-- evalAccum w = fmap snd . runAccum w
--
evalAccum :: Functor m => w -> AccumC w m a -> m a
newtype AccumC w m a
AccumC :: (w -> m (w, a)) -> AccumC w m a
instance GHC.Base.Monoid w => Control.Monad.Trans.Class.MonadTrans (Control.Carrier.Accum.FixedStrict.AccumC w)
instance GHC.Base.Functor m => GHC.Base.Functor (Control.Carrier.Accum.FixedStrict.AccumC w m)
instance (GHC.Base.Monad m, GHC.Base.Monoid w) => GHC.Base.Applicative (Control.Carrier.Accum.FixedStrict.AccumC w m)
instance (GHC.Base.Alternative m, GHC.Base.Monad m, GHC.Base.Monoid w) => GHC.Base.Alternative (Control.Carrier.Accum.FixedStrict.AccumC w m)
instance (GHC.Base.Monad m, GHC.Base.Monoid w) => GHC.Base.Monad (Control.Carrier.Accum.FixedStrict.AccumC w m)
instance (GHC.Base.MonadPlus m, GHC.Base.Monoid w) => GHC.Base.MonadPlus (Control.Carrier.Accum.FixedStrict.AccumC w m)
instance (Control.Monad.Fail.MonadFail m, GHC.Base.Monoid w) => Control.Monad.Fail.MonadFail (Control.Carrier.Accum.FixedStrict.AccumC w m)
instance (Control.Monad.Fix.MonadFix m, GHC.Base.Monoid w) => Control.Monad.Fix.MonadFix (Control.Carrier.Accum.FixedStrict.AccumC w m)
instance (Control.Monad.IO.Class.MonadIO m, GHC.Base.Monoid w) => Control.Monad.IO.Class.MonadIO (Control.Carrier.Accum.FixedStrict.AccumC w m)
instance (Control.Algebra.Algebra sig m, GHC.Base.Monoid w) => Control.Algebra.Algebra (Control.Effect.Accum.Internal.Accum w Control.Effect.Sum.:+: sig) (Control.Carrier.Accum.FixedStrict.AccumC w m)
-- | Simplification logic for boolean expressions that is not provided in
-- the boolexpr package.
module Data.BoolExpr.Simplify
cannotBeTrue :: Ord a => BoolExpr a -> Bool
replace :: Ord a => Map a Bool -> BoolExpr a -> BoolExpr a
-- | Constants used throughout the UI and game
module Swarm.Constant
swarmRepoUrl :: Text
wikiUrl :: Text
wikiCheatSheet :: Text
-- | A model for defining boolean expressions for Objective prerequisites.
--
-- This model is intended to be user-facing in the .yaml files, and is
-- distinct from that in BoolExpr.
module Swarm.Game.Scenario.Objective.Logic
type ObjectiveLabel = Text
-- | In contrast with the BoolExpr type, And and Or
-- can have one or more children instead of exactly two.
data Prerequisite a
And :: NonEmpty (Prerequisite a) -> Prerequisite a
Or :: NonEmpty (Prerequisite a) -> Prerequisite a
Not :: Prerequisite a -> Prerequisite a
Id :: a -> Prerequisite a
prerequisiteOptions :: Options
toBoolExpr :: Prerequisite a -> BoolExpr a
instance Data.Foldable.Foldable Swarm.Game.Scenario.Objective.Logic.Prerequisite
instance GHC.Base.Functor Swarm.Game.Scenario.Objective.Logic.Prerequisite
instance GHC.Generics.Generic (Swarm.Game.Scenario.Objective.Logic.Prerequisite a)
instance GHC.Show.Show a => GHC.Show.Show (Swarm.Game.Scenario.Objective.Logic.Prerequisite a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Swarm.Game.Scenario.Objective.Logic.Prerequisite a)
instance Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.Scenario.Objective.Logic.Prerequisite Swarm.Game.Scenario.Objective.Logic.ObjectiveLabel)
instance Data.Aeson.Types.FromJSON.FromJSON (Swarm.Game.Scenario.Objective.Logic.Prerequisite Swarm.Game.Scenario.Objective.Logic.ObjectiveLabel)
module Swarm.Game.Scenario.Style
data StyleFlag
Standout :: StyleFlag
Italic :: StyleFlag
Strikethrough :: StyleFlag
Underline :: StyleFlag
ReverseVideo :: StyleFlag
Blink :: StyleFlag
Dim :: StyleFlag
Bold :: StyleFlag
styleFlagJsonOptions :: Options
newtype HexColor
HexColor :: Text -> HexColor
data CustomAttr
CustomAttr :: String -> Maybe HexColor -> Maybe HexColor -> Maybe (Set StyleFlag) -> CustomAttr
[name] :: CustomAttr -> String
[fg] :: CustomAttr -> Maybe HexColor
[bg] :: CustomAttr -> Maybe HexColor
[style] :: CustomAttr -> Maybe (Set StyleFlag)
instance GHC.Generics.Generic Swarm.Game.Scenario.Style.StyleFlag
instance GHC.Show.Show Swarm.Game.Scenario.Style.StyleFlag
instance GHC.Classes.Ord Swarm.Game.Scenario.Style.StyleFlag
instance GHC.Classes.Eq Swarm.Game.Scenario.Style.StyleFlag
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Style.HexColor
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Style.HexColor
instance GHC.Generics.Generic Swarm.Game.Scenario.Style.HexColor
instance GHC.Show.Show Swarm.Game.Scenario.Style.HexColor
instance GHC.Classes.Eq Swarm.Game.Scenario.Style.HexColor
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Style.CustomAttr
instance GHC.Generics.Generic Swarm.Game.Scenario.Style.CustomAttr
instance GHC.Show.Show Swarm.Game.Scenario.Style.CustomAttr
instance GHC.Classes.Eq Swarm.Game.Scenario.Style.CustomAttr
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Style.CustomAttr
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Style.StyleFlag
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Style.StyleFlag
-- | Generic contexts (mappings from variables to other things, such as
-- types, values, or capability sets) used throughout the codebase.
module Swarm.Language.Context
-- | We use Text values to represent variables.
type Var = Text
-- | A context is a mapping from variable names to things.
newtype Ctx t
Ctx :: Map Var t -> Ctx t
[unCtx] :: Ctx t -> Map Var t
-- | The empty context.
empty :: Ctx t
-- | A singleton context.
singleton :: Var -> t -> Ctx t
-- | Look up a variable in a context.
lookup :: Var -> Ctx t -> Maybe t
-- | Delete a variable from a context.
delete :: Var -> Ctx t -> Ctx t
-- | Get the list of key-value associations from a context.
assocs :: Ctx t -> [(Var, t)]
-- | Add a key-value binding to a context (overwriting the old one if the
-- key is already present).
addBinding :: Var -> t -> Ctx t -> Ctx t
-- | Right-biased union of contexts.
union :: Ctx t -> Ctx t -> Ctx t
-- | Locally extend the context with an additional binding.
withBinding :: MonadReader (Ctx t) m => Var -> t -> m a -> m a
-- | Locally extend the context with an additional context of bindings.
withBindings :: MonadReader (Ctx t) m => Ctx t -> m a -> m a
instance Data.Aeson.Types.ToJSON.ToJSON t => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Language.Context.Ctx t)
instance Data.Aeson.Types.FromJSON.FromJSON t => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Language.Context.Ctx t)
instance GHC.Generics.Generic (Swarm.Language.Context.Ctx t)
instance Data.Data.Data t => Data.Data.Data (Swarm.Language.Context.Ctx t)
instance Data.Traversable.Traversable Swarm.Language.Context.Ctx
instance Data.Foldable.Foldable Swarm.Language.Context.Ctx
instance GHC.Base.Functor Swarm.Language.Context.Ctx
instance GHC.Show.Show t => GHC.Show.Show (Swarm.Language.Context.Ctx t)
instance GHC.Classes.Eq t => GHC.Classes.Eq (Swarm.Language.Context.Ctx t)
instance GHC.Base.Semigroup (Swarm.Language.Context.Ctx t)
instance GHC.Base.Monoid (Swarm.Language.Context.Ctx t)
instance Control.Lens.Empty.AsEmpty (Swarm.Language.Context.Ctx t)
-- | Types for the Swarm programming language and related utilities.
module Swarm.Language.Types
-- | Base types.
data BaseTy
-- | The void type, with no inhabitants.
BVoid :: BaseTy
-- | The unit type, with a single inhabitant.
BUnit :: BaseTy
-- | Signed, arbitrary-size integers.
BInt :: BaseTy
-- | Unicode strings.
BText :: BaseTy
-- | Directions.
BDir :: BaseTy
-- | Booleans.
BBool :: BaseTy
-- | Actors, i.e. anything that can do stuff. Internally, these are
-- all just "robots", but we give them a more generic in-game name
-- because they could represent other things like aliens, animals, seeds,
-- ...
BActor :: BaseTy
-- | Keys, i.e. things that can be pressed on the keyboard
BKey :: BaseTy
-- | We use Text values to represent variables.
type Var = Text
-- | A "structure functor" encoding the shape of type expressions. Actual
-- types are then represented by taking a fixed point of this functor. We
-- represent types in this way, via a "two-level type", so that we can
-- work with the unification-fd package (see
-- https://byorgey.wordpress.com/2021/09/08/implementing-hindley-milner-with-the-unification-fd-library/).
data TypeF t
-- | A base type.
TyBaseF :: BaseTy -> TypeF t
-- | A type variable.
TyVarF :: Var -> TypeF t
-- | Commands, with return type. Note that commands form a monad.
TyCmdF :: t -> TypeF t
-- | Type of delayed computations.
TyDelayF :: t -> TypeF t
-- | Sum type.
TySumF :: t -> t -> TypeF t
-- | Product type.
TyProdF :: t -> t -> TypeF t
-- | Function type.
TyFunF :: t -> t -> TypeF t
-- | Record type.
TyRcdF :: Map Var t -> TypeF t
-- | Type is now defined as the fixed point of TypeF. It
-- would be annoying to manually apply and match against Fix
-- constructors everywhere, so we provide pattern synonyms that allow us
-- to work with Type as if it were defined in a directly recursive
-- way.
type Type = Fix TypeF
-- | Get all the type variables contained in a Type.
tyVars :: Type -> Set Var
pattern TyBase :: BaseTy -> Type
pattern TyVar :: Var -> Type
pattern TyVoid :: Type
pattern TyUnit :: Type
pattern TyInt :: Type
pattern TyText :: Type
pattern TyDir :: Type
pattern TyBool :: Type
pattern TyActor :: Type
pattern TyKey :: Type
pattern (:+:) :: Type -> Type -> Type
infixr 5 :+:
pattern (:*:) :: Type -> Type -> Type
infixr 6 :*:
pattern (:->:) :: Type -> Type -> Type
infixr 1 :->:
pattern TyRcd :: Map Var Type -> Type
pattern TyCmd :: Type -> Type
pattern TyDelay :: Type -> Type
-- | UTypes are like Types, but also contain unification
-- variables. UType is defined via UTerm, which is also a
-- kind of fixed point (in fact, UType is the free monad
-- over TypeF).
--
-- Just as with Type, we provide a bunch of pattern synonyms for
-- working with UType as if it were defined directly.
type UType = UTerm TypeF IntVar
pattern UTyBase :: BaseTy -> UType
pattern UTyVar :: Var -> UType
pattern UTyVoid :: UType
pattern UTyUnit :: UType
pattern UTyInt :: UType
pattern UTyText :: UType
pattern UTyDir :: UType
pattern UTyBool :: UType
pattern UTyActor :: UType
pattern UTyKey :: UType
pattern UTySum :: UType -> UType -> UType
pattern UTyProd :: UType -> UType -> UType
pattern UTyFun :: UType -> UType -> UType
pattern UTyRcd :: Map Var UType -> UType
pattern UTyCmd :: UType -> UType
pattern UTyDelay :: UType -> UType
-- | A generic fold for things defined via UTerm (including,
-- in particular, UType). This probably belongs in the
-- unification-fd package, but since it doesn't provide one, we
-- define it here.
ucata :: Functor t => (v -> a) -> (t a -> a) -> UTerm t v -> a
-- | A quick-and-dirty method for turning an IntVar (used internally
-- as a unification variable) into a unique variable name, by appending a
-- number to the given name.
mkVarName :: Text -> IntVar -> Var
-- | A Poly t is a universally quantified t. The
-- variables in the list are bound inside the t. For example,
-- the type forall a. a -> a would be represented as
-- Forall ["a"] (TyFun "a" "a").
data Poly t
Forall :: [Var] -> t -> Poly t
-- | A polytype without unification variables.
type Polytype = Poly Type
pattern PolyUnit :: Polytype
-- | A polytype with unification variables.
type UPolytype = Poly UType
-- | A TCtx is a mapping from variables to polytypes. We generally
-- get one of these at the end of the type inference process.
type TCtx = Ctx Polytype
-- | A UCtx is a mapping from variables to polytypes with
-- unification variables. We generally have one of these while we are in
-- the midst of the type inference process.
type UCtx = Ctx UPolytype
-- | In several cases we have two versions of something: a "normal"
-- version, and a U version with unification variables in it
-- (e.g. Type vs UType, Polytype vs
-- UPolytype, TCtx vs UCtx). This class abstracts
-- over the process of converting back and forth between them.
--
-- In particular, WithU t represents the fact that the
-- type t also has a U counterpart, with a way to
-- convert back and forth. Note, however, that converting back may be
-- "unsafe" in the sense that it requires an extra burden of proof to
-- guarantee that it is used only on inputs that are safe.
class WithU t where {
-- | The associated "U-version" of the type t.
type U t :: Type;
}
-- | Convert from t to its associated "U-version". This
-- direction is always safe (we simply have no unification variables even
-- though the type allows it).
toU :: WithU t => t -> U t
-- | Convert from the associated "U-version" back to t.
-- Generally, this direction requires somehow knowing that there are no
-- longer any unification variables in the value being converted.
fromU :: WithU t => U t -> Maybe t
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Types.BaseTy
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Types.BaseTy
instance GHC.Generics.Generic Swarm.Language.Types.BaseTy
instance Data.Data.Data Swarm.Language.Types.BaseTy
instance GHC.Show.Show Swarm.Language.Types.BaseTy
instance GHC.Classes.Ord Swarm.Language.Types.BaseTy
instance GHC.Classes.Eq Swarm.Language.Types.BaseTy
instance Data.Aeson.Types.ToJSON.ToJSON t => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Language.Types.TypeF t)
instance Data.Aeson.Types.FromJSON.FromJSON t => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Language.Types.TypeF t)
instance Data.Data.Data t => Data.Data.Data (Swarm.Language.Types.TypeF t)
instance Control.Unification.Types.Unifiable Swarm.Language.Types.TypeF
instance GHC.Generics.Generic1 Swarm.Language.Types.TypeF
instance GHC.Generics.Generic (Swarm.Language.Types.TypeF t)
instance Data.Traversable.Traversable Swarm.Language.Types.TypeF
instance Data.Foldable.Foldable Swarm.Language.Types.TypeF
instance GHC.Base.Functor Swarm.Language.Types.TypeF
instance GHC.Classes.Eq t => GHC.Classes.Eq (Swarm.Language.Types.TypeF t)
instance GHC.Show.Show t => GHC.Show.Show (Swarm.Language.Types.TypeF t)
instance Data.Aeson.Types.ToJSON.ToJSON t => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Language.Types.Poly t)
instance Data.Aeson.Types.FromJSON.FromJSON t => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Language.Types.Poly t)
instance GHC.Generics.Generic (Swarm.Language.Types.Poly t)
instance Data.Data.Data t => Data.Data.Data (Swarm.Language.Types.Poly t)
instance Data.Traversable.Traversable Swarm.Language.Types.Poly
instance Data.Foldable.Foldable Swarm.Language.Types.Poly
instance GHC.Base.Functor Swarm.Language.Types.Poly
instance GHC.Classes.Eq t => GHC.Classes.Eq (Swarm.Language.Types.Poly t)
instance GHC.Show.Show t => GHC.Show.Show (Swarm.Language.Types.Poly t)
instance Data.Data.Data Swarm.Language.Types.Type
instance Data.Data.Data Swarm.Language.Types.UType
instance Data.Data.Data Control.Unification.IntVar.IntVar
instance GHC.Generics.Generic Swarm.Language.Types.Type
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Types.Type
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Types.Type
instance Swarm.Language.Types.WithU Swarm.Language.Types.Type
instance (Swarm.Language.Types.WithU t, Data.Traversable.Traversable f) => Swarm.Language.Types.WithU (f t)
instance Data.String.IsString Swarm.Language.Types.UType
instance Data.String.IsString Swarm.Language.Types.Type
instance GHC.Classes.Ord k => Control.Unification.Types.Unifiable (Data.Map.Internal.Map k)
-- | Utilities related to type unification.
module Swarm.Language.Typecheck.Unify
-- | The result of doing a unification check on two types.
data UnifyStatus
-- | The two types are definitely not equal; they will never unify no
-- matter how any unification variables get filled in. For example, (int
-- * u0) and (u1 -> u2) are apart: the first is a product type and the
-- second is a function type.
Apart :: UnifyStatus
-- | The two types might unify, depending on how unification variables get
-- filled in, but we're not sure. For example, (int * u0) and (u1 *
-- bool).
MightUnify :: UnifyStatus
-- | The two types are most definitely equal, and we don't need to bother
-- generating a constraint to make them so. For example, (int * text) and
-- (int * text).
Equal :: UnifyStatus
-- | Given two types, try hard to prove either that (1) they are
-- Apart, i.e. cannot possibly unify, or (2) they are definitely
-- Equal. In case (1), we can generate a much better error message
-- at the instant the two types come together than we could if we threw a
-- constraint into the unifier. In case (2), we don't have to bother with
-- generating a trivial constraint. If we don't know for sure whether
-- they will unify, return MightUnify.
unifyCheck :: UType -> UType -> UnifyStatus
instance GHC.Show.Show Swarm.Language.Typecheck.Unify.UnifyStatus
instance GHC.Read.Read Swarm.Language.Typecheck.Unify.UnifyStatus
instance GHC.Classes.Ord Swarm.Language.Typecheck.Unify.UnifyStatus
instance GHC.Classes.Eq Swarm.Language.Typecheck.Unify.UnifyStatus
instance GHC.Base.Semigroup Swarm.Language.Typecheck.Unify.UnifyStatus
instance GHC.Base.Monoid Swarm.Language.Typecheck.Unify.UnifyStatus
-- | Ensures that access to an IORef is read-only by hiding behind a
-- newtype.
module Swarm.ReadableIORef
mkReadonly :: IORef a -> ReadableIORef a
data ReadableIORef a
readIORef :: ReadableIORef a -> IO a
-- | Special border drawing functions that can include labels in more
-- places than just the top center.
module Swarm.TUI.Border
-- | Labels for a horizontal border, with optional left, middle, and right
-- labels.
data HBorderLabels n
-- | A plain horizontal border with no labels.
plainHBorder :: HBorderLabels n
leftLabel :: forall n_aXPL. Lens' (HBorderLabels n_aXPL) (Maybe (Widget n_aXPL))
centerLabel :: forall n_aXPL. Lens' (HBorderLabels n_aXPL) (Maybe (Widget n_aXPL))
rightLabel :: forall n_aXPL. Lens' (HBorderLabels n_aXPL) (Maybe (Widget n_aXPL))
-- | Labels for a rectangular border, with optional left, middle, and right
-- labels on the top and bottom.
data BorderLabels n
-- | A plain rectangular border with no labels.
plainBorder :: BorderLabels n
topLabels :: forall n_aXPK. Lens' (BorderLabels n_aXPK) (HBorderLabels n_aXPK)
bottomLabels :: forall n_aXPK. Lens' (BorderLabels n_aXPK) (HBorderLabels n_aXPK)
-- | Draw a horizontal border with three optional labels. The left label
-- (if present) will be placed two units away from the left end of the
-- border, and the right label will be placed two units away from the
-- right end. The center label, if present, will always be centered in
-- the border overall, regardless of the width of the left and right
-- labels. This ensures that when the labels change width, they do not
-- cause the other labels to wiggle.
hBorderWithLabels :: HBorderLabels n -> Widget n
-- | Put a rectangular border around the specified widget with the
-- specified label widgets placed around the border.
borderWithLabels :: BorderLabels n -> Widget n -> Widget n
-- | A special modified version of handleListEvent to deal with
-- skipping over separators.
module Swarm.TUI.List
-- | Handle a list event, taking an extra predicate to identify which list
-- elements are separators; separators will be skipped if possible.
handleListEventWithSeparators :: (Foldable t, Splittable t, Ord n, Searchable t) => Event -> (e -> Bool) -> EventM n (GenericList n t e) ()
module Swarm.TUI.Model.Name
data WorldEditorFocusable
BrushSelector :: WorldEditorFocusable
EntitySelector :: WorldEditorFocusable
AreaSelector :: WorldEditorFocusable
OutputPathSelector :: WorldEditorFocusable
MapSaveButton :: WorldEditorFocusable
ClearEntityButton :: WorldEditorFocusable
data FocusablePanel
-- | The panel containing the REPL.
REPLPanel :: FocusablePanel
-- | The panel containing the world view.
WorldPanel :: FocusablePanel
-- | The panel containing the world editor controls.
WorldEditorPanel :: FocusablePanel
-- | The panel showing robot info and inventory on the top left.
RobotPanel :: FocusablePanel
-- | The info panel on the bottom left.
InfoPanel :: FocusablePanel
data ScenarioConfigPanel
ScenarioConfigFileSelector :: ScenarioConfigPanel
ScenarioConfigPanelControl :: ScenarioConfigPanelFocusable -> ScenarioConfigPanel
data ScenarioConfigPanelFocusable
-- | The file selector for launching a scenario with a script
ScriptSelector :: ScenarioConfigPanelFocusable
SeedSelector :: ScenarioConfigPanelFocusable
StartGameButton :: ScenarioConfigPanelFocusable
data GoalWidget
ObjectivesList :: GoalWidget
GoalSummary :: GoalWidget
-- | Clickable buttons in modal dialogs.
data Button
CancelButton :: Button
KeepPlayingButton :: Button
StartOverButton :: Button
QuitButton :: Button
NextButton :: Button
-- | Name represents names to uniquely identify various components
-- of the UI, such as forms, panels, caches, extents, lists, and buttons.
data Name
FocusablePanel :: FocusablePanel -> Name
-- | An individual control within the world editor panel.
WorldEditorPanelControl :: WorldEditorFocusable -> Name
-- | The REPL input form.
REPLInput :: Name
-- | The render cache for the world view.
WorldCache :: Name
-- | The cached extent for the world view.
WorldExtent :: Name
-- | The cursor/viewCenter display in the bottom left of the World view
WorldPositionIndicator :: Name
-- | The list of possible entities to paint a map with.
EntityPaintList :: Name
-- | The entity paint item position in the EntityPaintList.
EntityPaintListItem :: Int -> Name
-- | The list of possible terrain materials.
TerrainList :: Name
-- | The terrain item position in the TerrainList.
TerrainListItem :: Int -> Name
-- | The list of inventory items for the currently focused robot.
InventoryList :: Name
-- | The inventory item position in the InventoryList.
InventoryListItem :: Int -> Name
-- | The list of main menu choices.
MenuList :: Name
-- | The list of achievements.
AchievementList :: Name
-- | An individual control within the scenario launch config panel
ScenarioConfigControl :: ScenarioConfigPanel -> Name
-- | The list of goals/objectives.
GoalWidgets :: GoalWidget -> Name
-- | The list of scenario choices.
ScenarioList :: Name
-- | The scrollable viewport for the info panel.
InfoViewport :: Name
-- | The scrollable viewport for any modal dialog.
ModalViewport :: Name
-- | A clickable button in a modal dialog.
Button :: Button -> Name
instance GHC.Enum.Enum Swarm.TUI.Model.Name.WorldEditorFocusable
instance GHC.Enum.Bounded Swarm.TUI.Model.Name.WorldEditorFocusable
instance GHC.Read.Read Swarm.TUI.Model.Name.WorldEditorFocusable
instance GHC.Show.Show Swarm.TUI.Model.Name.WorldEditorFocusable
instance GHC.Classes.Ord Swarm.TUI.Model.Name.WorldEditorFocusable
instance GHC.Classes.Eq Swarm.TUI.Model.Name.WorldEditorFocusable
instance GHC.Enum.Enum Swarm.TUI.Model.Name.FocusablePanel
instance GHC.Enum.Bounded Swarm.TUI.Model.Name.FocusablePanel
instance GHC.Read.Read Swarm.TUI.Model.Name.FocusablePanel
instance GHC.Show.Show Swarm.TUI.Model.Name.FocusablePanel
instance GHC.Classes.Ord Swarm.TUI.Model.Name.FocusablePanel
instance GHC.Classes.Eq Swarm.TUI.Model.Name.FocusablePanel
instance GHC.Enum.Enum Swarm.TUI.Model.Name.ScenarioConfigPanelFocusable
instance GHC.Enum.Bounded Swarm.TUI.Model.Name.ScenarioConfigPanelFocusable
instance GHC.Read.Read Swarm.TUI.Model.Name.ScenarioConfigPanelFocusable
instance GHC.Show.Show Swarm.TUI.Model.Name.ScenarioConfigPanelFocusable
instance GHC.Classes.Ord Swarm.TUI.Model.Name.ScenarioConfigPanelFocusable
instance GHC.Classes.Eq Swarm.TUI.Model.Name.ScenarioConfigPanelFocusable
instance GHC.Read.Read Swarm.TUI.Model.Name.ScenarioConfigPanel
instance GHC.Show.Show Swarm.TUI.Model.Name.ScenarioConfigPanel
instance GHC.Classes.Ord Swarm.TUI.Model.Name.ScenarioConfigPanel
instance GHC.Classes.Eq Swarm.TUI.Model.Name.ScenarioConfigPanel
instance GHC.Enum.Enum Swarm.TUI.Model.Name.GoalWidget
instance GHC.Enum.Bounded Swarm.TUI.Model.Name.GoalWidget
instance GHC.Read.Read Swarm.TUI.Model.Name.GoalWidget
instance GHC.Show.Show Swarm.TUI.Model.Name.GoalWidget
instance GHC.Classes.Ord Swarm.TUI.Model.Name.GoalWidget
instance GHC.Classes.Eq Swarm.TUI.Model.Name.GoalWidget
instance GHC.Enum.Enum Swarm.TUI.Model.Name.Button
instance GHC.Enum.Bounded Swarm.TUI.Model.Name.Button
instance GHC.Read.Read Swarm.TUI.Model.Name.Button
instance GHC.Show.Show Swarm.TUI.Model.Name.Button
instance GHC.Classes.Ord Swarm.TUI.Model.Name.Button
instance GHC.Classes.Eq Swarm.TUI.Model.Name.Button
instance GHC.Read.Read Swarm.TUI.Model.Name.Name
instance GHC.Show.Show Swarm.TUI.Model.Name.Name
instance GHC.Classes.Ord Swarm.TUI.Model.Name.Name
instance GHC.Classes.Eq Swarm.TUI.Model.Name.Name
-- | A small custom "panel widget" for use in the Swarm TUI. Panels draw a
-- border around some content, with the color of the border depending on
-- whether the panel is currently focused. Panels exist within a
-- FocusRing such that the user can cycle between the panels
-- (using e.g. the Tab key).
module Swarm.TUI.Panel
-- | Create a panel.
panel :: Eq n => AttrName -> FocusRing n -> n -> BorderLabels n -> Widget n -> Widget n
instance Brick.Widgets.Core.Named (Swarm.TUI.Panel.Panel n) n
-- | A random collection of small, useful functions that are (or could be)
-- used throughout the code base.
module Swarm.Util
-- | A convenient infix flipped version of fromMaybe: Just a ? b
-- = a, and Nothing ? b = b. It can also be chained, as in
-- x ? y ? z ? def, which takes the value inside the first
-- Just, defaulting to def as a last resort.
(?) :: Maybe a -> a -> a
infixr 1 ?
-- | Ensure the smaller value in a pair is the first element.
sortPair :: Ord b => (b, b) -> (b, b)
-- | Find the maximum of two values, comparing them according to a custom
-- projection function.
maxOn :: Ord b => (a -> b) -> a -> a -> a
-- | Find the maximum of a list of numbers, defaulting to 0 if the list is
-- empty.
maximum0 :: (Num a, Ord a) => [a] -> a
-- | Take the successor of an Enum type, wrapping around when it
-- reaches the end.
cycleEnum :: (Eq e, Enum e, Bounded e) => e -> e
listEnums :: (Enum e, Bounded e) => [e]
-- | Guaranteed to yield an element of the list
indexWrapNonEmpty :: Integral b => NonEmpty a -> b -> a
-- | Drop repeated elements that are adjacent to each other.
--
--
-- >>> uniq []
-- []
--
-- >>> uniq [1..5]
-- [1,2,3,4,5]
--
-- >>> uniq (replicate 10 'a')
-- "a"
--
-- >>> uniq "abbbccd"
-- "abcd"
--
uniq :: Eq a => [a] -> [a]
-- | Place the second element of the tuples into bins by the value of the
-- first element.
binTuples :: (Foldable t, Ord a) => t (a, b) -> Map a (NonEmpty b)
-- | Count occurrences of a value
histogram :: (Foldable t, Ord a) => t a -> Map a Int
-- | Find a duplicate element within the list, if any exists.
findDup :: Ord a => [a] -> Maybe a
both :: Bifunctor p => (a -> d) -> p a a -> p d d
allEqual :: Ord a => [a] -> Bool
surfaceEmpty :: Alternative f => (a -> Bool) -> a -> f a
applyWhen :: Bool -> (a -> a) -> a -> a
-- | Safely attempt to read a file.
readFileMay :: FilePath -> IO (Maybe String)
-- | Safely attempt to (efficiently) read a file.
readFileMayT :: FilePath -> IO (Maybe Text)
-- | Recursively acquire all files in the given directory with the given
-- extension, and their contents.
acquireAllWithExt :: FilePath -> String -> IO [(FilePath, String)]
-- | Predicate to test for characters which can be part of a valid
-- identifier: alphanumeric, underscore, or single quote.
--
--
-- >>> isIdentChar 'A' && isIdentChar 'b' && isIdentChar '9'
-- True
--
-- >>> isIdentChar '_' && isIdentChar '\''
-- True
--
-- >>> isIdentChar '$' || isIdentChar '.' || isIdentChar ' '
-- False
--
isIdentChar :: Char -> Bool
-- | replaceLast r t replaces the last word of t with
-- r.
--
--
-- >>> :set -XOverloadedStrings
--
-- >>> replaceLast "foo" "bar baz quux"
-- "bar baz foo"
--
-- >>> replaceLast "move" "(make"
-- "(move"
--
replaceLast :: Text -> Text -> Text
-- | Fail with a Text-based message, made out of phrases to be joined by
-- spaces.
failT :: MonadFail m => [Text] -> m a
-- | Show a value, but as Text.
showT :: Show a => a -> Text
-- | Show a value in all lowercase, but as Text.
showLowT :: Show a => a -> Text
-- | Reflow text by removing newlines and condensing whitespace.
reflow :: Text -> Text
-- | Surround some text in double quotes.
quote :: Text -> Text
-- | Surround some text in single quotes.
squote :: Text -> Text
-- | Surround some text in backticks.
bquote :: Text -> Text
-- | Surround some text in parentheses.
parens :: Text -> Text
-- | Surround some text in square brackets.
brackets :: Text -> Text
-- | Make a list of things with commas and the word "and".
commaList :: [Text] -> Text
-- | Prepend a noun with the proper indefinite article ("a" or "an").
indefinite :: Text -> Text
-- | Prepend a noun with the proper indefinite article, and surround the
-- noun in single quotes.
indefiniteQ :: Text -> Text
-- | Combine the subject word with the simple present tense of the verb.
--
-- Only some irregular verbs are handled, but it should be enough to
-- scrap some error message boilerplate and have fun!
--
--
-- >>> :set -XOverloadedStrings
--
-- >>> singularSubjectVerb "I" "be"
-- "I am"
--
-- >>> singularSubjectVerb "he" "can"
-- "he can"
--
-- >>> singularSubjectVerb "The target robot" "do"
-- "The target robot does"
--
singularSubjectVerb :: Text -> Text -> Text
-- | Pluralize a noun.
plural :: Text -> Text
-- | Either pluralize a noun or not, depending on the value of the number.
number :: Int -> Text -> Text
-- | Require that a Boolean value is True, or throw an exception.
holdsOr :: Has (Throw e) sig m => Bool -> e -> m ()
-- | Require that a Maybe value is Just, or throw an
-- exception.
isJustOr :: Has (Throw e) sig m => Maybe a -> e -> m a
-- | Require that an Either value is Right, or throw an
-- exception based on the value in the Left.
isRightOr :: Has (Throw e) sig m => Either b a -> (b -> e) -> m a
-- | Require that a Validation value is Success, or throw an
-- exception based on the value in the Failure.
isSuccessOr :: Has (Throw e) sig m => Validation b a -> (b -> e) -> m a
liftText :: Text -> Q Exp
(%%=) :: Has (State s) sig m => Over p ((,) r) s s a b -> p a (r, b) -> m r
infix 4 %%=
(<%=) :: Has (State s) sig m => LensLike' ((,) a) s a -> (a -> a) -> m a
infix 4 <%=
(<+=) :: (Has (State s) sig m, Num a) => LensLike' ((,) a) s a -> a -> m a
infix 4 <+=
(<<.=) :: Has (State s) sig m => LensLike ((,) a) s s a b -> b -> m a
infix 4 <<.=
(<>=) :: (Has (State s) sig m, Semigroup a) => ASetter' s a -> a -> m ()
infix 4 <>=
_NonEmpty :: Lens' (NonEmpty a) (a, [a])
-- | Remove any sets which are supersets of other sets. In other words, (1)
-- no two sets in the output are in a subset relationship (2) every
-- element in the input is a superset of some element in the output.
--
--
-- >>> import qualified Data.Set as S
--
-- >>> rss = map S.toList . S.toList . removeSupersets . S.fromList . map S.fromList
--
--
--
-- >>> rss [[1,2,3], [1]]
-- [[1]]
--
--
--
-- >>> rss [[1,2,3], [2,4], [2,3]]
-- [[2,3],[2,4]]
--
--
--
-- >>> rss [[], [1], [2,3]]
-- [[]]
--
--
--
-- >>> rss [[1,2], [1,3], [2,3]]
-- [[1,2],[1,3],[2,3]]
--
removeSupersets :: Ord a => Set (Set a) -> Set (Set a)
-- | Given a list of nonempty sets, find a hitting set, that is, a
-- set which has at least one element in common with each set in the
-- list. It is not guaranteed to be the smallest possible such
-- set, because that is NP-hard. Instead, we use a greedy algorithm that
-- will give us a reasonably small hitting set: first, choose all
-- elements in singleton sets, since those must necessarily be chosen.
-- Now take any sets which are still not hit, and find an element which
-- occurs in the largest possible number of remaining sets. Add this
-- element to the set of chosen elements, and filter out all the sets it
-- hits. Repeat, choosing a new element to hit the largest number of
-- unhit sets at each step, until all sets are hit. This algorithm
-- produces a hitting set which might be larger than optimal by a factor
-- of lg(m), where m is the number of sets in the input.
--
--
-- >>> import qualified Data.Set as S
--
-- >>> shs = smallHittingSet . map S.fromList
--
--
--
-- >>> shs ["a"]
-- fromList "a"
--
--
--
-- >>> shs ["ab", "b"]
-- fromList "b"
--
--
--
-- >>> shs ["ab", "bc"]
-- fromList "b"
--
--
--
-- >>> shs ["acd", "c", "aef", "a"]
-- fromList "ac"
--
--
--
-- >>> shs ["abc", "abd", "acd", "bcd"]
-- fromList "cd"
--
--
-- Here is an example of an input for which smallHittingSet does
-- not produce a minimal hitting set. "bc" is also a hitting set
-- and is smaller. b, c, and d all occur in exactly two sets, but d is
-- unluckily chosen first, leaving "be" and "ac" unhit and necessitating
-- choosing one more element from each.
--
--
-- >>> shs ["bd", "be", "ac", "cd"]
-- fromList "cde"
--
smallHittingSet :: Ord a => [Set a] -> Set a
instance Data.Aeson.Types.FromJSON.FromJSON System.Clock.TimeSpec
instance Data.Aeson.Types.ToJSON.ToJSON System.Clock.TimeSpec
-- | Types and helper functions for working with directions
module Swarm.Language.Direction
-- | The type of directions. Used e.g. to indicate which way a robot
-- will turn.
data Direction
DAbsolute :: AbsoluteDir -> Direction
DRelative :: RelativeDir -> Direction
-- | An absolute direction is one which is defined with respect to an
-- external frame of reference; robots need a compass in order to use
-- them.
--
-- NOTE: These values are ordered by increasing angle according to the
-- standard mathematical convention. That is, the right-pointing
-- direction, East, is considered the "reference angle" and the order
-- proceeds counter-clockwise. See
-- https://en.wikipedia.org/wiki/Polar_coordinate_system#Conventions
--
-- Do not alter this ordering, as there exist functions that depend on it
-- (e.g. "nearestDirection" and "relativeTo").
data AbsoluteDir
DEast :: AbsoluteDir
DNorth :: AbsoluteDir
DWest :: AbsoluteDir
DSouth :: AbsoluteDir
-- | A relative direction is one which is defined with respect to the
-- robot's frame of reference; no special capability is needed to use
-- them.
data RelativeDir
DPlanar :: PlanarRelativeDir -> RelativeDir
DDown :: RelativeDir
-- | Caution: Do not alter this ordering, as there exist functions that
-- depend on it (e.g. "nearestDirection" and "relativeTo").
data PlanarRelativeDir
DForward :: PlanarRelativeDir
DLeft :: PlanarRelativeDir
DBack :: PlanarRelativeDir
DRight :: PlanarRelativeDir
-- | Direction name is generated from the deepest nested data constructor
-- e.g. DLeft becomes "left"
directionSyntax :: Direction -> Text
-- | Check if the direction is absolute (e.g. north or
-- south).
isCardinal :: Direction -> Bool
allDirs :: [Direction]
instance GHC.Enum.Bounded Swarm.Language.Direction.AbsoluteDir
instance GHC.Enum.Enum Swarm.Language.Direction.AbsoluteDir
instance Data.Hashable.Class.Hashable Swarm.Language.Direction.AbsoluteDir
instance Data.Data.Data Swarm.Language.Direction.AbsoluteDir
instance GHC.Generics.Generic Swarm.Language.Direction.AbsoluteDir
instance GHC.Read.Read Swarm.Language.Direction.AbsoluteDir
instance GHC.Show.Show Swarm.Language.Direction.AbsoluteDir
instance GHC.Classes.Ord Swarm.Language.Direction.AbsoluteDir
instance GHC.Classes.Eq Swarm.Language.Direction.AbsoluteDir
instance GHC.Enum.Bounded Swarm.Language.Direction.PlanarRelativeDir
instance GHC.Enum.Enum Swarm.Language.Direction.PlanarRelativeDir
instance Data.Hashable.Class.Hashable Swarm.Language.Direction.PlanarRelativeDir
instance Data.Data.Data Swarm.Language.Direction.PlanarRelativeDir
instance GHC.Generics.Generic Swarm.Language.Direction.PlanarRelativeDir
instance GHC.Read.Read Swarm.Language.Direction.PlanarRelativeDir
instance GHC.Show.Show Swarm.Language.Direction.PlanarRelativeDir
instance GHC.Classes.Ord Swarm.Language.Direction.PlanarRelativeDir
instance GHC.Classes.Eq Swarm.Language.Direction.PlanarRelativeDir
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Direction.RelativeDir
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Direction.RelativeDir
instance Data.Hashable.Class.Hashable Swarm.Language.Direction.RelativeDir
instance Data.Data.Data Swarm.Language.Direction.RelativeDir
instance GHC.Generics.Generic Swarm.Language.Direction.RelativeDir
instance GHC.Read.Read Swarm.Language.Direction.RelativeDir
instance GHC.Show.Show Swarm.Language.Direction.RelativeDir
instance GHC.Classes.Ord Swarm.Language.Direction.RelativeDir
instance GHC.Classes.Eq Swarm.Language.Direction.RelativeDir
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Direction.Direction
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Direction.Direction
instance Data.Hashable.Class.Hashable Swarm.Language.Direction.Direction
instance Data.Data.Data Swarm.Language.Direction.Direction
instance GHC.Generics.Generic Swarm.Language.Direction.Direction
instance GHC.Read.Read Swarm.Language.Direction.Direction
instance GHC.Show.Show Swarm.Language.Direction.Direction
instance GHC.Classes.Ord Swarm.Language.Direction.Direction
instance GHC.Classes.Eq Swarm.Language.Direction.Direction
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Direction.PlanarRelativeDir
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Direction.PlanarRelativeDir
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Direction.AbsoluteDir
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Direction.AbsoluteDir
instance Data.Aeson.Types.ToJSON.ToJSONKey Swarm.Language.Direction.AbsoluteDir
instance Data.Aeson.Types.FromJSON.FromJSONKey Swarm.Language.Direction.AbsoluteDir
-- | Abstract syntax for terms of the Swarm programming language.
module Swarm.Language.Syntax
-- | The type of directions. Used e.g. to indicate which way a robot
-- will turn.
data Direction
DAbsolute :: AbsoluteDir -> Direction
DRelative :: RelativeDir -> Direction
-- | An absolute direction is one which is defined with respect to an
-- external frame of reference; robots need a compass in order to use
-- them.
--
-- NOTE: These values are ordered by increasing angle according to the
-- standard mathematical convention. That is, the right-pointing
-- direction, East, is considered the "reference angle" and the order
-- proceeds counter-clockwise. See
-- https://en.wikipedia.org/wiki/Polar_coordinate_system#Conventions
--
-- Do not alter this ordering, as there exist functions that depend on it
-- (e.g. "nearestDirection" and "relativeTo").
data AbsoluteDir
DEast :: AbsoluteDir
DNorth :: AbsoluteDir
DWest :: AbsoluteDir
DSouth :: AbsoluteDir
-- | A relative direction is one which is defined with respect to the
-- robot's frame of reference; no special capability is needed to use
-- them.
data RelativeDir
DPlanar :: PlanarRelativeDir -> RelativeDir
DDown :: RelativeDir
-- | Caution: Do not alter this ordering, as there exist functions that
-- depend on it (e.g. "nearestDirection" and "relativeTo").
data PlanarRelativeDir
DForward :: PlanarRelativeDir
DLeft :: PlanarRelativeDir
DBack :: PlanarRelativeDir
DRight :: PlanarRelativeDir
-- | Direction name is generated from the deepest nested data constructor
-- e.g. DLeft becomes "left"
directionSyntax :: Direction -> Text
-- | Check if the direction is absolute (e.g. north or
-- south).
isCardinal :: Direction -> Bool
allDirs :: [Direction]
-- | Constants, representing various built-in functions and commands.
--
-- IF YOU ADD A NEW CONSTANT, be sure to also update: 1. the
-- constInfo function (below) 2. the capability checker
-- (Swarm.Language.Capability) 3. the type checker
-- (Swarm.Language.Typecheck) 4. the runtime
-- (Swarm.Game.Step) 5. the emacs mode syntax highlighter
-- (contribs/swarm-mode.el)
--
-- GHC will warn you about incomplete pattern matches for the first four,
-- and CI will warn you about the last, so in theory it's not really
-- possible to forget. Note you do not need to update the parser or
-- pretty-printer, since they are auto-generated from constInfo.
data Const
-- | Do nothing. This is different than Wait in that it does not
-- take up a time step.
Noop :: Const
-- | Wait for a number of time steps without doing anything.
Wait :: Const
-- | Self-destruct.
Selfdestruct :: Const
-- | Move forward one step.
Move :: Const
-- | Move backward one step.
Backup :: Const
-- | Push an entity forward one step.
Push :: Const
-- | Move forward multiple steps.
Stride :: Const
-- | Turn in some direction.
Turn :: Const
-- | Grab an item from the current location.
Grab :: Const
-- | Harvest an item from the current location.
Harvest :: Const
-- | Try to place an item at the current location.
Place :: Const
-- | Give an item to another robot at the current location.
Give :: Const
-- | Equip a device on oneself.
Equip :: Const
-- | Unequip an equipped device, returning to inventory.
Unequip :: Const
-- | Make an item.
Make :: Const
-- | Sense whether we have a certain item.
Has :: Const
-- | Sense whether we have a certain device equipped.
Equipped :: Const
-- | Sense how many of a certain item we have.
Count :: Const
-- | Drill through an entity.
Drill :: Const
-- | Use an entity with another.
Use :: Const
-- | Construct a new robot.
Build :: Const
-- | Deconstruct an old robot.
Salvage :: Const
-- | Reprogram a robot that has executed it's command with a new command
Reprogram :: Const
-- | Emit a message.
Say :: Const
-- | Listen for a message from other robots.
Listen :: Const
-- | Emit a log message.
Log :: Const
-- | View a certain robot.
View :: Const
-- | Set what characters are used for display.
Appear :: Const
-- | Create an entity out of thin air. Only available in creative mode.
Create :: Const
-- | Tell a robot to halt.
Halt :: Const
-- | Get current time
Time :: Const
Scout :: Const
-- | Get the current x, y coordinates
Whereami :: Const
-- | Get the x, y coordinates of a named waypoint, by index
Waypoint :: Const
-- | Locate the closest instance of a given entity within the rectangle
-- specified by opposite corners, relative to the current location.
Detect :: Const
-- | Count the number of a given entity within the rectangle specified by
-- opposite corners, relative to the current location.
Resonate :: Const
-- | Count the number entities within the rectangle specified by opposite
-- corners, relative to the current location.
Density :: Const
-- | Get the distance to the closest instance of the specified entity.
Sniff :: Const
-- | Get the direction to the closest instance of the specified entity.
Chirp :: Const
-- | Register a location to interrupt a wait upon changes
Watch :: Const
-- | Register a (remote) location to interrupt a wait upon changes
Surveil :: Const
-- | Get the current heading.
Heading :: Const
-- | See if we can move forward or not.
Blocked :: Const
-- | Scan a nearby cell
Scan :: Const
-- | Upload knowledge to another robot
Upload :: Const
-- | See if a specific entity is here.
Ishere :: Const
-- | Check whether the current cell is empty
Isempty :: Const
-- | Get a reference to oneself
Self :: Const
-- | Get the robot's parent
Parent :: Const
-- | Get a reference to the base
Base :: Const
-- | Meet a nearby robot
Meet :: Const
-- | Meet all nearby robots
MeetAll :: Const
-- | Get the robot's display name
Whoami :: Const
-- | Set the robot's display name
Setname :: Const
-- | Get a uniformly random integer.
Random :: Const
-- | Run a program loaded from a file.
Run :: Const
-- | If-expressions.
If :: Const
-- | Left injection.
Inl :: Const
-- | Right injection.
Inr :: Const
-- | Case analysis on a sum type.
Case :: Const
-- | First projection.
Fst :: Const
-- | Second projection.
Snd :: Const
-- | Force a delayed evaluation.
Force :: Const
-- | Return for the cmd monad.
Return :: Const
-- | Try/catch block
Try :: Const
-- | Undefined
Undefined :: Const
-- | User error
Fail :: Const
-- | Logical negation.
Not :: Const
-- | Arithmetic negation.
Neg :: Const
-- | Logical equality comparison
Eq :: Const
-- | Logical unequality comparison
Neq :: Const
-- | Logical lesser-then comparison
Lt :: Const
-- | Logical greater-then comparison
Gt :: Const
-- | Logical lesser-or-equal comparison
Leq :: Const
-- | Logical greater-or-equal comparison
Geq :: Const
-- | Logical or.
Or :: Const
-- | Logical and.
And :: Const
-- | Arithmetic addition operator
Add :: Const
-- | Arithmetic subtraction operator
Sub :: Const
-- | Arithmetic multiplication operator
Mul :: Const
-- | Arithmetic division operator
Div :: Const
-- | Arithmetic exponentiation operator
Exp :: Const
-- | Turn an arbitrary value into a string
Format :: Const
-- | Concatenate string values
Concat :: Const
-- | Count number of characters.
Chars :: Const
-- | Split string into two parts.
Split :: Const
-- | Get the character at an index.
CharAt :: Const
-- | Create a singleton text value with the given character code.
ToChar :: Const
-- | Application operator - helps to avoid parentheses: f $ g $ h x = f
-- (g (h x))
AppF :: Const
-- | Swap placed entity with one in inventory. Essentially atomic grab and
-- place.
Swap :: Const
-- | When executing atomic c, a robot will not be interrupted,
-- that is, no other robots will execute any commands while the robot is
-- executing c.
Atomic :: Const
-- | Like atomic, but with no restriction on program size.
Instant :: Const
-- | Create key values.
Key :: Const
-- | Install a new keyboard input handler.
InstallKeyHandler :: Const
-- | Teleport a robot to the given position.
Teleport :: Const
-- | Run a command as if you were another robot.
As :: Const
-- | Find an actor by name.
RobotNamed :: Const
-- | Find an actor by number.
RobotNumbered :: Const
-- | Check if an entity is known.
Knows :: Const
allConst :: [Const]
data ConstInfo
ConstInfo :: Text -> Int -> ConstMeta -> ConstDoc -> Tangibility -> ConstInfo
[syntax] :: ConstInfo -> Text
[fixity] :: ConstInfo -> Int
[constMeta] :: ConstInfo -> ConstMeta
[constDoc] :: ConstInfo -> ConstDoc
[tangibility] :: ConstInfo -> Tangibility
data ConstDoc
ConstDoc :: Text -> Text -> ConstDoc
[briefDoc] :: ConstDoc -> Text
[longDoc] :: ConstDoc -> Text
data ConstMeta
-- | Function with arity of which some are commands
ConstMFunc :: Int -> Bool -> ConstMeta
-- | Unary operator with fixity and associativity.
ConstMUnOp :: MUnAssoc -> ConstMeta
-- | Binary operator with fixity and associativity.
ConstMBinOp :: MBinAssoc -> ConstMeta
-- | The meta type representing associativity of binary operator.
data MBinAssoc
-- | Left associative binary operator (see InfixL)
L :: MBinAssoc
-- | Non-associative binary operator (see InfixN)
N :: MBinAssoc
-- | Right associative binary operator (see InfixR)
R :: MBinAssoc
-- | The meta type representing associativity of unary operator.
data MUnAssoc
-- | Prefix unary operator (see Prefix)
P :: MUnAssoc
-- | Suffix unary operator (see Suffix)
S :: MUnAssoc
-- | Information about constants used in parsing and pretty printing.
--
-- It would be more compact to represent the information by testing
-- whether the constants are in certain sets, but using pattern matching
-- gives us warning if we add more constants.
constInfo :: Const -> ConstInfo
-- | The arity of a constant, i.e. how many arguments it expects.
-- The runtime system will collect arguments to a constant (see
-- VCApp) until it has enough, then dispatch the constant's
-- behavior.
arity :: Const -> Int
-- | Whether a constant represents a command. Constants which are
-- not commands are functions which are interpreted as soon as
-- they are evaluated. Commands, on the other hand, are not interpreted
-- until being executed, that is, when meeting an FExec
-- frame. When evaluated, commands simply turn into a VCApp.
isCmd :: Const -> Bool
-- | Function constants user can call with reserved words
-- (wait,...).
isUserFunc :: Const -> Bool
-- | Whether the constant is an operator. Useful predicate for
-- documentation.
isOperator :: Const -> Bool
-- | Whether the constant is a function which is interpreted as soon
-- as it is evaluated, but *not* including operators.
--
-- Note: This is used for documentation purposes and complements
-- isCmd and isOperator in that exactly one will accept a
-- given constant.
isBuiltinFunction :: Const -> Bool
-- | Whether the constant is a tangible command, that has an
-- external effect on the world. At most one tangible command may be
-- executed per tick.
isTangible :: Const -> Bool
-- | Whether the constant is a long command, that is, a tangible
-- command which could require multiple ticks to execute. Such commands
-- cannot be allowed in atomic blocks.
isLong :: Const -> Bool
-- | Maximum perception distance for chirp and sniff
-- commands
maxSniffRange :: Int32
maxScoutRange :: Int
maxStrideRange :: Int
-- | The surface syntax for the language, with location and type
-- annotations.
data Syntax' ty
Syntax' :: SrcLoc -> Term' ty -> ty -> Syntax' ty
[_sLoc] :: Syntax' ty -> SrcLoc
[_sTerm] :: Syntax' ty -> Term' ty
[_sType] :: Syntax' ty -> ty
sLoc :: forall ty_a1sLY. Lens' (Syntax' ty_a1sLY) SrcLoc
sTerm :: forall ty_a1sLY. Lens' (Syntax' ty_a1sLY) (Term' ty_a1sLY)
sType :: forall ty_a1sLY. Lens' (Syntax' ty_a1sLY) ty_a1sLY
type Syntax = Syntax' ()
pattern Syntax :: SrcLoc -> Term -> Syntax
-- | A variable with associated source location, used for variable binding
-- sites. (Variable occurrences are a bare TVar which gets wrapped in a
-- Syntax node, so we don't need LocVar for those.)
data LocVar
LV :: SrcLoc -> Var -> LocVar
[lvSrcLoc] :: LocVar -> SrcLoc
[lvVar] :: LocVar -> Var
data SrcLoc
NoLoc :: SrcLoc
-- | Half-open interval from start (inclusive) to end (exclusive)
SrcLoc :: Int -> Int -> SrcLoc
noLoc :: Term -> Syntax
-- | Match an untyped term without its SrcLoc.
pattern STerm :: Term -> Syntax
pattern TRequirements :: Text -> Term -> Term
-- | Match a TPair without syntax
pattern TPair :: Term -> Term -> Term
-- | Match a TLam without syntax
pattern TLam :: Var -> Maybe Type -> Term -> Term
-- | Match a TApp without syntax
pattern TApp :: Term -> Term -> Term
-- | Convenient infix pattern synonym for application.
pattern (:$:) :: Term -> Syntax -> Term
infixl 0 :$:
-- | Match a TLet without syntax
pattern TLet :: Bool -> Var -> Maybe Polytype -> Term -> Term -> Term
-- | Match a TDef without syntax
pattern TDef :: Bool -> Var -> Maybe Polytype -> Term -> Term
-- | Match a TBind without syntax
pattern TBind :: Maybe Var -> Term -> Term -> Term
-- | Match a TDelay without syntax
pattern TDelay :: DelayType -> Term -> Term
-- | Match a TRcd without syntax
pattern TRcd :: Map Var (Maybe Term) -> Term
pattern TProj :: Term -> Var -> Term
-- | Match a TAnnotate without syntax
pattern TAnnotate :: Term -> Polytype -> Term
-- | We use Text values to represent variables.
type Var = Text
-- | Different runtime behaviors for delayed expressions.
data DelayType
-- | A simple delay, implemented via a (non-memoized) VDelay
-- holding the delayed expression.
SimpleDelay :: DelayType
-- | A memoized delay, implemented by allocating a mutable cell with the
-- delayed expression and returning a reference to it. When the Maybe
-- Var is Just, a recursive binding of the variable with a
-- reference to the delayed expression will be provided while evaluating
-- the delayed expression itself. Note that there is no surface syntax
-- for binding a variable within a recursive delayed expression; the only
-- way we can get Just here is when we automatically generate a
-- delayed expression while interpreting a recursive let or
-- def.
MemoizedDelay :: Maybe Var -> DelayType
-- | Terms of the Swarm language.
data Term' ty
-- | The unit value.
TUnit :: Term' ty
-- | A constant.
TConst :: Const -> Term' ty
-- | A direction literal.
TDir :: Direction -> Term' ty
-- | An integer literal.
TInt :: Integer -> Term' ty
-- | An antiquoted Haskell variable name of type Integer.
TAntiInt :: Text -> Term' ty
-- | A text literal.
TText :: Text -> Term' ty
-- | An antiquoted Haskell variable name of type Text.
TAntiText :: Text -> Term' ty
-- | A Boolean literal.
TBool :: Bool -> Term' ty
-- | A robot reference. These never show up in surface syntax, but are here
-- so we can factor pretty-printing for Values through pretty-printing
-- for Terms.
TRobot :: Int -> Term' ty
-- | A memory reference. These likewise never show up in surface syntax,
-- but are here to facilitate pretty-printing.
TRef :: Int -> Term' ty
-- | Require a specific device to be installed.
TRequireDevice :: Text -> Term' ty
-- | Require a certain number of an entity.
TRequire :: Int -> Text -> Term' ty
-- | Primitive command to log requirements of a term. The Text field is to
-- store the unaltered original text of the term, for use in displaying
-- the log message (since once we get to execution time the original term
-- may have been elaborated, e.g. force may have been added
-- around some variables, etc.)
SRequirements :: Text -> Syntax' ty -> Term' ty
-- | A variable.
TVar :: Var -> Term' ty
-- | A pair.
SPair :: Syntax' ty -> Syntax' ty -> Term' ty
-- | A lambda expression, with or without a type annotation on the binder.
SLam :: LocVar -> Maybe Type -> Syntax' ty -> Term' ty
-- | Function application.
SApp :: Syntax' ty -> Syntax' ty -> Term' ty
-- | A (recursive) let expression, with or without a type annotation on the
-- variable. The Bool indicates whether it is known to be
-- recursive.
SLet :: Bool -> LocVar -> Maybe Polytype -> Syntax' ty -> Syntax' ty -> Term' ty
-- | A (recursive) definition command, which binds a variable to a value in
-- subsequent commands. The Bool indicates whether the
-- definition is known to be recursive.
SDef :: Bool -> LocVar -> Maybe Polytype -> Syntax' ty -> Term' ty
-- | A monadic bind for commands, of the form c1 ; c2 or x
-- <- c1; c2.
SBind :: Maybe LocVar -> Syntax' ty -> Syntax' ty -> Term' ty
-- | Delay evaluation of a term, written {...}. Swarm is an eager
-- language, but in some cases (e.g. for if statements and
-- recursive bindings) we need to delay evaluation. The counterpart to
-- {...} is force, where force {t} = t. Note
-- that Force is just a constant, whereas SDelay has to be
-- a special syntactic form so its argument can get special treatment
-- during evaluation.
SDelay :: DelayType -> Syntax' ty -> Term' ty
-- | Record literals [x1 = e1, x2 = e2, x3, ...] Names x
-- without an accompanying definition are sugar for writing x=x.
SRcd :: Map Var (Maybe (Syntax' ty)) -> Term' ty
-- | Record projection e.x
SProj :: Syntax' ty -> Var -> Term' ty
-- | Annotate a term with a type
SAnnotate :: Syntax' ty -> Polytype -> Term' ty
type Term = Term' ()
-- | COMPLETE pragma tells GHC using this set of pattern is complete for
-- Term
--
-- Make infix operation (e.g. 2 + 3) a curried function
-- application (((+) 2) 3).
mkOp :: Const -> Syntax -> Syntax -> Syntax
-- | Make infix operation, discarding any syntax related location
mkOp' :: Const -> Term -> Term -> Term
-- | Turn function application chain into a list.
--
--
-- >>> syntaxWrap f = fmap (^. sTerm) . f . Syntax NoLoc
--
-- >>> syntaxWrap unfoldApps (mkOp' Mul (TInt 1) (TInt 2)) -- 1 * 2
-- TConst Mul :| [TInt 1,TInt 2]
--
unfoldApps :: Syntax' ty -> NonEmpty (Syntax' ty)
-- | Erase a type-annotated term to a bare term.
erase :: Term' ty -> Term
-- | Erase a Syntax tree annotated with SrcLoc and type
-- information to a bare unannotated Term.
eraseS :: Syntax' ty -> Term
-- | Traversal over those subterms of a term which represent free
-- variables. The S suffix indicates that it is a Traversal over
-- the Syntax nodes (which contain type and source location info)
-- containing free variables inside a larger Syntax value. Note
-- that if you want to get the list of all Syntax nodes
-- representing free variables, you can do so via toListOf
-- freeVarsS.
freeVarsS :: forall ty. Traversal' (Syntax' ty) (Syntax' ty)
-- | Like freeVarsS, but traverse over the Terms containing
-- free variables. More direct if you don't need to know the types or
-- source locations of the variables. Note that if you want to get the
-- list of all Terms representing free variables, you can do so
-- via toListOf freeVarsT.
freeVarsT :: forall ty. Traversal' (Syntax' ty) (Term' ty)
-- | Traversal over the free variables of a term. Like freeVarsS and
-- freeVarsT, but traverse over the variable names themselves.
-- Note that if you want to get the set of all free variable names, you
-- can do so via setOf freeVarsV.
freeVarsV :: Traversal' (Syntax' ty) Var
-- | Apply a function to all free occurrences of a particular variable.
mapFreeS :: Var -> (Syntax' ty -> Syntax' ty) -> Syntax' ty -> Syntax' ty
locVarToSyntax' :: LocVar -> ty -> Syntax' ty
-- | Transform the AST into a Tree datatype. Useful for pretty-printing
-- (e.g. via "Data.Tree.drawTree").
asTree :: Data a => Syntax' a -> Tree (Syntax' a)
-- | Each constructor is a assigned a value of 1, plus any recursive syntax
-- it entails.
measureAstSize :: Data a => Syntax' a -> Int
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Syntax.Const
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Syntax.Const
instance GHC.Generics.Generic Swarm.Language.Syntax.Const
instance GHC.Show.Show Swarm.Language.Syntax.Const
instance Data.Data.Data Swarm.Language.Syntax.Const
instance GHC.Enum.Bounded Swarm.Language.Syntax.Const
instance GHC.Enum.Enum Swarm.Language.Syntax.Const
instance GHC.Classes.Ord Swarm.Language.Syntax.Const
instance GHC.Classes.Eq Swarm.Language.Syntax.Const
instance GHC.Show.Show Swarm.Language.Syntax.ConstDoc
instance GHC.Classes.Ord Swarm.Language.Syntax.ConstDoc
instance GHC.Classes.Eq Swarm.Language.Syntax.ConstDoc
instance GHC.Show.Show Swarm.Language.Syntax.MBinAssoc
instance GHC.Classes.Ord Swarm.Language.Syntax.MBinAssoc
instance GHC.Classes.Eq Swarm.Language.Syntax.MBinAssoc
instance GHC.Show.Show Swarm.Language.Syntax.MUnAssoc
instance GHC.Classes.Ord Swarm.Language.Syntax.MUnAssoc
instance GHC.Classes.Eq Swarm.Language.Syntax.MUnAssoc
instance GHC.Show.Show Swarm.Language.Syntax.ConstMeta
instance GHC.Classes.Ord Swarm.Language.Syntax.ConstMeta
instance GHC.Classes.Eq Swarm.Language.Syntax.ConstMeta
instance GHC.Enum.Enum Swarm.Language.Syntax.Length
instance GHC.Enum.Bounded Swarm.Language.Syntax.Length
instance GHC.Read.Read Swarm.Language.Syntax.Length
instance GHC.Show.Show Swarm.Language.Syntax.Length
instance GHC.Classes.Ord Swarm.Language.Syntax.Length
instance GHC.Classes.Eq Swarm.Language.Syntax.Length
instance GHC.Read.Read Swarm.Language.Syntax.Tangibility
instance GHC.Show.Show Swarm.Language.Syntax.Tangibility
instance GHC.Classes.Ord Swarm.Language.Syntax.Tangibility
instance GHC.Classes.Eq Swarm.Language.Syntax.Tangibility
instance GHC.Show.Show Swarm.Language.Syntax.ConstInfo
instance GHC.Classes.Ord Swarm.Language.Syntax.ConstInfo
instance GHC.Classes.Eq Swarm.Language.Syntax.ConstInfo
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Syntax.DelayType
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Syntax.DelayType
instance GHC.Generics.Generic Swarm.Language.Syntax.DelayType
instance Data.Data.Data Swarm.Language.Syntax.DelayType
instance GHC.Show.Show Swarm.Language.Syntax.DelayType
instance GHC.Classes.Eq Swarm.Language.Syntax.DelayType
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Syntax.SrcLoc
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Syntax.SrcLoc
instance GHC.Generics.Generic Swarm.Language.Syntax.SrcLoc
instance Data.Data.Data Swarm.Language.Syntax.SrcLoc
instance GHC.Show.Show Swarm.Language.Syntax.SrcLoc
instance GHC.Classes.Ord Swarm.Language.Syntax.SrcLoc
instance GHC.Classes.Eq Swarm.Language.Syntax.SrcLoc
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Syntax.LocVar
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Syntax.LocVar
instance GHC.Generics.Generic Swarm.Language.Syntax.LocVar
instance Data.Data.Data Swarm.Language.Syntax.LocVar
instance GHC.Show.Show Swarm.Language.Syntax.LocVar
instance GHC.Classes.Ord Swarm.Language.Syntax.LocVar
instance GHC.Classes.Eq Swarm.Language.Syntax.LocVar
instance Data.Aeson.Types.ToJSON.ToJSON ty => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Language.Syntax.Syntax' ty)
instance Data.Aeson.Types.FromJSON.FromJSON ty => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Language.Syntax.Syntax' ty)
instance GHC.Generics.Generic (Swarm.Language.Syntax.Syntax' ty)
instance Data.Data.Data ty => Data.Data.Data (Swarm.Language.Syntax.Syntax' ty)
instance Data.Traversable.Traversable Swarm.Language.Syntax.Syntax'
instance Data.Foldable.Foldable Swarm.Language.Syntax.Syntax'
instance GHC.Base.Functor Swarm.Language.Syntax.Syntax'
instance GHC.Show.Show ty => GHC.Show.Show (Swarm.Language.Syntax.Syntax' ty)
instance GHC.Classes.Eq ty => GHC.Classes.Eq (Swarm.Language.Syntax.Syntax' ty)
instance Data.Aeson.Types.ToJSON.ToJSON ty => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Language.Syntax.Term' ty)
instance Data.Aeson.Types.FromJSON.FromJSON ty => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Language.Syntax.Term' ty)
instance GHC.Generics.Generic (Swarm.Language.Syntax.Term' ty)
instance Data.Data.Data ty => Data.Data.Data (Swarm.Language.Syntax.Term' ty)
instance Data.Traversable.Traversable Swarm.Language.Syntax.Term'
instance Data.Foldable.Foldable Swarm.Language.Syntax.Term'
instance GHC.Base.Functor Swarm.Language.Syntax.Term'
instance GHC.Show.Show ty => GHC.Show.Show (Swarm.Language.Syntax.Term' ty)
instance GHC.Classes.Eq ty => GHC.Classes.Eq (Swarm.Language.Syntax.Term' ty)
instance Data.Data.Data ty => Control.Lens.Plated.Plated (Swarm.Language.Syntax.Term' ty)
instance Data.Data.Data ty => Control.Lens.Plated.Plated (Swarm.Language.Syntax.Syntax' ty)
instance GHC.Base.Semigroup Swarm.Language.Syntax.SrcLoc
instance GHC.Base.Monoid Swarm.Language.Syntax.SrcLoc
instance Data.String.IsString Swarm.Language.Syntax.ConstDoc
-- | A Module packages together a type-annotated syntax tree along
-- with a context of top-level definitions.
module Swarm.Language.Module
-- | A module generally represents the result of performing type inference
-- on a top-level expression, which in particular can contain definitions
-- (TDef). A module contains the type-annotated AST of the
-- expression itself, as well as the context giving the types of any
-- defined variables.
data Module s t
Module :: Syntax' s -> Ctx t -> Module s t
[moduleAST] :: Module s t -> Syntax' s
[moduleCtx] :: Module s t -> Ctx t
-- | A TModule is the final result of the type inference process on
-- an expression: we get a polytype for the expression, and a context of
-- polytypes for the defined variables.
type TModule = Module Polytype Polytype
-- | A UModule represents the type of an expression at some
-- intermediate stage during the type inference process. We get a
-- UType (not a UPolytype) for the expression, which
-- may contain some free unification or type variables, as well as a
-- context of UPolytypes for any defined variables.
type UModule = Module UType UPolytype
-- | The trivial module for a given AST, with the empty context.
trivMod :: Syntax' s -> Module s t
instance (Data.Aeson.Types.ToJSON.ToJSON t, Data.Aeson.Types.ToJSON.ToJSON s) => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Language.Module.Module s t)
instance (Data.Aeson.Types.FromJSON.FromJSON s, Data.Aeson.Types.FromJSON.FromJSON t) => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Language.Module.Module s t)
instance GHC.Generics.Generic (Swarm.Language.Module.Module s t)
instance (Data.Data.Data s, Data.Data.Data t) => Data.Data.Data (Swarm.Language.Module.Module s t)
instance GHC.Base.Functor (Swarm.Language.Module.Module s)
instance (GHC.Classes.Eq s, GHC.Classes.Eq t) => GHC.Classes.Eq (Swarm.Language.Module.Module s t)
instance (GHC.Show.Show s, GHC.Show.Show t) => GHC.Show.Show (Swarm.Language.Module.Module s t)
-- | Term elaboration which happens after type checking.
module Swarm.Language.Elaborate
-- | Perform some elaboration / rewriting on a fully type-annotated term.
-- This currently performs such operations as rewriting if
-- expressions and recursive let expressions to use laziness
-- appropriately. In theory it could also perform rewriting for
-- overloaded constants depending on the actual type they are used at,
-- but currently that sort of thing tends to make type inference fall
-- over.
elaborate :: Syntax' Polytype -> Syntax' Polytype
wrapForce :: Var -> Syntax' Polytype -> Syntax' Polytype
sForce :: Syntax' Polytype
-- | 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
-- | Various capabilities which robots can have.
data Capability
-- | Be powered, i.e. execute anything at all
CPower :: Capability
-- | Execute the Move command
CMove :: Capability
-- | Execute the Backup command
CBackup :: Capability
-- | Execute the Push command
CPush :: Capability
-- | Execute the Stride command
CMovemultiple :: Capability
-- | Execute the Move command for a heavy robot
CMoveheavy :: Capability
-- | Execute the Turn command
--
-- NOTE: using cardinal directions is separate COrient capability
CTurn :: Capability
-- | Execute the Selfdestruct command
CSelfdestruct :: Capability
-- | Execute the Grab command
CGrab :: Capability
-- | Execute the Harvest command
CHarvest :: Capability
-- | Execute the Place command
CPlace :: Capability
-- | Execute the Give command
CGive :: Capability
-- | Execute the Equip command
CEquip :: Capability
-- | Execute the Unequip command
CUnequip :: Capability
-- | Execute the Make command
CMake :: Capability
-- | Execute the Count command
CCount :: Capability
-- | Execute the Scout command. Reconnaissance along a line in a
-- direction.
CRecondir :: Capability
-- | Execute the Build command
CBuild :: Capability
-- | Execute the Salvage command
CSalvage :: Capability
-- | Execute the Drill command
CDrill :: Capability
-- | Execute the Whereami command
CSenseloc :: Capability
-- | Execute the Blocked command
CSensefront :: Capability
-- | Execute the Ishere and Isempty commands
CSensehere :: Capability
-- | Execute the Detect command
CDetectloc :: Capability
-- | Execute the Resonate and Density commands
CDetectcount :: Capability
-- | Execute the Sniff command
CDetectdistance :: Capability
-- | Execute the Chirp command
CDetectdirection :: Capability
-- | Execute the Watch command
CWakeself :: Capability
-- | Execute the Scan command
CScan :: Capability
-- | Execute the Random command
CRandom :: Capability
-- | Execute the Appear command
CAppear :: Capability
-- | Execute the Create command
CCreate :: Capability
-- | Execute the Listen command and passively log messages if also
-- has CLog
CListen :: Capability
-- | Execute the Log command
CLog :: Capability
-- | Format values as text
CFormat :: Capability
-- | Split text into two pieces
CConcat :: Capability
-- | Join two text values into one
CSplit :: Capability
-- | Count the characters in a text value
CCharcount :: Capability
-- | Convert between characters/text and Unicode values
CCode :: Capability
-- | Don't drown in liquid
CFloat :: Capability
-- | Evaluate conditional expressions
CCond :: Capability
-- | Negate boolean value
CNegation :: Capability
-- | Evaluate comparison operations
CCompare :: Capability
-- | Use cardinal direction constants.
COrient :: Capability
-- | Evaluate arithmetic operations
CArith :: Capability
-- | Store and look up definitions in an environment
CEnv :: Capability
-- | Interpret lambda abstractions
CLambda :: Capability
-- | Enable recursive definitions
CRecursion :: Capability
-- | Execute the Reprogram command
CReprogram :: Capability
-- | Execute the meet and meetAll commands.
CMeet :: Capability
-- | Capability to introspect and see its own name
CWhoami :: Capability
-- | Capability to set its own name
CSetname :: Capability
-- | Capability to move unrestricted to any place
CTeleport :: Capability
-- | Capability to run commands atomically
CAtomic :: Capability
-- | Capability to execute swap (grab and place atomically at the same
-- time).
CSwap :: Capability
-- | Capability to obtain absolute time, namely via the time
-- command.
CTimeabs :: Capability
-- | Capability to utilize relative passage of time, namely via the
-- wait command. This is strictly weaker than CTimeAbs.
CTimerel :: Capability
-- | Capability to execute try.
CTry :: Capability
-- | Capability for working with sum types.
CSum :: Capability
-- | Capability for working with product types.
CProd :: Capability
-- | Capability for working with record types.
CRecord :: Capability
-- | Debug capability.
CDebug :: Capability
-- | Capability to handle keyboard input.
CHandleinput :: Capability
-- | Capability to make other robots halt.
CHalt :: Capability
-- | God-like capabilities. For e.g. commands intended only for checking
-- challenge mode win conditions, and not for use by players.
CGod :: Capability
capabilityName :: Capability -> Text
-- | Capabilities needed to evaluate or execute a constant.
constCaps :: Const -> Maybe Capability
instance Data.Aeson.Types.ToJSON.ToJSONKey Swarm.Language.Capability.Capability
instance Data.Aeson.Types.FromJSON.FromJSONKey Swarm.Language.Capability.Capability
instance Data.Data.Data Swarm.Language.Capability.Capability
instance Data.Hashable.Class.Hashable Swarm.Language.Capability.Capability
instance GHC.Generics.Generic Swarm.Language.Capability.Capability
instance GHC.Enum.Bounded Swarm.Language.Capability.Capability
instance GHC.Enum.Enum Swarm.Language.Capability.Capability
instance GHC.Read.Read Swarm.Language.Capability.Capability
instance GHC.Show.Show Swarm.Language.Capability.Capability
instance GHC.Classes.Ord Swarm.Language.Capability.Capability
instance GHC.Classes.Eq Swarm.Language.Capability.Capability
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Capability.Capability
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Capability.Capability
-- | A requirement is something that is needed in order to successfully
-- build a robot running a certain program.
module Swarm.Language.Requirement
-- | A requirement is something a robot must have when it is built.
-- There are three types: - A robot can require a certain
-- Capability, which should be fulfilled by equipping an
-- appropriate device. - A robot can require a specific device,
-- which should be equipped. - A robot can require some number of a
-- specific entity in its inventory.
data Requirement
-- | Require a specific capability. This must be fulfilled by equipping an
-- appropriate device. Requiring the same capability multiple times is
-- the same as requiring it once.
ReqCap :: Capability -> Requirement
-- | Require a specific device to be equipped. Note that at this point it
-- is only a name, and has not been resolved to an actual
-- Entity. That's because programs have to be type- and
-- capability-checked independent of an EntityMap. The name will
-- be looked up at runtime, when actually executing a Build or
-- Reprogram command, and an appropriate exception thrown if a
-- device with the given name does not exist.
--
-- Requiring the same device multiple times is the same as requiring it
-- once.
ReqDev :: Text -> Requirement
-- | Require a certain number of a specific entity to be available in the
-- inventory. The same comments apply re: resolving the entity name to an
-- actual Entity.
--
-- Inventory requirements are additive, that is, say, requiring 5 of
-- entity e and later requiring 7 is the same as requiring 12.
ReqInv :: Int -> Text -> Requirement
-- | It is tempting to define Requirements = Set Requirement, but
-- that would be wrong, since two identical ReqInv should have
-- their counts added rather than simply being deduplicated.
--
-- Since we will eventually need to deal with the different types of
-- requirements separately, it makes sense to store them separately
-- anyway.
data Requirements
Requirements :: Set Capability -> Set Text -> Map Text Int -> Requirements
[capReqs] :: Requirements -> Set Capability
[devReqs] :: Requirements -> Set Text
[invReqs] :: Requirements -> Map Text Int
-- | Create a Requirements set with a single Requirement.
singleton :: Requirement -> Requirements
-- | For convenience, create a Requirements set with a single
-- Capability requirement.
singletonCap :: Capability -> Requirements
-- | For convenience, create a Requirements set with a single device
-- requirement.
singletonDev :: Text -> Requirements
-- | For convenience, create a Requirements set with a single
-- inventory requirement.
singletonInv :: Int -> Text -> Requirements
insert :: Requirement -> Requirements -> Requirements
-- | A requirement context records the requirements for the definitions
-- bound to variables.
type ReqCtx = Ctx Requirements
-- | Analyze a program to see what capabilities may be needed to execute
-- it. Also return a capability context mapping from any variables
-- declared via TDef to the capabilities needed by their
-- definitions.
--
-- Note that this is necessarily a conservative analysis, especially if
-- the program contains conditional expressions. Some capabilities may
-- end up not being actually needed if certain commands end up not being
-- executed. However, the analysis should be safe in the sense that a
-- robot with the indicated capabilities will always be able to run the
-- given program.
requirements :: ReqCtx -> Term -> (Requirements, ReqCtx)
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Requirement.Requirement
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Requirement.Requirement
instance Data.Data.Data Swarm.Language.Requirement.Requirement
instance Data.Hashable.Class.Hashable Swarm.Language.Requirement.Requirement
instance GHC.Generics.Generic Swarm.Language.Requirement.Requirement
instance GHC.Read.Read Swarm.Language.Requirement.Requirement
instance GHC.Show.Show Swarm.Language.Requirement.Requirement
instance GHC.Classes.Ord Swarm.Language.Requirement.Requirement
instance GHC.Classes.Eq Swarm.Language.Requirement.Requirement
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Requirement.Requirements
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Requirement.Requirements
instance GHC.Generics.Generic Swarm.Language.Requirement.Requirements
instance Data.Data.Data Swarm.Language.Requirement.Requirements
instance GHC.Show.Show Swarm.Language.Requirement.Requirements
instance GHC.Classes.Ord Swarm.Language.Requirement.Requirements
instance GHC.Classes.Eq Swarm.Language.Requirement.Requirements
instance GHC.Base.Semigroup Swarm.Language.Requirement.Requirements
instance GHC.Base.Monoid Swarm.Language.Requirement.Requirements
module Swarm.Language.Typed
-- | A value, or a hole, or something else that has its type &
-- requirements fixed
data Typed v
Typed :: v -> Polytype -> Requirements -> Typed v
[_value] :: Typed v -> v
[_polytype] :: Typed v -> Polytype
[_requires] :: Typed v -> Requirements
value :: forall v_a3dP3 v_a3e3W. Lens (Typed v_a3dP3) (Typed v_a3e3W) v_a3dP3 v_a3e3W
polytype :: forall v_a3dP3. Lens' (Typed v_a3dP3) Polytype
requires :: forall v_a3dP3. Lens' (Typed v_a3dP3) Requirements
instance Data.Aeson.Types.ToJSON.ToJSON v => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Language.Typed.Typed v)
instance Data.Aeson.Types.FromJSON.FromJSON v => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Language.Typed.Typed v)
instance GHC.Generics.Generic (Swarm.Language.Typed.Typed v)
instance GHC.Classes.Eq v => GHC.Classes.Eq (Swarm.Language.Typed.Typed v)
instance GHC.Show.Show v => GHC.Show.Show (Swarm.Language.Typed.Typed v)
-- | Data types and functions applicable across different scoring methods.
module Swarm.Game.Scenario.Scoring.GenericMetrics
-- | This is a subset of the ScenarioStatus type that excludes the
-- NotStarted case.
data Progress
Attempted :: Progress
Completed :: Progress
untaggedJsonOptions :: Options
data Metric a
Metric :: Progress -> a -> Metric a
getMetric :: Metric a -> a
-- | This encodes the notion of "more play is better" for incomplete games
-- (rationale: more play = more fun), whereas "smaller inputs are better"
-- for completed games.
--
-- Since Maybe has its own Ord instance where Nothing
-- < Just x regardless of x, when we want to choose the
-- minimum value we `fmap Down` to ensure that the Just is
-- selected while inverting the ordering of the inner member.
chooseBetter :: Ord a => (b -> Maybe a) -> Metric b -> Metric b -> Metric b
instance GHC.Generics.Generic Swarm.Game.Scenario.Scoring.GenericMetrics.Progress
instance GHC.Read.Read Swarm.Game.Scenario.Scoring.GenericMetrics.Progress
instance GHC.Show.Show Swarm.Game.Scenario.Scoring.GenericMetrics.Progress
instance GHC.Classes.Ord Swarm.Game.Scenario.Scoring.GenericMetrics.Progress
instance GHC.Classes.Eq Swarm.Game.Scenario.Scoring.GenericMetrics.Progress
instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.Scenario.Scoring.GenericMetrics.Metric a)
instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Game.Scenario.Scoring.GenericMetrics.Metric a)
instance GHC.Generics.Generic (Swarm.Game.Scenario.Scoring.GenericMetrics.Metric a)
instance GHC.Read.Read a => GHC.Read.Read (Swarm.Game.Scenario.Scoring.GenericMetrics.Metric a)
instance GHC.Show.Show a => GHC.Show.Show (Swarm.Game.Scenario.Scoring.GenericMetrics.Metric a)
instance GHC.Classes.Ord a => GHC.Classes.Ord (Swarm.Game.Scenario.Scoring.GenericMetrics.Metric a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Swarm.Game.Scenario.Scoring.GenericMetrics.Metric a)
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Scoring.GenericMetrics.Progress
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Scoring.GenericMetrics.Progress
-- | Locations and headings.
module Swarm.Game.Location
-- | A Location is a pair of (x,y) coordinates, both up to 32 bits. The
-- positive x-axis points east and the positive y-axis points north.
-- These are the coordinates that are shown to players.
--
-- See also the Coords type defined in Swarm.Game.World,
-- which use a (row, column) format instead, which is more convenient for
-- internal use. The Swarm.Game.World module also defines
-- conversions between Location and Coords.
type Location = Point V2 Int32
-- | A convenient way to pattern-match on Location values.
pattern Location :: Int32 -> Int32 -> Location
-- | A Heading is a 2D vector, with 32-bit coordinates.
--
-- Location and Heading are both represented using types
-- from the linear package, so they can be manipulated using a
-- large number of operators from that package. For example:
--
--
type Heading = V2 Int32
-- | The applyTurn function gives the meaning of each
-- Direction by turning relative to the given heading or by
-- turning to an absolute heading
applyTurn :: Direction -> Heading -> Heading
-- | Example: DWest relativeTo DSouth == DRight
relativeTo :: AbsoluteDir -> AbsoluteDir -> PlanarRelativeDir
-- | Possibly convert a heading into a Direction---that is, if the
-- vector happens to be a unit vector in one of the cardinal directions.
toDirection :: Heading -> Maybe Direction
-- | Logic adapted from:
-- https://gamedev.stackexchange.com/questions/49290/#comment213403_49300
nearestDirection :: Heading -> AbsoluteDir
-- | Convert a Direction into a corresponding heading. Note that
-- this only does something reasonable for DNorth, DSouth,
-- DEast, and DWest---other Directions return the
-- zero vector.
fromDirection :: Direction -> Heading
-- | Check if the direction is absolute (e.g. north or
-- south).
isCardinal :: Direction -> Bool
-- | The cardinal direction north = V2 0 1.
north :: Heading
-- | The cardinal direction south = V2 0 (-1).
south :: Heading
-- | The cardinal direction east = V2 1 0.
east :: Heading
-- | The cardinal direction west = V2 (-1) 0.
west :: Heading
-- | Manhattan distance between world locations.
manhattan :: Location -> Location -> Int32
-- | Euclidean distance between world locations.
euclidean :: Location -> Location -> Double
-- | Get elements that are in manhattan distance from location.
--
--
-- >>> v2s i = [(p, manhattan origin p) | x <- [-i..i], y <- [-i..i], let p = Location x y]
--
-- >>> v2s 0
-- [(P (V2 0 0),0)]
--
-- >>> map (\i -> length (getElemsInArea origin i (Map.fromList $ v2s i))) [0..8]
-- [1,5,13,25,41,61,85,113,145]
--
--
-- The last test is the sequence "Centered square numbers":
-- https://oeis.org/A001844
getElemsInArea :: Location -> Int32 -> Map Location e -> [e]
-- | An affine space is roughly a vector space in which we have forgotten
-- or at least pretend to have forgotten the origin.
--
--
-- a .+^ (b .-. a) = b@
-- (a .+^ u) .+^ v = a .+^ (u ^+^ v)@
-- (a .-. b) ^+^ v = (a .+^ v) .-. q@
--
class Additive Diff p => Affine (p :: Type -> Type) where {
type family Diff (p :: Type -> Type) :: Type -> Type;
}
-- | Get the difference between two points as a vector offset.
(.-.) :: (Affine p, Num a) => p a -> p a -> Diff p a
-- | Add a vector offset to a point.
(.+^) :: (Affine p, Num a) => p a -> Diff p a -> p a
-- | Subtract a vector offset from a point.
(.-^) :: (Affine p, Num a) => p a -> Diff p a -> p a
infixl 6 .-.
infixl 6 .+^
infixl 6 .-^
-- | A handy wrapper to help distinguish points from vectors at the type
-- level
newtype Point (f :: Type -> Type) a
P :: f a -> Point (f :: Type -> Type) a
-- | Vector spaces have origins.
origin :: forall (f :: Type -> Type) a. (Additive f, Num a) => Point f a
instance Data.Aeson.Types.ToJSON.ToJSON (Linear.V2.V2 GHC.Int.Int32)
instance Data.Aeson.Types.FromJSON.FromJSON (Linear.V2.V2 GHC.Int.Int32)
instance Data.Aeson.Types.FromJSON.FromJSONKey (Linear.V2.V2 GHC.Int.Int32)
instance Data.Aeson.Types.ToJSON.ToJSONKey (Linear.V2.V2 GHC.Int.Int32)
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Location.Location
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Location.Location
-- | World coordinates.
module Swarm.Game.World.Coords
-- | World coordinates use (row,column) format, with the row increasing as
-- we move down the screen. We use this format for indexing worlds
-- internally, since it plays nicely with things like drawing the screen,
-- and reading maps from configuration files. The locToCoords and
-- coordsToLoc functions convert back and forth between this type
-- and Location, which is used when presenting coordinates
-- externally to the player.
newtype Coords
Coords :: (Int32, Int32) -> Coords
[unCoords] :: Coords -> (Int32, Int32)
-- | Convert an external (x,y) location to an internal Coords value.
locToCoords :: Location -> Coords
-- | Convert an internal Coords value to an external (x,y) location.
coordsToLoc :: Coords -> Location
-- | Represents the top-left and bottom-right coordinates of a bounding
-- rectangle of cells in the world map
type BoundsRectangle = (Coords, Coords)
instance GHC.Generics.Generic Swarm.Game.World.Coords.Coords
instance GHC.Ix.Ix Swarm.Game.World.Coords.Coords
instance GHC.Show.Show Swarm.Game.World.Coords.Coords
instance GHC.Classes.Ord Swarm.Game.World.Coords.Coords
instance GHC.Classes.Eq Swarm.Game.World.Coords.Coords
instance Control.Lens.Wrapped.Rewrapped Swarm.Game.World.Coords.Coords t
instance Control.Lens.Wrapped.Wrapped Swarm.Game.World.Coords.Coords
module Swarm.Game.Universe
data SubworldName
DefaultRootSubworld :: SubworldName
SubworldName :: Text -> SubworldName
renderWorldName :: SubworldName -> Text
-- | The swarm universe consists of locations indexed by subworld. Not only
-- is this datatype useful for planar (2D) coordinates, but is also used
-- for named waypoints.
data Cosmic a
Cosmic :: SubworldName -> a -> Cosmic a
[_subworld] :: Cosmic a -> SubworldName
[_planar] :: Cosmic a -> a
subworld :: forall a_a3lgg. Lens' (Cosmic a_a3lgg) SubworldName
planar :: forall a_a3lgg a_a3lCq. Lens (Cosmic a_a3lgg) (Cosmic a_a3lCq) a_a3lgg a_a3lCq
defaultCosmicLocation :: Cosmic Location
data DistanceMeasure b
Measurable :: b -> DistanceMeasure b
InfinitelyFar :: DistanceMeasure b
-- | Returns InfinitelyFar if not within the same subworld.
cosmoMeasure :: (a -> a -> b) -> Cosmic a -> Cosmic a -> DistanceMeasure b
offsetBy :: Cosmic Location -> V2 Int32 -> Cosmic Location
instance GHC.Classes.Ord b => GHC.Classes.Ord (Swarm.Game.Universe.DistanceMeasure b)
instance GHC.Classes.Eq b => GHC.Classes.Eq (Swarm.Game.Universe.DistanceMeasure b)
instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Game.Universe.Cosmic a)
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Universe.SubworldName
instance GHC.Generics.Generic Swarm.Game.Universe.SubworldName
instance GHC.Classes.Ord Swarm.Game.Universe.SubworldName
instance GHC.Classes.Eq Swarm.Game.Universe.SubworldName
instance GHC.Show.Show Swarm.Game.Universe.SubworldName
instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.Universe.Cosmic a)
instance GHC.Generics.Generic (Swarm.Game.Universe.Cosmic a)
instance GHC.Base.Functor Swarm.Game.Universe.Cosmic
instance GHC.Classes.Ord a => GHC.Classes.Ord (Swarm.Game.Universe.Cosmic a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Swarm.Game.Universe.Cosmic a)
instance GHC.Show.Show a => GHC.Show.Show (Swarm.Game.Universe.Cosmic a)
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Universe.SubworldName
module Swarm.Game.Scenario.Topography.Area
data AreaDimensions
AreaDimensions :: Int32 -> Int32 -> AreaDimensions
[rectWidth] :: AreaDimensions -> Int32
[rectHeight] :: AreaDimensions -> Int32
renderRectDimensions :: AreaDimensions -> String
invertY :: V2 Int32 -> V2 Int32
-- | Incorporates an offset by -1, since the area is "inclusive" of the
-- lower-right coordinate. Inverse of "cornersToArea".
upperLeftToBottomRight :: AreaDimensions -> Location -> Location
-- | Converts the displacement vector between the two diagonal corners of
-- the rectangle into an AreaDimensions record. Adds one to both
-- dimensions since the corner coordinates are "inclusive". Inverse of
-- "upperLeftToBottomRight".
cornersToArea :: Location -> Location -> AreaDimensions
isEmpty :: AreaDimensions -> Bool
getAreaDimensions :: [[a]] -> AreaDimensions
module Swarm.Game.Scenario.Topography.Placement
newtype StructureName
StructureName :: Text -> StructureName
-- | Orientation transformations are applied before translation.
data Orientation
Orientation :: AbsoluteDir -> Bool -> Orientation
-- | e.g. For East, rotates 270 degrees.
[up] :: Orientation -> AbsoluteDir
-- | vertical flip, applied before rotation
[flipped] :: Orientation -> Bool
defaultOrientation :: Orientation
-- | This is the point-wise equivalent of "applyOrientationTransform"
reorientWaypoint :: Orientation -> AreaDimensions -> Location -> Location
-- | affine transformation
applyOrientationTransform :: Orientation -> [[a]] -> [[a]]
data Placement
Placement :: StructureName -> Location -> Orientation -> Placement
[src] :: Placement -> StructureName
[offset] :: Placement -> Location
[orient] :: Placement -> Orientation
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Topography.Placement.StructureName
instance GHC.Generics.Generic Swarm.Game.Scenario.Topography.Placement.StructureName
instance GHC.Show.Show Swarm.Game.Scenario.Topography.Placement.StructureName
instance GHC.Classes.Ord Swarm.Game.Scenario.Topography.Placement.StructureName
instance GHC.Classes.Eq Swarm.Game.Scenario.Topography.Placement.StructureName
instance GHC.Show.Show Swarm.Game.Scenario.Topography.Placement.Orientation
instance GHC.Classes.Eq Swarm.Game.Scenario.Topography.Placement.Orientation
instance GHC.Show.Show Swarm.Game.Scenario.Topography.Placement.Placement
instance GHC.Classes.Eq Swarm.Game.Scenario.Topography.Placement.Placement
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Topography.Placement.Placement
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Topography.Placement.Orientation
module Swarm.Game.Scenario.Topography.Navigation.Waypoint
-- | Indicates which structure something came from for debugging purposes.
data Originated a
Originated :: Maybe Placement -> a -> Originated a
[parent] :: Originated a -> Maybe Placement
[value] :: Originated a -> a
newtype WaypointName
WaypointName :: Text -> WaypointName
-- | Metadata about a waypoint
data WaypointConfig
WaypointConfig :: WaypointName -> Bool -> WaypointConfig
[wpName] :: WaypointConfig -> WaypointName
-- | Enforce global uniqueness of this waypoint
[wpUnique] :: WaypointConfig -> Bool
parseWaypointConfig :: Object -> Parser WaypointConfig
-- | A parent world shouldn't have to know the exact layout of a subworld
-- to specify where exactly a portal will deliver a robot to within the
-- subworld. Therefore, we define named waypoints in the subworld and the
-- parent world must reference them by name, rather than by coordinate.
data Waypoint
Waypoint :: WaypointConfig -> Location -> Waypoint
[wpConfig] :: Waypoint -> WaypointConfig
[wpLoc] :: Waypoint -> Location
-- | Basically "fmap" for the Location field
modifyLocation :: (Location -> Location) -> Waypoint -> Waypoint
-- | Translation by a vector
offsetWaypoint :: V2 Int32 -> Waypoint -> Waypoint
instance GHC.Base.Functor Swarm.Game.Scenario.Topography.Navigation.Waypoint.Originated
instance GHC.Classes.Eq a => GHC.Classes.Eq (Swarm.Game.Scenario.Topography.Navigation.Waypoint.Originated a)
instance GHC.Show.Show a => GHC.Show.Show (Swarm.Game.Scenario.Topography.Navigation.Waypoint.Originated a)
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Topography.Navigation.Waypoint.WaypointName
instance GHC.Generics.Generic Swarm.Game.Scenario.Topography.Navigation.Waypoint.WaypointName
instance GHC.Classes.Ord Swarm.Game.Scenario.Topography.Navigation.Waypoint.WaypointName
instance GHC.Classes.Eq Swarm.Game.Scenario.Topography.Navigation.Waypoint.WaypointName
instance GHC.Show.Show Swarm.Game.Scenario.Topography.Navigation.Waypoint.WaypointName
instance GHC.Classes.Eq Swarm.Game.Scenario.Topography.Navigation.Waypoint.WaypointConfig
instance GHC.Show.Show Swarm.Game.Scenario.Topography.Navigation.Waypoint.WaypointConfig
instance GHC.Classes.Eq Swarm.Game.Scenario.Topography.Navigation.Waypoint.Waypoint
instance GHC.Show.Show Swarm.Game.Scenario.Topography.Navigation.Waypoint.Waypoint
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Topography.Navigation.Waypoint.Waypoint
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Topography.Navigation.Waypoint.WaypointConfig
module Swarm.Game.Scenario.Topography.Navigation.Portal
type WaypointMap = Map WaypointName (NonEmpty Location)
data AnnotatedDestination a
AnnotatedDestination :: Bool -> Direction -> Cosmic a -> AnnotatedDestination a
[enforceConsistency] :: AnnotatedDestination a -> Bool
[reorientation] :: AnnotatedDestination a -> Direction
[destination] :: AnnotatedDestination a -> Cosmic a
-- | Parameterized on waypoint dimensionality
-- (additionalDimension) and on the portal location
-- specification method (portalExitLoc). ==
-- additionalDimension As a member of the
-- WorldDescription, waypoints are only known within a a single
-- subworld, so additionalDimension is Identity for the
-- map of waypoint names to planar locations. At the Scenario level, in
-- contrast, we have access to all subworlds, so we nest this map to
-- planar locations in additional mapping layer by subworld. ==
-- portalExitLoc At the subworld parsing level, we only can
-- obtain the planar location for portal entrances, but the
-- exits remain as waypoint names. At the Scenario-parsing level,
-- we finally have access to the waypoints across all subworlds, and can
-- therefore translate the portal exits to concrete planar locations.
data Navigation additionalDimension portalExitLoc
Navigation :: additionalDimension WaypointMap -> Map (Cosmic Location) (AnnotatedDestination portalExitLoc) -> Navigation additionalDimension portalExitLoc
-- | Note that waypoints defined at the "root" level are still relative to
-- the top-left corner of the map rectangle; they are not in absolute
-- world coordinates (as with applying the "ul" offset).
[waypoints] :: Navigation additionalDimension portalExitLoc -> additionalDimension WaypointMap
[portals] :: Navigation additionalDimension portalExitLoc -> Map (Cosmic Location) (AnnotatedDestination portalExitLoc)
data PortalExit
PortalExit :: WaypointName -> Maybe SubworldName -> PortalExit
[exit] :: PortalExit -> WaypointName
-- | Note: Nothing indicates that references a waypoint within the
-- same subworld.
[subworldName] :: PortalExit -> Maybe SubworldName
data Portal
Portal :: WaypointName -> PortalExit -> Bool -> PlanarRelativeDir -> Portal
[entrance] :: Portal -> WaypointName
[exitInfo] :: Portal -> PortalExit
[consistent] :: Portal -> Bool
[reorient] :: Portal -> PlanarRelativeDir
failUponDuplication :: (MonadFail m, Show a, Show b) => Text -> Map a (NonEmpty b) -> m ()
failWaypointLookup :: MonadFail m => WaypointName -> Maybe a -> m a
-- | The following constraints must be enforced: * portals based on plural
-- waypoint multiplicity can have multiple entrances but only a single
-- exit * no two portals share the same entrance location * waypoint
-- uniqueness within a subworld when the unique flag is
-- specified
--
-- Data flow:
--
-- Waypoints are defined within a subworld and are namespaced by it.
-- Optional intra-subworld uniqueness of Waypoints is enforced at
-- WorldDescription parse time. Portals are declared within a subworld.
-- The portal entrance must be a waypoint within this subworld. They can
-- reference waypoints in other subworlds as exits, but these references
-- are not validated until the Scenario parse level.
--
--
-- - Since portal entrances are specified at the subworld level,
-- validation that no entrances overlap can also be performed at that
-- level.
-- - However, enforcement of single-multiplicity on portal exits
-- must be performed at scenario-parse level, because for a portal exit
-- that references a waypoint in another subworld, we can't know at the
-- single-WorldDescription level whether that waypoint has plural
-- multiplicity.
--
validatePartialNavigation :: (MonadFail m, Traversable t) => SubworldName -> Location -> [Originated Waypoint] -> t Portal -> m (Navigation Identity WaypointName)
validatePortals :: MonadFail m => Navigation (Map SubworldName) WaypointName -> m (Map (Cosmic Location) (AnnotatedDestination Location))
-- | A portal can be marked as "consistent", meaning that it represents a
-- conventional physical passage rather than a "magical" teleportation.
--
-- If there exists more than one "consistent" portal between the same two
-- subworlds, then the portal locations must be spatially consistent
-- between the two worlds. I.e. the space comprising the two subworlds
-- forms a "conservative vector field".
--
-- Verifying this is simple: For all of the portals between Subworlds A
-- and B: * The coordinates of all "consistent" portal locations in
-- Subworld A are subtracted from the corresponding coordinates in
-- Subworld B. It does not matter which are exits vs. entrances. * The
-- resulting "vector" from every pair must be equal.
ensureSpatialConsistency :: MonadFail m => [(Cosmic Location, AnnotatedDestination Location)] -> m ()
-- | An implementation of sequenceA for Signed that does not
-- require an Applicative instance for the inner Functor.
--
-- Discussion
--
-- Compare to the Traversable instance of Signed:
-- instance Traversable Signed where traverse f (Positive x) = Positive
-- $ f x traverse f (Negative x) = Negative $ f x
--
-- if we were to substitute id for f: traverse id (Positive
-- x) = Positive $ id x traverse id (Negative x) = Negative
-- $ id x our implementation essentially becomes
-- traverse id.
--
-- However, we cannot simply write our implementation as traverse
-- id, because the traverse function has an
-- Applicative constraint, which is superfluous for our purpose.
--
-- Perhaps there is an opportunity to invent a typeclass for datatypes
-- which consist exclusively of unary (or more ambitiously, non-nullary?)
-- data constructors, for which a less-constrained sequence
-- function could be automatically derived. Compare to the
-- Comonad class and its extract function.
sequenceSigned :: Functor f => Signed (f a) -> f (Signed a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Swarm.Game.Scenario.Topography.Navigation.Portal.AnnotatedDestination a)
instance GHC.Show.Show a => GHC.Show.Show (Swarm.Game.Scenario.Topography.Navigation.Portal.AnnotatedDestination a)
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Topography.Navigation.Portal.PortalExit
instance GHC.Generics.Generic Swarm.Game.Scenario.Topography.Navigation.Portal.PortalExit
instance GHC.Classes.Eq Swarm.Game.Scenario.Topography.Navigation.Portal.PortalExit
instance GHC.Show.Show Swarm.Game.Scenario.Topography.Navigation.Portal.PortalExit
instance GHC.Classes.Eq Swarm.Game.Scenario.Topography.Navigation.Portal.Portal
instance GHC.Show.Show Swarm.Game.Scenario.Topography.Navigation.Portal.Portal
instance (GHC.Classes.Eq (a Swarm.Game.Scenario.Topography.Navigation.Portal.WaypointMap), GHC.Classes.Eq b) => GHC.Classes.Eq (Swarm.Game.Scenario.Topography.Navigation.Portal.Navigation a b)
instance (GHC.Show.Show (a Swarm.Game.Scenario.Topography.Navigation.Portal.WaypointMap), GHC.Show.Show b) => GHC.Show.Show (Swarm.Game.Scenario.Topography.Navigation.Portal.Navigation a b)
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Topography.Navigation.Portal.Portal
-- | Definitions of all possible achievements.
module Swarm.Game.Achievement.Definitions
data ExpectedEffort
Trivial :: ExpectedEffort
Easy :: ExpectedEffort
Moderate :: ExpectedEffort
Gruelling :: ExpectedEffort
data Quotation
Quotation :: Text -> Text -> Quotation
[attribution] :: Quotation -> Text
[content] :: Quotation -> Text
data FlavorText
Freeform :: Text -> FlavorText
FTQuotation :: Quotation -> FlavorText
data AchievementInfo
AchievementInfo :: Text -> Maybe FlavorText -> Text -> ExpectedEffort -> Bool -> AchievementInfo
-- | Guidelines: * prefer puns, pop culture references, etc. * should be a
-- phrase in Title Case. * For achievements that are "obfuscated", this
-- can be a vague "clue" as to what the attainment entails.
[title] :: AchievementInfo -> Text
-- | Explain the reference, e.g. in the form of a full quote from a movie,
-- or something you might find in a fortune cookie
[humorousElaboration] :: AchievementInfo -> Maybe FlavorText
-- | Precisely what must be done to obtain this achievement.
[attainmentProcess] :: AchievementInfo -> Text
[effort] :: AchievementInfo -> ExpectedEffort
-- | Hides the attainment process until after the achievement is attained.
-- Best when the title + elaboration constitute a good clue.
[isObfuscated] :: AchievementInfo -> Bool
data CategorizedAchievement
GlobalAchievement :: GlobalAchievement -> CategorizedAchievement
GameplayAchievement :: GameplayAchievement -> CategorizedAchievement
categorizedAchievementJsonOptions :: Options
-- | Achievements that entail some aggregate of actions across scenarios
data GlobalAchievement
CompletedSingleTutorial :: GlobalAchievement
CompletedAllTutorials :: GlobalAchievement
LookedAtAboutScreen :: GlobalAchievement
-- | Achievements obtained while playing a single scenario
data GameplayAchievement
CraftedBitcoin :: GameplayAchievement
RobotIntoWater :: GameplayAchievement
AttemptSelfDestructBase :: GameplayAchievement
DestroyedBase :: GameplayAchievement
LoseScenario :: GameplayAchievement
GetDisoriented :: GameplayAchievement
listAchievements :: [CategorizedAchievement]
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Achievement.Definitions.ExpectedEffort
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Achievement.Definitions.ExpectedEffort
instance GHC.Generics.Generic Swarm.Game.Achievement.Definitions.ExpectedEffort
instance GHC.Enum.Enum Swarm.Game.Achievement.Definitions.ExpectedEffort
instance GHC.Enum.Bounded Swarm.Game.Achievement.Definitions.ExpectedEffort
instance GHC.Show.Show Swarm.Game.Achievement.Definitions.ExpectedEffort
instance GHC.Classes.Ord Swarm.Game.Achievement.Definitions.ExpectedEffort
instance GHC.Classes.Eq Swarm.Game.Achievement.Definitions.ExpectedEffort
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Achievement.Definitions.Quotation
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Achievement.Definitions.Quotation
instance GHC.Generics.Generic Swarm.Game.Achievement.Definitions.Quotation
instance GHC.Show.Show Swarm.Game.Achievement.Definitions.Quotation
instance GHC.Classes.Eq Swarm.Game.Achievement.Definitions.Quotation
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Achievement.Definitions.FlavorText
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Achievement.Definitions.FlavorText
instance GHC.Generics.Generic Swarm.Game.Achievement.Definitions.FlavorText
instance GHC.Show.Show Swarm.Game.Achievement.Definitions.FlavorText
instance GHC.Classes.Eq Swarm.Game.Achievement.Definitions.FlavorText
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Achievement.Definitions.AchievementInfo
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Achievement.Definitions.AchievementInfo
instance GHC.Generics.Generic Swarm.Game.Achievement.Definitions.AchievementInfo
instance GHC.Show.Show Swarm.Game.Achievement.Definitions.AchievementInfo
instance GHC.Classes.Eq Swarm.Game.Achievement.Definitions.AchievementInfo
instance GHC.Generics.Generic Swarm.Game.Achievement.Definitions.GlobalAchievement
instance GHC.Enum.Enum Swarm.Game.Achievement.Definitions.GlobalAchievement
instance GHC.Enum.Bounded Swarm.Game.Achievement.Definitions.GlobalAchievement
instance GHC.Show.Show Swarm.Game.Achievement.Definitions.GlobalAchievement
instance GHC.Classes.Ord Swarm.Game.Achievement.Definitions.GlobalAchievement
instance GHC.Classes.Eq Swarm.Game.Achievement.Definitions.GlobalAchievement
instance GHC.Generics.Generic Swarm.Game.Achievement.Definitions.GameplayAchievement
instance GHC.Enum.Enum Swarm.Game.Achievement.Definitions.GameplayAchievement
instance GHC.Enum.Bounded Swarm.Game.Achievement.Definitions.GameplayAchievement
instance GHC.Show.Show Swarm.Game.Achievement.Definitions.GameplayAchievement
instance GHC.Classes.Ord Swarm.Game.Achievement.Definitions.GameplayAchievement
instance GHC.Classes.Eq Swarm.Game.Achievement.Definitions.GameplayAchievement
instance GHC.Generics.Generic Swarm.Game.Achievement.Definitions.CategorizedAchievement
instance GHC.Show.Show Swarm.Game.Achievement.Definitions.CategorizedAchievement
instance GHC.Classes.Ord Swarm.Game.Achievement.Definitions.CategorizedAchievement
instance GHC.Classes.Eq Swarm.Game.Achievement.Definitions.CategorizedAchievement
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Achievement.Definitions.CategorizedAchievement
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Achievement.Definitions.CategorizedAchievement
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Achievement.Definitions.GameplayAchievement
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Achievement.Definitions.GameplayAchievement
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Achievement.Definitions.GlobalAchievement
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Achievement.Definitions.GlobalAchievement
-- | Flavor text about all defined achievements.
module Swarm.Game.Achievement.Description
describe :: CategorizedAchievement -> AchievementInfo
-- | Metadata about achievements that the player has obtained
module Swarm.Game.Achievement.Attainment
data Attainment
Attainment :: CategorizedAchievement -> Maybe FilePath -> ZonedTime -> Attainment
[_achievement] :: Attainment -> CategorizedAchievement
-- | from which scenario was it obtained?
[_maybeScenarioPath] :: Attainment -> Maybe FilePath
[_obtainedAt] :: Attainment -> ZonedTime
obtainedAt :: Lens' Attainment ZonedTime
maybeScenarioPath :: Lens' Attainment (Maybe FilePath)
achievement :: Lens' Attainment CategorizedAchievement
achievementJsonOptions :: Options
instance GHC.Classes.Eq Swarm.Game.Achievement.Attainment.Attainment
instance GHC.Classes.Ord Swarm.Game.Achievement.Attainment.Attainment
instance GHC.Base.Semigroup Swarm.Game.Achievement.Attainment.Attainment
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Achievement.Attainment.Attainment
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Achievement.Attainment.Attainment
instance GHC.Generics.Generic Swarm.Game.Achievement.Attainment.Attainment
-- | Custom extension of Semigroup to Monoid that adds
-- identity + annihilator elements.
module Swarm.Util.Erasable
-- | Extend a semigroup to a monoid by adding an identity (ENothing)
-- and an annihilator (EErase). That is,
--
--
--
-- This allows us to "erase" previous values by combining with
-- EErase. The erasableToMaybe function turns an
-- Erasable into a Maybe by collapsing ENothing and
-- EErase both back into Nothing.
data Erasable e
ENothing :: Erasable e
EErase :: Erasable e
EJust :: e -> Erasable e
-- | Generic eliminator for Erasable values.
erasable :: a -> a -> (e -> a) -> Erasable e -> a
-- | Convert an Erasable value to Maybe, turning both
-- ENothing and EErase into Nothing.
erasableToMaybe :: Erasable e -> Maybe e
-- | Inject a Maybe value into Erasable using ENothing
-- and EJust.
maybeToErasable :: Maybe e -> Erasable e
instance GHC.Base.Functor Swarm.Util.Erasable.Erasable
instance GHC.Classes.Ord e => GHC.Classes.Ord (Swarm.Util.Erasable.Erasable e)
instance GHC.Classes.Eq e => GHC.Classes.Eq (Swarm.Util.Erasable.Erasable e)
instance GHC.Show.Show e => GHC.Show.Show (Swarm.Util.Erasable.Erasable e)
instance GHC.Base.Semigroup e => GHC.Base.Semigroup (Swarm.Util.Erasable.Erasable e)
instance GHC.Base.Semigroup e => GHC.Base.Monoid (Swarm.Util.Erasable.Erasable e)
-- | Lens generation utilities.
module Swarm.Util.Lens
-- | Generate lenses but with no type signatures, so we can explicitly give
-- type signatures and attach custom Haddock documentation to them.
makeLensesNoSigs :: Name -> DecsQ
-- | Generate lenses for the fields of a record type (with no type
-- signatures), except for a given list of excluded fields.
--
-- Especially useful in conjunction with the design pattern described in
-- https://byorgey.wordpress.com/2021/09/17/automatically-updated-cached-views-with-lens/
makeLensesExcluding :: [Name] -> Name -> DecsQ
module Swarm.TUI.Model.Repl
-- | An item in the REPL history.
data REPLHistItem
-- | Something entered by the user.
REPLEntry :: Text -> REPLHistItem
-- | A response printed by the system.
REPLOutput :: Text -> REPLHistItem
-- | Get the text of REPL input/output.
replItemText :: REPLHistItem -> Text
-- | Useful helper function to filter out REPL output.
isREPLEntry :: REPLHistItem -> Bool
-- | Useful helper function to only get user input text.
getREPLEntry :: REPLHistItem -> Maybe Text
-- | History of the REPL with indices (0 is first entry) to the current
-- line and to the first entry since loading saved history. We also
-- (ab)use the length of the REPL as the index of current input line,
-- since that number is one past the index of last entry.
data REPLHistory
-- | The current index in the REPL history (if the user is going back
-- through the history using up/down keys).
replIndex :: Lens' REPLHistory Int
-- | Current number lines of the REPL history - (ab)used as index of input
-- buffer.
replLength :: REPLHistory -> Int
-- | Note: Instead of adding a dedicated field to the REPLHistory record,
-- an early attempt entailed checking for:
--
-- _replIndex > _replStart
--
-- However, executing an initial script causes a REPLOutput to be
-- appended to the REPL history, which increments the replIndex, and thus
-- makes the Index greater than the Start even though the player has
-- input not commands into the REPL.
--
-- Therefore, a dedicated boolean is introduced into REPLHistory which
-- simply latches True when the user has input a command.
--
-- An alternative is described here:
-- https://github.com/swarm-game/swarm/pull/974#discussion_r1112380380
replHasExecutedManualInput :: Lens' REPLHistory Bool
-- | Sequence of REPL inputs and outputs, oldest entry is leftmost.
replSeq :: Lens' REPLHistory (Seq REPLHistItem)
-- | Create new REPL history (i.e. from loaded history file lines).
newREPLHistory :: [REPLHistItem] -> REPLHistory
-- | Add new REPL input - the index must have been pointing one past the
-- last element already, so we increment it to keep it that way.
addREPLItem :: REPLHistItem -> REPLHistory -> REPLHistory
-- | Point the start of REPL history after current last line. See
-- replStart.
restartREPLHistory :: REPLHistory -> REPLHistory
-- | Get the latest N items in history, starting with the oldest one.
--
-- This is used to show previous REPL lines in UI, so we need the items
-- sorted in the order they were entered and will be drawn top to bottom.
getLatestREPLHistoryItems :: Int -> REPLHistory -> [REPLHistItem]
moveReplHistIndex :: TimeDir -> Text -> REPLHistory -> REPLHistory
getCurrentItemText :: REPLHistory -> Maybe Text
replIndexIsAtInput :: REPLHistory -> Bool
data TimeDir
Newer :: TimeDir
Older :: TimeDir
-- | This data type tells us how to interpret the text typed by the player
-- at the prompt (which is stored in Editor).
data REPLPrompt
-- | Interpret the prompt text as a regular command. The list is for
-- potential completions, which we can cycle through by hitting Tab
-- repeatedly
CmdPrompt :: [Text] -> REPLPrompt
-- | Interpret the prompt text as "search this text in history"
SearchPrompt :: REPLHistory -> REPLPrompt
-- | Given some text, removes the REPLEntry within REPLHistory which is
-- equal to that. This is used when the user enters in search mode and
-- want to traverse the history. If a command has been used many times,
-- the history will be populated with it causing the effect that search
-- command always finds the same command.
removeEntry :: Text -> REPLHistory -> REPLHistory
data REPLState
-- | What is being done with user input to the REPL panel?
data ReplControlMode
-- | The user is typing at the REPL.
Typing :: ReplControlMode
-- | The user is driving the base using piloting mode.
Piloting :: ReplControlMode
-- | A custom user key handler is processing user input.
Handling :: ReplControlMode
-- | The way we interpret text typed by the player in the REPL prompt.
replPromptType :: Lens' REPLState REPLPrompt
-- | The prompt where the user can type input at the REPL.
replPromptEditor :: Lens' REPLState (Editor Text Name)
-- | Convinience lens to get text from editor and replace it with new one
-- that has the provided text.
replPromptText :: Lens' REPLState Text
-- | Whether the prompt text is a valid Term.
replValid :: Lens' REPLState Bool
-- | The last thing the user has typed which isn't part of the history.
-- This is used to restore the repl form after the user visited the
-- history.
replLast :: Lens' REPLState Text
-- | The type of the current REPL input which should be displayed to the
-- user (if any).
replType :: Lens' REPLState (Maybe Polytype)
-- | The current REPL control mode, i.e. how user input to the REPL panel
-- is being handled.
replControlMode :: Lens' REPLState ReplControlMode
-- | History of things the user has typed at the REPL, interleaved with
-- outputs the system has generated.
replHistory :: Lens' REPLState REPLHistory
newREPLEditor :: Text -> Editor Text Name
initREPLState :: REPLHistory -> REPLState
defaultPrompt :: REPLPrompt
-- | Get the last REPLEntry in REPLHistory matching the given text
lastEntry :: Text -> REPLHistory -> Maybe Text
instance GHC.Show.Show Swarm.TUI.Model.Repl.TimeDir
instance GHC.Classes.Ord Swarm.TUI.Model.Repl.TimeDir
instance GHC.Classes.Eq Swarm.TUI.Model.Repl.TimeDir
instance GHC.Enum.Enum Swarm.TUI.Model.Repl.ReplControlMode
instance GHC.Enum.Bounded Swarm.TUI.Model.Repl.ReplControlMode
instance GHC.Classes.Eq Swarm.TUI.Model.Repl.ReplControlMode
instance GHC.Read.Read Swarm.TUI.Model.Repl.REPLHistItem
instance GHC.Show.Show Swarm.TUI.Model.Repl.REPLHistItem
instance GHC.Classes.Ord Swarm.TUI.Model.Repl.REPLHistItem
instance GHC.Classes.Eq Swarm.TUI.Model.Repl.REPLHistItem
instance GHC.Show.Show Swarm.TUI.Model.Repl.REPLHistory
instance Servant.Docs.Internal.ToSample Swarm.TUI.Model.Repl.REPLHistItem
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.TUI.Model.Repl.REPLHistItem
-- | Parsing utilities for Swarm.
module Swarm.Util.Parse
-- | Run a parser "fully", consuming leading whitespace and ensuring that
-- the parser extends all the way to eof.
fully :: MonadParsec e s f => f () -> f a -> f a
-- | Run a parser "fully", consuming leading whitespace (including the
-- possibility that the input is nothing but whitespace) and ensuring
-- that the parser extends all the way to eof.
fullyMaybe :: MonadParsec e s f => f () -> f a -> f (Maybe a)
-- | Parser for the Swarm language. Note, you probably don't want to use
-- this directly, unless there is a good reason to parse a term without
-- also type checking it; use processTerm instead, which parses,
-- typechecks, elaborates, and capability checks a term all at once.
module Swarm.Language.Parse
-- | List of reserved words that cannot be used as variable names.
reservedWords :: [Text]
type Parser = ReaderT Antiquoting (Parsec Void Text)
-- | Parse a Swarm language polytype, which starts with an optional
-- quanitifation (forall followed by one or more variables and a
-- period) followed by a type. Note that anything accepted by
-- parseType is also accepted by parsePolytype.
parsePolytype :: Parser Polytype
-- | Parse a Swarm language (mono)type.
parseType :: Parser Type
-- | Parse a Swarm language term.
parseTerm :: Parser Syntax
-- | Precedences and parsers of binary operators.
--
--
-- >>> Map.map length binOps
-- fromList [(0,1),(2,1),(3,1),(4,6),(6,3),(7,2),(8,1)]
--
binOps :: Map Int [Operator Parser Syntax]
-- | Precedences and parsers of unary operators (currently only
-- Neg).
--
--
-- >>> Map.map length unOps
-- fromList [(7,1)]
--
unOps :: Map Int [Operator Parser Syntax]
-- | Run a parser on some input text, returning either the result or a
-- pretty-printed parse error message.
runParser :: Parser a -> Text -> Either Text a
-- | A utility for running a parser in an arbitrary MonadFail (which
-- is going to be the TemplateHaskell Q monad --- see
-- Swarm.Language.Parse.QQ), with a specified source position.
runParserTH :: (Monad m, MonadFail m) => (String, Int, Int) -> Parser a -> String -> m a
-- | Parse some input Text completely as a Term, consuming
-- leading whitespace and ensuring the parsing extends all the way to the
-- end of the input Text. Returns either the resulting Term
-- (or Nothing if the input was only whitespace) or a
-- pretty-printed parse error message.
readTerm :: Text -> Either Text (Maybe Syntax)
-- | A lower-level readTerm which returns the megaparsec bundle
-- error for precise error reporting.
readTerm' :: Text -> Either ParserError (Maybe Syntax)
-- | A utility for converting a ParserError into a one line message:
-- line-nr: error-msg
showShortError :: ParserError -> String
-- | A utility for converting a ParseError into a range and error message.
showErrorPos :: ParserError -> ((Int, Int), (Int, Int), Text)
-- | A utility for converting a SrcLoc into a range
getLocRange :: Text -> (Int, Int) -> ((Int, Int), (Int, Int))
unTuple :: Syntax' ty -> [Syntax' ty]
instance GHC.Show.Show Swarm.Language.Parse.Antiquoting
instance GHC.Classes.Ord Swarm.Language.Parse.Antiquoting
instance GHC.Classes.Eq Swarm.Language.Parse.Antiquoting
instance GHC.Show.Show Swarm.Language.Parse.Stmt
-- | A quasiquoter for Swarm polytypes.
module Swarm.Language.Parse.QQ
-- | A quasiquoter for Swarm polytypes, so we can conveniently write them
-- down using concrete syntax and have them parsed into abstract syntax
-- at compile time. This is used, for example, in writing down the
-- concrete types of constants (see Swarm.Language.Typecheck).
tyQ :: QuasiQuoter
-- | Type inference for the Swarm language. For the approach used here, see
-- https://byorgey.wordpress.com/2021/09/08/implementing-hindley-milner-with-the-unification-fd-library/
-- .
module Swarm.Language.Typecheck
-- | A type error along with various contextual information to help us
-- generate better error messages.
data ContextualTypeErr
CTE :: SrcLoc -> TCStack -> TypeErr -> ContextualTypeErr
[cteSrcLoc] :: ContextualTypeErr -> SrcLoc
[cteStack] :: ContextualTypeErr -> TCStack
[cteTypeErr] :: ContextualTypeErr -> TypeErr
-- | Errors that can occur during type checking. The idea is that each
-- error carries information that can be used to help explain what went
-- wrong (though the amount of information carried can and should be very
-- much improved in the future); errors can then separately be
-- pretty-printed to display them to the user.
data TypeErr
-- | An undefined variable was encountered.
UnboundVar :: Var -> TypeErr
-- | A Skolem variable escaped its local context.
EscapedSkolem :: Var -> TypeErr
-- | Occurs check failure, i.e. infinite type.
Infinite :: IntVar -> UType -> TypeErr
-- | Error generated by the unifier.
UnifyErr :: TypeF UType -> TypeF UType -> TypeErr
-- | Type mismatch caught by unifyCheck. The given term was expected
-- to have a certain type, but has a different type instead.
Mismatch :: Maybe Syntax -> TypeJoin -> TypeErr
-- | Lambda argument type mismatch.
LambdaArgMismatch :: TypeJoin -> TypeErr
-- | Record field mismatch, i.e. based on the expected type we were
-- expecting a record with certain fields, but found one with a different
-- field set.
FieldsMismatch :: Join (Set Var) -> TypeErr
-- | A definition was encountered not at the top level.
DefNotTopLevel :: Term -> TypeErr
-- | A term was encountered which we cannot infer the type of. This should
-- never happen.
CantInfer :: Term -> TypeErr
-- | We can't infer the type of a record projection r.x if we
-- don't concretely know the type of the record r.
CantInferProj :: Term -> TypeErr
-- | An attempt to project out a nonexistent field
UnknownProj :: Var -> Term -> TypeErr
-- | An invalid argument was provided to atomic.
InvalidAtomic :: InvalidAtomicReason -> Term -> TypeErr
-- | Some unification variables ended up in a type, probably due to
-- impredicativity. See
-- https://github.com/swarm-game/swarm/issues/351 .
Impredicative :: TypeErr
-- | Various reasons the body of an atomic might be invalid.
data InvalidAtomicReason
-- | The argument has too many tangible commands.
TooManyTicks :: Int -> InvalidAtomicReason
-- | The argument uses some way to duplicate code: def,
-- let, or lambda.
AtomicDupingThing :: InvalidAtomicReason
-- | The argument referred to a variable with a non-simple type.
NonSimpleVarType :: Var -> UPolytype -> InvalidAtomicReason
-- | The argument had a nested atomic
NestedAtomic :: InvalidAtomicReason
-- | The argument contained a long command
LongConst :: InvalidAtomicReason
-- | The source of a type during typechecking.
data Source
-- | An expected type that was "pushed down" from the context.
Expected :: Source
-- | An actual/inferred type that was "pulled up" from a term.
Actual :: Source
-- | Generic eliminator for Source. Choose the first argument if the
-- Source is Expected, and the second argument if
-- Actual.
withSource :: Source -> a -> a -> a
-- | A "join" where an expected thing meets an actual thing.
data Join a
-- | Convert a Join into a pair of (expected, actual).
getJoin :: Join a -> (a, a)
-- | A frame to keep track of something we were in the middle of doing
-- during typechecking.
data TCFrame
-- | Checking a definition.
[TCDef] :: Var -> TCFrame
-- | Inferring the LHS of a bind.
[TCBindL] :: TCFrame
-- | Inferring the RHS of a bind.
[TCBindR] :: TCFrame
-- | A typechecking stack frame together with the relevant SrcLoc.
data LocatedTCFrame
LocatedTCFrame :: SrcLoc -> TCFrame -> LocatedTCFrame
-- | A typechecking stack keeps track of what we are currently in the
-- middle of doing during typechecking.
type TCStack = [LocatedTCFrame]
-- | Push a frame on the typechecking stack within a local TC
-- computation.
withFrame :: SrcLoc -> TCFrame -> TC a -> TC a
-- | Get the current typechecking stack.
getTCStack :: TC TCStack
-- | The concrete monad used for type checking. IntBindingT is a
-- monad transformer provided by the unification-fd library
-- which supports various operations such as generating fresh variables
-- and unifying things.
type TC = ReaderT UCtx (ReaderT TCStack (ExceptT ContextualTypeErr (IntBindingT TypeF Identity)))
-- | Run a top-level inference computation, returning either a
-- TypeErr or a fully resolved TModule.
runTC :: TCtx -> TC UModule -> Either ContextualTypeErr TModule
-- | Generate a fresh unification variable.
fresh :: TC UType
-- | Perform a substitution over a UType, substituting for both type
-- and unification variables. Note that since UTypes do not have
-- any binding constructs, we don't have to worry about ignoring bound
-- variables; all variables in a UType are free.
substU :: Map (Either Var IntVar) UType -> UType -> UType
-- | unify t expTy actTy ensures that the given two types are
-- equal. If we know the actual term t which is supposed to have
-- these types, we can use it to generate better error messages.
--
-- We first do a quick-and-dirty check to see whether we know for sure
-- the types either are or cannot be equal, generating an equality
-- constraint for the unifier as a last resort.
unify :: Maybe Syntax -> TypeJoin -> TC UType
-- | unification-fd provides a function applyBindings which
-- fully substitutes for any bound unification variables (for efficiency,
-- it does not perform such substitution as it goes along). The
-- HasBindings class is for anything which has unification
-- variables in it and to which we can usefully apply
-- applyBindings.
class HasBindings u
applyBindings :: HasBindings u => u -> TC u
-- | To instantiate a UPolytype, we generate a fresh
-- unification variable for each variable bound by the Forall, and
-- then substitute them throughout the type.
instantiate :: UPolytype -> TC UType
-- | skolemize is like instantiate, except we substitute
-- fresh type variables instead of unification variables. Such
-- variables cannot unify with anything other than themselves. This is
-- used when checking something with a polytype explicitly specified by
-- the user.
skolemize :: UPolytype -> TC UType
-- | generalize is the opposite of instantiate: add a
-- Forall which closes over all free type and unification
-- variables.
--
-- Pick nice type variable names instead of reusing whatever fresh names
-- happened to be used for the free variables.
generalize :: UType -> TC UPolytype
-- | Top-level type inference function: given a context of definition types
-- and a top-level term, either return a type error or its type as a
-- TModule.
inferTop :: TCtx -> Syntax -> Either ContextualTypeErr TModule
-- | Infer the signature of a top-level expression which might contain
-- definitions.
inferModule :: Syntax -> TC UModule
-- | Infer the type of a term which does not contain definitions, returning
-- a type-annotated term.
--
-- The only cases explicitly handled in infer are those where
-- pushing an expected type down into the term can't possibly help, e.g.
-- most primitives, function application, and binds.
--
-- For most everything else we prefer check because it can often
-- result in better and more localized type error messages.
infer :: Syntax -> TC (Syntax' UType)
-- | Infer the type of a constant.
inferConst :: Const -> Polytype
-- | check t ty checks that t has type ty,
-- returning a type-annotated AST if so.
--
-- We try to stay in checking mode as far as possible, decomposing the
-- expected type as we go and pushing it through the recursion.
check :: Syntax -> UType -> TC (Syntax' UType)
-- | A simple type is a sum or product of base types.
isSimpleUType :: UType -> Bool
instance GHC.Show.Show Swarm.Language.Typecheck.TCFrame
instance GHC.Show.Show Swarm.Language.Typecheck.LocatedTCFrame
instance GHC.Enum.Enum Swarm.Language.Typecheck.Source
instance GHC.Enum.Bounded Swarm.Language.Typecheck.Source
instance GHC.Classes.Ord Swarm.Language.Typecheck.Source
instance GHC.Classes.Eq Swarm.Language.Typecheck.Source
instance GHC.Show.Show Swarm.Language.Typecheck.Source
instance GHC.Show.Show Swarm.Language.Typecheck.InvalidAtomicReason
instance GHC.Show.Show Swarm.Language.Typecheck.TypeErr
instance GHC.Show.Show Swarm.Language.Typecheck.ContextualTypeErr
instance GHC.Classes.Ord Control.Unification.IntVar.IntVar
instance Swarm.Language.Typecheck.FreeVars Swarm.Language.Types.UType
instance Swarm.Language.Typecheck.FreeVars t => Swarm.Language.Typecheck.FreeVars (Swarm.Language.Types.Poly t)
instance Swarm.Language.Typecheck.FreeVars Swarm.Language.Types.UCtx
instance Swarm.Language.Typecheck.HasBindings Swarm.Language.Types.UType
instance Swarm.Language.Typecheck.HasBindings Swarm.Language.Types.UPolytype
instance Swarm.Language.Typecheck.HasBindings Swarm.Language.Types.UCtx
instance (Swarm.Language.Typecheck.HasBindings u, Data.Data.Data u) => Swarm.Language.Typecheck.HasBindings (Swarm.Language.Syntax.Term' u)
instance (Swarm.Language.Typecheck.HasBindings u, Data.Data.Data u) => Swarm.Language.Typecheck.HasBindings (Swarm.Language.Syntax.Syntax' u)
instance Swarm.Language.Typecheck.HasBindings Swarm.Language.Module.UModule
instance Control.Unification.Types.Fallible Swarm.Language.Types.TypeF Control.Unification.IntVar.IntVar Swarm.Language.Typecheck.ContextualTypeErr
instance GHC.Show.Show a => GHC.Show.Show (Swarm.Language.Typecheck.Join a)
-- | Pretty-printing for the Swarm language.
module Swarm.Language.Pretty
-- | Type class for things that can be pretty-printed, given a precedence
-- level of their context.
class PrettyPrec a
prettyPrec :: PrettyPrec a => Int -> a -> Doc ann
-- | Pretty-print a thing, with a context precedence level of zero.
ppr :: PrettyPrec a => a -> Doc ann
-- | Render a pretty-printed document as Text.
docToText :: Doc a -> Text
-- | Pretty-print something and render it as Text.
prettyText :: PrettyPrec a => a -> Text
-- | Render a pretty-printed document as a String.
docToString :: Doc a -> String
-- | Pretty-print something and render it as a String.
prettyString :: PrettyPrec a => a -> String
-- | Optionally surround a document with parentheses depending on the
-- Bool argument.
pparens :: Bool -> Doc ann -> Doc ann
-- | Surround a document with backticks.
bquote :: Doc ann -> Doc ann
-- | Turn a Show instance into a Doc, lowercasing it in the
-- process.
prettyShowLow :: Show a => a -> Doc ann
data BulletList i
BulletList :: (forall a. Doc a) -> [i] -> BulletList i
[bulletListHeader] :: BulletList i -> forall a. Doc a
[bulletListItems] :: BulletList i -> [i]
-- | We can use the Wildcard value to replace unification variables
-- when we don't care about them, e.g. to print out the shape of a type
-- like (_ -> _) * _
data Wildcard
Wildcard :: Wildcard
prettyBinding :: (Pretty a, PrettyPrec b) => (a, b) -> Doc ann
prettyEquality :: (Pretty a, PrettyPrec b) => (a, Maybe b) -> Doc ann
prettyTuple :: Term -> Doc a
prettyPrecApp :: Int -> Term -> Term -> Doc a
appliedTermPrec :: Term -> Int
-- | Format a ContextualTypeError for the user and render it as
-- Text.
prettyTypeErrText :: Text -> ContextualTypeErr -> Text
-- | Format a ContextualTypeError for the user.
prettyTypeErr :: Text -> ContextualTypeErr -> Doc ann
-- | Given a type and its source, construct an appropriate description of
-- it to go in a type mismatch error message.
typeDescription :: Source -> UType -> Doc a
-- | Check whether a type contains any unification variables at all.
hasAnyUVars :: UType -> Bool
-- | Check whether a type consists of a top-level type constructor
-- immediately applied to unification variables.
isTopLevelConstructor :: UType -> Maybe (TypeF ())
-- | Return an English noun phrase describing things with the given
-- top-level type constructor.
tyNounPhrase :: TypeF () -> Doc a
-- | Return an English noun phrase describing things with the given base
-- type.
baseTyNounPhrase :: BaseTy -> Doc a
-- | Generate an appropriate message when the sets of fields in two record
-- types do not match, explaining which fields are extra and which are
-- missing.
fieldMismatchMsg :: Set Var -> Set Var -> Doc a
instance GHC.Show.Show Swarm.Language.Pretty.Wildcard
instance GHC.Classes.Ord Swarm.Language.Pretty.Wildcard
instance GHC.Classes.Eq Swarm.Language.Pretty.Wildcard
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Pretty.Wildcard
instance Swarm.Language.Pretty.PrettyPrec i => Swarm.Language.Pretty.PrettyPrec (Swarm.Language.Pretty.BulletList i)
instance Swarm.Language.Pretty.PrettyPrec Data.Text.Internal.Text
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Types.BaseTy
instance Swarm.Language.Pretty.PrettyPrec Control.Unification.IntVar.IntVar
instance Swarm.Language.Pretty.PrettyPrec (t (Data.Functor.Fixedpoint.Fix t)) => Swarm.Language.Pretty.PrettyPrec (Data.Functor.Fixedpoint.Fix t)
instance (Swarm.Language.Pretty.PrettyPrec (t (Control.Unification.Types.UTerm t v)), Swarm.Language.Pretty.PrettyPrec v) => Swarm.Language.Pretty.PrettyPrec (Control.Unification.Types.UTerm t v)
instance Swarm.Language.Pretty.PrettyPrec t => Swarm.Language.Pretty.PrettyPrec (Swarm.Language.Types.TypeF t)
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Types.Polytype
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Types.UPolytype
instance Swarm.Language.Pretty.PrettyPrec t => Swarm.Language.Pretty.PrettyPrec (Swarm.Language.Context.Ctx t)
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Direction.Direction
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Capability.Capability
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Syntax.Const
instance Swarm.Language.Pretty.PrettyPrec (Swarm.Language.Syntax.Syntax' ty)
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Syntax.Term
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Typecheck.TypeErr
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Typecheck.InvalidAtomicReason
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Typecheck.LocatedTCFrame
instance Swarm.Language.Pretty.PrettyPrec Swarm.Language.Typecheck.TCFrame
-- | A data type to represent system failures.
--
-- These failures are often not fatal and serve to create common
-- infrastructure for logging.
module Swarm.Game.Failure
data SystemFailure
AssetNotLoaded :: Asset -> FilePath -> LoadingFailure -> SystemFailure
ScenarioNotFound :: FilePath -> SystemFailure
OrderFileWarning :: FilePath -> OrderFileWarning -> SystemFailure
CustomFailure :: Text -> SystemFailure
data AssetData
AppAsset :: AssetData
NameGeneration :: AssetData
Entities :: AssetData
Recipes :: AssetData
Worlds :: AssetData
Scenarios :: AssetData
Script :: AssetData
data Asset
Achievement :: Asset
Data :: AssetData -> Asset
History :: Asset
Save :: Asset
data Entry
Directory :: Entry
File :: Entry
data LoadingFailure
DoesNotExist :: Entry -> LoadingFailure
EntryNot :: Entry -> LoadingFailure
CanNotParseYaml :: ParseException -> LoadingFailure
CanNotParseMegaparsec :: ParseErrorBundle Text Void -> LoadingFailure
DoesNotTypecheck :: Text -> LoadingFailure
Duplicate :: AssetData -> Text -> LoadingFailure
CustomMessage :: Text -> LoadingFailure
data OrderFileWarning
NoOrderFile :: OrderFileWarning
MissingFiles :: NonEmpty FilePath -> OrderFileWarning
DanglingFiles :: NonEmpty FilePath -> OrderFileWarning
instance GHC.Show.Show Swarm.Game.Failure.AssetData
instance GHC.Classes.Eq Swarm.Game.Failure.AssetData
instance GHC.Show.Show Swarm.Game.Failure.Asset
instance GHC.Classes.Eq Swarm.Game.Failure.Asset
instance GHC.Show.Show Swarm.Game.Failure.Entry
instance GHC.Classes.Eq Swarm.Game.Failure.Entry
instance GHC.Show.Show Swarm.Game.Failure.LoadingFailure
instance GHC.Show.Show Swarm.Game.Failure.OrderFileWarning
instance GHC.Classes.Eq Swarm.Game.Failure.OrderFileWarning
instance GHC.Show.Show Swarm.Game.Failure.SystemFailure
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.Failure.SystemFailure
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.Failure.OrderFileWarning
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.Failure.LoadingFailure
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.Failure.Entry
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.Failure.Asset
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.Failure.AssetData
-- | fused-effect utilities for Swarm.
module Swarm.Util.Effect
-- | Transform a Throw e1 constraint into a Throw e2
-- constraint, by supplying an adapter function of type (e1 ->
-- e2).
withThrow :: Has (Throw e2) sig m => (e1 -> e2) -> ThrowC e1 m a -> m a
-- | Transform a Throw e constrint into a concrete Maybe,
-- discarding the error.
throwToMaybe :: forall e m a. Functor m => ThrowC e m a -> m (Maybe a)
-- | Transform a Throw e constrint into a concrete Maybe,
-- logging any error as a warning.
throwToWarning :: Has (Accum (Seq e)) sig m => ThrowC e m a -> m (Maybe a)
-- | Run a computation with an Accum effect (typically
-- accumulating a list of warnings), ignoring the accumulated value.
ignoreWarnings :: forall e m a. (Monoid e, Functor m) => AccumC e m a -> m a
-- | Convert a fused-effects style computation using a Throw e
-- constraint into an ExceptT computation. This is mostly a stub
-- to convert from one style to the other while we are in the middle of
-- incrementally converting. Eventually this should not be needed.
asExceptT :: ThrowC e m a -> ExceptT e m a
-- | Log a single failure as a warning.
warn :: Has (Accum (Seq w)) sig m => w -> m ()
-- | A version of traverse/mapM that also accumulates
-- warnings.
--
-- Note that we can't generalize this to work over any Traversable
-- because it also needs to have a notion of "filtering".
-- Witherable provides exactly the right abstraction.
traverseW :: (Has (Accum (Seq w)) sig m, Witherable t) => (a -> m (Either w b)) -> t a -> m (t b)
-- | Flipped version of traverseW for convenience.
forMW :: (Has (Accum (Seq w)) sig m, Witherable t) => t a -> (a -> m (Either w b)) -> m (t b)
simpleErrorHandle :: ThrowC SystemFailure IO a -> IO a
-- | Various utilities related to loading game data files.
module Swarm.Game.ResourceLoading
-- | Get subdirectory from swarm data directory.
--
-- This will first look in Cabal generated path and then try a `data`
-- directory in XdgData path.
--
-- The idea is that when installing with Cabal/Stack the first is
-- preferred, but when the players install a binary they need to extract
-- the `data` archive to the XDG directory.
getDataDirSafe :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => AssetData -> FilePath -> m FilePath
-- | Get file from swarm data directory.
--
-- See the note in getDataDirSafe.
getDataFileNameSafe :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => AssetData -> FilePath -> m FilePath
-- | Get a nice message suggesting to download `data` directory to
-- XdgData.
dataNotFound :: FilePath -> IO LoadingFailure
-- | Get path to swarm data, optionally creating necessary directories.
-- This could fail if user has bad permissions on his own $HOME or
-- $XDG_DATA_HOME which is unlikely.
getSwarmXdgDataSubdir :: Bool -> FilePath -> IO FilePath
getSwarmXdgDataFile :: Bool -> FilePath -> IO FilePath
-- | Get path to swarm saves, optionally creating necessary directories.
getSwarmSavePath :: Bool -> IO FilePath
-- | Get path to swarm history, optionally creating necessary directories.
getSwarmHistoryPath :: Bool -> IO FilePath
-- | Read all the .txt files in the data/ directory.
readAppData :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => m (Map Text Text)
-- | Load/save logic for achievements.
module Swarm.Game.Achievement.Persistence
-- | Get path to swarm achievements, optionally creating necessary
-- directories.
getSwarmAchievementsPath :: Bool -> IO FilePath
-- | Load saved info about achievements from XDG data directory. Returns a
-- tuple of warnings and attained achievements.
loadAchievementsInfo :: (Has (Accum (Seq SystemFailure)) sig m, Has (Lift IO) sig m) => m [Attainment]
-- | Save info about achievements to XDG data directory.
saveAchievementsInfo :: [Attainment] -> IO ()
-- | Some convenient functions for putting together the whole Swarm
-- language processing pipeline: parsing, type checking, capability
-- checking, and elaboration. If you want to simply turn some raw text
-- representing a Swarm program into something useful, this is probably
-- the module you want.
module Swarm.Language.Pipeline
-- | A record containing the results of the language processing pipeline.
-- Put a Term in, and get one of these out. A ProcessedTerm
-- contains:
--
--
-- - The elaborated + type-annotated term, plus the types of any
-- embedded definitions (TModule)
-- - The Requirements of the term
-- - The requirements context for any definitions embedded in the term
-- (ReqCtx)
--
data ProcessedTerm
ProcessedTerm :: TModule -> Requirements -> ReqCtx -> ProcessedTerm
-- | Given a Text value representing a Swarm program,
--
--
-- - Parse it (see Swarm.Language.Parse)
-- - Typecheck it (see Swarm.Language.Typecheck)
-- - Elaborate it (see Swarm.Language.Elaborate)
-- - Check what capabilities it requires (see
-- Swarm.Language.Capability)
--
--
-- Return either the end result (or Nothing if the input was
-- only whitespace) or a pretty-printed error message.
processTerm :: Text -> Either Text (Maybe ProcessedTerm)
-- | Like processTerm, but use a term that has already been parsed.
processParsedTerm :: Syntax -> Either ContextualTypeErr ProcessedTerm
-- | Like processTerm, but use explicit starting contexts.
processTerm' :: TCtx -> ReqCtx -> Text -> Either Text (Maybe ProcessedTerm)
-- | Like processTerm', but use a term that has already been parsed.
processParsedTerm' :: TCtx -> ReqCtx -> Syntax -> Either ContextualTypeErr ProcessedTerm
processTermEither :: Text -> Either Text ProcessedTerm
instance GHC.Generics.Generic Swarm.Language.Pipeline.ProcessedTerm
instance GHC.Classes.Eq Swarm.Language.Pipeline.ProcessedTerm
instance GHC.Show.Show Swarm.Language.Pipeline.ProcessedTerm
instance Data.Data.Data Swarm.Language.Pipeline.ProcessedTerm
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Pipeline.ProcessedTerm
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Pipeline.ProcessedTerm
-- | Simple Markdown AST and related utilities.
--
-- Parametrising Document with the type of inline code and code
-- blocks allows us to inspect and validate Swarm code in descriptions.
--
-- See drawMarkdown for rendering the descriptions as brick
-- widgets.
module Swarm.Language.Text.Markdown
-- | The top-level markdown document.
newtype Document c
Document :: [Paragraph c] -> Document c
[paragraphs] :: Document c -> [Paragraph c]
-- | Markdown paragraphs that contain inline leaf nodes.
--
-- The idea is that paragraphs do not have line breaks, and so the inline
-- elements follow each other. In particular inline code can be followed
-- by text without space between them (e.g. loggers).
newtype Paragraph c
Paragraph :: [Node c] -> Paragraph c
[nodes] :: Paragraph c -> [Node c]
-- | Inline leaf nodes.
--
-- The raw node is from the raw_annotation extension, and can be used for
-- typesentitiesinvalid code.
data Node c
LeafText :: Set TxtAttr -> Text -> Node c
LeafRaw :: String -> Text -> Node c
LeafCode :: c -> Node c
LeafCodeBlock :: String -> c -> Node c
-- | Simple text attributes that make it easier to find key info in
-- descriptions.
data TxtAttr
Strong :: TxtAttr
Emphasis :: TxtAttr
-- | Read Markdown document and parse&validate the code.
--
-- If you want only the document with code as Text, use the
-- fromTextPure function.
fromTextM :: MonadFail m => Text -> m (Document Syntax)
-- | Parse Markdown document, but throw on invalid code.
fromText :: Text -> Document Syntax
-- | Convert Document to Text.
--
-- Note that this will strip some markdown, emphasis and bold marks. If
-- you want to get markdown again, use docToMark.
docToText :: PrettyPrec a => Document a -> Text
-- | Convert Document to markdown text.
docToMark :: PrettyPrec a => Document a -> Text
-- | Token stream that can be easily converted to text or brick widgets.
--
-- TODO: #574 Code blocks should probably be handled separately.
data StreamNode' t
TextNode :: Set TxtAttr -> t -> StreamNode' t
CodeNode :: t -> StreamNode' t
RawNode :: String -> t -> StreamNode' t
type StreamNode = StreamNode' Text
-- | Convert elements to one dimensional stream of nodes, that is easy to
-- format and layout.
--
-- If you want to split the stream at line length, use the
-- chunksOf function afterward.
class ToStream a
toStream :: ToStream a => a -> [StreamNode]
-- | This is the naive and easy way to get text from markdown document.
toText :: ToStream a => a -> Text
findCode :: Document Syntax -> [Syntax]
-- | Get chunks of nodes not exceeding length and broken at word boundary.
chunksOf :: Int -> [StreamNode] -> [[StreamNode]]
instance GHC.Classes.Ord Swarm.Language.Text.Markdown.TxtAttr
instance GHC.Show.Show Swarm.Language.Text.Markdown.TxtAttr
instance GHC.Classes.Eq Swarm.Language.Text.Markdown.TxtAttr
instance Data.Traversable.Traversable Swarm.Language.Text.Markdown.Node
instance Data.Foldable.Foldable Swarm.Language.Text.Markdown.Node
instance GHC.Base.Functor Swarm.Language.Text.Markdown.Node
instance GHC.Show.Show c => GHC.Show.Show (Swarm.Language.Text.Markdown.Node c)
instance GHC.Classes.Eq c => GHC.Classes.Eq (Swarm.Language.Text.Markdown.Node c)
instance GHC.Base.Monoid (Swarm.Language.Text.Markdown.Paragraph c)
instance GHC.Base.Semigroup (Swarm.Language.Text.Markdown.Paragraph c)
instance Data.Traversable.Traversable Swarm.Language.Text.Markdown.Paragraph
instance Data.Foldable.Foldable Swarm.Language.Text.Markdown.Paragraph
instance GHC.Base.Functor Swarm.Language.Text.Markdown.Paragraph
instance GHC.Show.Show c => GHC.Show.Show (Swarm.Language.Text.Markdown.Paragraph c)
instance GHC.Classes.Eq c => GHC.Classes.Eq (Swarm.Language.Text.Markdown.Paragraph c)
instance GHC.Base.Monoid (Swarm.Language.Text.Markdown.Document c)
instance GHC.Base.Semigroup (Swarm.Language.Text.Markdown.Document c)
instance Data.Traversable.Traversable Swarm.Language.Text.Markdown.Document
instance Data.Foldable.Foldable Swarm.Language.Text.Markdown.Document
instance GHC.Base.Functor Swarm.Language.Text.Markdown.Document
instance GHC.Show.Show c => GHC.Show.Show (Swarm.Language.Text.Markdown.Document c)
instance GHC.Classes.Eq c => GHC.Classes.Eq (Swarm.Language.Text.Markdown.Document c)
instance GHC.Base.Functor Swarm.Language.Text.Markdown.StreamNode'
instance GHC.Show.Show t => GHC.Show.Show (Swarm.Language.Text.Markdown.StreamNode' t)
instance GHC.Classes.Eq t => GHC.Classes.Eq (Swarm.Language.Text.Markdown.StreamNode' t)
instance Swarm.Language.Pretty.PrettyPrec a => Swarm.Language.Text.Markdown.ToStream (Swarm.Language.Text.Markdown.Node a)
instance Swarm.Language.Pretty.PrettyPrec a => Swarm.Language.Text.Markdown.ToStream (Swarm.Language.Text.Markdown.Paragraph a)
instance Commonmark.Types.Rangeable (Swarm.Language.Text.Markdown.Document c)
instance Commonmark.Types.HasAttributes (Swarm.Language.Text.Markdown.Document c)
instance GHC.Exts.IsList (Swarm.Language.Text.Markdown.Document a)
instance Data.String.IsString (Swarm.Language.Text.Markdown.Document Swarm.Language.Syntax.Syntax)
instance Data.String.IsString (Swarm.Language.Text.Markdown.Paragraph Swarm.Language.Syntax.Syntax)
instance Commonmark.Types.IsBlock (Swarm.Language.Text.Markdown.Paragraph Data.Text.Internal.Text) (Swarm.Language.Text.Markdown.Document Data.Text.Internal.Text)
instance Data.Aeson.Types.ToJSON.ToJSON (Swarm.Language.Text.Markdown.Document Swarm.Language.Syntax.Syntax)
instance Data.Aeson.Types.FromJSON.FromJSON (Swarm.Language.Text.Markdown.Document Swarm.Language.Syntax.Syntax)
instance Commonmark.Types.Rangeable (Swarm.Language.Text.Markdown.Paragraph c)
instance Commonmark.Types.HasAttributes (Swarm.Language.Text.Markdown.Paragraph c)
instance Commonmark.Types.IsInline (Swarm.Language.Text.Markdown.Paragraph Data.Text.Internal.Text)
instance Data.Aeson.Types.ToJSON.ToJSON (Swarm.Language.Text.Markdown.Paragraph Swarm.Language.Syntax.Syntax)
-- | A quasiquoter for Swarm terms.
module Swarm.Language.Pipeline.QQ
-- | A quasiquoter for Swarm language terms, so we can conveniently write
-- them down using concrete syntax and have them parsed into abstract
-- syntax at compile time. The quasiquoter actually runs the entire
-- pipeline on them (parsing, typechecking, elaborating), so a
-- quasiquoted Swarm program with a parse error or a type error will fail
-- at Haskell compile time. This is useful for creating system robot
-- programs (for example, see seedProgram).
tmQ :: QuasiQuoter
-- | Types and utilities to compute code size in terms of textual length
-- and AST.
module Swarm.Game.Scenario.Scoring.CodeSize
data CodeSizeDeterminators
CodeSizeDeterminators :: Maybe ProcessedTerm -> Bool -> CodeSizeDeterminators
[initialCode] :: CodeSizeDeterminators -> Maybe ProcessedTerm
[hasUsedREPL] :: CodeSizeDeterminators -> Bool
data ScenarioCodeMetrics
ScenarioCodeMetrics :: Int -> Int -> ScenarioCodeMetrics
[sourceTextLength] :: ScenarioCodeMetrics -> Int
[astSize] :: ScenarioCodeMetrics -> Int
codeSizeFromDeterminator :: CodeSizeDeterminators -> Maybe ScenarioCodeMetrics
instance GHC.Show.Show Swarm.Game.Scenario.Scoring.CodeSize.CodeSizeDeterminators
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Scoring.CodeSize.ScenarioCodeMetrics
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Scoring.CodeSize.ScenarioCodeMetrics
instance GHC.Generics.Generic Swarm.Game.Scenario.Scoring.CodeSize.ScenarioCodeMetrics
instance GHC.Read.Read Swarm.Game.Scenario.Scoring.CodeSize.ScenarioCodeMetrics
instance GHC.Show.Show Swarm.Game.Scenario.Scoring.CodeSize.ScenarioCodeMetrics
instance GHC.Classes.Ord Swarm.Game.Scenario.Scoring.CodeSize.ScenarioCodeMetrics
instance GHC.Classes.Eq Swarm.Game.Scenario.Scoring.CodeSize.ScenarioCodeMetrics
module Swarm.Game.Scenario.Objective
data PrerequisiteConfig
PrerequisiteConfig :: Bool -> Prerequisite ObjectiveLabel -> PrerequisiteConfig
-- | Typically, only the currently "active" objectives are displayed to the
-- user in the Goals dialog. An objective is "active" if all of its
-- prerequisites are met.
--
-- However, some objectives may be "high-level", in that they may explain
-- the broader intention behind potentially multiple prerequisites.
--
-- Set this to option True to display this goal in the "upcoming" section
-- even if the objective has currently unmet prerequisites.
[previewable] :: PrerequisiteConfig -> Bool
-- | Boolean expression of dependencies upon other objectives. Variables in
-- this expression are the "id"s of other objectives, and become "true"
-- if the corresponding objective is completed. The "condition" of the
-- objective at hand shall not be evaluated until its prerequisite
-- expression evaluates as True.
--
-- Note that the achievement of these objective dependencies is
-- persistent; once achieved, they still count even if their "condition"
-- might not still hold. The condition is never re-evaluated once True.
[logic] :: PrerequisiteConfig -> Prerequisite ObjectiveLabel
-- | An objective is a condition to be achieved by a player in a scenario.
data Objective
Objective :: Document Syntax -> Maybe Text -> ProcessedTerm -> Maybe ObjectiveLabel -> Bool -> Maybe PrerequisiteConfig -> Bool -> Maybe AchievementInfo -> Objective
[_objectiveGoal] :: Objective -> Document Syntax
[_objectiveTeaser] :: Objective -> Maybe Text
[_objectiveCondition] :: Objective -> ProcessedTerm
[_objectiveId] :: Objective -> Maybe ObjectiveLabel
[_objectiveOptional] :: Objective -> Bool
[_objectivePrerequisite] :: Objective -> Maybe PrerequisiteConfig
[_objectiveHidden] :: Objective -> Bool
[_objectiveAchievement] :: Objective -> Maybe AchievementInfo
-- | An explanation of the goal of the objective, shown to the player
-- during play. It is represented as a list of paragraphs.
objectiveGoal :: Lens' Objective (Document Syntax)
-- | A very short (3-5 words) description of the goal for displaying on the
-- left side of the Objectives modal.
objectiveTeaser :: Lens' Objective (Maybe Text)
-- | A winning condition for the objective, expressed as a program of type
-- cmd bool. By default, this program will be run to completion
-- every tick (the usual limits on the number of CESK steps per tick do
-- not apply).
objectiveCondition :: Lens' Objective ProcessedTerm
-- | Optional name by which this objective may be referenced as a
-- prerequisite for other objectives.
objectiveId :: Lens' Objective (Maybe Text)
-- | Indicates whether the objective is not required in order to "win" the
-- scenario. Useful for (potentially hidden) achievements. If the field
-- is not supplied, it defaults to False (i.e. the objective is mandatory
-- to "win").
objectiveOptional :: Lens' Objective Bool
-- | Dependencies upon other objectives
objectivePrerequisite :: Lens' Objective (Maybe PrerequisiteConfig)
-- | Whether the goal is displayed in the UI before completion. The goal
-- will always be revealed after it is completed.
--
-- This attribute often goes along with an Achievement.
objectiveHidden :: Lens' Objective Bool
-- | An optional Achievement that is to be registered globally when this
-- objective is completed.
objectiveAchievement :: Lens' Objective (Maybe AchievementInfo)
data CompletionBuckets
CompletionBuckets :: [Objective] -> [Objective] -> [Objective] -> CompletionBuckets
[incomplete] :: CompletionBuckets -> [Objective]
[completed] :: CompletionBuckets -> [Objective]
[unwinnable] :: CompletionBuckets -> [Objective]
-- | TODO: #1044 Could also add an ObjectiveFailed constructor...
newtype Announcement
ObjectiveCompleted :: Objective -> Announcement
data ObjectiveCompletion
ObjectiveCompletion :: CompletionBuckets -> Set ObjectiveLabel -> ObjectiveCompletion
-- | This is the authoritative "completion status" for all objectives. Note
-- that there is a separate Set to store the completion status of
-- prerequisite objectives, which must be carefully kept in sync with
-- this. Those prerequisite objectives are required to have labels, but
-- other objectives are not. Therefore only prerequisites exist in the
-- completion map keyed by label.
[completionBuckets] :: ObjectiveCompletion -> CompletionBuckets
[completedIDs] :: ObjectiveCompletion -> Set ObjectiveLabel
-- | Concatenates all incomplete and completed objectives.
listAllObjectives :: CompletionBuckets -> [Objective]
addCompleted :: Objective -> ObjectiveCompletion -> ObjectiveCompletion
addUnwinnable :: Objective -> ObjectiveCompletion -> ObjectiveCompletion
setIncomplete :: ([Objective] -> [Objective]) -> ObjectiveCompletion -> ObjectiveCompletion
addIncomplete :: Objective -> ObjectiveCompletion -> ObjectiveCompletion
-- | Returns the ObjectiveCompletion with the "incomplete" goals
-- extracted to a separate tuple member. This is intended as input to a
-- "fold".
extractIncomplete :: ObjectiveCompletion -> (ObjectiveCompletion, [Objective])
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Objective.CompletionBuckets
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Objective.CompletionBuckets
instance GHC.Generics.Generic Swarm.Game.Scenario.Objective.CompletionBuckets
instance GHC.Show.Show Swarm.Game.Scenario.Objective.CompletionBuckets
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Objective.Announcement
instance GHC.Generics.Generic Swarm.Game.Scenario.Objective.Announcement
instance GHC.Show.Show Swarm.Game.Scenario.Objective.Announcement
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Objective.ObjectiveCompletion
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Objective.ObjectiveCompletion
instance GHC.Generics.Generic Swarm.Game.Scenario.Objective.ObjectiveCompletion
instance GHC.Show.Show Swarm.Game.Scenario.Objective.ObjectiveCompletion
instance Servant.Docs.Internal.ToSample Swarm.Game.Scenario.Objective.Objective
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Objective.Objective
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Objective.PrerequisiteConfig
instance GHC.Generics.Generic Swarm.Game.Scenario.Objective.PrerequisiteConfig
instance GHC.Show.Show Swarm.Game.Scenario.Objective.PrerequisiteConfig
instance GHC.Classes.Eq Swarm.Game.Scenario.Objective.PrerequisiteConfig
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Objective.Objective
instance GHC.Generics.Generic Swarm.Game.Scenario.Objective.Objective
instance GHC.Show.Show Swarm.Game.Scenario.Objective.Objective
instance GHC.Classes.Eq Swarm.Game.Scenario.Objective.Objective
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Objective.PrerequisiteConfig
-- | Utilities to check whether conditions are met for a game win/loss.
module Swarm.Game.Scenario.Objective.WinCheck
-- | We have "won" if all of the "unwinnable" or remaining "incomplete"
-- objectives are "optional".
didWin :: ObjectiveCompletion -> Bool
-- | We have "lost" if any of the "unwinnable" objectives not "optional".
didLose :: ObjectiveCompletion -> Bool
isPrereqsSatisfied :: ObjectiveCompletion -> Objective -> Bool
isUnwinnablePrereq :: Set ObjectiveLabel -> Prerequisite ObjectiveLabel -> Bool
isUnwinnable :: ObjectiveCompletion -> Objective -> Bool
-- | The first element of the returned tuple consists of "active"
-- objectives, the second element "inactive".
partitionActiveObjectives :: ObjectiveCompletion -> ([Objective], [Objective])
getActiveObjectives :: ObjectiveCompletion -> [Objective]
-- | For debugging only (via Web API)
data PrereqSatisfaction
PrereqSatisfaction :: Objective -> Set (Signed ObjectiveLabel) -> Bool -> PrereqSatisfaction
[objective] :: PrereqSatisfaction -> Objective
[deps] :: PrereqSatisfaction -> Set (Signed ObjectiveLabel)
[prereqsSatisfied] :: PrereqSatisfaction -> Bool
-- | Used only by the web interface for debugging
getSatisfaction :: ObjectiveCompletion -> [PrereqSatisfaction]
getDistinctConstants :: Ord a => Prerequisite a -> Set (Signed a)
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Objective.WinCheck.PrereqSatisfaction
instance GHC.Generics.Generic Swarm.Game.Scenario.Objective.WinCheck.PrereqSatisfaction
instance GHC.Generics.Generic (Data.BoolExpr.Signed Swarm.Game.Scenario.Objective.Logic.ObjectiveLabel)
instance Data.Aeson.Types.ToJSON.ToJSON (Data.BoolExpr.Signed Swarm.Game.Scenario.Objective.Logic.ObjectiveLabel)
instance Servant.Docs.Internal.ToSample Swarm.Game.Scenario.Objective.WinCheck.PrereqSatisfaction
-- | A UI-centric model for Objective presentation.
module Swarm.TUI.Model.Goal
-- | These are intended to be used as keys in a map of lists of goals.
data GoalStatus
-- | Goals in this category have other goals as prerequisites. However,
-- they are only displayed if the "previewable" attribute is
-- true.
Upcoming :: GoalStatus
-- | Goals in this category may be pursued in parallel. However, they are
-- only displayed if the "hidden" attribute is false.
Active :: GoalStatus
-- | A goal's programmatic condition, as well as all its prerequisites,
-- were completed. This is a "latch" mechanism; at some point the
-- conditions required to meet the goal may no longer hold. Nonetheless,
-- the goal remains "completed".
Completed :: GoalStatus
-- | A goal that can no longer be achieved. If this goal is not an
-- "optional" goal, then the player also Loses the scenario.
--
-- Note that currently the only way to Fail a goal is by way of a
-- negative prerequisite that was completed.
Failed :: GoalStatus
type CategorizedGoals = Map GoalStatus (NonEmpty Objective)
data GoalEntry
Header :: GoalStatus -> GoalEntry
Goal :: GoalStatus -> Objective -> GoalEntry
Spacer :: GoalEntry
shouldSkipSelection :: GoalEntry -> Bool
data GoalTracking
GoalTracking :: [Announcement] -> CategorizedGoals -> GoalTracking
-- | TODO: #1044 the actual contents of these are not used yet, other than
-- as a flag to pop up the Goal dialog.
[announcements] :: GoalTracking -> [Announcement]
[goals] :: GoalTracking -> CategorizedGoals
data GoalDisplay
GoalDisplay :: GoalTracking -> List Name GoalEntry -> FocusRing Name -> GoalDisplay
[_goalsContent] :: GoalDisplay -> GoalTracking
-- | required for maintaining the selection/navigation state among list
-- items
[_listWidget] :: GoalDisplay -> List Name GoalEntry
[_focus] :: GoalDisplay -> FocusRing Name
listWidget :: Lens' GoalDisplay (List Name GoalEntry)
goalsContent :: Lens' GoalDisplay GoalTracking
focus :: Lens' GoalDisplay (FocusRing Name)
emptyGoalDisplay :: GoalDisplay
hasAnythingToShow :: GoalTracking -> Bool
hasMultipleGoals :: GoalTracking -> Bool
constructGoalMap :: Bool -> ObjectiveCompletion -> CategorizedGoals
instance Data.Aeson.Types.ToJSON.ToJSONKey Swarm.TUI.Model.Goal.GoalStatus
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.TUI.Model.Goal.GoalStatus
instance GHC.Generics.Generic Swarm.TUI.Model.Goal.GoalStatus
instance GHC.Enum.Enum Swarm.TUI.Model.Goal.GoalStatus
instance GHC.Enum.Bounded Swarm.TUI.Model.Goal.GoalStatus
instance GHC.Classes.Ord Swarm.TUI.Model.Goal.GoalStatus
instance GHC.Classes.Eq Swarm.TUI.Model.Goal.GoalStatus
instance GHC.Show.Show Swarm.TUI.Model.Goal.GoalStatus
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.TUI.Model.Goal.GoalTracking
instance GHC.Generics.Generic Swarm.TUI.Model.Goal.GoalTracking
instance Servant.Docs.Internal.ToSample Swarm.TUI.Model.Goal.GoalTracking
-- | Utilities for performing graph analysis on Objective prerequisites
module Swarm.Game.Scenario.Objective.Graph
-- | This is only needed for constructing a Graph, which requires all nodes
-- to have a key.
data ObjectiveId
Label :: Signed ObjectiveLabel -> ObjectiveId
-- | for unlabeled objectives
Ordinal :: Int -> ObjectiveId
data GraphInfo
GraphInfo :: Graph -> Bool -> [SCC Objective] -> [ObjectiveId] -> GraphInfo
[actualGraph] :: GraphInfo -> Graph
[isAcyclic] :: GraphInfo -> Bool
[sccInfo] :: GraphInfo -> [SCC Objective]
[nodeIDs] :: GraphInfo -> [ObjectiveId]
getConstFromSigned :: Signed a -> a
-- | Collect all of the constants that have a negation. This is necessary
-- for enumerating all of the distinct nodes when constructing a Graph,
-- as we treat a constant and its negation as distinct nodes.
getNegatedIds :: [Objective] -> Map ObjectiveLabel Objective
getObjectivesById :: [Objective] -> Map ObjectiveLabel Objective
-- | Uses the textual labels for those objectives that have them, and
-- assigns arbitrary integer IDs for the remaining.
--
-- Only necessary for constructing a Graph.
assignIds :: [Objective] -> Map ObjectiveId Objective
type Edges = [(Objective, ObjectiveId, [ObjectiveId])]
-- | NOTE: Based strictly on the goal labels, the graph could potentially
-- contain a cycle, if there exist mutually-exclusive goals. That is, if
-- goal A depends on the NOT of "goal B". Goal B could then also depend
-- on "NOT Goal A" (re-enforcing the mutual-exclusivity), or it could
-- mandate a completion order, e.g.: Goal A and Goal B are simultaneously
-- available to pursue. However, if the player completes Goal B first,
-- then it closes off the option to complete Goal A. However, if Goal A
-- is completed first, then the user is also allowed to complete Goal B.
--
-- To avoid a "cycle" in this circumstance, A needs to exist as a
-- distinct node from "NOT A" in the graph.
makeGraph :: Edges -> Graph
makeGraphEdges :: [Objective] -> Edges
isAcyclicGraph :: [SCC Objective] -> Bool
makeGraphInfo :: ObjectiveCompletion -> GraphInfo
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Objective.Graph.ObjectiveId
instance GHC.Generics.Generic Swarm.Game.Scenario.Objective.Graph.ObjectiveId
instance GHC.Show.Show Swarm.Game.Scenario.Objective.Graph.ObjectiveId
instance GHC.Classes.Ord Swarm.Game.Scenario.Objective.Graph.ObjectiveId
instance GHC.Classes.Eq Swarm.Game.Scenario.Objective.Graph.ObjectiveId
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Objective.Graph.GraphInfo
instance GHC.Generics.Generic Swarm.Game.Scenario.Objective.Graph.GraphInfo
instance GHC.Show.Show Swarm.Game.Scenario.Objective.Graph.GraphInfo
instance Servant.Docs.Internal.ToSample Swarm.Game.Scenario.Objective.Graph.GraphInfo
instance Data.Aeson.Types.ToJSON.ToJSON (Data.Graph.SCC Swarm.Game.Scenario.Objective.Objective)
instance Data.Aeson.Types.ToJSON.ToJSON Data.Graph.Graph
-- | Validity checking for Objective prerequisites
module Swarm.Game.Scenario.Objective.Validation
-- | Performs monadic validation before returning the "pure" construction
-- of a wrapper record. This validation entails: 1) Ensuring that all
-- goal references utilized in prerequisites actually exist 2) Ensuring
-- that the graph of dependencies is acyclic.
validateObjectives :: MonadFail m => [Objective] -> m [Objective]
module Swarm.Language.LSP.VarUsage
data BindingType
Lambda :: BindingType
Let :: BindingType
Bind :: BindingType
data VarUsage
VarUsage :: LocVar -> BindingType -> VarUsage
type BindingSites = Map Var (NonEmpty SrcLoc)
data Usage
Usage :: Set LocVar -> [VarUsage] -> Usage
-- | Variable references
[usages] :: Usage -> Set LocVar
-- | Variable declarations without any references
[problems] :: Usage -> [VarUsage]
toErrPos :: Text -> VarUsage -> Maybe (Range, Text)
-- | Descends the syntax tree rooted at a variable declaration,
-- accumulating variable references. Generates a "problem" if an
-- associated variable reference is not encountered in the subtree for
-- this declaration.
checkOccurrences :: BindingSites -> LocVar -> BindingType -> [Syntax] -> Usage
-- | Build up the bindings map as a function argument as we descend into
-- the syntax tree. Aggregates unused bindings as we return from each
-- layer.
getUsage :: BindingSites -> Syntax -> Usage
instance GHC.Show.Show Swarm.Language.LSP.VarUsage.BindingType
instance GHC.Classes.Eq Swarm.Language.LSP.VarUsage.BindingType
instance GHC.Base.Semigroup Swarm.Language.LSP.VarUsage.Usage
instance GHC.Base.Monoid Swarm.Language.LSP.VarUsage.Usage
module Swarm.Language.LSP.Hover
showHoverInfo :: NormalizedUri -> TextDocumentVersion -> Position -> VirtualFile -> Maybe (Text, Maybe Range)
renderDoc :: Int -> Text -> Text
treeToMarkdown :: Int -> Tree Text -> Text
-- | Find the most specific term for a given position within the code.
narrowToPosition :: ExplainableType ty => Syntax' ty -> Int -> Syntax' ty
explain :: ExplainableType ty => Syntax' ty -> Tree Text
instance Swarm.Language.LSP.Hover.ExplainableType ()
instance Swarm.Language.LSP.Hover.ExplainableType Swarm.Language.Types.Polytype
-- | Language Server Protocol (LSP) server for the Swarm language. See the
-- docs/EDITORS.md to learn how to use it.
module Swarm.Language.LSP
lspMain :: IO ()
diagnosticSourcePrefix :: Text
debug :: MonadIO m => Text -> m ()
validateSwarmCode :: NormalizedUri -> TextDocumentVersion -> Text -> LspM () ()
showTypeErrorPos :: Text -> ContextualTypeErr -> ((Int, Int), (Int, Int), Text)
handlers :: Handlers (LspM ())
-- | Parsing and pretty-printing for keys (as in, keys on a keyboard) and
-- key combos.
module Swarm.Language.Key
-- | A keyboard input, represented as a key + modifiers. Invariant: the
-- modifier list is always sorted.
data KeyCombo
-- | Smart constructor for KeyCombo.
mkKeyCombo :: [Modifier] -> Key -> KeyCombo
-- | Parse a key combo with nothing after it.
parseKeyComboFull :: Parser KeyCombo
-- | Parse a key combo like "M-C-F5", Down, or "C-x".
parseKeyCombo :: Parser KeyCombo
-- | Pretty-print a key combo, e.g. "C-M-F5". Right inverse to
-- parseKeyCombo. Left inverse up to reordering of modifiers.
prettyKeyCombo :: KeyCombo -> Text
specialKeyNames :: Set Text
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Key.KeyCombo
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Key.KeyCombo
instance GHC.Generics.Generic Swarm.Language.Key.KeyCombo
instance GHC.Show.Show Swarm.Language.Key.KeyCombo
instance GHC.Classes.Ord Swarm.Language.Key.KeyCombo
instance GHC.Classes.Eq Swarm.Language.Key.KeyCombo
instance Data.Aeson.Types.FromJSON.FromJSON Graphics.Vty.Input.Events.Key
instance Data.Aeson.Types.FromJSON.FromJSON Graphics.Vty.Input.Events.Modifier
instance Data.Aeson.Types.ToJSON.ToJSON Graphics.Vty.Input.Events.Key
instance Data.Aeson.Types.ToJSON.ToJSON Graphics.Vty.Input.Events.Modifier
instance Swarm.Language.Key.Names' f => Swarm.Language.Key.Names' (GHC.Generics.M1 GHC.Generics.D t f)
instance (Swarm.Language.Key.Names' f, Swarm.Language.Key.Names' g) => Swarm.Language.Key.Names' (f GHC.Generics.:+: g)
instance GHC.Generics.Constructor c => Swarm.Language.Key.Names' (GHC.Generics.C1 c f)
-- | Values and environments used for interpreting the Swarm language.
module Swarm.Language.Value
-- | A value is a term that cannot (or does not) take any more
-- evaluation steps on its own.
data Value
-- | The unit value.
[VUnit] :: Value
-- | An integer.
[VInt] :: Integer -> Value
-- | Literal text.
[VText] :: Text -> Value
-- | A direction.
[VDir] :: Direction -> Value
-- | A boolean.
[VBool] :: Bool -> Value
-- | A reference to a robot.
[VRobot] :: Int -> Value
-- | An injection into a sum type. False = left, True = right.
[VInj] :: Bool -> Value -> Value
-- | A pair.
[VPair] :: Value -> Value -> Value
-- | A closure, representing a lambda term along with an environment
-- containing bindings for any free variables in the body of the lambda.
[VClo] :: Var -> Term -> Env -> Value
-- | An application of a constant to some value arguments, potentially
-- waiting for more arguments. If a constant application is fully
-- saturated (as defined by its arity), whether it is a value or
-- not depends on whether or not it represents a command (as defined by
-- isCmd). If a command (e.g. Build), it is a value, and
-- awaits an FExec frame which will cause it to execute. Otherwise
-- (e.g. If), it is not a value, and will immediately reduce.
[VCApp] :: Const -> [Value] -> Value
-- | A definition, which does not take effect until executed. The
-- Bool indicates whether the definition is recursive.
[VDef] :: Bool -> Var -> Term -> Env -> Value
-- | The result of a command, consisting of the result of the command as
-- well as an environment of bindings from TDef commands.
[VResult] :: Value -> Env -> Value
-- | An unevaluated bind expression, waiting to be executed, of the form
-- i.e. c1 ; c2 or x <- c1; c2. We also store
-- an Env in which to interpret the commands.
[VBind] :: Maybe Var -> Term -> Term -> Env -> Value
-- | A (non-recursive) delayed term, along with its environment. If a term
-- would otherwise be evaluated but we don't want it to be (e.g.
-- as in the case of arguments to an 'if', or a recursive binding), we
-- can stick a TDelay on it, which turns it into a value. Delayed
-- terms won't be evaluated until Force is applied to them.
[VDelay] :: Term -> Env -> Value
-- | A reference to a memory cell in the store.
[VRef] :: Int -> Value
-- | A record value.
[VRcd] :: Map Var Value -> Value
-- | A keyboard input.
[VKey] :: KeyCombo -> Value
-- | A requirements command awaiting execution.
[VRequirements] :: Text -> Term -> Env -> Value
-- | Ensure that a value is not wrapped in VResult.
stripVResult :: Value -> Value
-- | Pretty-print a value.
prettyValue :: Value -> Text
-- | Inject a value back into a term.
valueToTerm :: Value -> Term
-- | An environment is a mapping from variable names to values.
type Env = Ctx Value
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Language.Value.Value
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Language.Value.Value
instance GHC.Generics.Generic Swarm.Language.Value.Value
instance GHC.Show.Show Swarm.Language.Value.Value
instance GHC.Classes.Eq Swarm.Language.Value.Value
-- | Various utilities related to parsing YAML files.
module Swarm.Util.Yaml
-- | A generic wrapper for computations which also depend on knowing a
-- value of type e.
newtype With e f a
E :: (e -> f a) -> With e f a
[runE] :: With e f a -> e -> f a
-- | A ParserE is a YAML Parser that can also depend on
-- knowing an value of type e. The E used to stand for
-- EntityMap, but now that it is generalized, it stands for
-- Environment.
type ParserE e = With e Parser
-- | Lift a computation that does not care about the environment value.
liftE :: Functor f => f a -> With e f a
-- | Locally modify an environment.
localE :: (e' -> e) -> With e f a -> With e' f a
-- | Locally merge an environment with the current one for given action.
withE :: Semigroup e => e -> With e f a -> With e f a
-- | Get the current environment.
getE :: Monad f => With e f e
-- | FromJSONE governs values that can be parsed from a YAML (or
-- JSON) file, but which also have access to an extra, read-only
-- environment value.
--
-- For things that don't care about the environment, the default
-- implementation of parseJSONE simply calls parseJSON from
-- a FromJSON instance.
class FromJSONE e a
parseJSONE :: FromJSONE e a => Value -> ParserE e a
parseJSONE :: (FromJSONE e a, FromJSON a) => Value -> ParserE e a
parseJSONE' :: FromJSONE e a => e -> Value -> Parser a
-- | Read a value from a YAML file, providing the needed extra environment.
decodeFileEitherE :: FromJSONE e a => e -> FilePath -> IO (Either ParseException a)
-- | A variant of .: for ParserE: project out a field of an
-- Value, passing along the extra environment.
(..:) :: FromJSONE e a => Object -> Text -> ParserE e a
-- | A variant of .:? for ParserE: project out an optional
-- field of an Value, passing along the extra environment.
(..:?) :: FromJSONE e a => Object -> Text -> ParserE e (Maybe a)
-- | A variant of .!= for any functor.
(..!=) :: Functor f => f (Maybe a) -> a -> f a
-- | withTextE name f value applies f to the
-- Text when value is a String and fails
-- otherwise.
withTextE :: String -> (Text -> ParserE e a) -> Value -> ParserE e a
-- | withObjectE name f value applies f to the
-- Value when value is an Value and fails
-- otherwise.
withObjectE :: String -> (Object -> ParserE e a) -> Value -> ParserE e a
-- | withArrayE name f value applies f to the
-- Value when value is an Value and fails
-- otherwise.
withArrayE :: String -> (Array -> ParserE e a) -> Value -> ParserE e a
instance GHC.Base.Alternative f => GHC.Base.Alternative (Swarm.Util.Yaml.With e f)
instance Control.Monad.Fail.MonadFail f => Control.Monad.Fail.MonadFail (Swarm.Util.Yaml.With e f)
instance GHC.Base.Monad f => GHC.Base.Monad (Swarm.Util.Yaml.With e f)
instance GHC.Base.Applicative f => GHC.Base.Applicative (Swarm.Util.Yaml.With e f)
instance GHC.Base.Functor f => GHC.Base.Functor (Swarm.Util.Yaml.With e f)
instance Swarm.Util.Yaml.FromJSONE e GHC.Types.Int
instance Swarm.Util.Yaml.FromJSONE e a => Swarm.Util.Yaml.FromJSONE e [a]
instance (Swarm.Util.Yaml.FromJSONE e a, Swarm.Util.Yaml.FromJSONE e b) => Swarm.Util.Yaml.FromJSONE e (a, b)
-- | Utilities for describing how to display in-game entities in the TUI.
module Swarm.Game.Display
-- | Display priority. Entities with higher priority will be drawn on top
-- of entities with lower priority.
type Priority = Int
-- | An internal attribute name.
data Attribute
ADefault :: Attribute
ARobot :: Attribute
AEntity :: Attribute
AWorld :: Text -> Attribute
ATerrain :: Text -> Attribute
-- | A record explaining how to display an entity in the TUI.
data Display
-- | The default character to use for display.
defaultChar :: Lens' Display Char
-- | For robots or other entities that have an orientation, this map
-- optionally associates different display characters with different
-- orientations. If an orientation is not in the map, the
-- defaultChar will be used.
orientationMap :: Lens' Display (Map AbsoluteDir Char)
-- | The display caches the current orientation of the entity, so we know
-- which character to use from the orientation map.
curOrientation :: Lens' Display (Maybe Direction)
-- | The attribute to use for display.
displayAttr :: Lens' Display Attribute
-- | This entity's display priority. Higher priorities are drawn on top of
-- lower.
displayPriority :: Lens' Display Priority
-- | Whether the entity is currently invisible.
invisible :: Lens' Display Bool
-- | Look up the character that should be used for a display.
displayChar :: Display -> Char
-- | Modify a display to use a ? character for entities that are
-- hidden/unknown.
hidden :: Display -> Display
-- | The default way to display some terrain using the given character and
-- attribute, with priority 0.
defaultTerrainDisplay :: Char -> Attribute -> Display
-- | Construct a default display for an entity that uses only a single
-- display character, the default entity attribute, and priority 1.
defaultEntityDisplay :: Char -> Display
-- | Construct a default robot display for a given orientation, with
-- display characters "X^>v<", the default robot
-- attribute, and priority 10.
--
-- Note that the defaultChar is used for direction DDown
-- and is overridden for the special base robot.
defaultRobotDisplay :: Display
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Display.Display
instance Swarm.Util.Yaml.FromJSONE Swarm.Game.Display.Display Swarm.Game.Display.Display
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Display.Display
instance GHC.Base.Monoid Swarm.Game.Display.Display
instance Data.Hashable.Class.Hashable Swarm.Game.Display.Attribute
instance GHC.Generics.Generic Swarm.Game.Display.Attribute
instance GHC.Show.Show Swarm.Game.Display.Attribute
instance GHC.Classes.Ord Swarm.Game.Display.Attribute
instance GHC.Classes.Eq Swarm.Game.Display.Attribute
instance Data.Hashable.Class.Hashable Swarm.Game.Display.Display
instance GHC.Generics.Generic Swarm.Game.Display.Display
instance GHC.Show.Show Swarm.Game.Display.Display
instance GHC.Classes.Ord Swarm.Game.Display.Display
instance GHC.Classes.Eq Swarm.Game.Display.Display
instance GHC.Base.Semigroup Swarm.Game.Display.Display
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Display.Attribute
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Display.Attribute
-- | Rendering attributes (i.e. foreground and background colors,
-- styles, etc.) used by the Swarm TUI.
--
-- We export constants only for those we use in the Haskell code and not
-- those used in the world map, to avoid abusing attributes. For example
-- using the robot attribute to highlight some text.
--
-- The few attributes that we use for drawing the logo are an exception.
module Swarm.TUI.Attr
-- | A mapping from the defined attribute names to TUI attributes.
swarmAttrMap :: AttrMap
-- | Colors of entities in the world.
--
-- Also used to color messages, so water is special and excluded.
worldAttributes :: [(AttrName, Attr)]
worldPrefix :: AttrName
toAttrName :: Attribute -> AttrName
dirtAttr :: AttrName
grassAttr :: AttrName
stoneAttr :: AttrName
waterAttr :: AttrName
iceAttr :: AttrName
entityAttr :: AttrName
-- | The default robot attribute.
robotAttr :: AttrName
rockAttr :: AttrName
plantAttr :: AttrName
-- | Some defined attribute names used in the Swarm TUI.
highlightAttr :: AttrName
-- | Some defined attribute names used in the Swarm TUI.
notifAttr :: AttrName
-- | Some defined attribute names used in the Swarm TUI.
infoAttr :: AttrName
-- | Some defined attribute names used in the Swarm TUI.
boldAttr :: AttrName
-- | Some defined attribute names used in the Swarm TUI.
italicAttr :: AttrName
-- | Some defined attribute names used in the Swarm TUI.
dimAttr :: AttrName
-- | Some basic colors used in TUI.
magentaAttr :: AttrName
-- | Some basic colors used in TUI.
cyanAttr :: AttrName
-- | Some basic colors used in TUI.
lightCyanAttr :: AttrName
-- | Some basic colors used in TUI.
yellowAttr :: AttrName
-- | Some basic colors used in TUI.
blueAttr :: AttrName
-- | Some basic colors used in TUI.
greenAttr :: AttrName
-- | Some basic colors used in TUI.
redAttr :: AttrName
-- | Some defined attribute names used in the Swarm TUI.
defAttr :: AttrName
customEditFocusedAttr :: AttrName
module Swarm.TUI.View.CustomStyling
toStyle :: StyleFlag -> Style
toAttrColor :: HexColor -> Color
toAttrPair :: CustomAttr -> (AttrName, Attr)
-- | Terrain types and properties.
module Swarm.Game.Terrain
-- | The different possible types of terrain. Unlike entities and robots,
-- these are hard-coded into the game.
data TerrainType
StoneT :: TerrainType
DirtT :: TerrainType
GrassT :: TerrainType
IceT :: TerrainType
BlankT :: TerrainType
readTerrain :: Text -> Maybe TerrainType
-- | A map containing a Display record for each different
-- TerrainType.
terrainMap :: Map TerrainType Display
getTerrainDefaultPaletteChar :: TerrainType -> Char
getTerrainWord :: TerrainType -> Text
instance GHC.Enum.Enum Swarm.Game.Terrain.TerrainType
instance GHC.Enum.Bounded Swarm.Game.Terrain.TerrainType
instance GHC.Read.Read Swarm.Game.Terrain.TerrainType
instance GHC.Show.Show Swarm.Game.Terrain.TerrainType
instance GHC.Classes.Ord Swarm.Game.Terrain.TerrainType
instance GHC.Classes.Eq Swarm.Game.Terrain.TerrainType
instance GHC.Base.Semigroup Swarm.Game.Terrain.TerrainType
instance GHC.Base.Monoid Swarm.Game.Terrain.TerrainType
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Terrain.TerrainType
-- | An Entity represents an object that exists in the world. Each
-- entity has a way to be displayed, some metadata such as a name and
-- description, some properties, and possibly an inventory of other
-- entities.
--
-- This module also defines the Inventory type, since the two
-- types are mutually recursive (an inventory contains entities, which
-- can have inventories).
module Swarm.Game.Entity
-- | Various properties that an entity can have, which affect how robots
-- can interact with it.
data EntityProperty
-- | Robots can't move onto a cell containing this entity.
Unwalkable :: EntityProperty
-- | Robots can pick this up (via Grab or Harvest).
Portable :: EntityProperty
-- | Obstructs the view of robots that attempt to "scout"
Opaque :: EntityProperty
-- | Regrows from a seed after it is harvested.
Growable :: EntityProperty
-- | Regenerates infinitely when grabbed or harvested.
Infinite :: EntityProperty
-- | Robots drown if they walk on this without a boat.
Liquid :: EntityProperty
-- | Robots automatically know what this is without having to scan it.
Known :: EntityProperty
-- | How long an entity takes to regrow. This represents the minimum and
-- maximum amount of time taken by one growth stage (there are two
-- stages). The actual time for each stage will be chosen uniformly at
-- random between these two values.
newtype GrowthTime
GrowthTime :: (Integer, Integer) -> GrowthTime
defaultGrowthTime :: GrowthTime
-- | A record to hold information about an entity.
--
-- The constructor for Entity is intentionally not exported. To
-- construct one manually, use the mkEntity function.
--
-- There are two main constraints on the way entities are stored:
--
--
-- - We want to be able to easily modify an entity in one particular
-- cell of the world (for example, painting one tree red).
-- - In an inventory, we want to store identical entities only once,
-- along with a count.
--
--
-- We could get (2) nicely by storing only names of entities, and having
-- a global lookup table from names to entity records. However, storing
-- names instead of actual entity records in the world makes (1) more
-- complex: every time we modify an entity we would have to generate a
-- fresh name for the modified entity and add it to the global entity
-- table. This approach is also annoying because it means we can't just
-- uses lenses to drill down into the properties of an entity in the
-- world or in an inventory, but have to do an intermediate lookup in the
-- global (mutable!) entity table.
--
-- On the other hand, if we just store entity records everywhere,
-- checking them for equality becomes expensive. Having an inventory be a
-- map with entities themselves as keys sounds awful.
--
-- The solution we adopt here is that every Entity record
-- carries along a hash value of all the other fields. We just assume
-- that these hashes are unique (a collision is of course possible but
-- extremely unlikely). Entities can be efficiently compared just by
-- looking at their hashes; they can be stored in a map using hash values
-- as keys; and we provide lenses which automatically recompute the hash
-- value when modifying a field of an entity record. Note also that world
-- storage is still efficient, too: thanks to referential transparency,
-- in practice most of the entities stored in the world that are the same
-- will literally just be stored as pointers to the same shared record.
data Entity
-- | Create an entity with no orientation, an empty inventory, providing no
-- capabilities (automatically filling in the hash value).
mkEntity :: Display -> Text -> Document Syntax -> [EntityProperty] -> [Capability] -> Entity
-- | The Display explaining how to draw this entity in the world
-- display.
entityDisplay :: Lens' Entity Display
-- | The name of the entity.
entityName :: Lens' Entity Text
-- | The irregular plural version of the entity's name, if there is one.
entityPlural :: Lens' Entity (Maybe Text)
-- | Get a version of the entity's name appropriate to the number---the
-- singular name for 1, and a plural name for any other number. The
-- plural name is obtained either by looking it up if irregular, or by
-- applying standard heuristics otherwise.
entityNameFor :: Int -> Getter Entity Text
-- | A longer, free-form description of the entity. Each Text value
-- represents a paragraph.
entityDescription :: Lens' Entity (Document Syntax)
-- | The direction this entity is facing (if it has one).
entityOrientation :: Lens' Entity (Maybe Heading)
-- | How long this entity takes to grow, if it regrows.
entityGrowth :: Lens' Entity (Maybe GrowthTime)
-- | The name of a different entity yielded when this entity is grabbed, if
-- any.
entityYields :: Lens' Entity (Maybe Text)
-- | The properties enjoyed by this entity.
entityProperties :: Lens' Entity (Set EntityProperty)
-- | Test whether an entity has a certain property.
hasProperty :: Entity -> EntityProperty -> Bool
-- | The capabilities this entity provides when equipped.
entityCapabilities :: Lens' Entity (Set Capability)
-- | The inventory of other entities carried by this entity.
entityInventory :: Lens' Entity Inventory
-- | Get the hash of an entity. Note that this is a getter, not a lens; the
-- Swarm.Game.Entity module carefully maintains some internal
-- invariants ensuring that hashes work properly, and by golly, no one
-- else is going to mess that up.
entityHash :: Getter Entity Int
-- | An EntityMap is a data structure containing all the loaded
-- entities, allowing them to be looked up either by name or by what
-- capabilities they provide (if any).
data EntityMap
EntityMap :: Map Text Entity -> Map Capability [Entity] -> EntityMap
[entitiesByName] :: EntityMap -> Map Text Entity
[entitiesByCap] :: EntityMap -> Map Capability [Entity]
-- | Build an EntityMap from a list of entities. The idea is that
-- this will be called once at startup, when loading the entities from a
-- file; see loadEntities.
buildEntityMap :: Has (Throw LoadingFailure) sig m => [Entity] -> m EntityMap
-- | Load entities from a data file called entities.yaml,
-- producing either an EntityMap or a parse error.
loadEntities :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => m EntityMap
-- | Find an entity with the given name.
lookupEntityName :: Text -> EntityMap -> Maybe Entity
-- | Find all entities which are devices that provide the given capability.
deviceForCap :: Capability -> EntityMap -> [Entity]
-- | An inventory is really just a bag/multiset of entities. That is, it
-- contains some entities, along with the number of times each occurs.
-- Entities can be looked up directly, or by name.
data Inventory
-- | A convenient synonym to remind us when an Int is supposed to
-- represent how many of something we have.
type Count = Int
-- | The empty inventory.
empty :: Inventory
-- | Create an inventory containing one entity.
singleton :: Entity -> Inventory
-- | Create an inventory from a list of entities.
fromList :: [Entity] -> Inventory
-- | Create an inventory from a list of entities and their counts.
fromElems :: [(Count, Entity)] -> Inventory
-- | Look up an entity in an inventory, returning the number of copies
-- contained.
lookup :: Entity -> Inventory -> Count
-- | Look up an entity by name in an inventory, returning a list of
-- matching entities. Note, if this returns some entities, it does *not*
-- mean we necessarily have any in our inventory! It just means we *know
-- about* them. If you want to know whether you have any, use
-- lookup and see whether the resulting Count is positive,
-- or just use countByName in the first place.
lookupByName :: Text -> Inventory -> [Entity]
-- | Look up an entity by name and see how many there are in the inventory.
-- If there are multiple entities with the same name, it just picks the
-- first one returned from lookupByName.
countByName :: Text -> Inventory -> Count
-- | Check whether an inventory contains at least one of a given entity.
contains :: Inventory -> Entity -> Bool
-- | Check whether an inventory has an entry for entity (used by robots).
contains0plus :: Entity -> Inventory -> Bool
-- | Get the entities in an inventory and their associated counts.
elems :: Inventory -> [(Count, Entity)]
-- | Check if the first inventory is a subset of the second. Note that
-- entities with a count of 0 are ignored.
isSubsetOf :: Inventory -> Inventory -> Bool
-- | Check whether an inventory is empty, meaning that it contains 0 total
-- entities (although it may still know about some entities, that
-- is, have them as keys with a count of 0).
isEmpty :: Inventory -> Bool
-- | Compute the set of capabilities provided by the devices in an
-- inventory.
inventoryCapabilities :: Inventory -> Set Capability
-- | List elements that possess a given Capability and exist with nonzero
-- count in the inventory.
extantElemsWithCapability :: Capability -> Inventory -> [Entity]
-- | Groups entities by the capabilities they offer.
entitiesByCapability :: Inventory -> Map Capability (NonEmpty Entity)
-- | Insert an entity into an inventory. If the inventory already contains
-- this entity, then only its count will be incremented.
insert :: Entity -> Inventory -> Inventory
-- | Insert a certain number of copies of an entity into an inventory. If
-- the inventory already contains this entity, then only its count will
-- be incremented.
insertCount :: Count -> Entity -> Inventory -> Inventory
-- | Delete a single copy of a certain entity from an inventory.
delete :: Entity -> Inventory -> Inventory
-- | Delete a specified number of copies of an entity from an inventory.
deleteCount :: Count -> Entity -> Inventory -> Inventory
-- | Delete all copies of a certain entity from an inventory.
deleteAll :: Entity -> Inventory -> Inventory
-- | Union two inventories.
union :: Inventory -> Inventory -> Inventory
-- | Subtract the second inventory from the first.
difference :: Inventory -> Inventory -> Inventory
instance Data.Hashable.Class.Hashable Swarm.Game.Entity.EntityProperty
instance GHC.Generics.Generic Swarm.Game.Entity.EntityProperty
instance GHC.Enum.Bounded Swarm.Game.Entity.EntityProperty
instance GHC.Enum.Enum Swarm.Game.Entity.EntityProperty
instance GHC.Read.Read Swarm.Game.Entity.EntityProperty
instance GHC.Show.Show Swarm.Game.Entity.EntityProperty
instance GHC.Classes.Ord Swarm.Game.Entity.EntityProperty
instance GHC.Classes.Eq Swarm.Game.Entity.EntityProperty
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Entity.GrowthTime
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Entity.GrowthTime
instance Data.Hashable.Class.Hashable Swarm.Game.Entity.GrowthTime
instance GHC.Generics.Generic Swarm.Game.Entity.GrowthTime
instance GHC.Read.Read Swarm.Game.Entity.GrowthTime
instance GHC.Show.Show Swarm.Game.Entity.GrowthTime
instance GHC.Classes.Ord Swarm.Game.Entity.GrowthTime
instance GHC.Classes.Eq Swarm.Game.Entity.GrowthTime
instance GHC.Generics.Generic Swarm.Game.Entity.Entity
instance GHC.Show.Show Swarm.Game.Entity.Entity
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Entity.Inventory
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Entity.Inventory
instance GHC.Generics.Generic Swarm.Game.Entity.Inventory
instance GHC.Show.Show Swarm.Game.Entity.Inventory
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Entity.EntityMap
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Entity.EntityMap
instance GHC.Generics.Generic Swarm.Game.Entity.EntityMap
instance GHC.Show.Show Swarm.Game.Entity.EntityMap
instance GHC.Classes.Eq Swarm.Game.Entity.EntityMap
instance GHC.Base.Semigroup Swarm.Game.Entity.EntityMap
instance GHC.Base.Monoid Swarm.Game.Entity.EntityMap
instance Swarm.Util.Yaml.FromJSONE Swarm.Game.Entity.EntityMap Swarm.Game.Entity.Entity
instance Data.Hashable.Class.Hashable Swarm.Game.Entity.Entity
instance GHC.Classes.Eq Swarm.Game.Entity.Entity
instance GHC.Classes.Ord Swarm.Game.Entity.Entity
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Entity.Entity
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Entity.Entity
instance Data.Hashable.Class.Hashable Swarm.Game.Entity.Inventory
instance GHC.Classes.Eq Swarm.Game.Entity.Inventory
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Entity.EntityProperty
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Entity.EntityProperty
module Swarm.TUI.Inventory.Sorting
data InventorySortOptions
InventorySortOptions :: InventorySortDirection -> InventorySortOrder -> InventorySortOptions
data InventorySortDirection
Ascending :: InventorySortDirection
Descending :: InventorySortDirection
data InventorySortOrder
ByNaturalAlphabetic :: InventorySortOrder
ByQuantity :: InventorySortOrder
ByType :: InventorySortOrder
cycleSortOrder :: InventorySortOptions -> InventorySortOptions
cycleSortDirection :: InventorySortOptions -> InventorySortOptions
defaultSortOptions :: InventorySortOptions
sortInventory :: Ord a => InventorySortOptions -> [(a, Entity)] -> [(a, Entity)]
renderSortMethod :: InventorySortOptions -> Text
instance GHC.Classes.Eq Swarm.TUI.Inventory.Sorting.InventorySortDirection
instance GHC.Enum.Bounded Swarm.TUI.Inventory.Sorting.InventorySortDirection
instance GHC.Enum.Enum Swarm.TUI.Inventory.Sorting.InventorySortDirection
instance GHC.Classes.Eq Swarm.TUI.Inventory.Sorting.InventorySortOrder
instance GHC.Enum.Bounded Swarm.TUI.Inventory.Sorting.InventorySortOrder
instance GHC.Enum.Enum Swarm.TUI.Inventory.Sorting.InventorySortOrder
-- | A world refers to the grid on which the game takes place, and
-- the things in it (besides robots). A world has a base, immutable
-- terrain layer, where each cell contains a terrain type, and a
-- mutable entity layer, with at most one entity per cell.
--
-- A world is technically finite but practically infinite (worlds are
-- indexed by 32-bit signed integers, so they correspond to a
-- <math> torus).
module Swarm.Game.World
-- | World coordinates use (row,column) format, with the row increasing as
-- we move down the screen. We use this format for indexing worlds
-- internally, since it plays nicely with things like drawing the screen,
-- and reading maps from configuration files. The locToCoords and
-- coordsToLoc functions convert back and forth between this type
-- and Location, which is used when presenting coordinates
-- externally to the player.
newtype Coords
Coords :: (Int32, Int32) -> Coords
[unCoords] :: Coords -> (Int32, Int32)
-- | Convert an external (x,y) location to an internal Coords value.
locToCoords :: Location -> Coords
-- | Convert an internal Coords value to an external (x,y) location.
coordsToLoc :: Coords -> Location
-- | Represents the top-left and bottom-right coordinates of a bounding
-- rectangle of cells in the world map
type BoundsRectangle = (Coords, Coords)
-- | A WorldFun t e represents a 2D world with terrain of type
-- t (exactly one per cell) and entities of type e (at
-- most one per cell).
newtype WorldFun t e
WF :: (Coords -> (t, Erasable (Last e))) -> WorldFun t e
[getWF] :: WorldFun t e -> Coords -> (t, Erasable (Last e))
runWF :: WorldFun t e -> Coords -> (t, Maybe e)
-- | Create a world function from a finite array of specified cells.
worldFunFromArray :: Monoid t => Array (Int32, Int32) (t, Erasable e) -> WorldFun t e
-- | A World consists of a WorldFun that specifies the
-- initial world, a cache of loaded square tiles to make lookups faster,
-- and a map storing locations whose entities have changed from their
-- initial values.
--
-- Right now the World simply holds on to all the tiles it has
-- ever loaded. Ideally it would use some kind of LRU caching scheme to
-- keep memory usage bounded, but it would be a bit tricky, and in any
-- case it's probably not going to matter much for a while. Once tile
-- loads can trigger robots to spawn, it would also make for some
-- difficult decisions in terms of how to handle respawning.
data World t e
type MultiWorld t e = Map SubworldName (World t e)
-- | Load the tile containing a specific cell.
loadCell :: IArray UArray t => Coords -> World t e -> World t e
-- | Load all the tiles which overlap the given rectangular region
-- (specified as an upper-left and lower-right corner, inclusive).
loadRegion :: forall t e. IArray UArray t => (Coords, Coords) -> World t e -> World t e
-- | Create a new World from a WorldFun.
newWorld :: WorldFun t e -> World t e
lookupCosmicTerrain :: IArray UArray Int => Cosmic Coords -> MultiWorld Int e -> TerrainType
-- | Look up the terrain value at certain coordinates: try looking it up in
-- the tile cache first, and fall back to running the WorldFun
-- otherwise.
--
-- This function does not ensure that the tile containing the
-- given coordinates is loaded. For that, see lookupTerrainM.
lookupTerrain :: IArray UArray t => Coords -> World t e -> t
lookupCosmicEntity :: Cosmic Coords -> MultiWorld t e -> Maybe e
-- | Look up the entity at certain coordinates: first, see if it is in the
-- map of locations with changed entities; then try looking it up in the
-- tile cache first; and finally fall back to running the
-- WorldFun.
--
-- This function does not ensure that the tile containing the
-- given coordinates is loaded. For that, see lookupEntityM.
lookupEntity :: Coords -> World t e -> Maybe e
-- | Update the entity (or absence thereof) at a certain location,
-- returning an updated World and a Boolean indicating whether the
-- update changed the entity here. See also updateM.
update :: Coords -> (Maybe Entity -> Maybe Entity) -> World t Entity -> (World t Entity, Bool)
-- | A stateful variant of lookupTerrain, which first loads the tile
-- containing the given coordinates if it is not already loaded, then
-- looks up the terrain value.
lookupTerrainM :: forall t e sig m. (Has (State (World t e)) sig m, IArray UArray t) => Coords -> m t
-- | A stateful variant of lookupEntity, which first loads the tile
-- containing the given coordinates if it is not already loaded, then
-- looks up the terrain value.
lookupEntityM :: forall t e sig m. (Has (State (World t e)) sig m, IArray UArray t) => Coords -> m (Maybe e)
-- | A stateful variant of update, which also ensures the tile
-- containing the given coordinates is loaded.
updateM :: forall t sig m. (Has (State (World t Entity)) sig m, IArray UArray t) => Coords -> (Maybe Entity -> Maybe Entity) -> m Bool
-- | Update world in an inspectable way.
--
-- This type is used for changes by e.g. the drill command at later tick.
-- Using ADT allows us to serialize and inspect the updates.
data WorldUpdate e
ReplaceEntity :: Cosmic Location -> e -> Maybe e -> WorldUpdate e
[updatedLoc] :: WorldUpdate e -> Cosmic Location
[originalEntity] :: WorldUpdate e -> e
[newEntity] :: WorldUpdate e -> Maybe e
instance GHC.Base.Monoid t => GHC.Base.Monoid (Swarm.Game.World.WorldFun t e)
instance GHC.Base.Semigroup t => GHC.Base.Semigroup (Swarm.Game.World.WorldFun t e)
instance GHC.Base.Functor (Swarm.Game.World.WorldFun t)
instance GHC.Generics.Generic Swarm.Game.World.TileCoords
instance GHC.Ix.Ix Swarm.Game.World.TileCoords
instance GHC.Show.Show Swarm.Game.World.TileCoords
instance GHC.Classes.Ord Swarm.Game.World.TileCoords
instance GHC.Classes.Eq Swarm.Game.World.TileCoords
instance GHC.Generics.Generic Swarm.Game.World.TileOffset
instance GHC.Ix.Ix Swarm.Game.World.TileOffset
instance GHC.Show.Show Swarm.Game.World.TileOffset
instance GHC.Classes.Ord Swarm.Game.World.TileOffset
instance GHC.Classes.Eq Swarm.Game.World.TileOffset
instance Data.Aeson.Types.ToJSON.ToJSON e => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.World.WorldUpdate e)
instance Data.Aeson.Types.FromJSON.FromJSON e => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Game.World.WorldUpdate e)
instance GHC.Generics.Generic (Swarm.Game.World.WorldUpdate e)
instance GHC.Show.Show e => GHC.Show.Show (Swarm.Game.World.WorldUpdate e)
instance GHC.Classes.Ord e => GHC.Classes.Ord (Swarm.Game.World.WorldUpdate e)
instance GHC.Classes.Eq e => GHC.Classes.Eq (Swarm.Game.World.WorldUpdate e)
instance Control.Lens.Wrapped.Rewrapped Swarm.Game.World.TileOffset t
instance Control.Lens.Wrapped.Wrapped Swarm.Game.World.TileOffset
instance Control.Lens.Wrapped.Rewrapped Swarm.Game.World.TileCoords t
instance Control.Lens.Wrapped.Wrapped Swarm.Game.World.TileCoords
instance Data.Bifunctor.Bifunctor Swarm.Game.World.WorldFun
-- | Stand-in type for an Entity for purposes that do not require
-- carrying around the entire state of an Entity.
--
-- Useful for simplified serialization, debugging, and equality checking,
-- particularly for the World Editor.
module Swarm.Game.Scenario.Topography.EntityFacade
type EntityName = Text
-- | This datatype is a lightweight stand-in for the full-fledged
-- Entity type without the baggage of all of its other fields. It
-- contains the bare minimum display information for rendering.
data EntityFacade
EntityFacade :: EntityName -> Display -> EntityFacade
mkFacade :: Entity -> EntityFacade
instance GHC.Classes.Eq Swarm.Game.Scenario.Topography.EntityFacade.EntityFacade
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Topography.EntityFacade.EntityFacade
-- | A recipe represents some kind of process for transforming some input
-- entities into some output entities.
module Swarm.Game.Recipe
-- | An ingredient list is a list of entities with multiplicity. It is
-- polymorphic in the entity type so that we can use either entity names
-- when serializing, or actual entity objects while the game is running.
type IngredientList e = [(Count, e)]
-- | A recipe is just a list of input entities and a list of output
-- entities (both with multiplicity). The idea is that it represents some
-- kind of process where the inputs are transformed into the outputs.
data Recipe e
Recipe :: IngredientList e -> IngredientList e -> IngredientList e -> Integer -> Integer -> Recipe e
[_recipeInputs] :: Recipe e -> IngredientList e
[_recipeOutputs] :: Recipe e -> IngredientList e
[_recipeRequirements] :: Recipe e -> IngredientList e
[_recipeTime] :: Recipe e -> Integer
[_recipeWeight] :: Recipe e -> Integer
-- | The inputs to a recipe.
recipeInputs :: Lens' (Recipe e) (IngredientList e)
-- | The outputs from a recipe.
recipeOutputs :: Lens' (Recipe e) (IngredientList e)
-- | Other entities which the recipe requires you to have, but which are
-- not consumed by the recipe (e.g. a furnace).
recipeRequirements :: Lens' (Recipe e) (IngredientList e)
-- | The time required to finish a recipe.
recipeTime :: Lens' (Recipe e) Integer
-- | How this recipe is weighted against other recipes. Any time there are
-- multiple valid recipes that fit certain criteria, one of the recipes
-- will be randomly chosen with probability proportional to its weight.
recipeWeight :: Lens' (Recipe e) Integer
-- | Given an already loaded EntityMap, try to load a list of
-- recipes from the data file recipes.yaml.
loadRecipes :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => EntityMap -> m [Recipe Entity]
-- | Build a map of recipes indexed by output ingredients.
outRecipeMap :: [Recipe Entity] -> IntMap [Recipe Entity]
-- | Build a map of recipes indexed by input ingredients.
inRecipeMap :: [Recipe Entity] -> IntMap [Recipe Entity]
-- | Build a map of recipes indexed by requirements.
reqRecipeMap :: [Recipe Entity] -> IntMap [Recipe Entity]
data MissingIngredient
MissingIngredient :: MissingType -> Count -> Entity -> MissingIngredient
data MissingType
MissingInput :: MissingType
MissingCatalyst :: MissingType
-- | Figure out if a recipe is available, but it can be lacking items.
knowsIngredientsFor :: (Inventory, Inventory) -> Recipe Entity -> Bool
-- | Get a list of all the recipes for the given entity. Look up an entity
-- in either an inRecipeMap or outRecipeMap depending on
-- whether you want to know recipes that consume or produce the given
-- entity, respectively.
recipesFor :: IntMap [Recipe Entity] -> Entity -> [Recipe Entity]
-- | Try to make a recipe, deleting the recipe's inputs from the inventory.
-- Return either a description of which items are lacking, if the
-- inventory does not contain sufficient inputs, or an inventory without
-- inputs and function adding outputs if it was successful.
make :: (Inventory, Inventory) -> Recipe Entity -> Either [MissingIngredient] (Inventory, IngredientList Entity, Recipe Entity)
-- | Try to make a recipe, but do not insert it yet.
make' :: (Inventory, Inventory) -> Recipe Entity -> Either [MissingIngredient] (Inventory, IngredientList Entity)
instance GHC.Classes.Eq Swarm.Game.Recipe.MissingType
instance GHC.Show.Show Swarm.Game.Recipe.MissingType
instance GHC.Classes.Eq Swarm.Game.Recipe.MissingIngredient
instance GHC.Show.Show Swarm.Game.Recipe.MissingIngredient
instance Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.Recipe.Recipe Data.Text.Internal.Text)
instance Data.Aeson.Types.FromJSON.FromJSON (Swarm.Game.Recipe.Recipe Data.Text.Internal.Text)
instance Swarm.Util.Yaml.FromJSONE Swarm.Game.Entity.EntityMap (Swarm.Game.Recipe.Recipe Swarm.Game.Entity.Entity)
instance GHC.Generics.Generic (Swarm.Game.Recipe.Recipe e)
instance Data.Traversable.Traversable Swarm.Game.Recipe.Recipe
instance Data.Foldable.Foldable Swarm.Game.Recipe.Recipe
instance GHC.Base.Functor Swarm.Game.Recipe.Recipe
instance GHC.Show.Show e => GHC.Show.Show (Swarm.Game.Recipe.Recipe e)
instance GHC.Classes.Ord e => GHC.Classes.Ord (Swarm.Game.Recipe.Recipe e)
instance GHC.Classes.Eq e => GHC.Classes.Eq (Swarm.Game.Recipe.Recipe e)
instance Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.Recipe.Recipe Swarm.Game.Entity.Entity)
instance Data.Aeson.Types.FromJSON.FromJSON (Swarm.Game.Recipe.Recipe Swarm.Game.Entity.Entity)
-- | Runtime exceptions for the Swarm language interpreter.
module Swarm.Game.Exception
-- | The type of exceptions that can be thrown by robot programs.
data Exn
-- | Something went very wrong. This is a bug in Swarm and cannot be caught
-- by a try block (but at least it will not crash the entire
-- UI).
Fatal :: Text -> Exn
-- | An infinite loop was detected via a blackhole. This cannot be caught
-- by a try block.
InfiniteLoop :: Exn
-- | A robot tried to do something for which it does not have some of the
-- required capabilities. This cannot be caught by a try block.
Incapable :: IncapableFix -> Requirements -> Term -> Exn
-- | A command failed in some "normal" way (e.g. a Move
-- command could not move, or a Grab command found nothing to
-- grab, etc.).
CmdFailed :: Const -> Text -> Maybe GameplayAchievement -> Exn
-- | The user program explicitly called Undefined or
-- Fail.
User :: Text -> Exn
-- | Suggested way to fix incapable error.
data IncapableFix
-- | Equip the missing device on yourself/target
FixByEquip :: IncapableFix
-- | Add the missing device to your inventory
FixByObtain :: IncapableFix
-- | Pretty-print an exception for displaying to the player.
formatExn :: EntityMap -> Exn -> Text
-- | Pretty print the incapable exception with an actionable suggestion on
-- how to fix it.
--
--
-- >>> import Data.Either (fromRight)
--
-- >>> import Control.Carrier.Throw.Either (runThrow)
--
-- >>> import Control.Algebra (run)
--
-- >>> import Swarm.Game.Failure (LoadingFailure)
--
-- >>> :set -XTypeApplications
--
-- >>> w = mkEntity (defaultEntityDisplay 'l') "magic wand" mempty mempty [CAppear]
--
-- >>> r = mkEntity (defaultEntityDisplay 'o') "the one ring" mempty mempty [CAppear]
--
-- >>> m = fromRight mempty . run . runThrow @LoadingFailure $ buildEntityMap [w,r]
--
-- >>> incapableError cs t = putStr . unpack $ formatIncapable m FixByEquip cs t
--
--
--
-- >>> incapableError (R.singletonCap CGod) (TConst As)
-- Thou shalt not utter such blasphemy:
-- 'as'
-- If God in troth thou wantest to play, try thou a Creative game.
--
--
--
-- >>> incapableError (R.singletonCap CAppear) (TConst Appear)
-- You do not have the devices required for:
-- 'appear'
-- Please equip:
-- - the one ring or magic wand
--
--
--
-- >>> incapableError (R.singletonCap CRandom) (TConst Random)
-- Missing the random capability for:
-- 'random'
-- but no device yet provides it. See
-- https://github.com/swarm-game/swarm/issues/26
--
--
--
-- >>> incapableError (R.singletonInv 3 "tree") (TConst Noop)
-- You are missing required inventory for:
-- 'noop'
-- Please obtain:
-- - tree (3)
--
formatIncapable :: EntityMap -> IncapableFix -> Requirements -> Term -> Text
formatIncapableFix :: IncapableFix -> Text
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Exception.IncapableFix
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Exception.IncapableFix
instance GHC.Generics.Generic Swarm.Game.Exception.IncapableFix
instance GHC.Show.Show Swarm.Game.Exception.IncapableFix
instance GHC.Classes.Eq Swarm.Game.Exception.IncapableFix
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Exception.Exn
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Exception.Exn
instance GHC.Generics.Generic Swarm.Game.Exception.Exn
instance GHC.Show.Show Swarm.Game.Exception.Exn
instance GHC.Classes.Eq Swarm.Game.Exception.Exn
-- | The Swarm interpreter uses a technique known as a CESK machine
-- (if you want to read up on them, you may want to start by reading
-- about CEK machines first). Execution happens simply by
-- iterating a step function, sending one state of the CESK machine to
-- the next. In addition to being relatively efficient, this means we can
-- easily run a bunch of robots synchronously, in parallel, without
-- resorting to any threads (by stepping their machines in a round-robin
-- fashion); pause and single-step the game; save and resume, and so on.
--
-- Essentially, a CESK machine state has four components:
--
--
-- - The Control is the thing we are currently focused on:
-- either a Term to evaluate, or a Value that we have just
-- finished evaluating.
-- - The Environment (Env) is a mapping from variables
-- that might occur free in the Control to their values.
-- - The Store (Store) is a mapping from abstract integer
-- locations to values. We use it to store delayed (lazy) values,
-- so they will be computed at most once.
-- - The Kontinuation (Cont) is a stack of Frames,
-- representing the evaluation context, i.e. what we are supposed
-- to do after we finish with the currently focused thing. When we reduce
-- the currently focused term to a value, the top frame on the stack
-- tells us how to proceed.
--
--
-- You can think of a CESK machine as a defunctionalization of a
-- recursive big-step interpreter, where we explicitly keep track of the
-- call stack and the environments that would be in effect at various
-- places in the recursion. One could probably even derive this
-- mechanically, by writing a recursive big-step interpreter, then
-- converting it to CPS, then defunctionalizing the continuations.
--
-- The slightly confusing thing about CESK machines is how we have to
-- pass around environments everywhere. Basically, anywhere there can be
-- unevaluated terms containing free variables (in values, in
-- continuation stack frames, ...), we have to store the proper
-- environment alongside so that when we eventually get around to
-- evaluating it, we will be able to pull out the environment to use.
module Swarm.Game.CESK
-- | A frame is a single component of a continuation stack, explaining what
-- to do next after we finish evaluating the currently focused term.
data Frame
-- | We were evaluating the first component of a pair; next, we should
-- evaluate the second component which was saved in this frame (and push
-- a FFst frame on the stack to save the first component).
FSnd :: Term -> Env -> Frame
-- | We were evaluating the second component of a pair; when done, we
-- should combine it with the value of the first component saved in this
-- frame to construct a fully evaluated pair.
FFst :: Value -> Frame
-- | FArg t e says that we were evaluating the left-hand side of
-- an application, so the next thing we should do is evaluate the term
-- t (the right-hand side, i.e. argument of the
-- application) in environment e. We will also push an
-- FApp frame on the stack.
FArg :: Term -> Env -> Frame
-- | FApp v says that we were evaluating the right-hand side of an
-- application; once we are done, we should pass the resulting value as
-- an argument to v.
FApp :: Value -> Frame
-- | FLet x t2 e says that we were evaluating a term t1
-- in an expression of the form let x = t1 in t2, that is, we
-- were evaluating the definition of x; the next thing we should
-- do is evaluate t2 in the environment e extended with
-- a binding for x.
FLet :: Var -> Term -> Env -> Frame
-- | We are executing inside a Try block. If an exception is raised,
-- we will execute the stored term (the "catch" block).
FTry :: Value -> Frame
-- | We were executing a command; next we should take any environment it
-- returned and union it with this one to produce the result of a bind
-- expression.
FUnionEnv :: Env -> Frame
-- | We were executing a command that might have definitions; next we
-- should take the resulting Env and add it to the robot's
-- robotEnv, along with adding this accompanying Ctx and
-- ReqCtx to the robot's robotCtx.
FLoadEnv :: TCtx -> ReqCtx -> Frame
-- | We were executing a definition; next we should take the resulting
-- value and return a context binding the variable to the value.
FDef :: Var -> Frame
-- | An FExec frame means the focused value is a command, which we
-- should now execute.
FExec :: Frame
-- | We are in the process of executing the first component of a bind; once
-- done, we should also execute the second component in the given
-- environment (extended by binding the variable, if there is one, to the
-- output of the first command).
FBind :: Maybe Var -> Term -> Env -> Frame
-- | Discard any environment generated as the result of executing a
-- command.
FDiscardEnv :: Frame
-- | Apply specific updates to the world and current robot.
--
-- The Const is used to track the original command for error
-- messages.
FImmediate :: Const -> [WorldUpdate Entity] -> [RobotUpdate] -> Frame
-- | Update the memory cell at a certain location with the computed value.
FUpdate :: Addr -> Frame
-- | Signal that we are done with an atomic computation.
FFinishAtomic :: Frame
-- | We are in the middle of running a computation for all the nearby
-- robots. We have the function to run, and the list of robot IDs to run
-- it on.
FMeetAll :: Value -> [Int] -> Frame
-- | We are in the middle of evaluating a record: some fields have already
-- been evaluated; we are focusing on evaluating one field; and some
-- fields have yet to be evaluated.
FRcd :: Env -> [(Var, Value)] -> Var -> [(Var, Maybe Term)] -> Frame
-- | We are in the middle of evaluating a record field projection.(:*:)
FProj :: Var -> Frame
-- | A continuation is just a stack of frames.
type Cont = [Frame]
-- | Update world in an inspectable way.
--
-- This type is used for changes by e.g. the drill command at later tick.
-- Using ADT allows us to serialize and inspect the updates.
data WorldUpdate e
ReplaceEntity :: Cosmic Location -> e -> Maybe e -> WorldUpdate e
[updatedLoc] :: WorldUpdate e -> Cosmic Location
[originalEntity] :: WorldUpdate e -> e
[newEntity] :: WorldUpdate e -> Maybe e
-- | Update the robot in an inspectable way.
--
-- This type is used for changes by e.g. the drill command at later tick.
-- Using ADT allows us to serialize and inspect the updates.
--
-- Note that this can not be in Robot as it would create a cyclic
-- dependency.
data RobotUpdate
AddEntity :: Count -> Entity -> RobotUpdate
LearnEntity :: Entity -> RobotUpdate
-- | Store represents a store, indexing integer locations to
-- Cells.
data Store
type Addr = Int
emptyStore :: Store
-- | A memory cell can be in one of three states.
data Cell
-- | A cell starts out life as an unevaluated term together with its
-- environment.
E :: Term -> Env -> Cell
-- | When the cell is Forced, it is set to a Blackhole while
-- being evaluated. If it is ever referenced again while still a
-- Blackhole, that means it depends on itself in a way that would
-- trigger an infinite loop, and we can signal an error. (Of course, we
-- <http://www.lel.ed.ac.uk/~gpullum/loopsnoop.html cannot
-- detect all infinite loops this way>.)
--
-- A Blackhole saves the original Term and Env that
-- are being evaluated; if Ctrl-C is used to cancel a computation while
-- we are in the middle of evaluating a cell, the Blackhole can be
-- reset to E.
Blackhole :: Term -> Env -> Cell
-- | Once evaluation is complete, we cache the final Value in the
-- Cell, so that subsequent lookups can just use it without
-- recomputing anything.
V :: Value -> Cell
-- | Allocate a new memory cell containing an unevaluated expression with
-- the current environment. Return the index of the allocated cell.
allocate :: Env -> Term -> Store -> (Addr, Store)
-- | Look up the cell at a given index.
lookupCell :: Addr -> Store -> Maybe Cell
-- | Set the cell at a given index.
setCell :: Addr -> Cell -> Store -> Store
-- | The overall state of a CESK machine, which can actually be one of
-- three kinds of states. The CESK machine is named after the first kind
-- of state, and it would probably be possible to inline a bunch of
-- things and get rid of the second state, but I find it much more
-- natural and elegant this way. Most tutorial presentations of CEK/CESK
-- machines only have one kind of state, but then again, most tutorial
-- presentations only deal with the bare lambda calculus, so one can tell
-- whether a term is a value just by seeing whether it is syntactically a
-- lambda. I learned this approach from Harper's Practical Foundations of
-- Programming Languages.
data CESK
-- | When we are on our way "in/down" into a term, we have a currently
-- focused term to evaluate in the environment, a store, and a
-- continuation. In this mode we generally pattern-match on the
-- Term to decide what to do next.
In :: Term -> Env -> Store -> Cont -> CESK
-- | Once we finish evaluating a term, we end up with a Value and we
-- switch into "out" mode, bringing the value back up out of the depths
-- to the context that was expecting it. In this mode we generally
-- pattern-match on the Cont to decide what to do next.
--
-- Note that there is no Env, because we don't have anything with
-- variables to evaluate at the moment, and we maintain the invariant
-- that any unevaluated terms buried inside a Value or Cont
-- must carry along their environment with them.
Out :: Value -> Store -> Cont -> CESK
-- | An exception has been raised. Keep unwinding the continuation stack
-- (until finding an enclosing Try in the case of a command
-- failure or a user-generated exception, or until the stack is empty in
-- the case of a fatal exception).
Up :: Exn -> Store -> Cont -> CESK
-- | The machine is waiting for the game to reach a certain time to resume
-- its execution.
Waiting :: TickNumber -> CESK -> CESK
-- | Initialize a machine state with a starting term along with its type;
-- the term will be executed or just evaluated depending on whether it
-- has a command type or not.
initMachine :: ProcessedTerm -> Env -> Store -> CESK
-- | Like initMachine, but also take an explicit starting
-- continuation.
initMachine' :: ProcessedTerm -> Env -> Store -> Cont -> CESK
-- | Cancel the currently running computation.
cancel :: CESK -> CESK
-- | Reset any Blackholes in the Store. We need to use this
-- any time a running computation is interrupted, either by an exception
-- or by a Ctrl+C.
resetBlackholes :: Store -> Store
-- | Is the CESK machine in a final (finished) state? If so, extract the
-- final value and store.
finalValue :: CESK -> Maybe (Value, Store)
newtype TickNumber
TickNumber :: Integer -> TickNumber
[getTickNumber] :: TickNumber -> Integer
addTicks :: Integer -> TickNumber -> TickNumber
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.CESK.TickNumber
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.CESK.TickNumber
instance GHC.Generics.Generic Swarm.Game.CESK.TickNumber
instance GHC.Read.Read Swarm.Game.CESK.TickNumber
instance GHC.Show.Show Swarm.Game.CESK.TickNumber
instance GHC.Classes.Ord Swarm.Game.CESK.TickNumber
instance GHC.Classes.Eq Swarm.Game.CESK.TickNumber
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.CESK.Cell
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.CESK.Cell
instance GHC.Generics.Generic Swarm.Game.CESK.Cell
instance GHC.Classes.Eq Swarm.Game.CESK.Cell
instance GHC.Show.Show Swarm.Game.CESK.Cell
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.CESK.Store
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.CESK.Store
instance GHC.Generics.Generic Swarm.Game.CESK.Store
instance GHC.Classes.Eq Swarm.Game.CESK.Store
instance GHC.Show.Show Swarm.Game.CESK.Store
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.CESK.RobotUpdate
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.CESK.RobotUpdate
instance GHC.Generics.Generic Swarm.Game.CESK.RobotUpdate
instance GHC.Show.Show Swarm.Game.CESK.RobotUpdate
instance GHC.Classes.Ord Swarm.Game.CESK.RobotUpdate
instance GHC.Classes.Eq Swarm.Game.CESK.RobotUpdate
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.CESK.Frame
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.CESK.Frame
instance GHC.Generics.Generic Swarm.Game.CESK.Frame
instance GHC.Show.Show Swarm.Game.CESK.Frame
instance GHC.Classes.Eq Swarm.Game.CESK.Frame
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.CESK.CESK
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.CESK.CESK
instance GHC.Generics.Generic Swarm.Game.CESK.CESK
instance GHC.Show.Show Swarm.Game.CESK.CESK
instance GHC.Classes.Eq Swarm.Game.CESK.CESK
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.CESK.CESK
instance Prettyprinter.Internal.Pretty Swarm.Game.CESK.TickNumber
-- | Data types and instances for specific scoring methods
module Swarm.Game.Scenario.Scoring.ConcreteMetrics
scenarioOptions :: Options
data DurationMetrics
DurationMetrics :: NominalDiffTime -> TickNumber -> DurationMetrics
-- | Time elapsed until winning the scenario.
[_scenarioElapsed] :: DurationMetrics -> NominalDiffTime
-- | Ticks elapsed until winning the scenario.
[_scenarioElapsedTicks] :: DurationMetrics -> TickNumber
scenarioElapsedTicks :: Lens' DurationMetrics TickNumber
scenarioElapsed :: Lens' DurationMetrics NominalDiffTime
emptyDurationMetric :: DurationMetrics
data AttemptMetrics
AttemptMetrics :: DurationMetrics -> Maybe ScenarioCodeMetrics -> AttemptMetrics
[_scenarioDurationMetrics] :: AttemptMetrics -> DurationMetrics
-- | Size of the user's program.
[_scenarioCodeMetrics] :: AttemptMetrics -> Maybe ScenarioCodeMetrics
emptyAttemptMetric :: AttemptMetrics
scenarioDurationMetrics :: Lens' AttemptMetrics DurationMetrics
scenarioCodeMetrics :: Lens' AttemptMetrics (Maybe ScenarioCodeMetrics)
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Scoring.ConcreteMetrics.AttemptMetrics
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Scoring.ConcreteMetrics.AttemptMetrics
instance GHC.Generics.Generic Swarm.Game.Scenario.Scoring.ConcreteMetrics.AttemptMetrics
instance GHC.Read.Read Swarm.Game.Scenario.Scoring.ConcreteMetrics.AttemptMetrics
instance GHC.Show.Show Swarm.Game.Scenario.Scoring.ConcreteMetrics.AttemptMetrics
instance GHC.Classes.Ord Swarm.Game.Scenario.Scoring.ConcreteMetrics.AttemptMetrics
instance GHC.Classes.Eq Swarm.Game.Scenario.Scoring.ConcreteMetrics.AttemptMetrics
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Scoring.ConcreteMetrics.DurationMetrics
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Scoring.ConcreteMetrics.DurationMetrics
instance GHC.Generics.Generic Swarm.Game.Scenario.Scoring.ConcreteMetrics.DurationMetrics
instance GHC.Read.Read Swarm.Game.Scenario.Scoring.ConcreteMetrics.DurationMetrics
instance GHC.Show.Show Swarm.Game.Scenario.Scoring.ConcreteMetrics.DurationMetrics
instance GHC.Classes.Ord Swarm.Game.Scenario.Scoring.ConcreteMetrics.DurationMetrics
instance GHC.Classes.Eq Swarm.Game.Scenario.Scoring.ConcreteMetrics.DurationMetrics
-- | Types and records for updating and retrieving the best scores for a
-- scenario.
module Swarm.Game.Scenario.Scoring.Best
data BestByCriteria
BestByTime :: BestByCriteria
BestByTicks :: BestByCriteria
BestByCharCount :: BestByCriteria
BestByAstSize :: BestByCriteria
describeCriteria :: BestByCriteria -> Text
data ProgressStats
ProgressStats :: ZonedTime -> AttemptMetrics -> ProgressStats
-- | Time when the scenario was started including time zone.
[_scenarioStarted] :: ProgressStats -> ZonedTime
[_scenarioAttemptMetrics] :: ProgressStats -> AttemptMetrics
scenarioStarted :: Lens' ProgressStats ZonedTime
scenarioAttemptMetrics :: Lens' ProgressStats AttemptMetrics
type ProgressMetric = Metric ProgressStats
data BestRecords
BestRecords :: ProgressMetric -> ProgressMetric -> ProgressMetric -> ProgressMetric -> BestRecords
[_scenarioBestByTime] :: BestRecords -> ProgressMetric
[_scenarioBestByTicks] :: BestRecords -> ProgressMetric
[_scenarioBestByCharCount] :: BestRecords -> ProgressMetric
[_scenarioBestByAstSize] :: BestRecords -> ProgressMetric
emptyBest :: ZonedTime -> BestRecords
updateBest :: ProgressMetric -> BestRecords -> BestRecords
-- | The best status of the scenario, measured in real world time.
scenarioBestByTime :: Lens' BestRecords ProgressMetric
-- | The best status of the scenario, measured in game ticks.
scenarioBestByTicks :: Lens' BestRecords ProgressMetric
-- | The best code size of the scenario, measured in character count.
scenarioBestByCharCount :: Lens' BestRecords ProgressMetric
-- | The best code size of the scenario, measured in AST size.
scenarioBestByAstSize :: Lens' BestRecords ProgressMetric
-- | Uses the start time of the play-attempt to de-dupe records that are
-- from the same game. The start time should be sufficient to uniquely
-- identify a game.
getBestGroups :: BestRecords -> [(Metric ProgressStats, NonEmpty BestByCriteria)]
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Scoring.Best.BestRecords
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Scoring.Best.BestRecords
instance GHC.Generics.Generic Swarm.Game.Scenario.Scoring.Best.BestRecords
instance GHC.Read.Read Swarm.Game.Scenario.Scoring.Best.BestRecords
instance GHC.Classes.Ord Swarm.Game.Scenario.Scoring.Best.BestRecords
instance GHC.Classes.Eq Swarm.Game.Scenario.Scoring.Best.BestRecords
instance GHC.Show.Show Swarm.Game.Scenario.Scoring.Best.BestRecords
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Scoring.Best.ProgressStats
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Scoring.Best.ProgressStats
instance GHC.Show.Show Swarm.Game.Scenario.Scoring.Best.BestByCriteria
instance GHC.Enum.Enum Swarm.Game.Scenario.Scoring.Best.BestByCriteria
instance GHC.Enum.Bounded Swarm.Game.Scenario.Scoring.Best.BestByCriteria
instance GHC.Classes.Ord Swarm.Game.Scenario.Scoring.Best.BestByCriteria
instance GHC.Classes.Eq Swarm.Game.Scenario.Scoring.Best.BestByCriteria
instance GHC.Generics.Generic Swarm.Game.Scenario.Scoring.Best.ProgressStats
instance GHC.Read.Read Swarm.Game.Scenario.Scoring.Best.ProgressStats
instance GHC.Show.Show Swarm.Game.Scenario.Scoring.Best.ProgressStats
instance GHC.Classes.Ord Swarm.Game.Scenario.Scoring.Best.ProgressStats
instance GHC.Classes.Eq Swarm.Game.Scenario.Scoring.Best.ProgressStats
instance GHC.Classes.Eq Data.Time.LocalTime.Internal.ZonedTime.ZonedTime
instance GHC.Classes.Ord Data.Time.LocalTime.Internal.ZonedTime.ZonedTime
-- | A data type to represent in-game logs by robots.
--
-- Because of the use of system robots, we sometimes want to use special
-- kinds of logs that will be shown to the player.
--
-- TODO: #1039 Currently we abuse this system for system logs, which is
-- fun, but we should eventually make a dedicated SystemLogEntry
-- type for RuntimeState message queue.
module Swarm.Game.Log
-- | Source of the robot log.
data LogSource
-- | Log produced by Say
Said :: LogSource
-- | Log produced by Log
Logged :: LogSource
-- | Log produced by an exception or system.
ErrorTrace :: ErrorLevel -> LogSource
-- | Severity of the error - critical errors are bugs and should be
-- reported as Issues.
data ErrorLevel
Debug :: ErrorLevel
Warning :: ErrorLevel
Error :: ErrorLevel
Critical :: ErrorLevel
-- | An entry in a robot's log.
data LogEntry
LogEntry :: TickNumber -> LogSource -> Text -> Int -> LogLocation (Cosmic Location) -> Text -> LogEntry
-- | The time at which the entry was created. Note that this is the first
-- field we sort on.
[_leTime] :: LogEntry -> TickNumber
-- | Whether this log records a said message.
[_leSource] :: LogEntry -> LogSource
-- | The name of the robot that generated the entry.
[_leRobotName] :: LogEntry -> Text
-- | The ID of the robot that generated the entry.
[_leRobotID] :: LogEntry -> Int
-- | Location of the robot at log entry creation.
[_leLocation] :: LogEntry -> LogLocation (Cosmic Location)
-- | The text of the log entry.
[_leText] :: LogEntry -> Text
data LogLocation a
Omnipresent :: LogLocation a
Located :: a -> LogLocation a
leText :: Lens' LogEntry Text
leSource :: Lens' LogEntry LogSource
leRobotName :: Lens' LogEntry Text
leTime :: Lens' LogEntry TickNumber
leLocation :: Lens' LogEntry (LogLocation (Cosmic Location))
leRobotID :: Lens' LogEntry Int
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Log.ErrorLevel
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Log.ErrorLevel
instance GHC.Generics.Generic Swarm.Game.Log.ErrorLevel
instance GHC.Classes.Ord Swarm.Game.Log.ErrorLevel
instance GHC.Classes.Eq Swarm.Game.Log.ErrorLevel
instance GHC.Show.Show Swarm.Game.Log.ErrorLevel
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Log.LogSource
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Log.LogSource
instance GHC.Generics.Generic Swarm.Game.Log.LogSource
instance GHC.Classes.Ord Swarm.Game.Log.LogSource
instance GHC.Classes.Eq Swarm.Game.Log.LogSource
instance GHC.Show.Show Swarm.Game.Log.LogSource
instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.Log.LogLocation a)
instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Game.Log.LogLocation a)
instance GHC.Generics.Generic (Swarm.Game.Log.LogLocation a)
instance GHC.Classes.Ord a => GHC.Classes.Ord (Swarm.Game.Log.LogLocation a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Swarm.Game.Log.LogLocation a)
instance GHC.Show.Show a => GHC.Show.Show (Swarm.Game.Log.LogLocation a)
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Log.LogEntry
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Log.LogEntry
instance GHC.Generics.Generic Swarm.Game.Log.LogEntry
instance GHC.Classes.Ord Swarm.Game.Log.LogEntry
instance GHC.Classes.Eq Swarm.Game.Log.LogEntry
instance GHC.Show.Show Swarm.Game.Log.LogEntry
-- | A data type to represent robots.
module Swarm.Game.Robot
-- | The phase of a robot description record.
data RobotPhase
-- | The robot record has just been read in from a scenario description; it
-- represents a template that may later be instantiated as one or
-- more concrete robots.
TemplateRobot :: RobotPhase
-- | The robot record represents a concrete robot in the world.
ConcreteRobot :: RobotPhase
-- | A unique identifier for a robot.
type RID = Int
-- | A value of type RobotR is a record representing the state of a
-- single robot. The f parameter is for tracking whether or not
-- the robot has been assigned a unique ID.
data RobotR (phase :: RobotPhase)
-- | A concrete robot, with a unique ID number and a specific location.
type Robot = RobotR 'ConcreteRobot
-- | A template robot, i.e. a template robot record without a unique ID
-- number, and possibly without a location.
type TRobot = RobotR 'TemplateRobot
-- | Update the robot in an inspectable way.
--
-- This type is used for changes by e.g. the drill command at later tick.
-- Using ADT allows us to serialize and inspect the updates.
--
-- Note that this can not be in Robot as it would create a cyclic
-- dependency.
data RobotUpdate
AddEntity :: Count -> Entity -> RobotUpdate
LearnEntity :: Entity -> RobotUpdate
-- | A record that stores the information for all definitions stored in a
-- Robot
data RobotContext
defTypes :: Lens' RobotContext TCtx
defReqs :: Lens' RobotContext ReqCtx
defVals :: Lens' RobotContext Env
defStore :: Lens' RobotContext Store
emptyRobotContext :: RobotContext
-- | Robots are not entities, but they have almost all the characteristics
-- of one (or perhaps we could think of robots as very special sorts of
-- entities), so for convenience each robot carries an Entity
-- record to store all the information it has in common with any
-- Entity.
--
-- Note there are various lenses provided for convenience that directly
-- reference fields inside this record; for example, one can use
-- robotName instead of writing robotEntity .
-- entityName.
robotEntity :: Lens' (RobotR phase) Entity
-- | The name of a robot.
robotName :: Lens' Robot Text
-- | The name of a robot template.
trobotName :: Lens' TRobot Text
-- | The creation date of the robot.
robotCreatedAt :: Lens' Robot TimeSpec
-- | The Display of a robot. This is a special lens that
-- automatically sets the curOrientation to the orientation of the
-- robot every time you do a get operation. Technically this
-- does not satisfy the lens laws---in particular, the get/put law does
-- not hold. But we should think of the curOrientation as being
-- simply a cache of the displayed entity's direction.
robotDisplay :: Lens' Robot Display
-- | The robot's current location, represented as (x,y). This is only a
-- getter, since when changing a robot's location we must remember to
-- update the robotsByLocation map as well. You can use the
-- updateRobotLocation function for this purpose.
robotLocation :: Getter Robot (Cosmic Location)
-- | Set a robot's location. This is unsafe and should never be called
-- directly except by the updateRobotLocation function. The
-- reason is that we need to make sure the robotsByLocation map
-- stays in sync.
unsafeSetRobotLocation :: Cosmic Location -> Robot -> Robot
-- | A template robot's location. Unlike robotLocation, this is a
-- lens, since when dealing with robot templates there is as yet no
-- robotsByLocation map to keep up-to-date.
trobotLocation :: Lens' TRobot (Maybe (Cosmic Location))
-- | Which way the robot is currently facing.
robotOrientation :: Lens' Robot (Maybe Heading)
-- | The robot's inventory.
robotInventory :: Lens' Robot Inventory
-- | A separate inventory for equipped devices, which provide the robot
-- with certain capabilities.
--
-- Note that every time the inventory of equipped devices is modified,
-- this lens recomputes a cached set of the capabilities the equipped
-- devices provide, to speed up subsequent lookups to see whether the
-- robot has a certain capability (see robotCapabilities)
equippedDevices :: Lens' Robot Inventory
-- | The robot's own private message log, most recent message last.
-- Messages can be added both by explicit use of the Log
-- command, and by uncaught exceptions. Stored as a Data.Sequence
-- so that we can efficiently add to the end and also process from
-- beginning to end. Note that updating via this lens will also set the
-- robotLogUpdated.
robotLog :: Lens' Robot (Seq LogEntry)
-- | Has the robotLog been updated since the last time it was
-- viewed?
robotLogUpdated :: Lens' Robot Bool
-- | A hash of a robot's entity record and equipped devices, to facilitate
-- quickly deciding whether we need to redraw the robot info panel.
inventoryHash :: Getter Robot Int
-- | Get the set of capabilities this robot possesses. This is only a
-- getter, not a lens, because it is automatically generated from the
-- equippedDevices. The only way to change a robot's capabilities
-- is to modify its equippedDevices.
robotCapabilities :: Getter Robot (Set Capability)
-- | The robot's context.
robotContext :: Lens' Robot RobotContext
-- | The robot's context.
trobotContext :: Lens' TRobot RobotContext
-- | The (unique) ID number of the robot. This is only a Getter since the
-- robot ID is immutable.
robotID :: Getter Robot RID
-- | The ID number of the robot's parent, that is, the robot that built (or
-- most recently reprogrammed) this robot, if there is one.
robotParentID :: Lens' Robot (Maybe RID)
-- | Is this robot extra heavy (thus requiring tank treads to move)?
robotHeavy :: Lens' Robot Bool
-- | The robot's current CEK machine state.
machine :: Lens' Robot CESK
-- | Is this robot a "system robot"? System robots are generated by the
-- system (as opposed to created by the user) and are not subject to the
-- usual capability restrictions.
systemRobot :: Lens' Robot Bool
-- | Does this robot wish to self destruct?
selfDestruct :: Lens' Robot Bool
-- | The need for tickSteps is a bit technical, and I hope I can
-- eventually find a different, better way to accomplish it. Ideally, we
-- would want each robot to execute a single command at every game
-- tick, so that e.g. two robots executing move;move;move
-- and repeat 3 move (given a suitable definition of
-- repeat) will move in lockstep. However, the second robot
-- actually has to do more computation than the first (it has to look up
-- the definition of repeat, reduce its application to the
-- number 3, etc.), so its CESK machine will take more steps. It won't do
-- to simply let each robot run until executing a command---because robot
-- programs can involve arbitrary recursion, it is very easy to write a
-- program that evaluates forever without ever executing a command, which
-- in this scenario would completely freeze the UI. (It also wouldn't
-- help to ensure all programs are terminating---it would still be
-- possible to effectively do the same thing by making a program that
-- takes a very, very long time to terminate.) So instead, we allocate
-- each robot a certain maximum number of computation steps per tick
-- (defined in evalStepsPerTick), and it suspends computation when
-- it either executes a command or reaches the maximum number of steps,
-- whichever comes first.
--
-- It seems like this really isn't something the robot should be keeping
-- track of itself, but that seemed the most technically convenient way
-- to do it at the time. The robot needs some way to signal when it has
-- executed a command, which it currently does by setting tickSteps to
-- zero. However, that has the disadvantage that when tickSteps becomes
-- zero, we can't tell whether that happened because the robot ran out of
-- steps, or because it executed a command and set it to zero manually.
--
-- Perhaps instead, each robot should keep a counter saying how many
-- commands it has executed. The loop stepping the robot can tell when
-- the counter increments.
tickSteps :: Lens' Robot Int
-- | Is the robot currently running an atomic block?
runningAtomic :: Lens' Robot Bool
-- | A general function for creating robots.
mkRobot :: RobotID phase -> Maybe Int -> Text -> Document Syntax -> RobotLocation phase -> Heading -> Display -> CESK -> [Entity] -> [(Count, Entity)] -> Bool -> Bool -> TimeSpec -> RobotR phase
-- | Instantiate a robot template to make it into a concrete robot, by
-- providing a robot ID. Concrete robots also require a location; if the
-- robot template didn't have a location already, just set the location
-- to (0,0) by default. If you want a different location, set it via
-- trobotLocation before calling instantiateRobot.
instantiateRobot :: RID -> TRobot -> Robot
-- | Does a robot know of an entity's existence?
robotKnows :: Robot -> Entity -> Bool
-- | Is the robot actively in the middle of a computation?
isActive :: Robot -> Bool
-- | Active robots include robots that are waiting;
-- wantsToStep is true if the robot actually wants to take another
-- step right now (this is a subset of active robots).
wantsToStep :: TickNumber -> Robot -> Bool
-- | The time until which the robot is waiting, if any.
waitingUntil :: Robot -> Maybe TickNumber
-- | Get the result of the robot's computation if it is finished.
getResult :: Robot -> Maybe (Value, Store)
hearingDistance :: Num i => i
instance Servant.Docs.Internal.ToSample Swarm.Game.Robot.Robot
instance Swarm.Util.Yaml.FromJSONE Swarm.Game.Entity.EntityMap Swarm.Game.Robot.TRobot
instance GHC.Generics.Generic (Swarm.Game.Robot.RobotR phase)
instance (GHC.Show.Show (Swarm.Game.Robot.RobotLocation phase), GHC.Show.Show (Swarm.Game.Robot.RobotID phase)) => GHC.Show.Show (Swarm.Game.Robot.RobotR phase)
instance (GHC.Classes.Eq (Swarm.Game.Robot.RobotLocation phase), GHC.Classes.Eq (Swarm.Game.Robot.RobotID phase)) => GHC.Classes.Eq (Swarm.Game.Robot.RobotR phase)
instance (Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.Robot.RobotLocation phase), Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.Robot.RobotID phase)) => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.Robot.RobotR phase)
instance Control.Lens.At.Ixed Swarm.Game.Robot.RobotContext
instance Control.Lens.At.At Swarm.Game.Robot.RobotContext
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Robot.RobotContext
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Robot.RobotContext
instance GHC.Generics.Generic Swarm.Game.Robot.RobotContext
instance GHC.Show.Show Swarm.Game.Robot.RobotContext
instance GHC.Classes.Eq Swarm.Game.Robot.RobotContext
-- | Abstract syntax for the Swarm world description DSL.
module Swarm.Game.World.Syntax
type World b = Coords -> b
type RawCellVal = [(Maybe CellTag, Text)]
data CellTag
CellTerrain :: CellTag
CellEntity :: CellTag
CellRobot :: CellTag
data CellVal
CellVal :: TerrainType -> Erasable (Last Entity) -> [Robot] -> CellVal
data Rot
Rot0 :: Rot
Rot90 :: Rot
Rot180 :: Rot
Rot270 :: Rot
type Var = Text
data Axis
X :: Axis
Y :: Axis
data Op
Not :: Op
Neg :: Op
And :: Op
Or :: Op
Add :: Op
Sub :: Op
Mul :: Op
Div :: Op
Mod :: Op
Eq :: Op
Neq :: Op
Lt :: Op
Leq :: Op
Gt :: Op
Geq :: Op
If :: Op
Perlin :: Op
Reflect :: Axis -> Op
Rot :: Rot -> Op
Mask :: Op
Overlay :: Op
Abs :: Op
data WExp
[WInt] :: Integer -> WExp
[WFloat] :: Double -> WExp
[WBool] :: Bool -> WExp
[WCell] :: RawCellVal -> WExp
[WVar] :: Text -> WExp
[WOp] :: Op -> [WExp] -> WExp
[WSeed] :: WExp
[WCoord] :: Axis -> WExp
[WHash] :: WExp
[WLet] :: [(Var, WExp)] -> WExp -> WExp
[WOverlay] :: NonEmpty WExp -> WExp
[WImport] :: Text -> WExp
instance GHC.Enum.Bounded Swarm.Game.World.Syntax.CellTag
instance GHC.Enum.Enum Swarm.Game.World.Syntax.CellTag
instance GHC.Show.Show Swarm.Game.World.Syntax.CellTag
instance GHC.Classes.Ord Swarm.Game.World.Syntax.CellTag
instance GHC.Classes.Eq Swarm.Game.World.Syntax.CellTag
instance GHC.Show.Show Swarm.Game.World.Syntax.CellVal
instance GHC.Classes.Eq Swarm.Game.World.Syntax.CellVal
instance GHC.Enum.Enum Swarm.Game.World.Syntax.Rot
instance GHC.Enum.Bounded Swarm.Game.World.Syntax.Rot
instance GHC.Show.Show Swarm.Game.World.Syntax.Rot
instance GHC.Classes.Ord Swarm.Game.World.Syntax.Rot
instance GHC.Classes.Eq Swarm.Game.World.Syntax.Rot
instance GHC.Enum.Enum Swarm.Game.World.Syntax.Axis
instance GHC.Enum.Bounded Swarm.Game.World.Syntax.Axis
instance GHC.Show.Show Swarm.Game.World.Syntax.Axis
instance GHC.Classes.Ord Swarm.Game.World.Syntax.Axis
instance GHC.Classes.Eq Swarm.Game.World.Syntax.Axis
instance GHC.Show.Show Swarm.Game.World.Syntax.Op
instance GHC.Classes.Ord Swarm.Game.World.Syntax.Op
instance GHC.Classes.Eq Swarm.Game.World.Syntax.Op
instance GHC.Show.Show Swarm.Game.World.Syntax.WExp
instance GHC.Classes.Eq Swarm.Game.World.Syntax.WExp
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.World.Syntax.Axis
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.World.Syntax.Rot
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.World.Syntax.CellVal
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.World.Syntax.CellTag
-- | Typechecking and elaboration for the Swarm world DSL. For more
-- information, see:
--
--
-- https://byorgey.wordpress.com/2023/07/13/compiling-to-intrinsically-typed-combinators/
module Swarm.Game.World.Typecheck
class Empty e
empty :: Empty e => e
class Over m
() :: Over m => m -> m -> m
class Applicable t
($$) :: Applicable t => t (a -> b) -> t a -> t b
infixl 1 $$
type family IsFun a
type NotFun a = IsFun a ~ 'False
-- | Type-indexed constants. These include both language built-ins
-- (if, arithmetic, comparison, <>, etc.) as well
-- as combinators (S, I, C, K,
-- B, Φ) we will use both for elaboration and later as
-- a compilation target.
data Const :: Type -> Type
[CLit] :: (Show a, NotFun a) => a -> Const a
[CCell] :: CellVal -> Const CellVal
[CFI] :: Const (Integer -> Double)
[CIf] :: Const (Bool -> a -> a -> a)
[CNot] :: Const (Bool -> Bool)
[CNeg] :: (Num a, NotFun a) => Const (a -> a)
[CAbs] :: (Num a, NotFun a) => Const (a -> a)
[CAnd] :: Const (Bool -> Bool -> Bool)
[COr] :: Const (Bool -> Bool -> Bool)
[CAdd] :: (Num a, NotFun a) => Const (a -> a -> a)
[CSub] :: (Num a, NotFun a) => Const (a -> a -> a)
[CMul] :: (Num a, NotFun a) => Const (a -> a -> a)
[CDiv] :: (Fractional a, NotFun a) => Const (a -> a -> a)
[CIDiv] :: (Integral a, NotFun a) => Const (a -> a -> a)
[CMod] :: (Integral a, NotFun a) => Const (a -> a -> a)
[CEq] :: (Eq a, NotFun a) => Const (a -> a -> Bool)
[CNeq] :: (Eq a, NotFun a) => Const (a -> a -> Bool)
[CLt] :: (Ord a, NotFun a) => Const (a -> a -> Bool)
[CLeq] :: (Ord a, NotFun a) => Const (a -> a -> Bool)
[CGt] :: (Ord a, NotFun a) => Const (a -> a -> Bool)
[CGeq] :: (Ord a, NotFun a) => Const (a -> a -> Bool)
[CMask] :: (Empty a, NotFun a) => Const (World Bool -> World a -> World a)
[CSeed] :: Const Integer
[CCoord] :: Axis -> Const (World Integer)
[CHash] :: Const (World Integer)
[CPerlin] :: Const (Integer -> Integer -> Double -> Double -> World Double)
[CReflect] :: Axis -> Const (World a -> World a)
[CRot] :: Rot -> Const (World a -> World a)
[COver] :: (Over a, NotFun a) => Const (a -> a -> a)
[K] :: Const (a -> b -> a)
[S] :: Const ((a -> b -> c) -> (a -> b) -> a -> c)
[I] :: Const (a -> a)
[B] :: Const ((b -> c) -> (a -> b) -> a -> c)
[C] :: Const ((a -> b -> c) -> b -> a -> c)
[Φ] :: Const ((a -> b -> c) -> (d -> a) -> (d -> b) -> d -> c)
class HasConst t
embed :: HasConst t => Const a -> t a
(.$$) :: (HasConst t, Applicable t) => Const (a -> b) -> t a -> t b
infixl 1 .$$
($$.) :: (HasConst t, Applicable t) => t (a -> b) -> Const a -> t b
infixl 1 $$.
(.$$.) :: (HasConst t, Applicable t) => Const (a -> b) -> Const a -> t b
infixl 1 .$$.
-- | Type-level list append.
type family Append (xs :: [k]) (ys :: [k]) :: [k]
-- | Type- and context-indexed de Bruijn indices. (v :: Idx g a) means v
-- represents a variable with type a in a type context g.
data Idx :: [Type] -> Type -> Type
[VZ] :: Idx (ty : g) ty
[VS] :: Idx g ty -> Idx (x : g) ty
idxToNat :: Idx g a -> Int
-- | A variable valid in one context is also valid in another extended
-- context with additional variables.
weakenVar :: forall h g a. Idx g a -> Idx (Append g h) a
-- | Type-indexed terms. Note this is a stripped-down core language, with
-- only variables, lambdas, application, and constants.
data TTerm :: [Type] -> Type -> Type
[TVar] :: Idx g a -> TTerm g a
[TLam] :: TTerm (ty1 : g) ty2 -> TTerm g (ty1 -> ty2)
[TApp] :: TTerm g (a -> b) -> TTerm g a -> TTerm g b
[TConst] :: Const a -> TTerm g a
-- | A term valid in one context is also valid in another extended context
-- with additional variables (which the term does not use).
weaken :: forall h g a. TTerm g a -> TTerm (Append g h) a
-- | Errors that can occur during typechecking/elaboration.
data CheckErr
[ApplyErr] :: Some (TTerm g) -> Some (TTerm g) -> CheckErr
[NoInstance] :: Text -> TTy a -> CheckErr
[Unbound] :: Text -> CheckErr
[BadType] :: Some (TTerm g) -> TTy b -> CheckErr
[BadDivType] :: TTy a -> CheckErr
[UnknownImport] :: Text -> CheckErr
[NotAThing] :: Text -> CellTag -> CheckErr
[NotAnything] :: Text -> CheckErr
-- | Base types.
data Base :: Type -> Type
[BInt] :: Base Integer
[BFloat] :: Base Double
[BBool] :: Base Bool
[BCell] :: Base CellVal
-- | Type representations indexed by the corresponding host language type.
data TTy :: Type -> Type
[TTyBase] :: Base t -> TTy t
[:->:] :: TTy a -> TTy b -> TTy (a -> b)
[TTyWorld] :: TTy t -> TTy (World t)
infixr 0 :->:
pattern TTyBool :: TTy Bool
pattern TTyInt :: TTy Integer
pattern TTyFloat :: TTy Double
pattern TTyCell :: TTy CellVal
-- | Check that a particular type has an Op instance, and run a
-- computation in a context provided with an Op constraint. The
-- other checkX functions are similar.
checkEq :: Has (Throw CheckErr) sig m => TTy ty -> ((Eq ty, NotFun ty) => m a) -> m a
checkOrd :: Has (Throw CheckErr) sig m => TTy ty -> ((Ord ty, NotFun ty) => m a) -> m a
checkNum :: Has (Throw CheckErr) sig m => TTy ty -> ((Num ty, NotFun ty) => m a) -> m a
checkIntegral :: Has (Throw CheckErr) sig m => TTy ty -> ((Integral ty, NotFun ty) => m a) -> m a
checkEmpty :: Has (Throw CheckErr) sig m => TTy ty -> ((Empty ty, NotFun ty) => m a) -> m a
checkOver :: Has (Throw CheckErr) sig m => TTy ty -> ((Over ty, NotFun ty) => m a) -> m a
-- | Wrap up a type-indexed thing to hide the type index, but package it
-- with a TTy which we can pattern-match on to recover the type
-- later.
data Some :: (Type -> Type) -> Type
[Some] :: TTy α -> t α -> Some t
mapSome :: (forall α. s α -> t α) -> Some s -> Some t
type SomeTy = Some (Const ())
pattern SomeTy :: TTy α -> SomeTy
type WorldMap = Map Text (Some (TTerm '[]))
-- | Type contexts, indexed by a type-level list of types of all the
-- variables in the context.
data Ctx :: [Type] -> Type
[CNil] :: Ctx '[]
[CCons] :: Text -> TTy ty -> Ctx g -> Ctx (ty : g)
-- | Look up a variable name in the context, returning a type-indexed de
-- Bruijn index.
lookup :: Has (Throw CheckErr) sig m => Text -> Ctx g -> m (Some (Idx g))
-- | Check that a term has a given type, and if so, return a corresponding
-- elaborated and type-indexed term. Note that this also deals with
-- subtyping: for example, if we check that the term 3 has type
-- World Int, we will get back a suitably lifted value
-- (i.e. const 3).
check :: (Has (Throw CheckErr) sig m, Has (Reader EntityMap) sig m, Has (Reader WorldMap) sig m) => Ctx g -> TTy t -> WExp -> m (TTerm g t)
-- | Get the underlying base type of a term which either has a base type or
-- a World type.
getBaseType :: Some (TTerm g) -> SomeTy
-- | Apply one term to another term, automatically handling promotion and
-- lifting, via the fact that World is Applicative. That is, (1) if a
-- term of type T is used where a term of type World T is expected, it
-- will automatically be promoted (by an application of const); (2) if a
-- function of type (T1 -> T2 -> ... -> Tn) is applied to any
-- arguments of type (World Ti), the function will be lifted to (World T1
-- -> World T2 -> ... -> World Tn).
apply :: Has (Throw CheckErr) sig m => Some (TTerm g) -> Some (TTerm g) -> m (Some (TTerm g))
applyTo :: Has (Throw CheckErr) sig m => Some (TTerm g) -> Some (TTerm g) -> m (Some (TTerm g))
-- | Infer the type of an operator: turn a raw operator into a type-indexed
-- constant. However, some operators are polymorphic, so we also provide
-- a list of type arguments. For example, the type of the negation
-- operator can be either (Int -> Int) or (Float -> Float) so we
-- provide it as an argument.
--
-- Currently, all operators take at most one type argument, so (Maybe
-- SomeTy) might seem more appropriate than [SomeTy], but that is just a
-- coincidence; in general one can easily imagine operators that are
-- polymorphic in more than one type variable, and we may wish to add
-- such in the future.
inferOp :: Has (Throw CheckErr) sig m => [SomeTy] -> Op -> m (Some (TTerm g))
-- | Given a raw operator and the terms the operator is applied to, select
-- which types should be supplied as the type arguments to the operator.
-- For example, for an operator like + we can just select the
-- type of its first argument; for an operator like if, we must
-- select the type of its second argument, since if : Bool -> a
-- -> a -> a. In all cases we must also select the underlying
-- base type in case the argument has a World type. For example
-- if + is applied to an argument of type World Int we
-- still want to give + the type Int -> Int ->
-- Int. It can be lifted to have type World Int -> World Int
-- -> World Int but that will be taken care of by application,
-- which will insert the right combinators to do the lifting.
typeArgsFor :: Op -> [Some (TTerm g)] -> [SomeTy]
-- | Typecheck the application of an operator to some terms, returning a
-- typed, elaborated version of the application.
applyOp :: (Has (Throw CheckErr) sig m, Has (Reader EntityMap) sig m, Has (Reader WorldMap) sig m) => Ctx g -> Op -> [WExp] -> m (Some (TTerm g))
-- | Infer the type of a term, and elaborate along the way.
infer :: forall sig m g. (Has (Throw CheckErr) sig m, Has (Reader EntityMap) sig m, Has (Reader WorldMap) sig m) => Ctx g -> WExp -> m (Some (TTerm g))
-- | Try to resolve a RawCellVal---containing only Text names
-- for terrain, entities, and robots---into a real CellVal with
-- references to actual terrain, entities, and robots.
resolveCell :: (Has (Throw CheckErr) sig m, Has (Reader EntityMap) sig m) => RawCellVal -> m CellVal
-- | Try to resolve one cell item name into an actual item (terrain,
-- entity, robot, etc.).
resolveCellItem :: forall sig m. (Has (Throw CheckErr) sig m, Has (Reader EntityMap) sig m) => (Maybe CellTag, Text) -> m CellVal
-- | Infer the type of a let expression, and elaborate into a series of
-- lambda applications.
inferLet :: (Has (Throw CheckErr) sig m, Has (Reader EntityMap) sig m, Has (Reader WorldMap) sig m) => Ctx g -> [(Var, WExp)] -> WExp -> m (Some (TTerm g))
-- | Infer the type of an overlay expression, and elaborate into a
-- chain of <> (over) operations.
inferOverlay :: (Has (Throw CheckErr) sig m, Has (Reader EntityMap) sig m, Has (Reader WorldMap) sig m) => Ctx g -> NonEmpty WExp -> m (Some (TTerm g))
instance GHC.Show.Show (Swarm.Game.World.Typecheck.Const ty)
instance GHC.Show.Show (Swarm.Game.World.Typecheck.Idx g ty)
instance GHC.Show.Show (Swarm.Game.World.Typecheck.TTerm g ty)
instance GHC.Show.Show Swarm.Game.World.Typecheck.CheckErr
instance GHC.Show.Show (Swarm.Game.World.Typecheck.Base ty)
instance GHC.Show.Show (Swarm.Game.World.Typecheck.TTy ty)
instance (forall α. GHC.Show.Show (t α)) => GHC.Show.Show (Swarm.Game.World.Typecheck.Some t)
instance Swarm.Language.Pretty.PrettyPrec Swarm.Game.World.Typecheck.CheckErr
instance Data.Type.Equality.TestEquality Swarm.Game.World.Typecheck.TTy
instance Swarm.Language.Pretty.PrettyPrec (Swarm.Game.World.Typecheck.TTy ty)
instance Data.Type.Equality.TestEquality Swarm.Game.World.Typecheck.Base
instance Swarm.Language.Pretty.PrettyPrec (Swarm.Game.World.Typecheck.Base α)
instance Swarm.Game.World.Typecheck.Applicable (Swarm.Game.World.Typecheck.TTerm g)
instance Swarm.Game.World.Typecheck.HasConst (Swarm.Game.World.Typecheck.TTerm g)
instance Swarm.Language.Pretty.PrettyPrec (Swarm.Game.World.Typecheck.TTerm g α)
instance Swarm.Language.Pretty.PrettyPrec (Swarm.Game.World.Typecheck.Const α)
instance Swarm.Game.World.Typecheck.Over GHC.Types.Bool
instance Swarm.Game.World.Typecheck.Over GHC.Num.Integer.Integer
instance Swarm.Game.World.Typecheck.Over GHC.Types.Double
instance Swarm.Game.World.Typecheck.Over Swarm.Game.World.Syntax.CellVal
instance Swarm.Game.World.Typecheck.Empty Swarm.Game.World.Syntax.CellVal
-- | Explicitly type-preserving bracket abstraction, a la Oleg Kiselyov.
-- Turn elaborated, type-indexed terms into variableless, type-indexed
-- terms with only constants and application.
--
-- For more information, see:
--
--
-- https://byorgey.wordpress.com/2023/07/13/compiling-to-intrinsically-typed-combinators/
module Swarm.Game.World.Abstract
-- | Closed, fully abstracted terms. All computation is represented by
-- combinators. This is the ultimate target for the bracket abstraction
-- operation.
data BTerm :: Type -> Type
[BApp] :: BTerm (a -> b) -> BTerm a -> BTerm b
[BConst] :: Const a -> BTerm a
-- | These explicitly open terms are an intermediate stage in the bracket
-- abstraction algorithm, i.e. they represent terms which have
-- been only partially abstracted.
data OTerm :: [Type] -> Type -> Type
[E] :: BTerm a -> OTerm g a
[V] :: OTerm (a : g) a
[N] :: OTerm g (a -> b) -> OTerm (a : g) b
[W] :: OTerm g b -> OTerm (a : g) b
-- | Bracket abstraction: convert the TTerm to an OTerm, then
-- project out the embedded BTerm. GHC can see this is total since
-- E is the only constructor that can produce an OTerm with
-- an empty environment.
bracket :: TTerm '[] a -> BTerm a
-- | Type-preserving conversion from TTerm to OTerm
-- (conv + the Applicable instance). Taken directly from
-- Kiselyov.
conv :: TTerm g a -> OTerm g a
instance GHC.Show.Show (Swarm.Game.World.Abstract.BTerm t)
instance Swarm.Game.World.Typecheck.HasConst (Swarm.Game.World.Abstract.OTerm g)
instance Swarm.Game.World.Typecheck.Applicable (Swarm.Game.World.Abstract.OTerm g)
instance Swarm.Game.World.Typecheck.Applicable Swarm.Game.World.Abstract.BTerm
instance Swarm.Game.World.Typecheck.HasConst Swarm.Game.World.Abstract.BTerm
-- | Parser for the Swarm world description DSL.
module Swarm.Game.World.Parse
type Parser = Parsec Void Text
type ParserError = ParseErrorBundle Text Void
sepByNE :: MonadPlus m => m a -> m sep -> m (NonEmpty a)
reservedWords :: [Text]
-- | Skip spaces and comments.
sc :: Parser ()
-- | In general, we follow the convention that every token parser assumes
-- no leading whitespace and consumes all trailing whitespace.
-- Concretely, we achieve this by wrapping every token parser using
-- lexeme.
lexeme :: Parser a -> Parser a
-- | A lexeme consisting of a literal string.
symbol :: Text -> Parser Text
operatorChar :: Parser Char
operator :: Text -> Parser Text
-- | A positive integer literal token.
integerOrFloat :: Parser (Either Integer Double)
-- | Parse a case-insensitive reserved word, making sure it is not a prefix
-- of a longer variable name, and allowing the parser to backtrack if it
-- fails.
reserved :: Text -> Parser ()
-- | Parse an identifier, i.e. any non-reserved string containing
-- alphanumeric characters and underscores and not starting with a
-- number.
identifier :: Parser Var
brackets :: Parser a -> Parser a
parens :: Parser a -> Parser a
braces :: Parser a -> Parser a
comma :: Parser ()
parseWExpAtom :: Parser WExp
parseWExp :: Parser WExp
parseCell :: Parser WExp
parseCellItem :: Parser (Maybe CellTag, Text)
parseCellTag :: Parser CellTag
parseName :: Parser Text
parseIf :: Parser WExp
parsePerlin :: Parser WExp
parseAbs :: Parser WExp
parseLet :: Parser WExp
parseOverlay :: Parser WExp
parseMask :: Parser WExp
parseImport :: Parser WExp
runParser :: Parser a -> Text -> Either ParserError a
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.World.Syntax.WExp
-- | Loading world descriptions from `worlds/*.world`.
module Swarm.Game.World.Load
-- | Load and typecheck all world descriptions from `worlds/*.world`. Emit
-- a warning for each one which fails to parse or typecheck.
loadWorlds :: (Has (Accum (Seq SystemFailure)) sig m, Has (Lift IO) sig m) => EntityMap -> m WorldMap
-- | Load a file containing a world DSL term, throwing an exception if it
-- fails to parse or typecheck.
loadWorld :: Has (Throw SystemFailure) sig m => FilePath -> EntityMap -> (FilePath, String) -> m (Text, Some (TTerm '[]))
-- | Strip a leading directory from a FilePath.
stripDir :: FilePath -> FilePath -> FilePath
-- | Utilities for working with procedurally generated worlds.
module Swarm.Game.World.Gen
type Seed = Int
-- | Extract a list of all entities mentioned in a given world DSL term.
extractEntities :: TTerm g a -> Set Entity
-- | Offset a world by a multiple of the skip in such a way that
-- it satisfies the given predicate.
findOffset :: Integer -> ((Coords -> (t, Erasable (Last e))) -> Bool) -> WorldFun t e -> WorldFun t e
-- | Offset the world so the base starts in a 32x32 patch containing at
-- least one of each of a list of required entities.
findPatchWith :: [Text] -> WorldFun t Entity -> WorldFun t Entity
-- | Offset the world so the base starts on empty spot next to tree and
-- grass.
findTreeOffset :: WorldFun t Entity -> WorldFun t Entity
-- | Offset the world so the base starts in a good patch (near necessary
-- items), next to a tree.
findGoodOrigin :: WorldFun t Entity -> WorldFun t Entity
-- | Interpreter for the Swarm world description DSL.
module Swarm.Game.World.Interpret
-- | Interpret an abstracted term into the host language.
interpBTerm :: Seed -> BTerm a -> a
-- | Interpret a constant into the host language.
interpConst :: Seed -> Const a -> a
-- | Interprect a reflection.
interpReflect :: Axis -> Coords -> Coords
-- | Interpret a rotation.
interpRot :: Rot -> Coords -> Coords
-- | Evaluation for the Swarm world description DSL.
module Swarm.Game.World.Eval
-- | Run a typechecked world description DSL term to produce a
-- WorldFun.
runWorld :: TTerm '[] (World CellVal) -> Seed -> WorldFun TerrainType Entity
-- | Compiling abstracted combinator expressions (BTerm) to native
-- Haskell terms. This can supposedly be more efficient than directly
-- interpreting BTerms, but some benchmarking is probably needed
-- to decide whether we want this or not.
--
-- For more info, see:
--
--
-- https://byorgey.wordpress.com/2023/07/13/compiling-to-intrinsically-typed-combinators/
module Swarm.Game.World.Compile
data CTerm a
[CFun] :: (CTerm a -> CTerm b) -> CTerm (a -> b)
[CConst] :: NotFun a => a -> CTerm a
compile :: Seed -> BTerm a -> CTerm a
compileConst :: Seed -> Const a -> CTerm a
unary :: (NotFun a, NotFun b) => (a -> b) -> CTerm (a -> b)
binary :: (NotFun a, NotFun b, NotFun c) => (a -> b -> c) -> CTerm (a -> b -> c)
compileMask :: (NotFun a, Empty a) => CTerm (World Bool -> World a -> World a)
compileHash :: CTerm (Coords -> Integer)
compilePerlin :: CTerm (Integer -> Integer -> Double -> Double -> World Double)
compileReflect :: Axis -> CTerm (World a -> World a)
compileRot :: Rot -> CTerm (World a -> World a)
type family NoFunParams a :: Constraint
-- | Interpret a compiled term into the host language.
runCTerm :: NoFunParams a => CTerm a -> a
instance Swarm.Game.World.Typecheck.Applicable Swarm.Game.World.Compile.CTerm
-- | Conversions from native Haskell values to values in the swarm
-- language.
--
-- SPDX-License-Identifier: BSD-3-Clause
module Swarm.Game.Value
type VRect = Value
pattern VRect :: Integer -> Integer -> Integer -> Integer -> VRect
-- | Conversion from native Haskell types to their swarm-lang equivalents,
-- useful for implementing swarm commands in Haskell.
class Valuable a
asValue :: Valuable a => a -> Value
instance Swarm.Game.Value.Valuable GHC.Int.Int32
instance Swarm.Game.Value.Valuable GHC.Types.Int
instance Swarm.Game.Value.Valuable a => Swarm.Game.Value.Valuable (Linear.V2.V2 a)
instance (Swarm.Game.Value.Valuable a, Swarm.Game.Value.Valuable b) => Swarm.Game.Value.Valuable (a, b)
instance Swarm.Game.Value.Valuable Swarm.Game.Location.Location
instance Swarm.Game.Value.Valuable Swarm.Game.Entity.Entity
instance Swarm.Game.Value.Valuable Swarm.Game.Robot.Robot
instance Swarm.Game.Value.Valuable a => Swarm.Game.Value.Valuable (GHC.Maybe.Maybe a)
instance (Swarm.Game.Value.Valuable a, Swarm.Game.Value.Valuable b) => Swarm.Game.Value.Valuable (Data.Either.Either a b)
module Swarm.Game.Scenario.RobotLookup
newtype RobotName
RobotName :: Text -> RobotName
-- | A robot template paired with its definition's index within the
-- Scenario file
type IndexedTRobot = (Int, TRobot)
-- | A map from names to robots, used to look up robots in scenario
-- descriptions.
type RobotMap = Map RobotName IndexedTRobot
-- | Create a RobotMap from a list of robot templates.
buildRobotMap :: [TRobot] -> RobotMap
-- | Look up a thing by name, throwing a parse error if it is not found.
getThing :: Show k => Text -> (k -> m -> Maybe a) -> k -> ParserE m a
-- | Look up an entity by name in an EntityMap, throwing a parse
-- error if it is not found.
getEntity :: Text -> ParserE EntityMap Entity
-- | Look up a robot by name in a RobotMap, throwing a parse error
-- if it is not found.
getRobot :: RobotName -> ParserE RobotMap IndexedTRobot
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.RobotLookup.RobotName
instance GHC.Generics.Generic Swarm.Game.Scenario.RobotLookup.RobotName
instance GHC.Classes.Ord Swarm.Game.Scenario.RobotLookup.RobotName
instance GHC.Classes.Eq Swarm.Game.Scenario.RobotLookup.RobotName
instance GHC.Show.Show Swarm.Game.Scenario.RobotLookup.RobotName
module Swarm.Game.Scenario.Topography.Cell
-- | A single cell in a world map, which contains a terrain value, and
-- optionally an entity and robot. It is parameterized on the Entity type
-- to facilitate less stateful versions of the Entity type in rendering
-- scenario data.
data PCell e
Cell :: TerrainType -> Erasable e -> [IndexedTRobot] -> PCell e
[cellTerrain] :: PCell e -> TerrainType
[cellEntity] :: PCell e -> Erasable e
[cellRobots] :: PCell e -> [IndexedTRobot]
-- | A single cell in a world map, which contains a terrain value, and
-- optionally an entity and robot.
type Cell = PCell Entity
-- | Supplements a cell with waypoint information
data AugmentedCell e
AugmentedCell :: Maybe WaypointConfig -> PCell e -> AugmentedCell e
[waypointCfg] :: AugmentedCell e -> Maybe WaypointConfig
[standardCell] :: AugmentedCell e -> PCell e
-- | Stateless cells used for the World Editor. These cells contain the
-- bare minimum display information for rendering.
type CellPaintDisplay = PCell EntityFacade
instance GHC.Show.Show e => GHC.Show.Show (Swarm.Game.Scenario.Topography.Cell.PCell e)
instance GHC.Classes.Eq e => GHC.Classes.Eq (Swarm.Game.Scenario.Topography.Cell.PCell e)
instance GHC.Show.Show e => GHC.Show.Show (Swarm.Game.Scenario.Topography.Cell.AugmentedCell e)
instance GHC.Classes.Eq e => GHC.Classes.Eq (Swarm.Game.Scenario.Topography.Cell.AugmentedCell e)
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Topography.Cell.CellPaintDisplay
instance Swarm.Util.Yaml.FromJSONE (Swarm.Game.Entity.EntityMap, Swarm.Game.Scenario.RobotLookup.RobotMap) (Swarm.Game.Scenario.Topography.Cell.AugmentedCell Swarm.Game.Entity.Entity)
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Topography.Cell.Cell
instance Swarm.Util.Yaml.FromJSONE (Swarm.Game.Entity.EntityMap, Swarm.Game.Scenario.RobotLookup.RobotMap) Swarm.Game.Scenario.Topography.Cell.Cell
module Swarm.Game.Scenario.Topography.WorldPalette
-- | A world palette maps characters to PCell values.
newtype WorldPalette e
WorldPalette :: KeyMap (AugmentedCell e) -> WorldPalette e
[unPalette] :: WorldPalette e -> KeyMap (AugmentedCell e)
type TerrainWith a = (TerrainType, Erasable a)
cellToTerrainPair :: CellPaintDisplay -> TerrainWith EntityFacade
toCellPaintDisplay :: Cell -> CellPaintDisplay
toKey :: TerrainWith EntityFacade -> TerrainWith EntityName
-- | We want to identify all of the unique (terrain, entity facade) pairs.
-- However, EntityFacade includes a Display record, which
-- contains more fields than desirable for use as a unique key.
-- Therefore, we extract just the entity name for use in a (terrain,
-- entity name) key, and couple it with the original (terrain, entity
-- facade) pair in a Map.
getUniqueTerrainFacadePairs :: [[CellPaintDisplay]] -> Map (TerrainWith EntityName) (TerrainWith EntityFacade)
constructPalette :: [(Char, TerrainWith EntityFacade)] -> KeyMap CellPaintDisplay
constructWorldMap :: [(Char, TerrainWith EntityFacade)] -> [[CellPaintDisplay]] -> Text
-- | All alphanumeric characters. These are used as supplemental map
-- placeholders in case a pre-existing display character is not available
-- to re-use.
genericCharacterPool :: Set Char
-- | Note that display characters are not unique across different entities!
-- However, the palette KeyMap as a conveyance serves to dedupe them.
prepForJson :: WorldPalette EntityFacade -> [[CellPaintDisplay]] -> (Text, KeyMap CellPaintDisplay)
instance GHC.Show.Show e => GHC.Show.Show (Swarm.Game.Scenario.Topography.WorldPalette.WorldPalette e)
instance GHC.Classes.Eq e => GHC.Classes.Eq (Swarm.Game.Scenario.Topography.WorldPalette.WorldPalette e)
instance Swarm.Util.Yaml.FromJSONE (Swarm.Game.Entity.EntityMap, Swarm.Game.Scenario.RobotLookup.RobotMap) (Swarm.Game.Scenario.Topography.WorldPalette.WorldPalette Swarm.Game.Entity.Entity)
module Swarm.TUI.Editor.Model
data BoundsSelectionStep
UpperLeftPending :: BoundsSelectionStep
-- | Stores the *world coords* of the upper-left click
LowerRightPending :: Cosmic Coords -> BoundsSelectionStep
SelectionComplete :: BoundsSelectionStep
data EntityPaint
Facade :: EntityFacade -> EntityPaint
Ref :: Entity -> EntityPaint
getDisplay :: EntityPaint -> Display
toFacade :: EntityPaint -> EntityFacade
getEntityName :: EntityFacade -> EntityName
data MapEditingBounds
MapEditingBounds :: Maybe (Cosmic BoundsRectangle) -> TimeSpec -> BoundsSelectionStep -> MapEditingBounds
-- | Upper-left and lower-right coordinates of the map to be saved.
[_boundsRect] :: MapEditingBounds -> Maybe (Cosmic BoundsRectangle)
[_boundsPersistDisplayUntil] :: MapEditingBounds -> TimeSpec
[_boundsSelectionStep] :: MapEditingBounds -> BoundsSelectionStep
boundsSelectionStep :: Lens' MapEditingBounds BoundsSelectionStep
boundsRect :: Lens' MapEditingBounds (Maybe (Cosmic BoundsRectangle))
boundsPersistDisplayUntil :: Lens' MapEditingBounds TimeSpec
data WorldEditor n
WorldEditor :: Bool -> List n TerrainType -> List n EntityFacade -> Map Coords (TerrainWith EntityFacade) -> MapEditingBounds -> FocusRing n -> FilePath -> Maybe String -> WorldEditor n
[_isWorldEditorEnabled] :: WorldEditor n -> Bool
[_terrainList] :: WorldEditor n -> List n TerrainType
-- | This field has deferred initialization; it gets populated when a game
-- is initialized.
[_entityPaintList] :: WorldEditor n -> List n EntityFacade
[_paintedTerrain] :: WorldEditor n -> Map Coords (TerrainWith EntityFacade)
[_editingBounds] :: WorldEditor n -> MapEditingBounds
[_editorFocusRing] :: WorldEditor n -> FocusRing n
[_outputFilePath] :: WorldEditor n -> FilePath
[_lastWorldEditorMessage] :: WorldEditor n -> Maybe String
terrainList :: forall n_a7o6s. Lens' (WorldEditor n_a7o6s) (List n_a7o6s TerrainType)
paintedTerrain :: forall n_a7o6s. Lens' (WorldEditor n_a7o6s) (Map Coords (TerrainWith EntityFacade))
outputFilePath :: forall n_a7o6s. Lens' (WorldEditor n_a7o6s) FilePath
lastWorldEditorMessage :: forall n_a7o6s. Lens' (WorldEditor n_a7o6s) (Maybe String)
isWorldEditorEnabled :: forall n_a7o6s. Lens' (WorldEditor n_a7o6s) Bool
entityPaintList :: forall n_a7o6s. Lens' (WorldEditor n_a7o6s) (List n_a7o6s EntityFacade)
editorFocusRing :: forall n_a7o6s. Lens' (WorldEditor n_a7o6s) (FocusRing n_a7o6s)
editingBounds :: forall n_a7o6s. Lens' (WorldEditor n_a7o6s) MapEditingBounds
initialWorldEditor :: TimeSpec -> WorldEditor Name
instance GHC.Classes.Eq Swarm.TUI.Editor.Model.EntityPaint
module Swarm.Game.Scenario.Topography.Structure
data NamedStructure c
NamedStructure :: StructureName -> PStructure c -> NamedStructure c
[name] :: NamedStructure c -> StructureName
[structure] :: NamedStructure c -> PStructure c
type InheritedStructureDefs = [NamedStructure (Maybe (PCell Entity))]
data PStructure c
Structure :: [[c]] -> [NamedStructure c] -> [Placement] -> [Waypoint] -> PStructure c
[area] :: PStructure c -> [[c]]
-- | structure definitions from parents shall be accessible by children
[structures] :: PStructure c -> [NamedStructure c]
-- | earlier placements will be overlaid on top of later placements in the
-- YAML file
[placements] :: PStructure c -> [Placement]
[waypoints] :: PStructure c -> [Waypoint]
data MergedStructure c
MergedStructure :: [[c]] -> [Originated Waypoint] -> MergedStructure c
-- | Destructively overlays one direct child structure upon the input
-- structure. However, the child structure is assembled recursively.
overlaySingleStructure :: Map StructureName (PStructure (Maybe a)) -> (Placement, PStructure (Maybe a)) -> MergedStructure (Maybe a) -> MergedStructure (Maybe a)
-- | Overlays all of the "child placements", such that the children
-- encountered earlier in the YAML file supersede the later ones (due to
-- use of "foldr" instead of "foldl").
mergeStructures :: Map StructureName (PStructure (Maybe a)) -> Maybe Placement -> PStructure (Maybe a) -> MergedStructure (Maybe a)
-- | Paint a world map using a WorldPalette, turning it from
-- a raw string into a nested list of PCell values by looking up
-- each character in the palette, failing if any character in the raw map
-- is not contained in the palette.
paintMap :: MonadFail m => Maybe Char -> WorldPalette e -> Text -> m ([[Maybe (PCell e)]], [Waypoint])
readMap :: Applicative f => (Char -> f b) -> Text -> f [[b]]
instance GHC.Show.Show c => GHC.Show.Show (Swarm.Game.Scenario.Topography.Structure.NamedStructure c)
instance GHC.Classes.Eq c => GHC.Classes.Eq (Swarm.Game.Scenario.Topography.Structure.NamedStructure c)
instance GHC.Show.Show c => GHC.Show.Show (Swarm.Game.Scenario.Topography.Structure.PStructure c)
instance GHC.Classes.Eq c => GHC.Classes.Eq (Swarm.Game.Scenario.Topography.Structure.PStructure c)
instance Swarm.Util.Yaml.FromJSONE (Swarm.Game.Entity.EntityMap, Swarm.Game.Scenario.RobotLookup.RobotMap) (Swarm.Game.Scenario.Topography.Structure.NamedStructure (GHC.Maybe.Maybe (Swarm.Game.Scenario.Topography.Cell.PCell Swarm.Game.Entity.Entity)))
instance Swarm.Util.Yaml.FromJSONE (Swarm.Game.Entity.EntityMap, Swarm.Game.Scenario.RobotLookup.RobotMap) (Swarm.Game.Scenario.Topography.Structure.PStructure (GHC.Maybe.Maybe (Swarm.Game.Scenario.Topography.Cell.PCell Swarm.Game.Entity.Entity)))
module Swarm.Game.Scenario.Topography.WorldDescription
-- | A description of a world parsed from a YAML file. This type is
-- parameterized to accommodate Cells that utilize a less stateful Entity
-- type.
data PWorldDescription e
WorldDescription :: Bool -> Bool -> WorldPalette e -> Location -> [[PCell e]] -> Navigation Identity WaypointName -> SubworldName -> Maybe (TTerm '[] (World CellVal)) -> PWorldDescription e
[offsetOrigin] :: PWorldDescription e -> Bool
[scrollable] :: PWorldDescription e -> Bool
[palette] :: PWorldDescription e -> WorldPalette e
[ul] :: PWorldDescription e -> Location
[area] :: PWorldDescription e -> [[PCell e]]
[navigation] :: PWorldDescription e -> Navigation Identity WaypointName
[worldName] :: PWorldDescription e -> SubworldName
[worldProg] :: PWorldDescription e -> Maybe (TTerm '[] (World CellVal))
type WorldDescription = PWorldDescription Entity
-- | A pared-down (stateless) version of WorldDescription just for
-- the purpose of rendering a Scenario file
type WorldDescriptionPaint = PWorldDescription EntityFacade
instance GHC.Show.Show e => GHC.Show.Show (Swarm.Game.Scenario.Topography.WorldDescription.PWorldDescription e)
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Topography.WorldDescription.WorldDescriptionPaint
instance Swarm.Util.Yaml.FromJSONE (Swarm.Game.World.Typecheck.WorldMap, Swarm.Game.Scenario.Topography.Structure.InheritedStructureDefs, Swarm.Game.Entity.EntityMap, Swarm.Game.Scenario.RobotLookup.RobotMap) Swarm.Game.Scenario.Topography.WorldDescription.WorldDescription
module Swarm.TUI.Editor.Json
data SkeletonScenario
SkeletonScenario :: Int -> Text -> Text -> Bool -> [Entity] -> WorldDescriptionPaint -> [String] -> SkeletonScenario
[version] :: SkeletonScenario -> Int
[name] :: SkeletonScenario -> Text
[description] :: SkeletonScenario -> Text
[creative] :: SkeletonScenario -> Bool
[entities] :: SkeletonScenario -> [Entity]
[world] :: SkeletonScenario -> WorldDescriptionPaint
[robots] :: SkeletonScenario -> [String]
instance GHC.Generics.Generic Swarm.TUI.Editor.Json.SkeletonScenario
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.TUI.Editor.Json.SkeletonScenario
-- | Scenarios are standalone worlds with specific starting and winning
-- conditions, which can be used both for building interactive tutorials
-- and for standalone puzzles and scenarios.
module Swarm.Game.Scenario
-- | A single cell in a world map, which contains a terrain value, and
-- optionally an entity and robot. It is parameterized on the Entity type
-- to facilitate less stateful versions of the Entity type in rendering
-- scenario data.
data PCell e
Cell :: TerrainType -> Erasable e -> [IndexedTRobot] -> PCell e
[cellTerrain] :: PCell e -> TerrainType
[cellEntity] :: PCell e -> Erasable e
[cellRobots] :: PCell e -> [IndexedTRobot]
-- | A single cell in a world map, which contains a terrain value, and
-- optionally an entity and robot.
type Cell = PCell Entity
-- | A description of a world parsed from a YAML file. This type is
-- parameterized to accommodate Cells that utilize a less stateful Entity
-- type.
data PWorldDescription e
WorldDescription :: Bool -> Bool -> WorldPalette e -> Location -> [[PCell e]] -> Navigation Identity WaypointName -> SubworldName -> Maybe (TTerm '[] (World CellVal)) -> PWorldDescription e
[offsetOrigin] :: PWorldDescription e -> Bool
[scrollable] :: PWorldDescription e -> Bool
[palette] :: PWorldDescription e -> WorldPalette e
[ul] :: PWorldDescription e -> Location
[area] :: PWorldDescription e -> [[PCell e]]
[navigation] :: PWorldDescription e -> Navigation Identity WaypointName
[worldName] :: PWorldDescription e -> SubworldName
[worldProg] :: PWorldDescription e -> Maybe (TTerm '[] (World CellVal))
type WorldDescription = PWorldDescription Entity
-- | A robot template paired with its definition's index within the
-- Scenario file
type IndexedTRobot = (Int, TRobot)
-- | A Scenario contains all the information to describe a scenario.
data Scenario
Scenario :: Int -> Text -> Maybe Text -> Text -> Bool -> Maybe Int -> [CustomAttr] -> EntityMap -> [Recipe Entity] -> [Text] -> NonEmpty WorldDescription -> Navigation (Map SubworldName) Location -> [TRobot] -> [Objective] -> Maybe ProcessedTerm -> Maybe Int -> Scenario
[_scenarioVersion] :: Scenario -> Int
[_scenarioName] :: Scenario -> Text
[_scenarioAuthor] :: Scenario -> Maybe Text
[_scenarioDescription] :: Scenario -> Text
[_scenarioCreative] :: Scenario -> Bool
[_scenarioSeed] :: Scenario -> Maybe Int
[_scenarioAttrs] :: Scenario -> [CustomAttr]
[_scenarioEntities] :: Scenario -> EntityMap
[_scenarioRecipes] :: Scenario -> [Recipe Entity]
[_scenarioKnown] :: Scenario -> [Text]
[_scenarioWorlds] :: Scenario -> NonEmpty WorldDescription
[_scenarioNavigation] :: Scenario -> Navigation (Map SubworldName) Location
[_scenarioRobots] :: Scenario -> [TRobot]
[_scenarioObjectives] :: Scenario -> [Objective]
[_scenarioSolution] :: Scenario -> Maybe ProcessedTerm
[_scenarioStepsPerTick] :: Scenario -> Maybe Int
-- | The version number of the scenario schema. Currently, this should
-- always be 1, but it is ignored. In the future, this may be used to
-- convert older formats to newer ones, or simply to print a nice error
-- message when we can't read an older format.
scenarioVersion :: Lens' Scenario Int
-- | The name of the scenario.
scenarioName :: Lens' Scenario Text
-- | The author of the scenario.
scenarioAuthor :: Lens' Scenario (Maybe Text)
-- | A high-level description of the scenario, shown e.g. in the
-- menu.
scenarioDescription :: Lens' Scenario Text
-- | Whether the scenario should start in creative mode.
scenarioCreative :: Lens' Scenario Bool
-- | The seed used for the random number generator. If Nothing,
-- use a random seed / prompt the user for the seed.
scenarioSeed :: Lens' Scenario (Maybe Int)
-- | Custom attributes defined in the scenario.
scenarioAttrs :: Lens' Scenario [CustomAttr]
-- | Any custom entities used for this scenario.
scenarioEntities :: Lens' Scenario EntityMap
-- | Any custom recipes used in this scenario.
scenarioRecipes :: Lens' Scenario [Recipe Entity]
-- | List of entities that should be considered "known", so robots do not
-- have to scan them.
scenarioKnown :: Lens' Scenario [Text]
-- | The subworlds of the scenario. The "root" subworld shall always be at
-- the head of the list, by construction.
scenarioWorlds :: Lens' Scenario (NonEmpty WorldDescription)
-- | Waypoints and inter-world portals
scenarioNavigation :: Lens' Scenario (Navigation (Map SubworldName) Location)
-- | The starting robots for the scenario. Note this should include the
-- base.
scenarioRobots :: Lens' Scenario [TRobot]
-- | A sequence of objectives for the scenario (if any).
scenarioObjectives :: Lens' Scenario [Objective]
-- | An optional solution of the scenario, expressed as a program of type
-- cmd a. This is useful for automated testing of the win
-- condition.
scenarioSolution :: Lens' Scenario (Maybe ProcessedTerm)
-- | Optionally, specify the maximum number of steps each robot may take
-- during a single tick.
scenarioStepsPerTick :: Lens' Scenario (Maybe Int)
-- | Load a scenario with a given name from disk, given an entity map to
-- use. This function is used if a specific scenario is requested on the
-- command line.
loadScenario :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => FilePath -> EntityMap -> WorldMap -> m (Scenario, FilePath)
-- | Load a scenario from a file.
loadScenarioFile :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => EntityMap -> WorldMap -> FilePath -> m Scenario
getScenarioPath :: Has (Lift IO) sig m => FilePath -> m (Maybe FilePath)
instance Swarm.Util.Yaml.FromJSONE (Swarm.Game.Entity.EntityMap, Swarm.Game.World.Typecheck.WorldMap) Swarm.Game.Scenario.Scenario
instance GHC.Show.Show Swarm.Game.Scenario.Scenario
module Swarm.TUI.Editor.Palette
makeSuggestedPalette :: Maybe Scenario -> [[CellPaintDisplay]] -> KeyMap (AugmentedCell EntityFacade)
-- | Generate a "skeleton" scenario with placeholders for certain required
-- fields
constructScenario :: Maybe Scenario -> [[CellPaintDisplay]] -> SkeletonScenario
-- | High-level status of scenario play. Representation of progress, logic
-- for updating.
module Swarm.Game.Scenario.Status
-- | These launch parameters are used in a number of ways: * Serializing
-- the seed/script path for saves * Holding parse status from form
-- fields, including Error info * Carrying fully-validated launch
-- parameters.
--
-- Type parameters are utilized to support all of these use cases.
data ParameterizableLaunchParams code f
LaunchParams :: f (Maybe Seed) -> f (Maybe code) -> ParameterizableLaunchParams code f
[seedVal] :: ParameterizableLaunchParams code f -> f (Maybe Seed)
[initialCode] :: ParameterizableLaunchParams code f -> f (Maybe code)
type SerializableLaunchParams = ParameterizableLaunchParams FilePath Identity
-- | A ScenarioStatus stores the status of a scenario along with
-- appropriate metadata: NotStarted, or Played. The
-- Played status has two sub-states: Attempted or
-- Completed.
data ScenarioStatus
NotStarted :: ScenarioStatus
Played :: SerializableLaunchParams -> ProgressMetric -> BestRecords -> ScenarioStatus
getLaunchParams :: ScenarioStatus -> SerializableLaunchParams
-- | A ScenarioInfo record stores metadata about a scenario: its
-- canonical path and status. By way of the ScenarioStatus record,
-- it stores the most recent status and best-ever status.
data ScenarioInfo
ScenarioInfo :: FilePath -> ScenarioStatus -> ScenarioInfo
[_scenarioPath] :: ScenarioInfo -> FilePath
[_scenarioStatus] :: ScenarioInfo -> ScenarioStatus
type ScenarioInfoPair = (Scenario, ScenarioInfo)
-- | The path of the scenario, relative to data/scenarios.
scenarioPath :: Lens' ScenarioInfo FilePath
-- | The status of the scenario.
scenarioStatus :: Lens' ScenarioInfo ScenarioStatus
-- | Update the current ScenarioInfo record when quitting a game.
--
-- Note that when comparing "best" times, shorter is not always better!
-- As long as the scenario is not completed (e.g. some do not have win
-- condition) we consider having fun _longer_ to be better.
updateScenarioInfoOnFinish :: CodeSizeDeterminators -> ZonedTime -> TickNumber -> Bool -> ScenarioInfo -> ScenarioInfo
instance GHC.Generics.Generic Swarm.Game.Scenario.Status.ScenarioStatus
instance GHC.Read.Read Swarm.Game.Scenario.Status.ScenarioStatus
instance GHC.Show.Show Swarm.Game.Scenario.Status.ScenarioStatus
instance GHC.Classes.Ord Swarm.Game.Scenario.Status.ScenarioStatus
instance GHC.Classes.Eq Swarm.Game.Scenario.Status.ScenarioStatus
instance GHC.Generics.Generic Swarm.Game.Scenario.Status.ScenarioInfo
instance GHC.Read.Read Swarm.Game.Scenario.Status.ScenarioInfo
instance GHC.Show.Show Swarm.Game.Scenario.Status.ScenarioInfo
instance GHC.Classes.Ord Swarm.Game.Scenario.Status.ScenarioInfo
instance GHC.Classes.Eq Swarm.Game.Scenario.Status.ScenarioInfo
instance GHC.Classes.Eq Swarm.Game.Scenario.Status.SerializableLaunchParams
instance GHC.Classes.Ord Swarm.Game.Scenario.Status.SerializableLaunchParams
instance GHC.Show.Show Swarm.Game.Scenario.Status.SerializableLaunchParams
instance GHC.Read.Read Swarm.Game.Scenario.Status.SerializableLaunchParams
instance GHC.Generics.Generic Swarm.Game.Scenario.Status.SerializableLaunchParams
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Status.SerializableLaunchParams
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Status.SerializableLaunchParams
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Status.ScenarioInfo
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Status.ScenarioInfo
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.Scenario.Status.ScenarioStatus
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.Scenario.Status.ScenarioStatus
-- | Saving and loading info about scenarios (status, path, etc.) as well
-- as loading recursive scenario collections.
module Swarm.Game.ScenarioInfo
-- | A ScenarioStatus stores the status of a scenario along with
-- appropriate metadata: NotStarted, or Played. The
-- Played status has two sub-states: Attempted or
-- Completed.
data ScenarioStatus
NotStarted :: ScenarioStatus
Played :: SerializableLaunchParams -> ProgressMetric -> BestRecords -> ScenarioStatus
_NotStarted :: Prism' ScenarioStatus ()
-- | A ScenarioInfo record stores metadata about a scenario: its
-- canonical path and status. By way of the ScenarioStatus record,
-- it stores the most recent status and best-ever status.
data ScenarioInfo
ScenarioInfo :: FilePath -> ScenarioStatus -> ScenarioInfo
[_scenarioPath] :: ScenarioInfo -> FilePath
[_scenarioStatus] :: ScenarioInfo -> ScenarioStatus
-- | The path of the scenario, relative to data/scenarios.
scenarioPath :: Lens' ScenarioInfo FilePath
-- | The status of the scenario.
scenarioStatus :: Lens' ScenarioInfo ScenarioStatus
data CodeSizeDeterminators
CodeSizeDeterminators :: Maybe ProcessedTerm -> Bool -> CodeSizeDeterminators
-- | Update the current ScenarioInfo record when quitting a game.
--
-- Note that when comparing "best" times, shorter is not always better!
-- As long as the scenario is not completed (e.g. some do not have win
-- condition) we consider having fun _longer_ to be better.
updateScenarioInfoOnFinish :: CodeSizeDeterminators -> ZonedTime -> TickNumber -> Bool -> ScenarioInfo -> ScenarioInfo
type ScenarioInfoPair = (Scenario, ScenarioInfo)
-- | A scenario collection is a tree of scenarios, keyed by name, together
-- with an optional order. Invariant: every item in the scOrder exists as
-- a key in the scMap.
data ScenarioCollection
SC :: Maybe [FilePath] -> Map FilePath ScenarioItem -> ScenarioCollection
[scOrder] :: ScenarioCollection -> Maybe [FilePath]
[scMap] :: ScenarioCollection -> Map FilePath ScenarioItem
-- | Convert a scenario collection to a list of scenario items.
scenarioCollectionToList :: ScenarioCollection -> [ScenarioItem]
flatten :: ScenarioItem -> [ScenarioInfoPair]
-- | Access and modify ScenarioItems in collection based on their path.
scenarioItemByPath :: FilePath -> Traversal' ScenarioCollection ScenarioItem
-- | Canonicalize a scenario path, making it usable as a unique key.
normalizeScenarioPath :: MonadIO m => ScenarioCollection -> FilePath -> m FilePath
-- | A scenario item is either a specific scenario, or a collection of
-- scenarios (*e.g.* the scenarios contained in a subdirectory).
data ScenarioItem
SISingle :: ScenarioInfoPair -> ScenarioItem
SICollection :: Text -> ScenarioCollection -> ScenarioItem
-- | Retrieve the name of a scenario item.
scenarioItemName :: ScenarioItem -> Text
_SISingle :: Prism' ScenarioItem ScenarioInfoPair
-- | Load all the scenarios from the scenarios data directory.
loadScenarios :: (Has (Accum (Seq SystemFailure)) sig m, Has (Lift IO) sig m) => EntityMap -> WorldMap -> m ScenarioCollection
-- | Load saved info about played scenario from XDG data directory.
loadScenarioInfo :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => FilePath -> m ScenarioInfo
-- | Save info about played scenario to XDG data directory.
saveScenarioInfo :: FilePath -> ScenarioInfo -> IO ()
instance GHC.Show.Show Swarm.Game.ScenarioInfo.ScenarioItem
instance GHC.Show.Show Swarm.Game.ScenarioInfo.ScenarioCollection
-- | Definition of the record holding all the game-related state, and
-- various related utility functions.
module Swarm.Game.State
-- | The ViewCenterRule specifies how to determine the center of the
-- world viewport.
data ViewCenterRule
-- | The view should be centered on an absolute position.
VCLocation :: Cosmic Location -> ViewCenterRule
-- | The view should be centered on a certain robot.
VCRobot :: RID -> ViewCenterRule
-- | A data type to represent the current status of the REPL.
data REPLStatus
-- | The REPL is not doing anything actively at the moment. We persist the
-- last value and its type though. INVARIANT: the Value stored here is
-- not a VResult.
REPLDone :: Maybe (Typed Value) -> REPLStatus
-- | A command entered at the REPL is currently being run. The
-- Polytype represents the type of the expression that was
-- entered. The Maybe Value starts out as Nothing and
-- gets filled in with a result once the command completes.
REPLWorking :: Typed (Maybe Value) -> REPLStatus
data WinStatus
-- | There are one or more objectives remaining that the player has not yet
-- accomplished.
Ongoing :: WinStatus
-- | The player has won. The boolean indicates whether they have already
-- been congratulated.
Won :: Bool -> WinStatus
-- | The player has completed certain "goals" that preclude (via negative
-- prerequisites) the completion of all of the required goals. The
-- boolean indicates whether they have already been informed.
Unwinnable :: Bool -> WinStatus
data WinCondition
-- | There is no winning condition.
NoWinCondition :: WinCondition
-- | NOTE: It is possible to continue to achieve "optional" objectives even
-- after the game has been won (or deemed unwinnable).
WinConditions :: WinStatus -> ObjectiveCompletion -> WinCondition
data ObjectiveCompletion
ObjectiveCompletion :: CompletionBuckets -> Set ObjectiveLabel -> ObjectiveCompletion
-- | This is the authoritative "completion status" for all objectives. Note
-- that there is a separate Set to store the completion status of
-- prerequisite objectives, which must be carefully kept in sync with
-- this. Those prerequisite objectives are required to have labels, but
-- other objectives are not. Therefore only prerequisites exist in the
-- completion map keyed by label.
[completionBuckets] :: ObjectiveCompletion -> CompletionBuckets
[completedIDs] :: ObjectiveCompletion -> Set ObjectiveLabel
_NoWinCondition :: Prism' WinCondition ()
_WinConditions :: Prism' WinCondition (WinStatus, ObjectiveCompletion)
-- | TODO: #1044 Could also add an ObjectiveFailed constructor...
newtype Announcement
ObjectiveCompleted :: Objective -> Announcement
-- | A data type to keep track of the pause mode.
data RunStatus
-- | The game is running.
Running :: RunStatus
-- | The user paused the game, and it should stay pause after visiting the
-- help.
ManualPause :: RunStatus
-- | The game got paused while visiting the help, and it should unpause
-- after returning back to the game.
AutoPause :: RunStatus
type Seed = Int
-- | Game step mode - we use the single step mode when debugging robot
-- CESK machine.
data Step
WorldTick :: Step
RobotStep :: SingleStep -> Step
-- | Type for remebering which robots will be run next in a robot step
-- mode.
--
-- Once some robots have run, we need to store RID to know which ones
-- should go next. At SBefore no robots were run yet, so it is
-- safe to transition to and from WorldTick.
--
--
-- tick
-- ┌────────────────────────────────────┐
-- │ │
-- │ step │
-- │ ┌────┐ │
-- ▼ ▼ │ │
-- ┌───────┐ step ┌───────┴───┐ step ┌────┴─────┐
-- │SBefore├──────►│SSingle RID├──────►│SAfter RID│
-- └──┬────┘ └───────────┘ └────┬─────┘
-- │ ▲ player ▲ │
-- ▼ │ switch └───────────────────┘
-- ┌────┴────┐ view RID > oldRID
-- │WorldTick│
-- └─────────┘
--
data SingleStep
-- | Run the robots from the beginning until the focused robot
-- (noninclusive).
SBefore :: SingleStep
-- | Run a single step of the focused robot.
SSingle :: RID -> SingleStep
-- | Run robots after the (previously) focused robot and finish the tick.
SAfter :: RID -> SingleStep
-- | The main record holding the state for the game itself (as distinct
-- from the UI). See the lenses below for access to its fields.
data GameState
-- | Is the user in creative mode (i.e. able to do anything without
-- restriction)?
creativeMode :: Lens' GameState Bool
-- | How to step the game - WorldTick or RobotStep for
-- debugging the CESK machine.
gameStep :: Lens' GameState Step
-- | How to determine whether the player has won.
winCondition :: Lens' GameState WinCondition
-- | How to win (if possible). This is useful for automated testing and to
-- show help to cheaters (or testers).
winSolution :: Lens' GameState (Maybe ProcessedTerm)
-- | Map of in-game achievements that were attained
gameAchievements :: Lens' GameState (Map GameplayAchievement Attainment)
-- | A queue of global announcements. Note that this is distinct from the
-- "messageQueue", which is for messages emitted by robots.
--
-- Note that we put the newest entry to the right.
announcementQueue :: Lens' GameState (Seq Announcement)
-- | The current RunStatus.
runStatus :: Lens' GameState RunStatus
-- | Whether the game is currently paused.
paused :: Getter GameState Bool
-- | All the robots that currently exist in the game, indexed by ID.
robotMap :: Lens' GameState (IntMap Robot)
-- | The names of all robots that currently exist in the game, indexed by
-- location (which we need both for e.g. the Salvage
-- command as well as for actually drawing the world). Unfortunately
-- there is no good way to automatically keep this up to date, since we
-- don't just want to completely rebuild it every time the
-- robotMap changes. Instead, we just make sure to update it every
-- time the location of a robot changes, or a robot is created or
-- destroyed. Fortunately, there are relatively few ways for these things
-- to happen.
robotsByLocation :: Lens' GameState (Map SubworldName (Map Location IntSet))
-- | Get a list of all the robots at a particular location.
robotsAtLocation :: Cosmic Location -> GameState -> [Robot]
-- | Get a list of all the robots that are "watching" by location.
robotsWatching :: Lens' GameState (Map (Cosmic Location) (Set RID))
-- | Get all the robots within a given Manhattan distance from a location.
robotsInArea :: Cosmic Location -> Int32 -> GameState -> [Robot]
-- | The base robot, if it exists.
baseRobot :: Traversal' GameState Robot
-- | The names of the robots that are currently not sleeping.
activeRobots :: Getter GameState IntSet
-- | The names of the robots that are currently sleeping, indexed by wake
-- up time. Note that this may not include all sleeping robots,
-- particularly those that are only taking a short nap (e.g. wait 1).
waitingRobots :: Getter GameState (Map TickNumber [RID])
-- | The list of available recipes.
availableRecipes :: Lens' GameState (Notifications (Recipe Entity))
-- | The list of available commands.
availableCommands :: Lens' GameState (Notifications Const)
-- | Get the notification list of messages from the point of view of
-- focused robot.
messageNotifications :: Getter GameState (Notifications LogEntry)
-- | The list of entities that have been discovered.
allDiscoveredEntities :: Lens' GameState Inventory
-- | A counter used to generate globally unique IDs.
gensym :: Lens' GameState Int
-- | The initial seed that was used for the random number generator, and
-- world generation.
seed :: Lens' GameState Seed
-- | Pseudorandom generator initialized at start.
randGen :: Lens' GameState StdGen
-- | Read-only list of words, for use in building random robot names.
adjList :: Getter GameState (Array Int Text)
-- | Read-only list of words, for use in building random robot names.
nameList :: Getter GameState (Array Int Text)
-- | Code that is run upon scenario start, before any REPL interaction.
initiallyRunCode :: Lens' GameState (Maybe ProcessedTerm)
-- | The catalog of all entities that the game knows about.
entityMap :: Lens' GameState EntityMap
-- | All recipes the game knows about, indexed by outputs.
recipesOut :: Lens' GameState (IntMap [Recipe Entity])
-- | All recipes the game knows about, indexed by inputs.
recipesIn :: Lens' GameState (IntMap [Recipe Entity])
-- | All recipes the game knows about, indexed by requirement/catalyst.
recipesReq :: Lens' GameState (IntMap [Recipe Entity])
-- | The filepath of the currently running scenario.
--
-- This is useful as an index to scenarios collection, see
-- scenarioItemByPath.
currentScenarioPath :: Lens' GameState (Maybe FilePath)
-- | The names of entities that should be considered "known", that is,
-- robots know what they are without having to scan them.
knownEntities :: Lens' GameState [Text]
-- | Includes a Map of named locations and an "Edge list" (graph)
-- that maps portal entrances to exits
worldNavigation :: Lens' GameState (Navigation (Map SubworldName) Location)
-- | The current state of the world (terrain and entities only; robots are
-- stored in the robotMap). Int is used instead of
-- TerrainType because we need to be able to store terrain values
-- in unboxed tile arrays.
multiWorld :: Lens' GameState (MultiWorld Int Entity)
-- | Whether the world map is supposed to be scrollable or not.
worldScrollable :: Lens' GameState Bool
-- | The current rule for determining the center of the world view. It
-- updates also, viewCenter and focusedRobotName to keep everything
-- synchronize.
viewCenterRule :: Lens' GameState ViewCenterRule
-- | The current center of the world view. Note that this cannot be
-- modified directly, since it is calculated automatically from the
-- viewCenterRule. To modify the view center, either set the
-- viewCenterRule, or use modifyViewCenter.
viewCenter :: Getter GameState (Cosmic Location)
-- | Whether the world view needs to be redrawn.
needsRedraw :: Lens' GameState Bool
-- | The current status of the REPL.
replStatus :: Lens' GameState REPLStatus
-- | The index of the next it{index} value
replNextValueIndex :: Lens' GameState Integer
-- | Whether the repl is currently working.
replWorking :: Getter GameState Bool
-- | Either the type of the command being executed, or of the last command
replActiveType :: Getter REPLStatus (Maybe Polytype)
-- | The currently installed input handler and hint text.
inputHandler :: Lens' GameState (Maybe (Text, Value))
-- | A queue of global messages.
--
-- Note that we put the newest entry to the right.
messageQueue :: Lens' GameState (Seq LogEntry)
-- | Last time message queue has been viewed (used for notification).
lastSeenMessageTime :: Lens' GameState TickNumber
-- | The current robot in focus.
--
-- It is only a Getter because this value should be updated only
-- when the viewCenterRule is specified to be a robot.
--
-- Technically it's the last robot ID specified by viewCenterRule,
-- but that robot may not be alive anymore - to be safe use
-- focusedRobot.
focusedRobotID :: Getter GameState RID
-- | The number of ticks elapsed since the game started.
ticks :: Lens' GameState TickNumber
-- | The maximum number of CESK machine steps a robot may take during a
-- single tick.
robotStepsPerTick :: Lens' GameState Int
-- | A data type to keep track of discovered recipes and commands
data Notifications a
Notifications :: Int -> [a] -> Notifications a
[_notificationsCount] :: Notifications a -> Int
[_notificationsContent] :: Notifications a -> [a]
notificationsCount :: forall a_a7Nb2. Lens' (Notifications a_a7Nb2) Int
notificationsContent :: forall a_a7Nb2 a_a7NDC. Lens (Notifications a_a7Nb2) (Notifications a_a7NDC) [a_a7Nb2] [a_a7NDC]
type LaunchParams a = ParameterizableLaunchParams CodeToRun a
-- | In this stage in the UI pipeline, both fields have already been
-- validated, and Nothing means that the field is simply absent.
type ValidatedLaunchParams = LaunchParams Identity
-- | Record to pass information needed to create an initial
-- GameState record when starting a scenario.
data GameStateConfig
GameStateConfig :: Array Int Text -> Array Int Text -> EntityMap -> [Recipe Entity] -> WorldMap -> GameStateConfig
[initAdjList] :: GameStateConfig -> Array Int Text
[initNameList] :: GameStateConfig -> Array Int Text
[initEntities] :: GameStateConfig -> EntityMap
[initRecipes] :: GameStateConfig -> [Recipe Entity]
[initWorldMap] :: GameStateConfig -> WorldMap
-- | Create an initial, fresh game state record when starting a new
-- scenario.
initGameState :: GameStateConfig -> GameState
-- | Create an initial game state corresponding to the given scenario.
scenarioToGameState :: Scenario -> ValidatedLaunchParams -> GameStateConfig -> IO GameState
data CodeToRun
CodeToRun :: SolutionSource -> ProcessedTerm -> CodeToRun
newtype Sha1
Sha1 :: String -> Sha1
data SolutionSource
ScenarioSuggested :: SolutionSource
-- | Includes the SHA1 of the program text for the purpose of corroborating
-- solutions on a leaderboard.
PlayerAuthored :: FilePath -> Sha1 -> SolutionSource
parseCodeFile :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => FilePath -> m CodeToRun
-- | Given a current mapping from robot names to robots, apply a
-- ViewCenterRule to derive the location it refers to. The result
-- is Maybe because the rule may refer to a robot which does not
-- exist.
applyViewCenterRule :: ViewCenterRule -> IntMap Robot -> Maybe (Cosmic Location)
-- | Recalculate the veiw center (and cache the result in the
-- viewCenter field) based on the current viewCenterRule.
-- If the viewCenterRule specifies a robot which does not exist,
-- simply leave the current viewCenter as it is. Set
-- needsRedraw if the view center changes.
recalcViewCenter :: GameState -> GameState
-- | Modify the viewCenter by applying an arbitrary function to the
-- current value. Note that this also modifies the viewCenterRule
-- to match. After calling this function the viewCenterRule will
-- specify a particular location, not a robot.
modifyViewCenter :: (Cosmic Location -> Cosmic Location) -> GameState -> GameState
-- | Given a width and height, compute the region, centered on the
-- viewCenter, that should currently be in view.
viewingRegion :: GameState -> (Int32, Int32) -> Cosmic BoundsRectangle
-- | Unfocus by modifying the view center rule to look at the
-- current location instead of a specific robot, and also set the focused
-- robot ID to an invalid value. In classic mode this causes the map view
-- to become nothing but static.
unfocus :: GameState -> GameState
-- | Find out which robot has been last specified by the
-- viewCenterRule, if any.
focusedRobot :: GameState -> Maybe Robot
-- | Type for describing how far away a robot is from the base, which
-- determines what kind of communication can take place.
data RobotRange
-- | Close; communication is perfect.
Close :: RobotRange
-- | Mid-range; communication is possible but lossy.
MidRange :: Double -> RobotRange
-- | Far; communication is not possible.
Far :: RobotRange
-- | Check how far away the focused robot is from the base.
-- Nothing is returned if there is no focused robot; otherwise,
-- return a RobotRange value as follows.
--
--
-- - If we are in creative or scroll-enabled mode, the focused robot is
-- always considered Close.
-- - Otherwise, there is a "minimum radius" and "maximum radius".
-- - If the robot is within the minimum radius, it is
-- Close.
-- - If the robot is between the minimum and maximum radii, it is
-- MidRange, with a Double value ranging linearly from 0 to
-- 1 proportional to the distance from the minimum to maximum radius. For
-- example, 'MidRange 0.5' would indicate a robot exactly halfway between
-- the minimum and maximum radii.
-- - If the robot is beyond the maximum radius, it is Far.
-- - By default, the minimum radius is 16, and maximum is 64.
-- - If the focused robot has an antenna installed, it doubles
-- both radii.
-- - If the base has an antenna installed, it also doubles
-- both radii.
--
focusedRange :: GameState -> Maybe RobotRange
-- | Clear the robotLogUpdated flag of the focused robot.
clearFocusedRobotLogUpdated :: Has (State GameState) sig m => m ()
-- | Add a robot to the game state, adding it to the main robot map, the
-- active robot set, and to to the index of robots by location.
addRobot :: Has (State GameState) sig m => Robot -> m ()
-- | Helper function for updating the "robotsByLocation" bookkeeping
addRobotToLocation :: Has (State GameState) sig m => RID -> Cosmic Location -> m ()
-- | Add a concrete instance of a robot template to the game state: first,
-- generate a unique ID number for it. Then, add it to the main robot
-- map, the active robot set, and to to the index of robots by location.
-- Return the updated robot.
addTRobot :: Has (State GameState) sig m => TRobot -> m Robot
-- | Add a message to the message queue.
emitMessage :: Has (State GameState) sig m => LogEntry -> m ()
-- | Iterates through all of the currently "wait"-ing robots, and moves
-- forward the wake time of the ones that are watching this location.
--
-- NOTE: Clearing TickNumber map entries from
-- "internalWaitingRobots" upon wakeup is handled by
-- "wakeUpRobotsDoneSleeping" in State.hs
wakeWatchingRobots :: Has (State GameState) sig m => Cosmic Location -> m ()
-- | Takes a robot out of the activeRobots set and puts it in the
-- waitingRobots queue.
sleepUntil :: Has (State GameState) sig m => RID -> TickNumber -> m ()
-- | Takes a robot out of the activeRobots set.
sleepForever :: Has (State GameState) sig m => RID -> m ()
-- | Removes robots whose wake up time matches the current game ticks count
-- from the waitingRobots queue and put them back in the activeRobots set
-- if they still exist in the keys of robotMap.
wakeUpRobotsDoneSleeping :: Has (State GameState) sig m => m ()
deleteRobot :: Has (State GameState) sig m => RID -> m ()
-- | Makes sure empty sets don't hang around in the robotsByLocation
-- map. We don't want a key with an empty set at every location any robot
-- has ever visited!
removeRobotFromLocationMap :: Has (State GameState) sig m => Cosmic Location -> RID -> m ()
-- | Adds a robot to the activeRobots set.
activateRobot :: Has (State GameState) sig m => RID -> m ()
-- | Switch (auto or manually) paused game to running and running to
-- manually paused.
--
-- Note that this function is not safe to use in the app directly,
-- because the UI also tracks time between ticks - use
-- safeTogglePause instead.
toggleRunStatus :: RunStatus -> RunStatus
messageIsRecent :: GameState -> LogEntry -> Bool
-- | Reconciles the possibilities of log messages being omnipresent and
-- robots being in different worlds
messageIsFromNearby :: Cosmic Location -> LogEntry -> Bool
getRunCodePath :: CodeToRun -> Maybe FilePath
instance GHC.Classes.Ord Swarm.Game.State.RobotRange
instance GHC.Classes.Eq Swarm.Game.State.RobotRange
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.State.RunStatus
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.State.RunStatus
instance GHC.Generics.Generic Swarm.Game.State.RunStatus
instance GHC.Show.Show Swarm.Game.State.RunStatus
instance GHC.Classes.Eq Swarm.Game.State.RunStatus
instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Swarm.Game.State.Notifications a)
instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Swarm.Game.State.Notifications a)
instance GHC.Generics.Generic (Swarm.Game.State.Notifications a)
instance GHC.Show.Show a => GHC.Show.Show (Swarm.Game.State.Notifications a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Swarm.Game.State.Notifications a)
instance GHC.Base.Semigroup (Swarm.Game.State.Notifications a)
instance GHC.Base.Monoid (Swarm.Game.State.Notifications a)
instance Servant.Docs.Internal.ToSample Swarm.Game.State.WinCondition
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.State.REPLStatus
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.State.REPLStatus
instance GHC.Generics.Generic Swarm.Game.State.REPLStatus
instance GHC.Show.Show Swarm.Game.State.REPLStatus
instance GHC.Classes.Eq Swarm.Game.State.REPLStatus
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.State.WinStatus
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.State.WinStatus
instance GHC.Generics.Generic Swarm.Game.State.WinStatus
instance GHC.Show.Show Swarm.Game.State.WinStatus
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.State.WinCondition
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.State.WinCondition
instance GHC.Generics.Generic Swarm.Game.State.WinCondition
instance GHC.Show.Show Swarm.Game.State.WinCondition
instance Data.Aeson.Types.ToJSON.ToJSON Swarm.Game.State.ViewCenterRule
instance Data.Aeson.Types.FromJSON.FromJSON Swarm.Game.State.ViewCenterRule
instance GHC.Generics.Generic Swarm.Game.State.ViewCenterRule
instance GHC.Show.Show Swarm.Game.State.ViewCenterRule
instance GHC.Classes.Ord Swarm.Game.State.ViewCenterRule
instance GHC.Classes.Eq Swarm.Game.State.ViewCenterRule
module Swarm.TUI.Model.Menu
data ScenarioOutcome
WinModal :: ScenarioOutcome
LoseModal :: ScenarioOutcome
data ModalType
HelpModal :: ModalType
RecipesModal :: ModalType
CommandsModal :: ModalType
MessagesModal :: ModalType
EntityPaletteModal :: ModalType
TerrainPaletteModal :: ModalType
RobotsModal :: ModalType
ScenarioEndModal :: ScenarioOutcome -> ModalType
QuitModal :: ModalType
KeepPlayingModal :: ModalType
DescriptionModal :: Entity -> ModalType
GoalModal :: ModalType
data ButtonAction
Cancel :: ButtonAction
KeepPlaying :: ButtonAction
StartOver :: Seed -> ScenarioInfoPair -> ButtonAction
QuitAction :: ButtonAction
Next :: ScenarioInfoPair -> ButtonAction
data Modal
Modal :: ModalType -> Dialog ButtonAction Name -> Modal
[_modalType] :: Modal -> ModalType
[_modalDialog] :: Modal -> Dialog ButtonAction Name
modalType :: Lens' Modal ModalType
modalDialog :: Lens' Modal (Dialog ButtonAction Name)
data MainMenuEntry
NewGame :: MainMenuEntry
Tutorial :: MainMenuEntry
Achievements :: MainMenuEntry
Messages :: MainMenuEntry
About :: MainMenuEntry
Quit :: MainMenuEntry
data Menu
-- | We started playing directly from command line, no menu to show
NoMenu :: Menu
MainMenu :: List Name MainMenuEntry -> Menu
-- | Stack of scenario item lists. INVARIANT: the currently selected menu
-- item is ALWAYS the same as the scenario currently being played. See
-- https://github.com/swarm-game/swarm/issues/1064 and
-- https://github.com/swarm-game/swarm/pull/1065.
NewGameMenu :: NonEmpty (List Name ScenarioItem) -> Menu
AchievementsMenu :: List Name CategorizedAchievement -> Menu
MessagesMenu :: Menu
AboutMenu :: Menu
mainMenu :: MainMenuEntry -> List Name MainMenuEntry
_AboutMenu :: Prism' Menu ()
_MessagesMenu :: Prism' Menu ()
_AchievementsMenu :: Prism' Menu (List Name CategorizedAchievement)
_NewGameMenu :: Prism' Menu (NonEmpty (List Name ScenarioItem))
_MainMenu :: Prism' Menu (List Name MainMenuEntry)
_NoMenu :: Prism' Menu ()
-- | Create a brick List of scenario items from a
-- ScenarioCollection.
mkScenarioList :: Bool -> ScenarioCollection -> List Name ScenarioItem
-- | Given a ScenarioCollection and a FilePath which is the
-- canonical path to some folder or scenario, construct a
-- NewGameMenu stack focused on the given item, if possible.
mkNewGameMenu :: Bool -> ScenarioCollection -> FilePath -> Maybe Menu
-- | An entry in the inventory list displayed in the info panel. We can
-- either have an entity with a count in the robot's inventory, an entity
-- equipped on the robot, or a labelled separator. The purpose of the
-- separators is to show a clear distinction between the robot's
-- inventory and its equipped devices.
data InventoryListEntry
Separator :: Text -> InventoryListEntry
InventoryEntry :: Count -> Entity -> InventoryListEntry
EquippedEntry :: Entity -> InventoryListEntry
_EquippedEntry :: Prism' InventoryListEntry Entity
_InventoryEntry :: Prism' InventoryListEntry (Count, Entity)
_Separator :: Prism' InventoryListEntry Text
instance GHC.Classes.Eq Swarm.TUI.Model.Menu.InventoryListEntry
instance GHC.Enum.Enum Swarm.TUI.Model.Menu.MainMenuEntry
instance GHC.Enum.Bounded Swarm.TUI.Model.Menu.MainMenuEntry
instance GHC.Read.Read Swarm.TUI.Model.Menu.MainMenuEntry
instance GHC.Show.Show Swarm.TUI.Model.Menu.MainMenuEntry
instance GHC.Classes.Ord Swarm.TUI.Model.Menu.MainMenuEntry
instance GHC.Classes.Eq Swarm.TUI.Model.Menu.MainMenuEntry
instance GHC.Show.Show Swarm.TUI.Model.Menu.ScenarioOutcome
instance GHC.Show.Show Swarm.TUI.Model.Menu.ModalType
-- | Types for representing state of the launch dialog, along with
-- conversion functions for validated launch parameters.
module Swarm.TUI.Launch.Model
-- | Use this to store error messages on individual fields
type EditingLaunchParams = LaunchParams (Either Text)
toSerializableParams :: ValidatedLaunchParams -> SerializableLaunchParams
fromSerializableParams :: SerializableLaunchParams -> IO EditingLaunchParams
data FileBrowserControl
FileBrowserControl :: FileBrowser Name -> Maybe FilePath -> Bool -> FileBrowserControl
[_fbWidget] :: FileBrowserControl -> FileBrowser Name
[_maybeSelectedFile] :: FileBrowserControl -> Maybe FilePath
[_fbIsDisplayed] :: FileBrowserControl -> Bool
maybeSelectedFile :: Lens' FileBrowserControl (Maybe FilePath)
fbWidget :: Lens' FileBrowserControl (FileBrowser Name)
fbIsDisplayed :: Lens' FileBrowserControl Bool
-- | UI elements to configure scenario launch options
data LaunchControls
LaunchControls :: FileBrowserControl -> Editor Text Name -> FocusRing Name -> Maybe ScenarioInfoPair -> LaunchControls
[_fileBrowser] :: LaunchControls -> FileBrowserControl
[_seedValueEditor] :: LaunchControls -> Editor Text Name
[_scenarioConfigFocusRing] :: LaunchControls -> FocusRing Name
[_isDisplayedFor] :: LaunchControls -> Maybe ScenarioInfoPair
seedValueEditor :: Lens' LaunchControls (Editor Text Name)
scenarioConfigFocusRing :: Lens' LaunchControls (FocusRing Name)
isDisplayedFor :: Lens' LaunchControls (Maybe ScenarioInfoPair)
fileBrowser :: Lens' LaunchControls FileBrowserControl
-- | UI elements to configure scenario launch options
data LaunchOptions
LaunchOptions :: LaunchControls -> EditingLaunchParams -> LaunchOptions
[_controls] :: LaunchOptions -> LaunchControls
[_editingParams] :: LaunchOptions -> EditingLaunchParams
editingParams :: Lens' LaunchOptions EditingLaunchParams
controls :: Lens' LaunchOptions LaunchControls
-- | Prepares and validates scenario launch parameters
module Swarm.TUI.Launch.Prep
swarmLangFileExtension :: String
toValidatedParams :: EditingLaunchParams -> Either Text ValidatedLaunchParams
parseSeedInput :: Editor Text Name -> Either Text (Maybe Seed)
parseWidgetParams :: LaunchControls -> IO EditingLaunchParams
makeFocusRingWith :: [ScenarioConfigPanelFocusable] -> FocusRing Name
initEditorWidget :: Text -> Editor Text Name
-- | Called before any particular scenario is selected, so we supply some
-- Nothings as defaults to the ValidatedLaunchParams.
initConfigPanel :: IO LaunchOptions
initFileBrowserWidget :: MonadIO m => Maybe FilePath -> m (FileBrowser Name)
-- | If the selected scenario has been launched with an initial script
-- before, set the file browser to initially open that script's
-- directory. Then set the launch dialog to be displayed.
--
-- Note that the FileBrowser widget normally allows multiple selections
-- ("marked" files). However, there do not exist any public "setters" set
-- the marked files, so we have some workarounds: * When the user marks
-- the first file, we immediately close the FileBrowser widget. * We
-- re-instantiate the FileBrowser from scratch every time it is opened,
-- so that it is not possible to mark more than one file. * The "marked
-- file" is persisted outside of the FileBrowser state, and the "initial
-- directory" is set upon instantiation from that external state.
prepareLaunchDialog :: ScenarioInfoPair -> EventM Name LaunchOptions ()
module Swarm.TUI.Model.UI
-- | The main record holding the UI state. For access to the fields, see
-- the lenses below.
data UIState
UIState :: Menu -> Bool -> Bool -> FocusRing Name -> LaunchOptions -> Maybe (Cosmic Coords) -> WorldEditor Name -> REPLState -> Maybe (Int, List Name InventoryListEntry) -> InventorySortOptions -> Maybe Text -> Bool -> Bool -> Bool -> Maybe Text -> Maybe Modal -> GoalDisplay -> Bool -> Map CategorizedAchievement Attainment -> Bool -> Bool -> Bool -> Bool -> TimeSpec -> Bool -> Double -> Double -> Int -> Int -> Int -> Int -> TimeSpec -> TimeSpec -> TimeSpec -> AttrMap -> Maybe ScenarioInfoPair -> UIState
[_uiMenu] :: UIState -> Menu
[_uiPlaying] :: UIState -> Bool
[_uiCheatMode] :: UIState -> Bool
[_uiFocusRing] :: UIState -> FocusRing Name
[_uiLaunchConfig] :: UIState -> LaunchOptions
[_uiWorldCursor] :: UIState -> Maybe (Cosmic Coords)
[_uiWorldEditor] :: UIState -> WorldEditor Name
[_uiREPL] :: UIState -> REPLState
[_uiInventory] :: UIState -> Maybe (Int, List Name InventoryListEntry)
[_uiInventorySort] :: UIState -> InventorySortOptions
[_uiInventorySearch] :: UIState -> Maybe Text
[_uiMoreInfoTop] :: UIState -> Bool
[_uiMoreInfoBot] :: UIState -> Bool
[_uiScrollToEnd] :: UIState -> Bool
[_uiError] :: UIState -> Maybe Text
[_uiModal] :: UIState -> Maybe Modal
[_uiGoal] :: UIState -> GoalDisplay
[_uiHideGoals] :: UIState -> Bool
[_uiAchievements] :: UIState -> Map CategorizedAchievement Attainment
[_uiShowFPS] :: UIState -> Bool
[_uiShowREPL] :: UIState -> Bool
[_uiShowZero] :: UIState -> Bool
[_uiShowDebug] :: UIState -> Bool
[_uiHideRobotsUntil] :: UIState -> TimeSpec
[_uiInventoryShouldUpdate] :: UIState -> Bool
[_uiTPF] :: UIState -> Double
[_uiFPS] :: UIState -> Double
[_lgTicksPerSecond] :: UIState -> Int
[_tickCount] :: UIState -> Int
[_frameCount] :: UIState -> Int
[_frameTickCount] :: UIState -> Int
[_lastFrameTime] :: UIState -> TimeSpec
[_accumulatedTime] :: UIState -> TimeSpec
[_lastInfoTime] :: UIState -> TimeSpec
[_uiAttrMap] :: UIState -> AttrMap
[_scenarioRef] :: UIState -> Maybe ScenarioInfoPair
data GoalDisplay
GoalDisplay :: GoalTracking -> List Name GoalEntry -> FocusRing Name -> GoalDisplay
[_goalsContent] :: GoalDisplay -> GoalTracking
-- | required for maintaining the selection/navigation state among list
-- items
[_listWidget] :: GoalDisplay -> List Name GoalEntry
[_focus] :: GoalDisplay -> FocusRing Name
-- | The current menu state.
uiMenu :: Lens' UIState Menu
-- | Are we currently playing the game? True = we are playing, and should
-- thus display a world, REPL, etc.; False = we should display the
-- current menu.
uiPlaying :: Lens' UIState Bool
-- | Cheat mode, i.e. are we allowed to turn creative mode on and off?
uiCheatMode :: Lens' UIState Bool
-- | The focus ring is the set of UI panels we can cycle among using the
-- Tab key.
uiFocusRing :: Lens' UIState (FocusRing Name)
-- | Configuration modal when launching a scenario
uiLaunchConfig :: Lens' UIState LaunchOptions
-- | The last clicked position on the world view.
uiWorldCursor :: Lens' UIState (Maybe (Cosmic Coords))
-- | State of all World Editor widgets
uiWorldEditor :: Lens' UIState (WorldEditor Name)
-- | The state of REPL panel.
uiREPL :: Lens' UIState REPLState
-- | The hash value of the focused robot entity (so we can tell if its
-- inventory changed) along with a list of the items in the focused
-- robot's inventory.
uiInventory :: Lens' UIState (Maybe (Int, List Name InventoryListEntry))
-- | The order and direction of sorting inventory list.
uiInventorySort :: Lens' UIState InventorySortOptions
-- | The current search string used to narrow the inventory view.
uiInventorySearch :: Lens' UIState (Maybe Text)
-- | Does the info panel contain more content past the top of the panel?
uiMoreInfoTop :: Lens' UIState Bool
-- | Does the info panel contain more content past the bottom of the panel?
uiMoreInfoBot :: Lens' UIState Bool
-- | A flag telling the UI to scroll the info panel to the very end (used
-- when a new log message is appended).
uiScrollToEnd :: Lens' UIState Bool
-- | When this is Just, it represents a popup box containing an
-- error message that is shown on top of the rest of the UI.
uiError :: Lens' UIState (Maybe Text)
-- | When this is Just, it represents a modal to be displayed on
-- top of the UI, e.g. for the Help screen.
uiModal :: Lens' UIState (Maybe Modal)
-- | Status of the scenario goal: whether there is one, and whether it has
-- been displayed to the user initially.
uiGoal :: Lens' UIState GoalDisplay
-- | When running with --autoplay, suppress the goal dialogs.
--
-- For developement, the --cheat flag shows goals again.
uiHideGoals :: Lens' UIState Bool
-- | Map of achievements that were attained
uiAchievements :: Lens' UIState (Map CategorizedAchievement Attainment)
-- | The base-2 logarithm of the current game speed in ticks/second. Note
-- that we cap this value to the range of +/- log2 INTMAX.
lgTicksPerSecond :: Lens' UIState Int
-- | The time of the last Frame event.
lastFrameTime :: Lens' UIState TimeSpec
-- | The amount of accumulated real time. Every time we get a
-- Frame event, we accumulate the amount of real time that
-- happened since the last frame, then attempt to take an appropriate
-- number of ticks to "catch up", based on the target tick rate.
--
-- See https://gafferongames.com/post/fix_your_timestep/ .
accumulatedTime :: Lens' UIState TimeSpec
-- | A counter used to track how many ticks have happened since the last
-- time we updated the ticks/frame statistics.
tickCount :: Lens' UIState Int
-- | A counter used to track how many frames have been rendered since the
-- last time we updated the ticks/frame statistics.
frameCount :: Lens' UIState Int
-- | A counter used to track how many ticks have happened in the current
-- frame, so we can stop when we get to the tick cap.
frameTickCount :: Lens' UIState Int
-- | The time of the last info widget update
lastInfoTime :: Lens' UIState TimeSpec
-- | A toggle to show the FPS by pressing f
uiShowFPS :: Lens' UIState Bool
-- | A toggle to expand or collapse the REPL by pressing `Ctrl-k`
uiShowREPL :: Lens' UIState Bool
-- | A toggle to show or hide inventory items with count 0 by pressing `0`
uiShowZero :: Lens' UIState Bool
-- | A toggle to show debug.
--
-- TODO: #1112 use record for selection of debug features?
uiShowDebug :: Lens' UIState Bool
-- | Whether to show or hide robots on the world map.
uiShowRobots :: Getter UIState Bool
-- | Hide robots on the world map.
uiHideRobotsUntil :: Lens' UIState TimeSpec
-- | Whether the Inventory ui panel should update
uiInventoryShouldUpdate :: Lens' UIState Bool
-- | Computed ticks per milli seconds
uiTPF :: Lens' UIState Double
-- | Computed frames per milli seconds
uiFPS :: Lens' UIState Double
-- | Attribute map
uiAttrMap :: Lens' UIState AttrMap
-- | The currently active Scenario description, useful for starting over.
scenarioRef :: Lens' UIState (Maybe ScenarioInfoPair)
-- | The initial state of the focus ring. NOTE: Normally, the Tab key might
-- cycle through the members of the focus ring. However, the REPL already
-- uses Tab. So, to is not used at all right now for navigating the
-- toplevel focus ring.
initFocusRing :: FocusRing Name
-- | The initial tick speed.
defaultInitLgTicksPerSecond :: Int
-- | Initialize the UI state. This needs to be in the IO monad since it
-- involves reading a REPL history file, getting the current time, and
-- loading text files from the data directory. The Bool
-- parameter indicates whether we should start off by showing the main
-- menu.
initUIState :: (Has (Accum (Seq SystemFailure)) sig m, Has (Lift IO) sig m) => Int -> Bool -> Bool -> m UIState
-- | Facilities for stepping the robot CESK machines, i.e. the
-- actual interpreter for the Swarm language.
--
--
--
-- The only reason we need IO is so that robots can run programs
-- loaded from files, via the Run command. This could be avoided
-- by using Import command instead and parsing the required
-- files at the time of declaration. See
-- https://github.com/swarm-game/swarm/issues/495.
module Swarm.Game.Step
-- | The main function to do one game tick.
--
-- Note that the game may be in RobotStep mode and not finish the
-- tick. Use the return value to check whether a full tick happened.
gameTick :: (Has (State GameState) sig m, Has (Lift IO) sig m) => m Bool
-- | Finish a game tick in progress and set the game to WorldTick
-- mode afterwards.
--
-- Use this function if you need to unpause the game.
finishGameTick :: (Has (State GameState) sig m, Has (Lift IO) sig m) => m ()
insertBackRobot :: Has (State GameState) sig m => RID -> Robot -> m ()
runRobotIDs :: (Has (State GameState) sig m, Has (Lift IO) sig m) => IntSet -> m ()
singleStep :: (Has (State GameState) sig m, Has (Lift IO) sig m) => SingleStep -> RID -> IntSet -> m Bool
-- | An accumulator for folding over the incomplete objectives to evaluate
-- for their completion
data CompletionsWithExceptions
CompletionsWithExceptions :: [Text] -> ObjectiveCompletion -> [Objective] -> CompletionsWithExceptions
[exceptions] :: CompletionsWithExceptions -> [Text]
[completions] :: CompletionsWithExceptions -> ObjectiveCompletion
-- | Upon completion, an objective is enqueued. It is dequeued when
-- displayed on the UI.
[completionAnnouncementQueue] :: CompletionsWithExceptions -> [Objective]
-- | Execute the win condition check *hypothetically*: i.e. in a fresh CESK
-- machine, using a copy of the current game state.
--
-- The win check is performed only on "active" goals; that is, the goals
-- that are currently unmet and have had all of their prerequisites
-- satisfied. Note that it may be possible, while traversing through the
-- goal list, for one goal to be met earlier in the list that happens to
-- be a prerequisite later in the traversal. This is why: 1) We must not
-- pre-filter the goals to be traversed based on satisfied prerequisites
-- (i.e. we cannot use the "getActiveObjectives" function). 2) The
-- traversal order must be "reverse topological" order, so that
-- prerequisites are evaluated before dependent goals. 3) The iteration
-- needs to be a "fold", so that state is updated after each element.
hypotheticalWinCheck :: (Has (State GameState) sig m, Has (Lift IO) sig m) => EntityMap -> GameState -> WinStatus -> ObjectiveCompletion -> m ()
evalPT :: (Has (Lift IO) sig m, Has (Throw Exn) sig m, Has (State GameState) sig m) => ProcessedTerm -> m Value
getNow :: Has (Lift IO) sig m => m TimeSpec
-- | Create a special robot to check some hypothetical, for example the win
-- condition.
--
-- Use ID (-1) so it won't conflict with any robots currently in the
-- robot map.
hypotheticalRobot :: CESK -> TimeSpec -> Robot
evaluateCESK :: (Has (Lift IO) sig m, Has (Throw Exn) sig m, Has (State GameState) sig m) => CESK -> m Value
runCESK :: (Has (Lift IO) sig m, Has (Throw Exn) sig m, Has (State GameState) sig m, Has (State Robot) sig m) => CESK -> m Value
-- | Set a flag telling the UI that the world needs to be redrawn.
flagRedraw :: Has (State GameState) sig m => m ()
-- | Perform an action requiring a World state component in a larger
-- context with a GameState.
zoomWorld :: Has (State GameState) sig m => SubworldName -> StateC (World Int Entity) Identity b -> m (Maybe b)
-- | Get the entity (if any) at a given location.
entityAt :: Has (State GameState) sig m => Cosmic Location -> m (Maybe Entity)
-- | Modify the entity (if any) at a given location.
updateEntityAt :: Has (State GameState) sig m => Cosmic Location -> (Maybe Entity -> Maybe Entity) -> m ()
-- | Get the robot with a given ID.
robotWithID :: Has (State GameState) sig m => RID -> m (Maybe Robot)
-- | Get the robot with a given name.
robotWithName :: Has (State GameState) sig m => Text -> m (Maybe Robot)
-- | Generate a uniformly random number using the random generator in the
-- game state.
uniform :: (Has (State GameState) sig m, UniformRange a) => (a, a) -> m a
-- | Given a weighting function and a list of values, choose one of the
-- values randomly (using the random generator in the game state), with
-- the probability of each being proportional to its weight. Return
-- Nothing if the list is empty.
weightedChoice :: Has (State GameState) sig m => (a -> Integer) -> [a] -> m (Maybe a)
-- | Generate a random robot name in the form adjective_name.
randomName :: Has (State GameState) sig m => m Text
-- | Create a log entry given current robot and game time in ticks noting
-- whether it has been said.
--
-- This is the more generic version used both for (recorded) said
-- messages and normal logs.
createLogEntry :: (Has (State GameState) sig m, Has (State Robot) sig m) => LogSource -> Text -> m LogEntry
-- | Print some text via the robot's log.
traceLog :: (Has (State GameState) sig m, Has (State Robot) sig m) => LogSource -> Text -> m LogEntry
-- | Print a showable value via the robot's log.
--
-- Useful for debugging.
traceLogShow :: (Has (State GameState) sig m, Has (State Robot) sig m, Show a) => a -> m ()
-- | Capabilities needed for a specific robot to evaluate or execute a
-- constant. Right now, the only difference is whether the robot is heavy
-- or not when executing the Move command, but there might be
-- other exceptions added in the future.
constCapsFor :: Const -> Robot -> Maybe Capability
-- | Ensure that a robot is capable of executing a certain constant (either
-- because it has a device which gives it that capability, or it is a
-- system robot, or we are in creative mode).
ensureCanExecute :: (Has (State Robot) sig m, Has (State GameState) sig m, Has (Throw Exn) sig m) => Const -> m ()
-- | Test whether the current robot has a given capability (either because
-- it has a device which gives it that capability, or it is a system
-- robot, or we are in creative mode).
hasCapability :: (Has (State Robot) sig m, Has (State GameState) sig m) => Capability -> m Bool
-- | Ensure that either a robot has a given capability, OR we are in
-- creative mode.
hasCapabilityFor :: (Has (State Robot) sig m, Has (State GameState) sig m, Has (Throw Exn) sig m) => Capability -> Term -> m ()
-- | Create an exception about a command failing.
cmdExn :: Const -> [Text] -> Exn
-- | Create an exception about a command failing, with an achievement
cmdExnWithAchievement :: Const -> [Text] -> GameplayAchievement -> Exn
-- | Raise an exception about a command failing with a formatted error
-- message.
raise :: Has (Throw Exn) sig m => Const -> [Text] -> m a
-- | Run a subcomputation that might throw an exception in a context where
-- we are returning a CESK machine; any exception will be turned into an
-- Up state.
withExceptions :: Monad m => Store -> Cont -> ThrowC Exn m CESK -> m CESK
-- | Run a robot for one tick, which may consist of up to
-- robotStepsPerTick CESK machine steps and at most one tangible
-- command execution, whichever comes first.
tickRobot :: (Has (State GameState) sig m, Has (Lift IO) sig m) => Robot -> m Robot
-- | Recursive helper function for tickRobot, which checks if the
-- robot is actively running and still has steps left, and if so runs it
-- for one step, then calls itself recursively to continue stepping the
-- robot.
tickRobotRec :: (Has (State GameState) sig m, Has (Lift IO) sig m) => Robot -> m Robot
-- | Single-step a robot by decrementing its tickSteps counter and
-- running its CESK machine for one step.
stepRobot :: (Has (State GameState) sig m, Has (Lift IO) sig m) => Robot -> m Robot
-- | replace some entity in the world with another entity
updateWorld :: (Has (State GameState) sig m, Has (Throw Exn) sig m) => Const -> WorldUpdate Entity -> m ()
applyRobotUpdates :: (Has (State GameState) sig m, Has (State Robot) sig m) => [RobotUpdate] -> m ()
data SKpair
SKpair :: Store -> Cont -> SKpair
-- | Performs some side-effectful computation for an FImmediate
-- Frame. Aborts processing the continuation stack if an error is
-- encountered.
--
-- Compare to "withExceptions".
processImmediateFrame :: (Has (State GameState) sig m, Has (State Robot) sig m, Has (Lift IO) sig m) => Value -> SKpair -> ErrorC Exn m () -> m CESK
updateWorldAndRobots :: HasRobotStepState sig m => Const -> [WorldUpdate Entity] -> [RobotUpdate] -> m ()
-- | The main CESK machine workhorse. Given a robot, look at its CESK
-- machine state and figure out a single next step.
stepCESK :: (Has (State GameState) sig m, Has (State Robot) sig m, Has (Lift IO) sig m) => CESK -> m CESK
-- | Eexecute a constant, catching any exception thrown and returning it
-- via a CESK machine state.
evalConst :: (Has (State GameState) sig m, Has (State Robot) sig m, Has (Lift IO) sig m) => Const -> [Value] -> Store -> Cont -> m CESK
-- | A system program for a "seed robot", to regrow a growable entity after
-- it is harvested.
seedProgram :: Integer -> Integer -> Text -> ProcessedTerm
-- | Construct a "seed robot" from entity, time range and position, and add
-- it to the world. It has low priority and will be covered by placed
-- entities.
addSeedBot :: Has (State GameState) sig m => Entity -> (Integer, Integer) -> Cosmic Location -> TimeSpec -> m ()
-- | All functions that are used for robot step can access GameState
-- and the current Robot.
--
-- They can also throw exception of our custom type, which is handled
-- elsewhere. Because of that the constraint is only Throw, but
-- not Catch/ErrorLevel.
type HasRobotStepState sig m = (Has (State GameState) sig m, Has (State Robot) sig m, Has (Throw Exn) sig m)
-- | Interpret the execution (or evaluation) of a constant application to
-- some values.
execConst :: (HasRobotStepState sig m, Has (Lift IO) sig m) => Const -> [Value] -> Store -> Cont -> m CESK
addWatchedLocation :: HasRobotStepState sig m => Cosmic Location -> m ()
-- | Clear watches that are out of range
purgeFarAwayWatches :: HasRobotStepState sig m => m ()
-- | Exempts the robot from various command constraints when it is either a
-- system robot or playing in creative mode
isPrivilegedBot :: (Has (State GameState) sig m, Has (State Robot) sig m) => m Bool
-- | Requires that the target location is within one cell. Requirement is
-- waived if the bot is privileged.
isNearbyOrExempt :: Bool -> Cosmic Location -> Cosmic Location -> Bool
grantAchievement :: (Has (State GameState) sig m, Has (Lift IO) sig m) => GameplayAchievement -> m ()
data MoveFailureMode
PathBlocked :: MoveFailureMode
PathLiquid :: MoveFailureMode
data MoveFailureDetails
MoveFailureDetails :: Entity -> MoveFailureMode -> MoveFailureDetails
-- | How to handle failure, for example when moving to blocked location
data RobotFailure
ThrowExn :: RobotFailure
Destroy :: RobotFailure
IgnoreFail :: RobotFailure
-- | How to handle failure when moving/teleporting to a location.
data MoveFailure
MoveFailure :: RobotFailure -> RobotFailure -> MoveFailure
[failIfBlocked] :: MoveFailure -> RobotFailure
[failIfDrown] :: MoveFailure -> RobotFailure
data GrabbingCmd
Grab' :: GrabbingCmd
Harvest' :: GrabbingCmd
Swap' :: GrabbingCmd
Push' :: GrabbingCmd
verbGrabbingCmd :: GrabbingCmd -> Text
verbedGrabbingCmd :: GrabbingCmd -> Text
-- | Format a set of suggested devices for use in an error message, in the
-- format device1 or device2 or ... or deviceN.
formatDevices :: Set Entity -> Text
-- | Give some entities from a parent robot (the robot represented by the
-- ambient State Robot effect) to a child robot (represented by
-- the given RID) as part of a Build or Reprogram
-- command. The first Inventory is devices to be equipped, and the
-- second is entities to be transferred.
--
-- In classic mode, the entities will be transferred (that is,
-- removed from the parent robot's inventory); in creative mode, the
-- entities will be copied/created, that is, no entities will be removed
-- from the parent robot.
provisionChild :: HasRobotStepState sig m => RID -> Inventory -> Inventory -> m ()
-- | Update the location of a robot, and simultaneously update the
-- robotsByLocation map, so we can always look up robots by
-- location. This should be the only way to update the location of
-- a robot. Also implements teleportation by portals.
updateRobotLocation :: HasRobotStepState sig m => Cosmic Location -> Cosmic Location -> m ()
-- | Execute a stateful action on a target robot --- whether the current
-- one or another.
onTarget :: HasRobotStepState sig m => RID -> (forall sig' m'. HasRobotStepState sig' m' => m' ()) -> m ()
-- | Evaluate the application of a comparison operator. Returns
-- Nothing if the application does not make sense.
evalCmp :: Has (Throw Exn) sig m => Const -> Value -> Value -> m Bool
-- | Compare two values, returning an Ordering if they can be
-- compared, or Nothing if they cannot.
compareValues :: Has (Throw Exn) sig m => Value -> Value -> m Ordering
-- | Values with different types were compared; this should not be possible
-- since the type system should catch it.
incompatCmp :: Has (Throw Exn) sig m => Value -> Value -> m a
-- | Values were compared of a type which cannot be compared (e.g.
-- functions, etc.).
incomparable :: Has (Throw Exn) sig m => Value -> Value -> m a
-- | Evaluate the application of an arithmetic operator, returning an
-- exception in the case of a failing operation, or in case we
-- incorrectly use it on a bad Const in the library.
evalArith :: Has (Throw Exn) sig m => Const -> Integer -> Integer -> m Integer
-- | Perform an integer division, but return Nothing for division
-- by zero.
safeDiv :: Has (Throw Exn) sig m => Integer -> Integer -> m Integer
-- | Perform exponentiation, but return Nothing if the power is
-- negative.
safeExp :: Has (Throw Exn) sig m => Integer -> Integer -> m Integer
-- | Update the global list of discovered entities, and check for new
-- recipes.
updateDiscoveredEntities :: HasRobotStepState sig m => Entity -> m ()
-- | Update the availableRecipes list. This implementation is not
-- efficient: * Every time we discover a new entity, we iterate through
-- the entire list of recipes to see which ones we can make. Trying to do
-- something more clever seems like it would definitely be a case of
-- premature optimization. One doesn't discover new entities all that
-- often. * For each usable recipe, we do a linear search through the
-- list of known recipes to see if we already know it. This is a little
-- more troubling, since it's quadratic in the number of recipes. But it
-- probably doesn't really make that much difference until we get up to
-- thousands of recipes.
updateAvailableRecipes :: Has (State GameState) sig m => (Inventory, Inventory) -> Entity -> m ()
updateAvailableCommands :: Has (State GameState) sig m => Entity -> m ()
instance GHC.Show.Show Swarm.Game.Step.GrabbingCmd
instance GHC.Classes.Eq Swarm.Game.Step.GrabbingCmd
-- | Query current and upstream Swarm version.
module Swarm.Version
-- | Check that the tag follows the PVP versioning policy.
--
-- Note that this filters out VS Code plugin releases.
isSwarmReleaseTag :: String -> Bool
version :: String
-- | Read Swarm tag as Version.
--
-- Swarm tags follow the PVP versioning scheme, so comparing them makes
-- sense.
--
--
-- >>> map (first versionBranch) $ readP_to_S parseVersion "0.1.0.0"
-- [([0],".1.0.0"),([0,1],".0.0"),([0,1,0],".0"),([0,1,0,0],"")]
--
-- >>> Version [0,0,0,1] [] < tagToVersion "0.1.0.0"
-- True
--
tagToVersion :: String -> Version
-- | Get the current upstream release version if any.
upstreamReleaseVersion :: IO (Either NewReleaseFailure String)
-- | Get a newer upstream release version.
--
-- This function can fail if the current branch is not main, if there is
-- no Internet connection or no newer release.
getNewerReleaseVersion :: Maybe GitInfo -> IO (Either NewReleaseFailure String)
data NewReleaseFailure
[FailedReleaseQuery] :: String -> NewReleaseFailure
[NoMainUpstreamRelease] :: [String] -> NewReleaseFailure
[OnDevelopmentBranch] :: String -> NewReleaseFailure
[OldUpstreamRelease] :: Version -> Version -> NewReleaseFailure
instance GHC.Show.Show Swarm.Version.NewReleaseFailure
-- | Application state for the brick-based Swarm TUI.
module Swarm.TUI.Model
-- | AppEvent represents a type for custom event types our app can
-- receive. The primary custom event Frame is sent by a separate
-- thread as fast as it can, telling the TUI to render a new frame.
data AppEvent
Frame :: AppEvent
Web :: WebCommand -> AppEvent
UpstreamVersion :: Either NewReleaseFailure String -> AppEvent
newtype WebCommand
RunWebCode :: Text -> WebCommand
data FocusablePanel
-- | The panel containing the REPL.
REPLPanel :: FocusablePanel
-- | The panel containing the world view.
WorldPanel :: FocusablePanel
-- | The panel containing the world editor controls.
WorldEditorPanel :: FocusablePanel
-- | The panel showing robot info and inventory on the top left.
RobotPanel :: FocusablePanel
-- | The info panel on the bottom left.
InfoPanel :: FocusablePanel
-- | Name represents names to uniquely identify various components
-- of the UI, such as forms, panels, caches, extents, lists, and buttons.
data Name
FocusablePanel :: FocusablePanel -> Name
-- | An individual control within the world editor panel.
WorldEditorPanelControl :: WorldEditorFocusable -> Name
-- | The REPL input form.
REPLInput :: Name
-- | The render cache for the world view.
WorldCache :: Name
-- | The cached extent for the world view.
WorldExtent :: Name
-- | The cursor/viewCenter display in the bottom left of the World view
WorldPositionIndicator :: Name
-- | The list of possible entities to paint a map with.
EntityPaintList :: Name
-- | The entity paint item position in the EntityPaintList.
EntityPaintListItem :: Int -> Name
-- | The list of possible terrain materials.
TerrainList :: Name
-- | The terrain item position in the TerrainList.
TerrainListItem :: Int -> Name
-- | The list of inventory items for the currently focused robot.
InventoryList :: Name
-- | The inventory item position in the InventoryList.
InventoryListItem :: Int -> Name
-- | The list of main menu choices.
MenuList :: Name
-- | The list of achievements.
AchievementList :: Name
-- | An individual control within the scenario launch config panel
ScenarioConfigControl :: ScenarioConfigPanel -> Name
-- | The list of goals/objectives.
GoalWidgets :: GoalWidget -> Name
-- | The list of scenario choices.
ScenarioList :: Name
-- | The scrollable viewport for the info panel.
InfoViewport :: Name
-- | The scrollable viewport for any modal dialog.
ModalViewport :: Name
-- | A clickable button in a modal dialog.
Button :: Button -> Name
data ModalType
HelpModal :: ModalType
RecipesModal :: ModalType
CommandsModal :: ModalType
MessagesModal :: ModalType
EntityPaletteModal :: ModalType
TerrainPaletteModal :: ModalType
RobotsModal :: ModalType
ScenarioEndModal :: ScenarioOutcome -> ModalType
QuitModal :: ModalType
KeepPlayingModal :: ModalType
DescriptionModal :: Entity -> ModalType
GoalModal :: ModalType
data ScenarioOutcome
WinModal :: ScenarioOutcome
LoseModal :: ScenarioOutcome
-- | Clickable buttons in modal dialogs.
data Button
CancelButton :: Button
KeepPlayingButton :: Button
StartOverButton :: Button
QuitButton :: Button
NextButton :: Button
data ButtonAction
Cancel :: ButtonAction
KeepPlaying :: ButtonAction
StartOver :: Seed -> ScenarioInfoPair -> ButtonAction
QuitAction :: ButtonAction
Next :: ScenarioInfoPair -> ButtonAction
data Modal
Modal :: ModalType -> Dialog ButtonAction Name -> Modal
[_modalType] :: Modal -> ModalType
[_modalDialog] :: Modal -> Dialog ButtonAction Name
modalType :: Lens' Modal ModalType
modalDialog :: Lens' Modal (Dialog ButtonAction Name)
data MainMenuEntry
NewGame :: MainMenuEntry
Tutorial :: MainMenuEntry
Achievements :: MainMenuEntry
Messages :: MainMenuEntry
About :: MainMenuEntry
Quit :: MainMenuEntry
mainMenu :: MainMenuEntry -> List Name MainMenuEntry
data Menu
-- | We started playing directly from command line, no menu to show
NoMenu :: Menu
MainMenu :: List Name MainMenuEntry -> Menu
-- | Stack of scenario item lists. INVARIANT: the currently selected menu
-- item is ALWAYS the same as the scenario currently being played. See
-- https://github.com/swarm-game/swarm/issues/1064 and
-- https://github.com/swarm-game/swarm/pull/1065.
NewGameMenu :: NonEmpty (List Name ScenarioItem) -> Menu
AchievementsMenu :: List Name CategorizedAchievement -> Menu
MessagesMenu :: Menu
AboutMenu :: Menu
_NewGameMenu :: Prism' Menu (NonEmpty (List Name ScenarioItem))
-- | Create a brick List of scenario items from a
-- ScenarioCollection.
mkScenarioList :: Bool -> ScenarioCollection -> List Name ScenarioItem
-- | Given a ScenarioCollection and a FilePath which is the
-- canonical path to some folder or scenario, construct a
-- NewGameMenu stack focused on the given item, if possible.
mkNewGameMenu :: Bool -> ScenarioCollection -> FilePath -> Maybe Menu
-- | An item in the REPL history.
data REPLHistItem
-- | Something entered by the user.
REPLEntry :: Text -> REPLHistItem
-- | A response printed by the system.
REPLOutput :: Text -> REPLHistItem
-- | Get the text of REPL input/output.
replItemText :: REPLHistItem -> Text
-- | Useful helper function to filter out REPL output.
isREPLEntry :: REPLHistItem -> Bool
-- | Useful helper function to only get user input text.
getREPLEntry :: REPLHistItem -> Maybe Text
-- | History of the REPL with indices (0 is first entry) to the current
-- line and to the first entry since loading saved history. We also
-- (ab)use the length of the REPL as the index of current input line,
-- since that number is one past the index of last entry.
data REPLHistory
-- | The current index in the REPL history (if the user is going back
-- through the history using up/down keys).
replIndex :: Lens' REPLHistory Int
-- | Current number lines of the REPL history - (ab)used as index of input
-- buffer.
replLength :: REPLHistory -> Int
-- | Sequence of REPL inputs and outputs, oldest entry is leftmost.
replSeq :: Lens' REPLHistory (Seq REPLHistItem)
-- | Create new REPL history (i.e. from loaded history file lines).
newREPLHistory :: [REPLHistItem] -> REPLHistory
-- | Add new REPL input - the index must have been pointing one past the
-- last element already, so we increment it to keep it that way.
addREPLItem :: REPLHistItem -> REPLHistory -> REPLHistory
-- | Point the start of REPL history after current last line. See
-- replStart.
restartREPLHistory :: REPLHistory -> REPLHistory
-- | Get the latest N items in history, starting with the oldest one.
--
-- This is used to show previous REPL lines in UI, so we need the items
-- sorted in the order they were entered and will be drawn top to bottom.
getLatestREPLHistoryItems :: Int -> REPLHistory -> [REPLHistItem]
moveReplHistIndex :: TimeDir -> Text -> REPLHistory -> REPLHistory
getCurrentItemText :: REPLHistory -> Maybe Text
replIndexIsAtInput :: REPLHistory -> Bool
data TimeDir
Newer :: TimeDir
Older :: TimeDir
-- | This data type tells us how to interpret the text typed by the player
-- at the prompt (which is stored in Editor).
data REPLPrompt
-- | Interpret the prompt text as a regular command. The list is for
-- potential completions, which we can cycle through by hitting Tab
-- repeatedly
CmdPrompt :: [Text] -> REPLPrompt
-- | Interpret the prompt text as "search this text in history"
SearchPrompt :: REPLHistory -> REPLPrompt
-- | Given some text, removes the REPLEntry within REPLHistory which is
-- equal to that. This is used when the user enters in search mode and
-- want to traverse the history. If a command has been used many times,
-- the history will be populated with it causing the effect that search
-- command always finds the same command.
removeEntry :: Text -> REPLHistory -> REPLHistory
-- | An entry in the inventory list displayed in the info panel. We can
-- either have an entity with a count in the robot's inventory, an entity
-- equipped on the robot, or a labelled separator. The purpose of the
-- separators is to show a clear distinction between the robot's
-- inventory and its equipped devices.
data InventoryListEntry
Separator :: Text -> InventoryListEntry
InventoryEntry :: Count -> Entity -> InventoryListEntry
EquippedEntry :: Entity -> InventoryListEntry
_Separator :: Prism' InventoryListEntry Text
_InventoryEntry :: Prism' InventoryListEntry (Count, Entity)
_EquippedEntry :: Prism' InventoryListEntry Entity
data REPLState
-- | What is being done with user input to the REPL panel?
data ReplControlMode
-- | The user is typing at the REPL.
Typing :: ReplControlMode
-- | The user is driving the base using piloting mode.
Piloting :: ReplControlMode
-- | A custom user key handler is processing user input.
Handling :: ReplControlMode
-- | The way we interpret text typed by the player in the REPL prompt.
replPromptType :: Lens' REPLState REPLPrompt
-- | The prompt where the user can type input at the REPL.
replPromptEditor :: Lens' REPLState (Editor Text Name)
-- | Convinience lens to get text from editor and replace it with new one
-- that has the provided text.
replPromptText :: Lens' REPLState Text
-- | Whether the prompt text is a valid Term.
replValid :: Lens' REPLState Bool
-- | The last thing the user has typed which isn't part of the history.
-- This is used to restore the repl form after the user visited the
-- history.
replLast :: Lens' REPLState Text
-- | The type of the current REPL input which should be displayed to the
-- user (if any).
replType :: Lens' REPLState (Maybe Polytype)
-- | The current REPL control mode, i.e. how user input to the REPL panel
-- is being handled.
replControlMode :: Lens' REPLState ReplControlMode
-- | History of things the user has typed at the REPL, interleaved with
-- outputs the system has generated.
replHistory :: Lens' REPLState REPLHistory
newREPLEditor :: Text -> Editor Text Name
-- | Given the focused robot, populate the UI inventory list in the info
-- panel with information about its inventory.
populateInventoryList :: MonadState UIState m => Maybe Robot -> m ()
infoScroll :: ViewportScroll Name
modalScroll :: ViewportScroll Name
data RuntimeState
-- | The port on which the HTTP debug service is running.
webPort :: Lens' RuntimeState (Maybe Port)
-- | The upstream release version.
upstreamRelease :: Lens' RuntimeState (Either NewReleaseFailure String)
-- | A log of runtime events.
--
-- This logging is separate from the logging done during game-play. If
-- some error happens before a game is even selected, this is the place
-- to log it.
eventLog :: Lens' RuntimeState (Notifications LogEntry)
-- | A collection of typechecked world DSL terms that are available to be
-- used in scenario definitions.
worlds :: Lens' RuntimeState WorldMap
-- | The collection of scenarios that comes with the game.
scenarios :: Lens' RuntimeState ScenarioCollection
-- | The standard entity map loaded from disk. Individual scenarios may
-- define additional entities which will get added to this map when
-- loading the scenario.
stdEntityMap :: Lens' RuntimeState EntityMap
-- | The standard list of recipes loaded from disk. Individual scenarios
-- may define additional recipes which will get added to this list when
-- loading the scenario.
stdRecipes :: Lens' RuntimeState [Recipe Entity]
-- | Free-form data loaded from the data directory, for things
-- like the logo, about page, tutorial story, etc.
appData :: Lens' RuntimeState (Map Text Text)
-- | List of words for use in building random robot names.
stdAdjList :: Lens' RuntimeState (Array Int Text)
-- | List of words for use in building random robot names.
stdNameList :: Lens' RuntimeState (Array Int Text)
-- | Simply log to the runtime event log.
logEvent :: LogSource -> (Text, RID) -> Text -> Notifications LogEntry -> Notifications LogEntry
-- | Create a GameStateConfig record from the RuntimeState.
mkGameStateConfig :: RuntimeState -> GameStateConfig
-- | The AppState just stores together the other states.
--
-- This is so you can use a smaller state when e.g. writing some game
-- logic or updating the UI. Also consider that GameState can change when
-- loading a new scenario - if the state should persist games, use
-- RuntimeState.
data AppState
AppState :: GameState -> UIState -> RuntimeState -> AppState
-- | The GameState record.
gameState :: Lens' AppState GameState
-- | The UIState record.
uiState :: Lens' AppState UIState
-- | The RuntimeState record
runtimeState :: Lens' AppState RuntimeState
-- | Command-line options for configuring the app.
data AppOpts
AppOpts :: Maybe Seed -> Maybe FilePath -> Maybe FilePath -> Bool -> Int -> Bool -> Maybe ColorMode -> Maybe Port -> Maybe GitInfo -> AppOpts
-- | Explicit seed chosen by the user.
[userSeed] :: AppOpts -> Maybe Seed
-- | Scenario the user wants to play.
[userScenario] :: AppOpts -> Maybe FilePath
-- | Code to be run on base.
[scriptToRun] :: AppOpts -> Maybe FilePath
-- | Automatically run the solution defined in the scenario file
[autoPlay] :: AppOpts -> Bool
-- | Initial game speed (logarithm)
[speed] :: AppOpts -> Int
-- | Should cheat mode be enabled?
[cheatMode] :: AppOpts -> Bool
-- | What colour mode should be used?
[colorMode] :: AppOpts -> Maybe ColorMode
-- | Explicit port on which to run the web API
[userWebPort] :: AppOpts -> Maybe Port
-- | Information about the Git repository (not present in release).
[repoGitInfo] :: AppOpts -> Maybe GitInfo
-- | A default/empty AppOpts record.
defaultAppOpts :: AppOpts
type Seed = Int
data ColorMode
NoColor :: ColorMode
ColorMode8 :: ColorMode
ColorMode16 :: ColorMode
ColorMode240 :: !Word8 -> ColorMode
FullColor :: ColorMode
-- | Context for the REPL commands to execute in. Contains the base robot
-- context plus the it variable that refer to the previously
-- computed values. (Note that `it{n}` variables are set in the base
-- robot context; we only set it here because it's so transient)
topContext :: AppState -> RobotContext
-- | Get the currently focused InventoryListEntry from the robot
-- info panel (if any).
focusedItem :: AppState -> Maybe InventoryListEntry
-- | Get the currently focused entity from the robot info panel (if any).
-- This is just like focusedItem but forgets the distinction
-- between plain inventory items and equipped devices.
focusedEntity :: AppState -> Maybe Entity
-- | Extract the scenario which would come next in the menu from the
-- currently selected scenario (if any). Can return Nothing if
-- either we are not in the NewGameMenu, or the current scenario
-- is the last among its siblings.
nextScenario :: Menu -> Maybe ScenarioInfoPair
initRuntimeState :: (Has (Throw SystemFailure) sig m, Has (Accum (Seq SystemFailure)) sig m, Has (Lift IO) sig m) => m RuntimeState
instance GHC.Show.Show Swarm.TUI.Model.WebCommand
instance GHC.Show.Show Swarm.TUI.Model.AppEvent
module Swarm.TUI.View.Achievement
padAllEvenly :: Int -> Widget Name -> Widget Name
getCompletionIcon :: Bool -> Widget Name
drawAchievementsMenuUI :: AppState -> List Name CategorizedAchievement -> Widget Name
drawAchievementListItem :: Map CategorizedAchievement Attainment -> CategorizedAchievement -> Widget Name
singleAchievementDetails :: Map CategorizedAchievement Attainment -> CategorizedAchievement -> Widget Name
module Swarm.TUI.Editor.Util
getEntitiesForList :: EntityMap -> Vector EntityFacade
getEditingBounds :: WorldDescription -> (Bool, Cosmic BoundsRectangle)
getContentAt :: WorldEditor Name -> MultiWorld Int Entity -> Cosmic Coords -> (TerrainType, Maybe EntityPaint)
getTerrainAt :: WorldEditor Name -> MultiWorld Int Entity -> Cosmic Coords -> TerrainType
isOutsideTopLeftCorner :: Coords -> Coords -> Bool
isOutsideBottomRightCorner :: Coords -> Coords -> Bool
isOutsideRegion :: BoundsRectangle -> Coords -> Bool
getEditedMapRectangle :: WorldEditor Name -> Maybe (Cosmic BoundsRectangle) -> MultiWorld Int Entity -> [[CellPaintDisplay]]
module Swarm.TUI.Model.StateUpdate
-- | Initialize the AppState from scratch.
initAppState :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => AppOpts -> m AppState
-- | Initialize the more persistent parts of the app state, i.e. the
-- RuntimeState and UIState. This is split out into a
-- separate function so that in the integration test suite we can call
-- this once and reuse the resulting states for all tests.
initPersistentState :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => AppOpts -> m (RuntimeState, UIState)
-- | Construct an AppState from an already-loaded
-- RuntimeState and UIState, given the AppOpts the
-- app was started with.
constructAppState :: (Has (Throw SystemFailure) sig m, Has (Lift IO) sig m) => RuntimeState -> UIState -> AppOpts -> m AppState
-- | Create an initial app state for a specific scenario. Note that this
-- function is used only for unit tests, integration tests, and
-- benchmarks.
--
-- In normal play, an AppState already exists and we simply need
-- to update it using scenarioToAppState.
initAppStateForScenario :: String -> Maybe Seed -> Maybe FilePath -> ExceptT Text IO AppState
-- | For convenience, the AppState corresponding to the classic game
-- with seed 0. This is used only for benchmarks and unit tests.
classicGame0 :: ExceptT Text IO AppState
-- | Load a Scenario and start playing the game.
startGame :: (MonadIO m, MonadState AppState m) => ScenarioInfoPair -> Maybe CodeToRun -> m ()
-- | Load a Scenario and start playing the game, with the
-- possibility for the user to override the seed.
startGameWithSeed :: (MonadIO m, MonadState AppState m) => ScenarioInfoPair -> ValidatedLaunchParams -> m ()
-- | Re-initialize the game from the stored reference to the current
-- scenario.
--
-- Note that "restarting" is intended only for "scenarios"; with some
-- scenarios, it may be possible to get stuck so that it is either
-- impossible or very annoying to win, so being offered an option to
-- restart is more user-friendly.
--
-- Since scenarios are stored as a Maybe in the UI state, we handle the
-- Nothing case upstream so that the Scenario passed to this function
-- definitely exists.
restartGame :: (MonadIO m, MonadState AppState m) => Seed -> ScenarioInfoPair -> m ()
attainAchievement :: (MonadIO m, MonadState AppState m) => CategorizedAchievement -> m ()
attainAchievement' :: (MonadIO m, MonadState AppState m) => ZonedTime -> Maybe FilePath -> CategorizedAchievement -> m ()
-- | Modify the AppState appropriately when starting a new scenario.
scenarioToAppState :: (MonadIO m, MonadState AppState m) => ScenarioInfoPair -> ValidatedLaunchParams -> m ()
module Swarm.TUI.Editor.Masking
shouldHideWorldCell :: UIState -> Coords -> Bool
-- | Rendering of cells in the map view
--
-- SPDX-License-Identifier: BSD-3-Clause
module Swarm.TUI.View.CellDisplay
-- | Render a display as a UI widget.
renderDisplay :: Display -> Widget n
-- | Render the Display for a specific location.
drawLoc :: UIState -> GameState -> Cosmic Coords -> Widget Name
displayTerrainCell :: WorldEditor Name -> GameState -> Cosmic Coords -> Display
displayRobotCell :: GameState -> Cosmic Coords -> [Display]
displayEntityCell :: WorldEditor Name -> GameState -> Cosmic Coords -> [Display]
data HideEntity
HideAllEntities :: HideEntity
HideNoEntity :: HideEntity
HideEntityUnknownTo :: Robot -> HideEntity
hidingMode :: GameState -> HideEntity
-- | Get the Display for a specific location, by combining the
-- Displays for the terrain, entity, and robots at the location,
-- and taking into account "static" based on the distance to the robot
-- being viewed.
displayLoc :: Bool -> WorldEditor Name -> GameState -> Cosmic Coords -> Display
-- | Get the Display for a specific location, by combining the
-- Displays for the terrain, entity, and robots at the location.
displayLocRaw :: Bool -> WorldEditor Name -> GameState -> Cosmic Coords -> Display
-- | Random "static" based on the distance to the robot being
-- viewed.
staticDisplay :: GameState -> Coords -> Display
-- | Draw static given a number from 0-15 representing the state of the
-- four quarter-pixels in a cell
displayStatic :: Word32 -> Display
-- | Given a value from 0--15, considered as 4 bits, pick the character
-- with the corresponding quarter pixels turned on.
staticChar :: Word32 -> Char
-- | Random "static" based on the distance to the robot being
-- viewed. A cell can either be static-free (represented by
-- Nothing) or can have one of sixteen values (representing the
-- state of the four quarter-pixels in one cell).
getStatic :: GameState -> Coords -> Maybe Word32
module Swarm.TUI.View.Util
-- | Generate a fresh modal window of the requested type.
generateModal :: AppState -> ModalType -> Modal
-- | Render the type of the current REPL input to be shown to the user.
drawType :: Polytype -> Widget Name
-- | Draw markdown document with simple codebolditalic attributes.
--
-- TODO: #574 Code blocks should probably be handled separately.
drawMarkdown :: Document Syntax -> Widget Name
drawLabeledTerrainSwatch :: TerrainType -> Widget Name
descriptionTitle :: Entity -> String
-- | Width cap for modal and error message windows
maxModalWindowWidth :: Int
-- | Get the name of the current New Game menu.
curMenuName :: AppState -> Maybe Text
quitMsg :: Menu -> Text
locationToString :: Location -> String
-- | Display a list of text-wrapped paragraphs with one blank line after
-- each.
displayParagraphs :: [Text] -> Widget Name
-- | Display a list of paragraphs with one blank line after each.
--
-- For the common case of `[Text]` use displayParagraphs.
layoutParagraphs :: [Widget Name] -> Widget Name
data EllipsisSide
Beginning :: EllipsisSide
End :: EllipsisSide
withEllipsis :: EllipsisSide -> Text -> Widget Name
-- | Make a widget scrolling if it is bigger than the available vertical
-- space. Thanks to jtdaugherty for this code.
maybeScroll :: (Ord n, Show n) => n -> Widget n -> Widget n
-- | Display logic for Objectives.
module Swarm.TUI.View.Objective
makeListWidget :: GoalTracking -> List Name GoalEntry
renderGoalsDisplay :: GoalDisplay -> Widget Name
getCompletionIcon :: Objective -> GoalStatus -> Widget Name
drawGoalListItem :: Bool -> GoalEntry -> Widget Name
singleGoalDetails :: GoalEntry -> Widget Name
-- | Rendering of the scenario launch configuration dialog.
module Swarm.TUI.Launch.View
drawFileBrowser :: FileBrowser Name -> Widget Name
optionDescription :: ScenarioConfigPanelFocusable -> Maybe Text
drawLaunchConfigPanel :: LaunchOptions -> [Widget Name]
module Swarm.TUI.Editor.View
drawWorldEditor :: FocusRing Name -> UIState -> Widget Name
drawLabeledEntitySwatch :: EntityFacade -> Widget Name
drawTerrainSelector :: AppState -> Widget Name
listDrawTerrainElement :: Int -> Bool -> TerrainType -> Widget Name
drawEntityPaintSelector :: AppState -> Widget Name
listDrawEntityPaintElement :: Int -> Bool -> EntityFacade -> Widget Name
module Swarm.TUI.Controller.Util
-- | Pattern synonyms to simplify brick event handler
pattern Key :: Key -> BrickEvent n e
pattern CharKey :: Char -> BrickEvent n e
pattern ControlChar :: Char -> BrickEvent n e
pattern MetaChar :: Char -> BrickEvent n e
pattern ShiftKey :: Key -> BrickEvent n e
pattern EscapeKey :: BrickEvent n e
pattern BackspaceKey :: BrickEvent n e
pattern FKey :: Int -> BrickEvent n e
openModal :: ModalType -> EventM Name AppState ()
-- | The running modals do not autopause the game.
isRunningModal :: ModalType -> Bool
setFocus :: FocusablePanel -> EventM Name AppState ()
immediatelyRedrawWorld :: EventM Name AppState ()
-- | Make sure all tiles covering the visible part of the world are loaded.
loadVisibleRegion :: EventM Name AppState ()
mouseLocToWorldCoords :: Location -> EventM Name GameState (Maybe (Cosmic Coords))
-- | Event handling for the scenario launch configuration dialog.
module Swarm.TUI.Launch.Controller
updateFocusRing :: EditingLaunchParams -> EventM Name LaunchOptions ()
cacheValidatedInputs :: EventM Name LaunchOptions ()
-- | Split this out from the combined parameter-validation function because
-- validating the seed is cheap, and shouldn't have to pay the cost of
-- re-parsing script code as the user types in the seed selection field.
cacheValidatedSeedInput :: EventM Name LaunchOptions ()
-- | If the FileBrowser is in "search mode", then we allow more of the key
-- events to pass through. Otherwise, we intercept things like "q" (for
-- quit) and Space (so that we can restrict file selection to at most
-- one).
handleFBEvent :: BrickEvent Name AppEvent -> EventM Name AppState ()
handleLaunchOptionsEvent :: ScenarioInfoPair -> BrickEvent Name AppEvent -> EventM Name AppState ()
module Swarm.TUI.Editor.Controller
activateWorldEditorFunction :: WorldEditorFocusable -> EventM Name AppState ()
handleCtrlLeftClick :: Location -> EventM Name AppState ()
handleRightClick :: Location -> EventM Name AppState ()
-- | "Eye Dropper" tool:
handleMiddleClick :: Location -> EventM Name AppState ()
-- | Handle user input events in the robot panel.
handleWorldEditorPanelEvent :: BrickEvent Name AppEvent -> EventM Name AppState ()
-- | Return value: whether the cursor position should be updated
updateAreaBounds :: Maybe (Cosmic Coords) -> EventM Name AppState Bool
saveMapFile :: EventM Name AppState ()
-- | Event handlers for the TUI.
module Swarm.TUI.Controller
-- | The top-level event handler for the TUI.
handleEvent :: BrickEvent Name AppEvent -> EventM Name AppState ()
-- | Quit a game.
--
--
-- - writes out the updated REPL history to a .swarm_history
-- file
-- - saves current scenario status (InProgress/Completed)
-- - advances the menu to the next scenario IF the current one was
-- won
-- - returns to the previous menu
--
quitGame :: EventM Name AppState ()
-- | Run the game for a single frame (i.e. screen redraw),
-- then update the UI. Depending on how long it is taking to draw each
-- frame, and how many ticks per second we are trying to achieve, this
-- may involve stepping the game any number of ticks (including zero).
runFrameUI :: EventM Name AppState ()
-- | Run the game for a single frame, without updating the UI.
runFrame :: EventM Name AppState ()
ticksPerFrameCap :: Int
-- | Do zero or more ticks, with each tick notionally taking the given
-- timestep, until we have used up all available accumulated time, OR
-- until we have hit the cap on ticks per frame, whichever comes first.
runFrameTicks :: TimeSpec -> EventM Name AppState ()
-- | Run the game for a single tick, and update the UI.
runGameTickUI :: EventM Name AppState ()
-- | Run the game for a single tick (without updating the UI). Every
-- robot is given a certain amount of maximum computation to perform a
-- single world action (like moving, turning, grabbing, etc.).
runGameTick :: EventM Name AppState ()
-- | Update the UI. This function is used after running the game for some
-- number of ticks.
updateUI :: EventM Name AppState Bool
runBaseWebCode :: MonadState AppState m => Text -> m ()
-- | Handle a user input event for the REPL.
handleREPLEvent :: BrickEvent Name AppEvent -> EventM Name AppState ()
-- | Validate the REPL input when it changes: see if it parses and
-- typechecks, and set the color accordingly.
validateREPLForm :: AppState -> AppState
-- | Update our current position in the REPL history.
adjReplHistIndex :: TimeDir -> AppState -> AppState
data TimeDir
Newer :: TimeDir
Older :: TimeDir
-- | Handle a user input event in the world view panel.
handleWorldEvent :: BrickEvent Name AppEvent -> EventM Name AppState ()
-- | Convert a directional key into a direction.
keyToDir :: Key -> Heading
-- | Manually scroll the world view.
scrollView :: (Location -> Location) -> EventM Name AppState ()
-- | Adjust the ticks per second speed.
adjustTPS :: (Int -> Int -> Int) -> AppState -> AppState
-- | Handle user events in the info panel (just scrolling).
handleInfoPanelEvent :: ViewportScroll Name -> BrickEvent Name AppEvent -> EventM Name AppState ()
getTutorials :: ScenarioCollection -> ScenarioCollection
instance GHC.Classes.Eq Swarm.TUI.Controller.CompletionType
-- | Code for drawing the TUI.
module Swarm.TUI.View
-- | The main entry point for drawing the entire UI. Figures out which menu
-- screen we should show (if any), or just the game itself.
drawUI :: AppState -> [Widget Name]
-- | Draw info about the current number of ticks per second.
drawTPS :: AppState -> Widget Name
-- | Draw the error dialog window, if it should be displayed right now.
drawDialog :: AppState -> Widget Name
-- | Hide the cursor when a modal is set
chooseCursor :: AppState -> [CursorLocation n] -> Maybe (CursorLocation n)
-- | Draw a menu explaining what key commands are available for the current
-- panel. This menu is displayed as one or two lines in between the world
-- panel and the REPL.
--
-- This excludes the F-key modals that are shown elsewhere.
drawKeyMenu :: AppState -> Widget Name
-- | Draw the F-key modal menu. This is displayed in the top left world
-- corner.
drawModalMenu :: AppState -> Widget Name
-- | Draw a single key command in the menu.
drawKeyCmd :: (KeyHighlight, Text, Text) -> Widget Name
-- | Draw the current world view.
drawWorld :: UIState -> GameState -> Widget Name
-- | Draw info about the currently focused robot, such as its name,
-- position, orientation, and inventory, as long as it is not too far
-- away.
drawRobotPanel :: AppState -> Widget Name
-- | Draw an inventory entry.
drawItem :: Maybe Int -> Int -> Bool -> InventoryListEntry -> Widget Name
-- | Draw the name of an entity, labelled with its visual representation as
-- a cell in the world.
drawLabelledEntityName :: Entity -> Widget Name
-- | Draw the info panel in the bottom-left corner, which shows info about
-- the currently focused inventory item.
drawInfoPanel :: AppState -> Widget Name
-- | Display info about the currently focused inventory entity, such as its
-- description and relevant recipes.
explainFocusedItem :: AppState -> Widget Name
-- | Draw the REPL.
drawREPL :: AppState -> Widget Name
-- | Assess pedagogical soundness of the tutorials.
--
-- Approach: 1. Obtain a list of all of the tutorial scenarios, in order
-- 2. Search their "solution" code for commands 3. "fold" over
-- the tutorial list, noting which tutorial was first to introduce each
-- command
module Swarm.Doc.Pedagogy
renderTutorialProgression :: IO Text
-- | Extract the tutorials from the complete scenario collection and derive
-- their command coverage info.
generateIntroductionsSequence :: ScenarioCollection -> [CoverageInfo]
-- | Tutorials augmented by the set of commands that they introduce.
-- Generated by folding over all of the tutorials in sequence.
data CoverageInfo
CoverageInfo :: TutorialInfo -> Map Const [SrcLoc] -> CoverageInfo
[tutInfo] :: CoverageInfo -> TutorialInfo
[novelSolutionCommands] :: CoverageInfo -> Map Const [SrcLoc]
-- | Tutorial scenarios with the set of commands introduced in their
-- solution and descriptions having been extracted
data TutorialInfo
TutorialInfo :: ScenarioInfoPair -> Int -> Map Const [SrcLoc] -> Set Const -> TutorialInfo
[scenarioPair] :: TutorialInfo -> ScenarioInfoPair
[tutIndex] :: TutorialInfo -> Int
[solutionCommands] :: TutorialInfo -> Map Const [SrcLoc]
[descriptionCommands] :: TutorialInfo -> Set Const
module Swarm.Doc.Gen
generateDocs :: GenerateDocs -> IO ()
data GenerateDocs
-- | Entity dependencies by recipes.
[RecipeGraph] :: GenerateDocs
-- | Keyword lists for editors.
[EditorKeywords] :: Maybe EditorType -> GenerateDocs
-- | List of special key names recognized by key command
[SpecialKeyNames] :: GenerateDocs
[CheatSheet] :: PageAddress -> Maybe SheetType -> GenerateDocs
-- | List command introductions by tutorial
[TutorialCoverage] :: GenerateDocs
data EditorType
Emacs :: EditorType
VSCode :: EditorType
data SheetType
Entities :: SheetType
Commands :: SheetType
Capabilities :: SheetType
Recipes :: SheetType
-- | Get formatted list of basic functions/commands.
keywordsCommands :: EditorType -> Text
-- | Get formatted list of directions.
keywordsDirections :: EditorType -> Text
operatorNames :: Text
builtinFunctionList :: EditorType -> Text
editorList :: EditorType -> [Text] -> Text
data PageAddress
PageAddress :: Text -> Text -> Text -> Text -> PageAddress
[entityAddress] :: PageAddress -> Text
[commandsAddress] :: PageAddress -> Text
[capabilityAddress] :: PageAddress -> Text
[recipesAddress] :: PageAddress -> Text
commandsPage :: Text
capabilityPage :: PageAddress -> EntityMap -> Text
noPageAddresses :: PageAddress
instance GHC.Enum.Bounded Swarm.Doc.Gen.EditorType
instance GHC.Enum.Enum Swarm.Doc.Gen.EditorType
instance GHC.Show.Show Swarm.Doc.Gen.EditorType
instance GHC.Classes.Eq Swarm.Doc.Gen.EditorType
instance GHC.Enum.Bounded Swarm.Doc.Gen.SheetType
instance GHC.Enum.Enum Swarm.Doc.Gen.SheetType
instance GHC.Show.Show Swarm.Doc.Gen.SheetType
instance GHC.Classes.Eq Swarm.Doc.Gen.SheetType
instance GHC.Show.Show Swarm.Doc.Gen.PageAddress
instance GHC.Classes.Eq Swarm.Doc.Gen.PageAddress
instance GHC.Show.Show Swarm.Doc.Gen.GenerateDocs
instance GHC.Classes.Eq Swarm.Doc.Gen.GenerateDocs
-- | A web service for Swarm.
--
-- The service can be started using the `--port 5357` command line
-- argument, or through the REPL by calling demoWeb.
--
-- Once running, here are the available endpoints:
--
--
-- - /robots : return the list of robots
-- - robotID : return a single robot identified by its id
--
--
-- Missing endpoints:
--
--
-- - TODO: #625 run endpoint to load definitions
-- - TODO: #493 export the whole game state
--
module Swarm.Web
newtype RobotID
RobotID :: Int -> RobotID
type SwarmAPI = "robots" :> Get '[JSON] [Robot] :<|> "robot" :> Capture "id" RobotID :> Get '[JSON] (Maybe Robot) :<|> "goals" :> "prereqs" :> Get '[JSON] [PrereqSatisfaction] :<|> "goals" :> "active" :> Get '[JSON] [Objective] :<|> "goals" :> "graph" :> Get '[JSON] (Maybe GraphInfo) :<|> "goals" :> "uigoal" :> Get '[JSON] GoalTracking :<|> "goals" :> Get '[JSON] WinCondition :<|> "code" :> "render" :> ReqBody '[PlainText] Text :> Post '[PlainText] Text :<|> "code" :> "run" :> ReqBody '[PlainText] Text :> Post '[PlainText] Text :<|> "repl" :> "history" :> "full" :> Get '[JSON] [REPLHistItem]
swarmApi :: Proxy SwarmAPI
type ToplevelAPI = SwarmAPI :<|> Raw
api :: Proxy ToplevelAPI
docsBS :: ByteString
mkApp :: ReadableIORef AppState -> BChan AppEvent -> Server SwarmAPI
-- | Simple result type to report errors from forked startup thread.
data WebStartResult
WebStarted :: WebStartResult
WebStartError :: String -> WebStartResult
webMain :: Maybe (MVar WebStartResult) -> Port -> ReadableIORef AppState -> BChan AppEvent -> IO ()
defaultPort :: Port
-- | Attempt to start a web thread on the requested port, or a default one
-- if none is requested (or don't start a web thread if the requested
-- port is 0). If an explicit port was requested, fail if startup doesn't
-- work. Otherwise, ignore the failure. In any case, return a Maybe
-- Port value representing whether a web server is actually running,
-- and if so, what port it is on.
startWebThread :: Maybe Port -> ReadableIORef AppState -> BChan AppEvent -> IO (Either String Port)
instance Web.Internal.HttpApiData.FromHttpApiData Swarm.Web.RobotID
instance Servant.Docs.Internal.ToCapture (Servant.API.Capture.Capture "id" Swarm.Web.RobotID)
instance Servant.Docs.Internal.ToSample Data.Text.Internal.Text
-- | Main entry point for the Swarm application.
module Swarm.App
type EventHandler = BrickEvent Name AppEvent -> EventM Name AppState ()
-- | The definition of the app used by the brick library.
app :: EventHandler -> App AppState AppEvent Name
-- | The main IO computation which initializes the state, sets up
-- some communication channels, and runs the UI.
appMain :: AppOpts -> IO ()
-- | A demo program to run the web service directly, without the terminal
-- application. This is useful to live update the code using `ghcid -W
-- --test "Swarm.App.demoWeb"`
demoWeb :: IO ()
-- | If available for the terminal emulator, enable bracketed paste mode.
enablePasteMode :: EventM n s ()