diff --git a/data/scenarios/Testing/1034-custom-attributes.yaml b/data/scenarios/Testing/1034-custom-attributes.yaml index d736a13664..c6f07bc8ff 100644 --- a/data/scenarios/Testing/1034-custom-attributes.yaml +++ b/data/scenarios/Testing/1034-custom-attributes.yaml @@ -1,9 +1,14 @@ version: 1 name: Rainbow color custom attributes description: | - Custom attributes with rainbow colors + Custom attributes with rainbow colors. + + Participates as a do-nothing integration test to ensure parseability. creative: false attrs: + - name: robotWithBackground + bg: "#880088" + - name: rainbow1 fg: "#ffadad" - name: rainbow2 @@ -18,11 +23,27 @@ attrs: fg: "#a0c4ff" - name: rainbow7 fg: "#bdb2ff" + + - name: rainbow1bg + bg: "#ffadad" + - name: rainbow2bg + bg: "#ffd6a5" + - name: rainbow3bg + bg: "#ffff96" + - name: rainbow4bg + bg: "#caffbf" + - name: rainbow5bg + bg: "#9bf6ff" + - name: rainbow6bg + bg: "#a0c4ff" + - name: rainbow7bg + bg: "#bdb2ff" + - name: redOnYellow fg: "#ff0000" - bg: ffff00 + bg: "#ffff00" - name: cyanOnMagenta - fg: "#00ffff + fg: "#00ffff" bg: "#ff00ff" - name: greenForeground fg: "#00ff00" @@ -38,6 +59,12 @@ attrs: style: - Bold - Strikethrough +objectives: + - goal: + - Do nothing + condition: | + pos <- as base {whereami}; + return $ fst pos > 7; entities: - name: color1 display: @@ -88,6 +115,57 @@ entities: description: - c7 properties: [known] + + - name: color1bg + display: + char: ' ' + attr: rainbow1bg + description: + - c1bg + properties: [known] + - name: color2bg + display: + char: ' ' + attr: rainbow2bg + description: + - c2bg + properties: [known] + - name: color3bg + display: + char: ' ' + attr: rainbow3bg + description: + - c3bg + properties: [known] + - name: color4bg + display: + char: ' ' + attr: rainbow4bg + description: + - c4bg + properties: [known] + - name: color5bg + display: + char: ' ' + attr: rainbow5bg + description: + - c5bg + properties: [known] + - name: color6bg + display: + char: ' ' + attr: rainbow6bg + description: + - c6bg + properties: [known] + - name: color7bg + display: + char: ' ' + attr: rainbow7bg + description: + - c7bg + properties: [known] + - name: color1f display: char: '█' @@ -179,9 +257,36 @@ entities: description: - Bold and Strikethrough properties: [known] -robots: [] +robots: + - name: base + dir: east + devices: + - treads + - name: companion + dir: east + devices: + - treads + program: | + move; move; move; move; + move; move; move; move; + - name: companion2 + dir: east + display: + attr: robotWithBackground + devices: + - treads + program: | + move; move; move; move; + move; move; move; move; +solution: | + move; move; move; move; + move; move; move; move; world: palette: + 'Ω': [blank, null, base] + 'α': [blank, null, companion] + 'β': [blank, null, companion2] + '.': [blank] '1': [blank, color1] '2': [blank, color2] @@ -190,6 +295,15 @@ world: '5': [blank, color5] '6': [blank, color6] '7': [blank, color7] + + 'T': [blank, color1bg] + 'U': [blank, color2bg] + 'V': [blank, color3bg] + 'W': [blank, color4bg] + 'X': [blank, color5bg] + 'Y': [blank, color6bg] + 'Z': [blank, color7bg] + 'a': [blank, color1f] 'b': [blank, color2f] 'c': [blank, color3f] @@ -197,6 +311,7 @@ world: 'e': [blank, color5f] 'f': [blank, color6f] 'g': [blank, color7f] + 'y': [blank, blueBackround] 'z': [blank, greenForeground] 'R': [blank, redYellow] @@ -205,7 +320,7 @@ world: 'B': [blank, boldStrikethrough] upperleft: [0, 0] map: |- - .1234567..Rzzy...IIy - .1234567y.R.z....... - .abcdefg......C..BBz - .abcdefgyy.yy..Cz.z. + α.1234567..Rzzy...IIy + Ω.TUVWXYZy.R.z....... + β.TUVWXYZ......C..BBz + α.abcdefgyy.yy..Cz.z. diff --git a/src/Swarm/TUI/View/CellDisplay.hs b/src/Swarm/TUI/View/CellDisplay.hs index 29d58a8590..8e23310329 100644 --- a/src/Swarm/TUI/View/CellDisplay.hs +++ b/src/Swarm/TUI/View/CellDisplay.hs @@ -9,6 +9,7 @@ module Swarm.TUI.View.CellDisplay where import Brick import Control.Applicative ((<|>)) import Control.Lens (to, view, (&), (.~), (^.)) +import Control.Monad (guard) import Data.ByteString (ByteString) import Data.Hash.Murmur import Data.List.NonEmpty qualified as NE @@ -32,12 +33,14 @@ import Swarm.Game.Display ( displayObscured, displayPriority, hidden, + invisible, ) import Swarm.Game.Entity import Swarm.Game.Entity.Cosmetic import Swarm.Game.Entity.Cosmetic.Assignment (terrainAttributes) import Swarm.Game.Robot -import Swarm.Game.Scenario.Topography.Cell (PCell (..)) +import Swarm.Game.Scenario (scenarioCosmetics) +import Swarm.Game.Scenario.Topography.Cell (CellPaintDisplay, PCell (..)) import Swarm.Game.Scenario.Topography.EntityFacade import Swarm.Game.Scenario.Topography.Structure.Recognition (foundStructures) import Swarm.Game.Scenario.Topography.Structure.Recognition.Registry (foundByLocation) @@ -54,7 +57,7 @@ import Swarm.TUI.Model.Name import Swarm.TUI.Model.UI import Swarm.TUI.View.Attribute.Attr import Swarm.Util (applyWhen) -import Swarm.Util.Erasable (erasableToMaybe) +import Swarm.Util.Erasable (erasableToMaybe, maybeToErasable) import Witch (from) import Witch.Encoding qualified as Encoding @@ -74,16 +77,29 @@ getTerrainEntityColor aMap (Cell terr cellEnt _) = AWorld n -> M.lookup (WorldAttr $ T.unpack n) aMap _ -> Nothing +getCellBackground :: UIState -> CellPaintDisplay -> Maybe V.Color +getCellBackground ui mycell = do + (myScenario, _) <- ui ^. scenarioRef + hifi <- getTerrainEntityColor (myScenario ^. scenarioCosmetics) mycell + getBackground $ fmap mkBrickColor hifi + -- | Render the 'Display' for a specific location. drawLoc :: UIState -> GameState -> Cosmic W.Coords -> Widget Name drawLoc ui g cCoords@(Cosmic _ coords) = if shouldHideWorldCell ui coords then str " " - else boldStructure drawCell + else boldStructure $ passthroughBackgroundForRobot drawCell where showRobots = ui ^. uiShowRobots we = ui ^. uiWorldEditor . worldOverdraw - drawCell = renderDisplay $ displayLoc showRobots we g cCoords + + (combinedDisplay, maybeBgForRobot) = displayLoc ui showRobots we g cCoords + drawCell = renderDisplay combinedDisplay + + passthroughBackgroundForRobot = + case maybeBgForRobot of + Just c -> modifyDefAttr (`V.withBackColor` c) + Nothing -> id boldStructure = applyWhen isStructure $ modifyDefAttr (`V.withStyle` V.bold) where @@ -152,28 +168,59 @@ displayEntityCell :: Cosmic W.Coords -> [Display] displayEntityCell worldEditor ri coords = - maybeToList $ displayForEntity <$> maybeEntity + maybeToList $ displayForEntity ri <$> maybeEntity where (_, maybeEntity) = EU.getEditorContentAt worldEditor (multiworldInfo ri) coords - displayForEntity :: EntityPaint -> Display - displayForEntity e = (if isKnownFunc ri e then id else hidden) $ getDisplay e +displayForEntity :: RenderingInput -> EntityPaint -> Display +displayForEntity ri e = (if isKnownFunc ri e then id else hidden) $ getDisplay e -- | Get the 'Display' for a specific location, by combining the -- 'Display's for the terrain, entity, and robots at the location, and -- taking into account "static" based on the distance to the robot -- being @view@ed. -displayLoc :: Bool -> WorldOverdraw -> GameState -> Cosmic W.Coords -> Display -displayLoc showRobots we g cCoords@(Cosmic _ coords) = - staticDisplay g coords - <> displayLocRaw we ri robots cCoords +displayLoc :: + UIState -> + -- | Should show robots + Bool -> + WorldOverdraw -> + GameState -> + Cosmic W.Coords -> + (Display, Maybe V.Color) +displayLoc ui showRobots we g cCoords@(Cosmic _ coords) = + (combinedDisplay, maybeRobotPassthroughBg) where ri = RenderingInput (g ^. landscape . multiWorld) (getEntityIsKnown $ mkEntityKnowledge g) - robots = + + combinedDisplay = + staticDisplay g coords + <> terrainEntityRobotDisplay + + (terrain, maybeEntity) = EU.getEditorContentAt we (multiworldInfo ri) cCoords + + hasVisibleRobot = + not (combinedDisplay ^. displayObscured) + && not (all (view invisible) robotDisplays) + + cellPaint = + Cell + terrain + (toFacade <$> maybeToErasable maybeEntity) + [] + + maybeRobotPassthroughBg = do + guard hasVisibleRobot + getCellBackground ui cellPaint + + entityDisplays = maybeToList $ displayForEntity ri <$> maybeEntity + terrainDisplay = terrainMap M.! terrain + robotDisplays = if showRobots then displayRobotCell g cCoords else [] + terrainEntityRobotDisplay = sconcat $ terrainDisplay NE.:| entityDisplays <> robotDisplays + -- | Get the 'Display' for a specific location, by combining the -- 'Display's for the terrain, entity, and robots at the location. displayLocRaw :: diff --git a/test/integration/Main.hs b/test/integration/Main.hs index a51c9cc5f4..dab82f842c 100644 --- a/test/integration/Main.hs +++ b/test/integration/Main.hs @@ -332,6 +332,7 @@ testScenarioSolutions rs ui = , testSolution Default "Testing/958-isempty" , testSolution Default "Testing/1007-use-command" , testSolution Default "Testing/1024-sand" + , testSolution Default "Testing/1034-custom-attributes" , testSolution Default "Testing/1140-detect-command" , testSolution Default "Testing/1157-drill-return-value" , testSolution Default "Testing/1171-sniff-command"