From 839a447abee88a4d6a546c0c032e30b793bafe2f Mon Sep 17 00:00:00 2001 From: Karl Ostmo Date: Sat, 16 Sep 2023 22:50:03 -0700 Subject: [PATCH] disambiguate doc links, elaborate waypoint ordering --- src/Swarm/Doc/Gen.hs | 2 +- src/Swarm/Game/Exception.hs | 8 ++--- src/Swarm/Game/Location.hs | 12 ++++---- src/Swarm/Game/Robot.hs | 17 ++++++----- src/Swarm/Game/Scenario/Style.hs | 2 ++ src/Swarm/Game/Scenario/Topography/Area.hs | 5 +++- .../Scenario/Topography/Navigation/Portal.hs | 6 ++-- .../Topography/Navigation/Waypoint.hs | 16 ++++++++++ .../Game/Scenario/Topography/Structure.hs | 2 +- src/Swarm/Game/ScenarioInfo.hs | 10 ++++--- src/Swarm/Game/State.hs | 8 ++--- src/Swarm/Game/Step.hs | 11 +++---- src/Swarm/Game/Step/Combustion.hs | 12 ++++---- src/Swarm/Game/Universe.hs | 15 ++++++++-- src/Swarm/Game/World/Coords.hs | 4 +-- src/Swarm/Game/World/Typecheck.hs | 4 +-- src/Swarm/Language/Direction.hs | 6 ++-- src/Swarm/Language/Key.hs | 6 ++-- src/Swarm/Language/Parse.hs | 8 ++--- src/Swarm/Language/Requirement.hs | 12 ++++---- src/Swarm/Language/Syntax.hs | 2 +- src/Swarm/Language/Text/Markdown.hs | 2 +- src/Swarm/TUI/Controller.hs | 4 +-- src/Swarm/TUI/Launch/Prep.hs | 10 +++---- src/Swarm/TUI/Model/Repl.hs | 18 ++++++------ src/Swarm/TUI/Model/UI.hs | 29 ++++++++++--------- src/Swarm/TUI/View.hs | 7 +++-- 27 files changed, 139 insertions(+), 99 deletions(-) diff --git a/src/Swarm/Doc/Gen.hs b/src/Swarm/Doc/Gen.hs index 80590b350..6feb33a1c 100644 --- a/src/Swarm/Doc/Gen.hs +++ b/src/Swarm/Doc/Gen.hs @@ -78,7 +78,7 @@ data GenerateDocs where RecipeGraph :: GenerateDocs -- | Keyword lists for editors. EditorKeywords :: Maybe EditorType -> GenerateDocs - -- | List of special key names recognized by 'key' command + -- | List of special key names recognized by 'Swarm.Language.Syntax.Key' command SpecialKeyNames :: GenerateDocs -- | Cheat sheets for inclusion on the Swarm wiki. CheatSheet :: PageAddress -> Maybe SheetType -> GenerateDocs diff --git a/src/Swarm/Game/Exception.hs b/src/Swarm/Game/Exception.hs index c12006cbf..f1b957117 100644 --- a/src/Swarm/Game/Exception.hs +++ b/src/Swarm/Game/Exception.hs @@ -51,7 +51,7 @@ import Witch (from) -- | Suggested way to fix things when a robot does not meet the -- requirements to run a command. data IncapableFix - = -- | Equip the missing device on yourself/target + = -- | 'Swarm.Language.Syntax.Equip' the missing device on yourself/target FixByEquip | -- | Add the missing device to your inventory FixByObtain @@ -72,11 +72,11 @@ data Exn -- term that caused the problem, and a suggestion for how to fix -- things. Incapable IncapableFix Requirements Term - | -- | A command failed in some "normal" way (/e.g./ a 'Move' - -- command could not move, or a 'Grab' command found nothing to + | -- | A command failed in some "normal" way (/e.g./ a 'Swarm.Language.Syntax.Move' + -- command could not move, or a 'Swarm.Language.Syntax.Grab' command found nothing to -- grab, /etc./). Can be caught by a @try@ block. CmdFailed Const Text (Maybe GameplayAchievement) - | -- | The user program explicitly called 'Undefined' or 'Fail'. Can + | -- | The user program explicitly called 'Swarm.Language.Syntax.Undefined' or 'Swarm.Language.Syntax.Fail'. Can -- be caught by a @try@ block. User Text deriving (Eq, Show, Generic, FromJSON, ToJSON) diff --git a/src/Swarm/Game/Location.hs b/src/Swarm/Game/Location.hs index cd677e96e..3df776c3f 100644 --- a/src/Swarm/Game/Location.hs +++ b/src/Swarm/Game/Location.hs @@ -52,17 +52,17 @@ import Swarm.Util qualified as Util -- >>> import Linear -- >>> import Swarm.Language.Direction --- | A Location is a pair of (x,y) coordinates, both up to 32 bits. +-- | A t'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 'Swarm.Game.World.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 'Swarm.Game.World.Coords'. +-- conversions between t'Location' and 'Swarm.Game.World.Coords'. type Location = Point V2 Int32 --- | A convenient way to pattern-match on 'Location' values. +-- | A convenient way to pattern-match on t'Location' values. pattern Location :: Int32 -> Int32 -> Location pattern Location x y = P (V2 x y) @@ -76,13 +76,13 @@ instance ToJSON Location where -- | A @Heading@ is a 2D vector, with 32-bit coordinates. -- --- 'Location' and 'Heading' are both represented using types from +-- t'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: -- -- * Two headings can be added with '^+^'. --- * The difference between two 'Location's is a 'Heading' (via '.-.'). --- * A 'Location' plus a 'Heading' is another 'Location' (via 'Linear.Affine..^+'). +-- * The difference between two t'Location's is a 'Heading' (via '.-.'). +-- * A t'Location' plus a 'Heading' is another t'Location' (via 'Linear.Affine..^+'). type Heading = V2 Int32 deriving instance ToJSON (V2 Int32) diff --git a/src/Swarm/Game/Robot.hs b/src/Swarm/Game/Robot.hs index 6b27d8057..aafd0004d 100644 --- a/src/Swarm/Game/Robot.hs +++ b/src/Swarm/Game/Robot.hs @@ -183,7 +183,8 @@ data ActivityCounts = ActivityCounts makeLensesNoSigs ''ActivityCounts -- | A counter that is decremented upon each step of the robot within the --- CESK machine. Initially set to 'robotStepsPerTick' at each new tick. +-- CESK machine. Initially set to 'Swarm.Game.State.robotStepsPerTick' +-- at each new tick. -- -- The need for 'tickStepBudget' is a bit technical, and I hope I can -- eventually find a different, better way to accomplish it. @@ -341,20 +342,20 @@ robotDisplay = lens getDisplay setDisplay -- | 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. +-- to update the 'Swarm.Game.State.robotsByLocation' map as well. You can use the +-- 'Swarm.Game.Step.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' +-- called directly except by the 'Swarm.Game.Step.updateRobotLocation' function. +-- The reason is that we need to make sure the 'Swarm.Game.State.robotsByLocation' -- map stays in sync. unsafeSetRobotLocation :: Cosmic Location -> Robot -> Robot unsafeSetRobotLocation loc r = r {_robotLocation = loc} -- | 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. +-- 'Swarm.Game.State.robotsByLocation' map to keep up-to-date. trobotLocation :: Lens' TRobot (Maybe (Cosmic Location)) trobotLocation = lens _robotLocation (\r l -> r {_robotLocation = l}) @@ -414,8 +415,8 @@ equippedDevices = lens _equippedDevices setEquipped } -- | 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 +-- Messages can be added both by explicit use of the 'Swarm.Language.Syntax.Log' command, +-- and by uncaught exceptions. Stored as a 'Seq' 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'. diff --git a/src/Swarm/Game/Scenario/Style.hs b/src/Swarm/Game/Scenario/Style.hs index 76af8442f..69c7471ed 100644 --- a/src/Swarm/Game/Scenario/Style.hs +++ b/src/Swarm/Game/Scenario/Style.hs @@ -32,6 +32,8 @@ instance FromJSON StyleFlag where instance ToJSON StyleFlag where toJSON = genericToJSON styleFlagJsonOptions +-- | Hexadecimal color notation. +-- May include a leading hash symbol (see 'Data.Colour.SRGB.sRGB24read'). newtype HexColor = HexColor Text deriving (Eq, Show, Generic, FromJSON, ToJSON) diff --git a/src/Swarm/Game/Scenario/Topography/Area.hs b/src/Swarm/Game/Scenario/Topography/Area.hs index 84e6ecc8e..678617184 100644 --- a/src/Swarm/Game/Scenario/Topography/Area.hs +++ b/src/Swarm/Game/Scenario/Topography/Area.hs @@ -10,6 +10,7 @@ import Data.Maybe (listToMaybe) import Linear (V2 (..)) import Swarm.Game.Location +-- | Height and width of a 2D map region data AreaDimensions = AreaDimensions { rectWidth :: Int32 , rectHeight :: Int32 @@ -22,7 +23,7 @@ renderRectDimensions (AreaDimensions w h) = invertY :: V2 Int32 -> V2 Int32 invertY (V2 x y) = V2 x (-y) --- | Incorporates an offset by -1, since the area is +-- | Incorporates an offset by @-1@, since the area is -- "inclusive" of the lower-right coordinate. -- Inverse of 'cornersToArea'. upperLeftToBottomRight :: AreaDimensions -> Location -> Location @@ -41,9 +42,11 @@ cornersToArea upperLeft lowerRight = where V2 x y = (+ 1) <$> invertY (lowerRight .-. upperLeft) +-- | Has zero width or height. isEmpty :: AreaDimensions -> Bool isEmpty (AreaDimensions w h) = w == 0 || h == 0 +-- | Extracts the dimensions of a map grid. getAreaDimensions :: [[a]] -> AreaDimensions getAreaDimensions cellGrid = AreaDimensions w h diff --git a/src/Swarm/Game/Scenario/Topography/Navigation/Portal.hs b/src/Swarm/Game/Scenario/Topography/Navigation/Portal.hs index e20f80bda..9bcae2a1e 100644 --- a/src/Swarm/Game/Scenario/Topography/Navigation/Portal.hs +++ b/src/Swarm/Game/Scenario/Topography/Navigation/Portal.hs @@ -51,7 +51,7 @@ data AnnotatedDestination a = AnnotatedDestination -- on the portal location specification method ('portalExitLoc'). -- -- == @additionalDimension@ --- As a member of the 'WorldDescription', waypoints are only known within a +-- As a member of the 'Swarm.Game.Scenario.Topography.WorldDescription.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 @@ -129,7 +129,7 @@ failWaypointLookup (WaypointName rawName) = -- == Data flow -- -- Waypoints are defined within a subworld and are namespaced by it. --- Optional intra-subworld uniqueness of Waypoints is enforced at WorldDescription +-- Optional intra-subworld uniqueness of Waypoints is enforced at 'Swarm.Game.Scenario.Topography.WorldDescription.WorldDescription' -- parse time. -- Portals are declared within a subworld. The portal entrance must be a waypoint -- within this subworld. @@ -140,7 +140,7 @@ failWaypointLookup (WaypointName rawName) = -- 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 +-- another subworld, we can't know at the single-'Swarm.Game.Scenario.Topography.WorldDescription.WorldDescription' level whether -- that waypoint has plural multiplicity. validatePartialNavigation :: (MonadFail m, Traversable t) => diff --git a/src/Swarm/Game/Scenario/Topography/Navigation/Waypoint.hs b/src/Swarm/Game/Scenario/Topography/Navigation/Waypoint.hs index dfd13628f..c983b2ad9 100644 --- a/src/Swarm/Game/Scenario/Topography/Navigation/Waypoint.hs +++ b/src/Swarm/Game/Scenario/Topography/Navigation/Waypoint.hs @@ -2,6 +2,22 @@ -- | -- SPDX-License-Identifier: BSD-3-Clause +-- +-- Landmarks that are used to specify portal locations +-- and can serve as navigation aids via the `waypoint` command. +-- +-- = Waypoint ordering +-- +-- The sequence of waypoints of a given name is dictated by criteria in the following order: +-- +-- 1. Ordering of structure placements +-- (see implementation of 'Swarm.Game.Scenario.Topography.Structure.mergeStructures'); +-- later placements are ordered first. +-- 2. Placement of cells within a map. Map locations go by row-major order +-- (compare to docs for 'Swarm.Game.State.genRobotTemplates'). +-- +-- TODO (#1366): May be useful to have a mechanism for more +-- precise control of ordering. module Swarm.Game.Scenario.Topography.Navigation.Waypoint where import Data.Int (Int32) diff --git a/src/Swarm/Game/Scenario/Topography/Structure.hs b/src/Swarm/Game/Scenario/Topography/Structure.hs index d4a8e0d6f..226d76664 100644 --- a/src/Swarm/Game/Scenario/Topography/Structure.hs +++ b/src/Swarm/Game/Scenario/Topography/Structure.hs @@ -125,7 +125,7 @@ instance FromJSONE (EntityMap, RobotMap) (PStructure (Maybe (PCell Entity))) whe return $ Structure maskedArea localStructureDefs placementDefs $ waypointDefs <> mapWaypoints -- | \"Paint\" a world map using a 'WorldPalette', turning it from a raw --- string into a nested list of 'Cell' values by looking up each +-- 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 :: diff --git a/src/Swarm/Game/ScenarioInfo.hs b/src/Swarm/Game/ScenarioInfo.hs index acd907ef0..23eb08a63 100644 --- a/src/Swarm/Game/ScenarioInfo.hs +++ b/src/Swarm/Game/ScenarioInfo.hs @@ -75,7 +75,7 @@ import Witch (into) -- ---------------------------------------------------------------------------- -- | A scenario item is either a specific scenario, or a collection of --- scenarios (*e.g.* the scenarios contained in a subdirectory). +-- scenarios (/e.g./ the scenarios contained in a subdirectory). data ScenarioItem = SISingle ScenarioInfoPair | SICollection Text ScenarioCollection deriving (Show) @@ -85,15 +85,17 @@ scenarioItemName (SISingle (s, _ss)) = s ^. scenarioName scenarioItemName (SICollection name _) = name -- | 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. +-- together with an optional order. +-- +-- /Invariant:/ every item in the +-- 'scOrder' exists as a key in the 'scMap'. data ScenarioCollection = SC { scOrder :: Maybe [FilePath] , scMap :: Map FilePath ScenarioItem } deriving (Show) --- | Access and modify ScenarioItems in collection based on their path. +-- | Access and modify 'ScenarioItem's in collection based on their path. scenarioItemByPath :: FilePath -> Traversal' ScenarioCollection ScenarioItem scenarioItemByPath path = ixp ps where diff --git a/src/Swarm/Game/State.hs b/src/Swarm/Game/State.hs index 4fa905017..b1bfc53a7 100644 --- a/src/Swarm/Game/State.hs +++ b/src/Swarm/Game/State.hs @@ -253,7 +253,7 @@ 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'. + -- INVARIANT: the 'Value' stored here is not a 'Swarm.Language.Value.VResult'. REPLDone (Maybe (Typed Value)) | -- | A command entered at the REPL is currently being run. The -- 'Polytype' represents the type of the expression that was @@ -694,7 +694,7 @@ recipesInfo :: Lens' GameState Recipes -- | The filepath of the currently running scenario. -- --- This is useful as an index to 'scenarios' collection, +-- This is useful as an index to the scenarios collection, -- see 'Swarm.Game.ScenarioInfo.scenarioItemByPath'. currentScenarioPath :: Lens' GameState (Maybe FilePath) @@ -732,7 +732,7 @@ focusedRobotID = to _focusedRobotID ------------------------------------------------------------ -- | The current rule for determining the center of the world view. --- It updates also, viewCenter and 'focusedRobotName' to keep +-- It updates also, 'viewCenter' and 'focusedRobot' to keep -- everything synchronized. viewCenterRule :: Lens' GameState ViewCenterRule viewCenterRule = lens getter setter @@ -740,7 +740,7 @@ viewCenterRule = lens getter setter getter :: GameState -> ViewCenterRule getter = _viewCenterRule - -- The setter takes care of updating viewCenter and focusedRobotName + -- The setter takes care of updating 'viewCenter' and 'focusedRobot' -- So non of this fields get out of sync. setter :: GameState -> ViewCenterRule -> GameState setter g rule = diff --git a/src/Swarm/Game/Step.hs b/src/Swarm/Game/Step.hs index 72808de57..6e6db9a2c 100644 --- a/src/Swarm/Game/Step.hs +++ b/src/Swarm/Game/Step.hs @@ -15,8 +15,8 @@ -- ** Note on the IO: -- -- 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 +-- loaded from files, via the 'Swarm.Language.Syntax.Run' command. +-- This could be avoided by using a hypothetical @import@ command instead and parsing -- the required files at the time of declaration. -- See . module Swarm.Game.Step where @@ -457,7 +457,7 @@ traceLogShow = void . traceLog Logged Info . from . show -- | 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 +-- heavy or not when executing the 'Swarm.Language.Syntax.Move' command, but there might -- be other exceptions added in the future. constCapsFor :: Const -> Robot -> Maybe Capability constCapsFor Move r @@ -796,7 +796,7 @@ stepCESK cesk = case cesk of runningAtomic .= False return $ Out v s k - -- Machinery for implementing the 'meetAll' command. + -- Machinery for implementing the 'Swarm.Language.Syntax.MeetAll' command. -- First case: done meeting everyone. Out b s (FMeetAll _ [] : k) -> return $ Out b s k -- More still to meet: apply the function to the current value b and @@ -2615,7 +2615,8 @@ formatDevices = T.intercalate " or " . map (^. entityName) . S.toList -- | 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. +-- by the given 'RID') as part of a 'Swarm.Language.Syntax.Build' +-- or 'Swarm.Language.Syntax.Reprogram' command. -- The first 'Inventory' is devices to be equipped, and the second -- is entities to be transferred. -- diff --git a/src/Swarm/Game/Step/Combustion.hs b/src/Swarm/Game/Step/Combustion.hs index 7e354f239..59a5020a8 100644 --- a/src/Swarm/Game/Step/Combustion.hs +++ b/src/Swarm/Game/Step/Combustion.hs @@ -7,7 +7,7 @@ -- | -- SPDX-License-Identifier: BSD-3-Clause -- --- Some entities are "combustible". A command, `ignite`, will +-- Some entities are "combustible". A command, 'Swarm.Language.Syntax.Ignite', will -- initiate combustion on such an entity. -- Furthermore, combustion can spread to (4-)adjacent entities, depending -- on the 'ignition' property of that entity. @@ -77,7 +77,7 @@ igniteCommand c d = do -- by placed entities. -- The "combustion bot" represents the burning of a single -- entity; propagating the fire to neighbors is handled upstream, --- within the `ignite` command. +-- within the 'Swarm.Language.Syntax.Ignite' command. addCombustionBot :: Has (State GameState) sig m => Entity -> @@ -143,8 +143,8 @@ ignitionProgram waitTime = -- -- 1. Create sub-partitions (of say, 10-tick duration) of the combustion duration -- to re-evaluate opportunities to light adjacent entities on fire. --- 2. Use the `watch` command to observe for changes to adjacent entities. --- Note that if we "wake" from our `wait` due to the `watch` being triggered, +-- 2. Use the 'Swarm.Language.Syntax.Watch' command to observe for changes to adjacent entities. +-- Note that if we "wake" from our 'Swarm.Language.Syntax.Wait' due to the 'Swarm.Language.Syntax.Watch' being triggered, -- we would need to maintain bookkeeping of how much time is left. -- 3. Spawn more robots whose sole purpose is to observe for changes to neighbor -- cells. This would avoid polluting the logic of the currently burning cell @@ -165,7 +165,7 @@ combustionProgram combustionDuration (Combustibility _ _ maybeCombustionProduct) Nothing -> (0, "") Just p -> (1, p) --- | We treat the 'ignition' field in the 'Combustion' record +-- | We treat the 'ignition' field in the 'Combustibility' record -- as a /rate/ in a Poisson distribution. -- Ignition of neighbors depends on that particular neighbor entity's -- combustion /rate/, but also on the duration @@ -197,7 +197,7 @@ igniteNeighbor creationTime sourceDuration loc = do probabilityOfIgnition = 1 - exp (negate $ rate * fromIntegral sourceDuration) -- | Construct an invisible "ignition robot" and add it to the world. --- Its sole purpose is to delay the `ignite` command for a neighbor +-- Its sole purpose is to delay the 'Swarm.Language.Syntax.Ignite' command for a neighbor -- that has been a priori determined that it shall be ignited. addIgnitionBot :: Has (State GameState) sig m => diff --git a/src/Swarm/Game/Universe.hs b/src/Swarm/Game/Universe.hs index cdcb92a38..dd7d42773 100644 --- a/src/Swarm/Game/Universe.hs +++ b/src/Swarm/Game/Universe.hs @@ -3,6 +3,9 @@ -- | -- SPDX-License-Identifier: BSD-3-Clause +-- +-- Types and utilities for working with "universal locations"; +-- locations that encompass different 2-D subworlds. module Swarm.Game.Universe where import Control.Lens (makeLenses, view) @@ -14,6 +17,8 @@ import GHC.Generics (Generic) import Linear (V2 (..)) import Swarm.Game.Location +-- * Referring to subworlds + data SubworldName = DefaultRootSubworld | SubworldName Text deriving (Show, Eq, Ord, Generic, ToJSON) @@ -25,6 +30,8 @@ renderWorldName = \case SubworldName s -> s DefaultRootSubworld -> "" +-- * Universal location + -- | The swarm universe consists of locations -- indexed by subworld. -- Not only is this parameterized datatype useful for planar (2D) @@ -47,8 +54,7 @@ instance (FromJSON a) => FromJSON (Cosmic a) where <$> v .: "subworld" <*> v .: "loc" -defaultCosmicLocation :: Cosmic Location -defaultCosmicLocation = Cosmic DefaultRootSubworld origin +-- * Measurement data DistanceMeasure b = Measurable b | InfinitelyFar deriving (Eq, Ord) @@ -59,5 +65,10 @@ cosmoMeasure f a b | ((/=) `on` view subworld) a b = InfinitelyFar | otherwise = Measurable $ (f `on` view planar) a b +-- * Utilities + +defaultCosmicLocation :: Cosmic Location +defaultCosmicLocation = Cosmic DefaultRootSubworld origin + offsetBy :: Cosmic Location -> V2 Int32 -> Cosmic Location offsetBy loc v = fmap (.+^ v) loc diff --git a/src/Swarm/Game/World/Coords.hs b/src/Swarm/Game/World/Coords.hs index e51761e6d..c373c0ab2 100644 --- a/src/Swarm/Game/World/Coords.hs +++ b/src/Swarm/Game/World/Coords.hs @@ -22,12 +22,12 @@ import Swarm.Game.Location (Location, pattern Location) -- World coordinates ------------------------------------------------------------ --- | World coordinates use (row,column) format, with the row +-- | 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 +-- and forth between this type and t'Location', which is used when -- presenting coordinates externally to the player. newtype Coords = Coords {unCoords :: (Int32, Int32)} deriving (Eq, Ord, Show, Ix, Generic) diff --git a/src/Swarm/Game/World/Typecheck.hs b/src/Swarm/Game/World/Typecheck.hs index 14fbc4625..2eaeb549b 100644 --- a/src/Swarm/Game/World/Typecheck.hs +++ b/src/Swarm/Game/World/Typecheck.hs @@ -367,8 +367,8 @@ instance PrettyPrec (TTy ty) where ------------------------------------------------------------ -- Instance checking --- | Check that a particular type has an 'Eq' instance, and run a --- computation in a context provided with an 'Eq' constraint. The +-- | Check that a particular type has an 'GHC.Classes.Eq' instance, and run a +-- computation in a context provided with an 'GHC.Classes.Eq' constraint. The -- other @checkX@ functions are similar. checkEq :: (Has (Throw CheckErr) sig m) => TTy ty -> ((Eq ty, NotFun ty) => m a) -> m a checkEq (TTyBase BBool) a = a diff --git a/src/Swarm/Language/Direction.hs b/src/Swarm/Language/Direction.hs index 69690c834..46bc231eb 100644 --- a/src/Swarm/Language/Direction.hs +++ b/src/Swarm/Language/Direction.hs @@ -44,7 +44,7 @@ import Witch.From (from) -- 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'). +-- (e.g. 'Swarm.Game.Location.nearestDirection' and 'Swarm.Game.Location.relativeTo'). data AbsoluteDir = DEast | DNorth | DWest | DSouth deriving (Eq, Ord, Show, Read, Generic, Data, Hashable, Enum, Bounded) @@ -82,7 +82,7 @@ data RelativeDir = DPlanar PlanarRelativeDir | DDown deriving (Eq, Ord, Show, Read, Generic, Data, Hashable, ToJSON, FromJSON) -- | Caution: Do not alter this ordering, as there exist functions that depend on it --- (e.g. 'nearestDirection' and 'relativeTo'). +-- (e.g. 'Swarm.Game.Location.nearestDirection' and 'Swarm.Game.Location.relativeTo'). data PlanarRelativeDir = DForward | DLeft | DBack | DRight deriving (Eq, Ord, Show, Read, Generic, Data, Hashable, Enum, Bounded) @@ -106,7 +106,7 @@ directionSyntax d = toLower . T.tail . from $ case d of DPlanar y -> show y _ -> show x --- | Check if the direction is absolute (e.g. 'north' or 'south'). +-- | Check if the direction is absolute (e.g. 'Swarm.Game.Location.north' or 'Swarm.Game.Location.south'). isCardinal :: Direction -> Bool isCardinal = \case DAbsolute _ -> True diff --git a/src/Swarm/Language/Key.hs b/src/Swarm/Language/Key.hs index 3ae2a8fdf..82c069106 100644 --- a/src/Swarm/Language/Key.hs +++ b/src/Swarm/Language/Key.hs @@ -55,7 +55,7 @@ mkKeyCombo mods k = KeyCombo k (sort mods) parseKeyComboFull :: Parser KeyCombo parseKeyComboFull = parseKeyCombo <* eof --- | Parse a key combo like "M-C-F5", "Down", or "C-x". +-- | Parse a key combo like @\"M-C-F5\"@, @\"Down\"@, or @\"C-x\"@. parseKeyCombo :: Parser KeyCombo parseKeyCombo = mkKeyCombo <$> many (try (parseModifier <* char '-')) <*> parseKey @@ -115,8 +115,8 @@ instance (Constructor c) => Names' (C1 c f) where ------------------------------------------------------------ -- Pretty-printing --- | Pretty-print a key combo, e.g. "C-M-F5". Right inverse to --- parseKeyCombo. Left inverse up to reordering of modifiers. +-- | Pretty-print a key combo, e.g. @\"C-M-F5\"@. Right inverse to +-- 'parseKeyCombo'. Left inverse up to reordering of modifiers. prettyKeyCombo :: KeyCombo -> Text prettyKeyCombo (KeyCombo k mods) = T.append (T.concat (map prettyModifier mods)) (prettyKey k) diff --git a/src/Swarm/Language/Parse.hs b/src/Swarm/Language/Parse.hs index e72dc10bd..982d31694 100644 --- a/src/Swarm/Language/Parse.hs +++ b/src/Swarm/Language/Parse.hs @@ -478,7 +478,7 @@ runParser :: Parser a -> Text -> Either Text a runParser p t = first (from . errorBundlePretty) (parse (runReaderT p DisallowAntiquoting) "" t) -- | A utility for running a parser in an arbitrary 'MonadFail' (which --- is going to be the TemplateHaskell 'Q' monad --- see +-- is going to be the TemplateHaskell 'Language.Haskell.TH.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 runParserTH (file, line, col) p s = @@ -489,7 +489,7 @@ runParserTH (file, line, col) p s = -- This is annoying --- megaparsec does not export its function to -- construct an initial parser state, so we can't just use that -- and then change the one field we need to be different (the - -- pstateSourcePos). We have to copy-paste the whole thing. + -- 'pstateSourcePos'). We have to copy-paste the whole thing. initState :: State Text Void initState = State @@ -509,7 +509,7 @@ runParserTH (file, line, col) p s = -- | 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 +-- 'Nothing' if the input was only whitespace) or a pretty-printed -- parse error message. readTerm :: Text -> Either Text (Maybe Syntax) readTerm = runParser (fullyMaybe sc parseTerm) @@ -520,7 +520,7 @@ readTerm' :: Text -> Either ParserError (Maybe Syntax) readTerm' = parse (runReaderT (fullyMaybe sc parseTerm) DisallowAntiquoting) "" -- | A utility for converting a ParserError into a one line message: --- : +-- @: @ showShortError :: ParserError -> String showShortError pe = show (line + 1) <> ": " <> from msg where diff --git a/src/Swarm/Language/Requirement.hs b/src/Swarm/Language/Requirement.hs index 92e52b75b..af3b7dc25 100644 --- a/src/Swarm/Language/Requirement.hs +++ b/src/Swarm/Language/Requirement.hs @@ -51,10 +51,10 @@ data Requirement ReqCap Capability | -- | 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 + -- 'Swarm.Game.Entity.Entity'. That's because programs have to be type- and + -- capability-checked independent of an 'Swarm.Game.Entity.EntityMap'. The name + -- will be looked up at runtime, when actually executing a 'Swarm.Language.Syntax.Build' + -- or 'Swarm.Language.Syntax.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 @@ -62,10 +62,10 @@ data Requirement ReqDev Text | -- | 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'. + -- entity name to an actual 'Swarm.Game.Entity.Entity'. -- -- Inventory requirements are additive, that is, say, requiring 5 - -- of entity `e` and later requiring 7 is the same as requiring + -- of entity @"e"@ and later requiring 7 is the same as requiring -- 12. ReqInv Int Text deriving (Eq, Ord, Show, Read, Generic, Hashable, Data, FromJSON, ToJSON) diff --git a/src/Swarm/Language/Syntax.hs b/src/Swarm/Language/Syntax.hs index e29362551..18d501a2d 100644 --- a/src/Swarm/Language/Syntax.hs +++ b/src/Swarm/Language/Syntax.hs @@ -108,7 +108,7 @@ import Swarm.Util qualified as Util import Witch.From (from) -- | Maximum perception distance for --- 'chirp' and 'sniff' commands +-- 'Chirp' and 'Sniff' commands maxSniffRange :: Int32 maxSniffRange = 256 diff --git a/src/Swarm/Language/Text/Markdown.hs b/src/Swarm/Language/Text/Markdown.hs index 75c9b5f42..b85c1ea22 100644 --- a/src/Swarm/Language/Text/Markdown.hs +++ b/src/Swarm/Language/Text/Markdown.hs @@ -69,7 +69,7 @@ newtype Document c = Document {paragraphs :: [Paragraph c]} -- 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. `logger`s). +-- space between them (e.g. @\`logger\`s@). newtype Paragraph c = Paragraph {nodes :: [Node c]} deriving (Eq, Show, Functor, Foldable, Traversable) deriving (Semigroup, Monoid) via [Node c] diff --git a/src/Swarm/TUI/Controller.hs b/src/Swarm/TUI/Controller.hs index af51da065..bddb2b1ab 100644 --- a/src/Swarm/TUI/Controller.hs +++ b/src/Swarm/TUI/Controller.hs @@ -10,7 +10,7 @@ module Swarm.TUI.Controller ( handleEvent, quitGame, - -- ** Handling 'Frame' events + -- ** Handling 'Swarm.TUI.Model.Frame' events runFrameUI, runFrame, ticksPerFrameCap, @@ -646,7 +646,7 @@ runFrameUI = do -- | Run the game for a single frame, without updating the UI. runFrame :: EventM Name AppState () runFrame = do - -- Reset the needsRedraw flag. While procssing the frame and stepping the robots, + -- Reset the needsRedraw flag. While processing the frame and stepping the robots, -- the flag will get set to true if anything changes that requires redrawing the -- world (e.g. a robot moving or disappearing). gameState . needsRedraw .= False diff --git a/src/Swarm/TUI/Launch/Prep.hs b/src/Swarm/TUI/Launch/Prep.hs index cfd414a4f..2b18f3251 100644 --- a/src/Swarm/TUI/Launch/Prep.hs +++ b/src/Swarm/TUI/Launch/Prep.hs @@ -73,7 +73,7 @@ initEditorWidget = -- supply some 'Nothing's as defaults to the 'ValidatedLaunchParams'. initConfigPanel :: IO LaunchOptions initConfigPanel = do - -- NOTE: This is kind of pointless, because we must re-instantiate the 'FileBrowser' + -- NOTE: This is kind of pointless, because we must re-instantiate the 'FB.FileBrowser' -- when it is first displayed, anyway. fb <- FB.newFileBrowser @@ -105,14 +105,14 @@ initFileBrowserWidget maybePlayedScript = do -- 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). +-- Note that the 'FB.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 +-- * When the user marks the first file, we immediately close the 'FB.FileBrowser' widget. +-- * We re-instantiate the 'FB.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 +-- * The "marked file" is persisted outside of the 'FB.FileBrowser' state, and the -- "initial directory" is set upon instantiation from that external state. prepareLaunchDialog :: ScenarioInfoPair -> diff --git a/src/Swarm/TUI/Model/Repl.hs b/src/Swarm/TUI/Model/Repl.hs index 594b4ae97..f8331fed0 100644 --- a/src/Swarm/TUI/Model/Repl.hs +++ b/src/Swarm/TUI/Model/Repl.hs @@ -137,21 +137,21 @@ replStart :: Lens' REPLHistory Int -- | Keep track of whether the user has explicitly executed commands -- at the REPL prompt, thus making them ineligible for code size scoring. -- --- Note: Instead of adding a dedicated field to the REPLHistory record, +-- Note: Instead of adding a dedicated field to the 'REPLHistory' record, -- an early attempt entailed checking for: -- --- _replIndex > _replStart +-- @_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 not input commands directly into the REPL. -- --- Therefore, a dedicated boolean is introduced into REPLHistory +-- 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 +-- An alternative is described in +-- . replHasExecutedManualInput :: Lens' REPLHistory Bool -- | Create new REPL history (i.e. from loaded history file lines). @@ -221,14 +221,14 @@ getCurrentItemText history = replItemText <$> Seq.lookup (history ^. replIndex) replIndexIsAtInput :: REPLHistory -> Bool replIndexIsAtInput repl = repl ^. replIndex == replLength repl --- | Given some text, removes the REPLEntry within REPLHistory which is equal to that. +-- | 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 removeEntry foundtext hist = hist & replSeq %~ Seq.filter (/= REPLEntry foundtext) --- | Get the last REPLEntry in REPLHistory matching the given text +-- | Get the last 'REPLEntry' in 'REPLHistory' matching the given text lastEntry :: Text -> REPLHistory -> Maybe Text lastEntry t h = case Seq.viewr $ Seq.filter matchEntry $ h ^. replSeq of @@ -302,7 +302,7 @@ 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 +-- | Convenience lens to get text from editor and replace it with new -- one that has the provided text. replPromptText :: Lens' REPLState Text replPromptText = lens g s @@ -310,7 +310,7 @@ replPromptText = lens g s g r = r ^. replPromptEditor . to getEditContents . to T.concat s r t = r & replPromptEditor .~ newREPLEditor t --- | Whether the prompt text is a valid 'Term'. +-- | Whether the prompt text is a valid 'Swarm.Language.Syntax.Term'. replValid :: Lens' REPLState Bool -- | The type of the current REPL input which should be displayed to diff --git a/src/Swarm/TUI/Model/UI.hs b/src/Swarm/TUI/Model/UI.hs index 7d1093259..3000df69c 100644 --- a/src/Swarm/TUI/Model/UI.hs +++ b/src/Swarm/TUI/Model/UI.hs @@ -136,8 +136,11 @@ makeLensesExcluding ['_lgTicksPerSecond] ''UIState -- | 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 +-- | 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 @@ -148,7 +151,7 @@ uiCheatMode :: Lens' UIState Bool uiLaunchConfig :: Lens' UIState LaunchOptions -- | The focus ring is the set of UI panels we can cycle among using --- the Tab key. +-- the @Tab@ key. uiFocusRing :: Lens' UIState (FocusRing Name) -- | The last clicked position on the world view. @@ -175,7 +178,7 @@ uiInventory :: Lens' UIState (Maybe (Int, BL.List Name InventoryListEntry)) -- (used when a new log message is appended). uiScrollToEnd :: Lens' UIState Bool --- | When this is @Just@, it represents a modal to be displayed on +-- | 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) @@ -183,21 +186,21 @@ uiModal :: Lens' UIState (Maybe Modal) -- has been displayed to the user initially. uiGoal :: Lens' UIState GoalDisplay --- | When running with --autoplay, suppress the goal dialogs. +-- | When running with @--autoplay@, suppress the goal dialogs. -- --- For developement, the --cheat flag shows goals again. +-- For development, the @--cheat@ flag shows goals again. uiHideGoals :: Lens' UIState Bool -- | Map of achievements that were attained uiAchievements :: Lens' UIState (Map CategorizedAchievement Attainment) --- | A toggle to show the FPS by pressing `f` +-- | 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` +-- | 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` +-- | A toggle to show or hide inventory items with count 0 by pressing @0@ uiShowZero :: Lens' UIState Bool -- | A toggle to show debug. @@ -215,10 +218,10 @@ uiShowRobots = to (\ui -> ui ^. lastFrameTime > ui ^. uiHideRobotsUntil) -- | Whether the Inventory ui panel should update uiInventoryShouldUpdate :: Lens' UIState Bool --- | Computed ticks per milli seconds +-- | Computed ticks per milliseconds uiTPF :: Lens' UIState Double --- | Computed frames per milli seconds +-- | Computed frames per milliseconds uiFPS :: Lens' UIState Double -- | Attribute map @@ -256,10 +259,10 @@ frameTickCount :: Lens' UIState Int -- | The time of the last info widget update lastInfoTime :: Lens' UIState TimeSpec --- | The time of the last 'Frame' event. +-- | The time of the last 'Swarm.TUI.Model.Frame' event. lastFrameTime :: Lens' UIState TimeSpec --- | The amount of accumulated real time. Every time we get a 'Frame' +-- | The amount of accumulated real time. Every time we get a 'Swarm.TUI.Model.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. diff --git a/src/Swarm/TUI/View.hs b/src/Swarm/TUI/View.hs index e88be42c2..d415fda11 100644 --- a/src/Swarm/TUI/View.hs +++ b/src/Swarm/TUI/View.hs @@ -24,6 +24,7 @@ module Swarm.TUI.View ( drawRobotPanel, drawItem, drawLabelledEntityName, + renderDutyCycle, -- * Info panel drawInfoPanel, @@ -645,10 +646,10 @@ drawModal s = \case -- due to the sliding window. -- -- == Use of previous tick --- The 'gameTick' function runs all robots, then increments the current tick. +-- The 'Swarm.Game.Step.gameTick' function runs all robots, then increments the current tick. -- So at the time we are rendering a frame, the current tick will always be --- strictly greater than any ticks stored in the 'WindowedCounter' for any robot; --- hence 'getOccupancy' will never be @1@ if we use the current tick directly as +-- strictly greater than any ticks stored in the 'WC.WindowedCounter' for any robot; +-- hence 'WC.getOccupancy' will never be @1@ if we use the current tick directly as -- obtained from the 'ticks' function. -- So we "rewind" it to the previous tick for the purpose of this display. renderDutyCycle :: GameState -> Robot -> Widget Name