Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extensible terrain #1775

Merged
merged 4 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"data/scenarios/**/*.yaml",
"scenarios/**/*.yaml"
],
"data/schema/terrains.json": [
"data/terrains.yaml"
],
"data/schema/entities.json": [
"data/entities.yaml"
],
Expand Down
1 change: 1 addition & 0 deletions app/doc/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ cliParser =
Data.Foldable.asum
[ pure Nothing
, Just Entities <$ switch (long "entities" <> help "Generate entities page (uses data from entities.yaml)")
, Just Terrain <$ switch (long "terrain" <> help "Generate terrain page (uses data from terrains.yaml)")
, Just Recipes <$ switch (long "recipes" <> help "Generate recipes page (uses data from recipes.yaml)")
, Just Capabilities <$ switch (long "capabilities" <> help "Generate capabilities page (uses entity map)")
, Just Commands <$ switch (long "commands" <> help "Generate commands page (uses constInfo, constCaps and inferConst)")
Expand Down
3 changes: 2 additions & 1 deletion app/doc/Swarm/Doc/Gen.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import Swarm.Doc.Util
import Swarm.Doc.Wiki.Cheatsheet
import Swarm.Game.Entity (Entity, EntityMap (entitiesByName), entityName)
import Swarm.Game.Entity qualified as E
import Swarm.Game.Land
import Swarm.Game.Recipe (Recipe, recipeCatalysts, recipeInputs, recipeOutputs)
import Swarm.Game.Robot (Robot, equippedDevices, robotInventory)
import Swarm.Game.Scenario (GameStateInputs (..), loadStandaloneScenario, scenarioLandscape)
Expand Down Expand Up @@ -135,7 +136,7 @@ generateSpecialKeyNames =

generateRecipe :: IO String
generateRecipe = simpleErrorHandle $ do
(classic, GameStateInputs worlds entities recipes) <- loadStandaloneScenario "data/scenarios/classic.yaml"
(classic, GameStateInputs worlds (TerrainEntityMaps _ entities) recipes) <- loadStandaloneScenario "data/scenarios/classic.yaml"
baseRobot <- instantiateBaseRobot $ classic ^. scenarioLandscape
return . Dot.showDot $ recipesToDot baseRobot (worlds ! "classic") entities recipes

Expand Down
8 changes: 6 additions & 2 deletions app/doc/Swarm/Doc/Wiki/Cheatsheet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ import Swarm.Game.Display (displayChar)
import Swarm.Game.Entity (Entity, EntityMap (entitiesByName), entityDisplay, entityName, loadEntities)
import Swarm.Game.Entity qualified as E
import Swarm.Game.Recipe (Recipe, loadRecipes, recipeCatalysts, recipeInputs, recipeOutputs, recipeTime, recipeWeight)
import Swarm.Game.Terrain (loadTerrain, terrainByName)
import Swarm.Language.Capability (Capability)
import Swarm.Language.Capability qualified as Capability
import Swarm.Language.Pretty (prettyText, prettyTextLine)
import Swarm.Language.Syntax (Const (..))
import Swarm.Language.Syntax qualified as Syntax
import Swarm.Language.Text.Markdown as Markdown (docToMark)
import Swarm.Language.Typecheck (inferConst)
import Swarm.Util (listEnums)
import Swarm.Util (listEnums, showT)
import Swarm.Util.Effect (simpleErrorHandle)

-- * Types
Expand All @@ -54,7 +55,7 @@ data PageAddress = PageAddress
deriving (Eq, Show)

-- | An enumeration of the kinds of cheat sheets we can produce.
data SheetType = Entities | Commands | CommandMatrix | Capabilities | Recipes | Scenario
data SheetType = Entities | Terrain | Commands | CommandMatrix | Capabilities | Recipes | Scenario
deriving (Eq, Show, Enum, Bounded)

-- * Functions
Expand All @@ -73,6 +74,9 @@ makeWikiPage address s = case s of
Entities -> simpleErrorHandle $ do
entities <- loadEntities
sendIO $ T.putStrLn $ entitiesPage address (Map.elems $ entitiesByName entities)
Terrain -> simpleErrorHandle $ do
terrains <- loadTerrain
sendIO . T.putStrLn . T.unlines . map showT . Map.elems $ terrainByName terrains
Recipes -> simpleErrorHandle $ do
entities <- loadEntities
recipes <- loadRecipes entities
Expand Down
1 change: 1 addition & 0 deletions data/scenarios/Testing/00-ORDER.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,4 @@ Achievements
1634-message-colors.yaml
1681-pushable-entity.yaml
1747-volume-command.yaml
1775-custom-terrain.yaml
58 changes: 58 additions & 0 deletions data/scenarios/Testing/1775-custom-terrain.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
version: 1
name: Demo custom terrain
description: |
Colorful new terrain
creative: false
attrs:
- name: beachsand
bg: "#c2b280"
- name: lava
bg: "#dd7733"
- name: lilac
bg: "#a4a4bb"
terrains:
- name: beach
attr: beachsand
description: |
Shoreline covering, laborious to cross
- name: lava
attr: lava
description: |
Scorching, liquid rock
- name: heather
attr: lilac
description: |
Flowery ground cover
objectives:
- goal:
- |
No entities should be here
condition: |
as base {
isEmpty
}
solution: |
noop
robots:
- name: base
dir: east
known: []
world:
dsl: |
{grass}
palette:
'B': [heather, null, base]
'.': [heather]
'i': [ice]
'b': [beach]
'v': [lava]
upperleft: [0, 0]
map: |
vvvvvvvv
vvvvvvvv
B.......
........
iiiiiiii
iiiiiiii
bbbbbbbb
bbbbbbbb
27 changes: 27 additions & 0 deletions data/scenarios/Testing/_Validation/1775-invalid-terrain-attr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: 1
name: Custom terrain - invalid attribute
description: |
Colorful new terrain
creative: false
attrs:
- name: lava
bg: "#dd7733"
terrains:
- name: lava
attr: baklava
description: |
Scorching, liquid rock
robots:
- name: base
dir: east
known: []
world:
dsl: |
{grass}
palette:
'B': [grass, null, base]
'.': [lava]
upperleft: [0, 0]
map: |
B.
..
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: 1
name: Custom terrain - invalid terrain reference
description: |
Colorful new terrain
creative: false
attrs:
- name: lava
bg: "#dd7733"
terrains:
- name: lava
attr: lava
description: |
Scorching, liquid rock
robots:
- name: base
dir: east
known: []
world:
dsl: |
{grass}
palette:
'B': [grass, null, base]
'.': [liver]
upperleft: [0, 0]
map: |
B.
..
7 changes: 7 additions & 0 deletions data/schema/scenario.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@
"default": null,
"type": "number"
},
"terrains": {
"description": "An optional list of custom terrain, to be used in addition to the built-in terrain.",
"default": [],
"items": {
"$ref": "terrain.json"
kostmo marked this conversation as resolved.
Show resolved Hide resolved
}
},
"entities": {
"description": "An optional list of custom entities, to be used in addition to the built-in entities.",
"default": [],
Expand Down
27 changes: 27 additions & 0 deletions data/schema/terrain.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://raw.githubusercontent.com/swarm-game/swarm/main/data/schema/terrain.json",
"title": "Terrain",
"description": "Description of a terrain in the Swarm game",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"description": "The name of the terrain."
},
"description": {
"type": "string",
"description": "A description of the terrain."
},
"attr": {
"type": "string",
"examples": [
"red",
"ice",
"dirt"
],
"description": "The name of the attribute that should be used to style the robot or entity. A list of currently valid attributes can be found [here](https://github.com/swarm-game/swarm/blob/main/src/Swarm/TUI/View/Attribute/Attr.hs)."
}
}
}
10 changes: 10 additions & 0 deletions data/schema/terrains.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://raw.githubusercontent.com/swarm-game/swarm/main/data/schema/terrains.json",
"title": "Entities",
kostmo marked this conversation as resolved.
Show resolved Hide resolved
"description": "Description of terrain in the Swarm game",
"type": "array",
"items": {
"$ref": "terrain.json"
}
}
16 changes: 16 additions & 0 deletions data/terrains.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
- name: stone
attr: stone
description: |
Solid, impenetrable material
kostmo marked this conversation as resolved.
Show resolved Hide resolved
- name: dirt
attr: dirt
description: |
Soil amenable to plant growth
- name: grass
attr: grass
description: |
Soft, verdant ground
- name: ice
attr: ice
description: |
Cold, solid, and slippery.
2 changes: 1 addition & 1 deletion scripts/enforce-todo-issues.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
cd $SCRIPT_DIR/..


if grep --line-number --include \*.hs -riP '(TODO|FIXME|XXX)\b' src 2>&1 | grep -vP '#\d+'; then
if grep --line-number --include \*.hs -riP '(TODO|FIXME|XXX)\b' src app 2>&1 | grep -vP '#\d+'; then
echo "Please add a link to Issue, for example: TODO: #123"
exit 1
else
Expand Down
1 change: 1 addition & 0 deletions scripts/validate-json-schemas.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ cd $SCRIPT_DIR/..

find data/scenarios -name "*.yaml" -type f -print0 | xargs -0 check-jsonschema --base-uri $(git rev-parse --show-toplevel)/data/schema/scenario.json --schemafile data/schema/scenario.json

check-jsonschema --base-uri $(git rev-parse --show-toplevel)/data/schema/terrains.json --schemafile data/schema/terrains.json data/terrains.yaml
check-jsonschema --base-uri $(git rev-parse --show-toplevel)/data/schema/entities.json --schemafile data/schema/entities.json data/entities.yaml
check-jsonschema --base-uri $(git rev-parse --show-toplevel)/data/schema/recipes.json --schemafile data/schema/recipes.json data/recipes.yaml
9 changes: 5 additions & 4 deletions src/Swarm/Doc/Pedagogy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ import Data.Set qualified as S
import Data.Text (Text)
import Data.Text qualified as T
import Swarm.Constant
import Swarm.Game.Entity (loadEntities)
import Swarm.Game.Failure (SystemFailure)
import Swarm.Game.Land
import Swarm.Game.Scenario (
Scenario,
scenarioDescription,
Expand Down Expand Up @@ -174,13 +174,14 @@ generateIntroductionsSequence =
-- For unit tests, can instead access the scenarios via the GameState.
loadScenarioCollection :: IO ScenarioCollection
loadScenarioCollection = simpleErrorHandle $ do
entities <- loadEntities
tem <- loadEntitiesAndTerrain

-- Note we ignore any warnings generated by 'loadWorlds' and
-- 'loadScenarios' below. Any warnings will be caught when loading
-- all the scenarios via the usual code path; we do not need to do
-- anything with them here while simply rendering pedagogy info.
worlds <- ignoreWarnings @(Seq SystemFailure) $ loadWorlds entities
ignoreWarnings @(Seq SystemFailure) $ loadScenarios entities worlds
worlds <- ignoreWarnings @(Seq SystemFailure) $ loadWorlds tem
ignoreWarnings @(Seq SystemFailure) $ loadScenarios tem worlds

renderUsagesMarkdown :: CoverageInfo -> Text
renderUsagesMarkdown (CoverageInfo (TutorialInfo (s, si) idx _sCmds dCmds) novelCmds) =
Expand Down
3 changes: 2 additions & 1 deletion src/Swarm/TUI/Controller.hs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import Swarm.Game.Achievement.Definitions
import Swarm.Game.Achievement.Persistence
import Swarm.Game.CESK (CESK (Out), Frame (FApp, FExec), cancel, emptyStore, initMachine)
import Swarm.Game.Entity hiding (empty)
import Swarm.Game.Land
import Swarm.Game.Location
import Swarm.Game.ResourceLoading (getSwarmHistoryPath)
import Swarm.Game.Robot
Expand Down Expand Up @@ -1191,7 +1192,7 @@ handleREPLEventTyping = \case
CharKey '\t' -> do
s <- get
let names = s ^.. gameState . baseRobot . robotContext . defTypes . to assocs . traverse . _1
uiState . uiGameplay . uiREPL %= tabComplete (CompletionContext (s ^. gameState . creativeMode)) names (s ^. gameState . landscape . entityMap)
uiState . uiGameplay . uiREPL %= tabComplete (CompletionContext (s ^. gameState . creativeMode)) names (s ^. gameState . landscape . terrainAndEntities . entityMap)
modify validateREPLForm
EscapeKey -> do
formSt <- use $ uiState . uiGameplay . uiREPL . replPromptType
Expand Down
6 changes: 5 additions & 1 deletion src/Swarm/TUI/Editor/Controller.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Control.Monad.Trans.Maybe (MaybeT (..), runMaybeT)
import Data.Map qualified as M
import Data.Yaml qualified as Y
import Graphics.Vty qualified as V
import Swarm.Game.Land
import Swarm.Game.Scenario.Topography.EntityFacade
import Swarm.Game.State
import Swarm.Game.State.Landscape
Expand Down Expand Up @@ -83,9 +84,11 @@ handleMiddleClick mouseLoc = do
worldEditor <- use $ uiState . uiGameplay . uiWorldEditor
when (worldEditor ^. worldOverdraw . isWorldEditorEnabled) $ do
w <- use $ gameState . landscape . multiWorld
tem <- use $ gameState . landscape . terrainAndEntities . terrainMap
kostmo marked this conversation as resolved.
Show resolved Hide resolved
let setTerrainPaint coords = do
let (terrain, maybeElementPaint) =
EU.getEditorContentAt
tem
(worldEditor ^. worldOverdraw)
w
coords
Expand Down Expand Up @@ -142,7 +145,8 @@ saveMapFile = do
worldEditor <- use $ uiState . uiGameplay . uiWorldEditor
maybeBounds <- use $ uiState . uiGameplay . uiWorldEditor . editingBounds . boundsRect
w <- use $ gameState . landscape . multiWorld
let mapCellGrid = EU.getEditedMapRectangle (worldEditor ^. worldOverdraw) maybeBounds w
tm <- use $ gameState . landscape . terrainAndEntities . terrainMap
let mapCellGrid = EU.getEditedMapRectangle tm (worldEditor ^. worldOverdraw) maybeBounds w

let fp = worldEditor ^. outputFilePath
maybeScenarioPair <- use $ uiState . uiGameplay . scenarioRef
Expand Down
2 changes: 1 addition & 1 deletion src/Swarm/TUI/Editor/Model.hs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ initialWorldEditor :: TimeSpec -> WorldEditor Name
initialWorldEditor ts =
WorldEditor
(WorldOverdraw False mempty)
(BL.list TerrainList (V.fromList listEnums) 1)
(BL.list TerrainList (V.fromList []) 1)
(BL.list EntityPaintList (V.fromList []) 1)
bounds
(focusRing $ map WorldEditorPanelControl listEnums)
Expand Down
Loading
Loading