Skip to content

Commit

Permalink
Fix Semigroup EntityMap instance to update Capabilities map properly …
Browse files Browse the repository at this point in the history
…when there are overridden devices (#2242)

Fixes #2240.  Fixes the `Semigroup EntityMap` instance so that devices which are overridden are removed from the lists of devices providing certain capabilities.

- Also adds a test scenario which generated an incorrect error message before this fix.
- Also adds the test scenario from #2241 to the test suite which was missed previously.
  • Loading branch information
byorgey authored Dec 31, 2024
1 parent a753a01 commit 79ba1b7
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 6 deletions.
1 change: 1 addition & 0 deletions data/scenarios/Testing/00-ORDER.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,4 @@ Achievements
2085-toplevel-mask.yaml
2086-structure-palette.yaml
2239-custom-entity.yaml
2240-overridden-entity-capabilities.yaml
49 changes: 49 additions & 0 deletions data/scenarios/Testing/2240-overridden-entity-capabilities.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
version: 1
name: Overridden entity capabilities
description: |
Overridden standard entity should not still be suggested for its
capabilities. The error message should suggest "- tank treads", not
"- treads or tank treads".
creative: false
objectives:
- goal:
- Place a rock
condition: |
as base {
isHere "rock"
};
entities:
- name: treads
display:
char: '#'
attr: red
description:
- Broken treads
properties: [known, pickable]
robots:
- name: base
dir: east
devices:
- logger
- clock
- grabber
inventory:
- [1, rock]
- name: crasher
dir: east
devices:
- logger
- treads
program: |
move
solution: |
wait 5; place "rock"
world:
dsl: |
{grass}
palette:
'C': [grass, null, crasher]
'B': [grass, null, base]
upperleft: [0, 0]
map: |
BC
22 changes: 16 additions & 6 deletions src/swarm-scenario/Swarm/Game/Entity.hs
Original file line number Diff line number Diff line change
Expand Up @@ -440,16 +440,26 @@ data EntityMap = EntityMap
-- Note that duplicates in a single 'EntityMap' are precluded by the
-- 'buildEntityMap' function. But it is possible for the right-hand
-- 'EntityMap' to override members of the left-hand with the same name.
-- This replacement happens automatically with 'Map', but needs to
-- be explicitly handled for the list concatenation of
-- 'entityDefinitionOrder' (overridden entries are removed from the
-- former 'EntityMap').
-- For example, this is how custom entities defined in a scenario
-- can override standard entities. This replacement happens
-- automatically with 'Map' (as long as we keep in mind that Map
-- union is *left*-biased), but needs to be explicitly handled for the
-- list concatenation of 'entityDefinitionOrder' (overridden entries
-- are removed from the former 'EntityMap'), and for 'entitiesByCap',
-- which are organized by capability rather than by entity.
instance Semigroup EntityMap where
EntityMap n1 c1 d1 <> EntityMap n2 c2 d2 =
EntityMap
(n2 <> n1)
(c1 <> c2)
(filter ((`M.notMember` n2) . view entityName) d1 <> d2)
(removeOverriddenDevices c1 <> c2)
(filter notOverridden d1 <> d2)
where
notOverridden :: Entity -> Bool
notOverridden = (`M.notMember` n2) . view entityName
removeOverriddenDevices (Capabilities m) =
Capabilities
. M.mapMaybe (NE.nonEmpty . NE.filter (notOverridden . device))
$ m

instance Monoid EntityMap where
mempty = EntityMap M.empty mempty []
Expand Down
6 changes: 6 additions & 0 deletions test/integration/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,12 @@ testScenarioSolutions rs ui key =
assertEqual "Incorrect step count." 62 $ view lifetimeStepCount counters
, expectFailBecause "Awaiting fix for #231" $
testSolution Default "Testing/231-requirements/231-command-transformer-reqs"
, testSolution Default "Testing/2239-custom-entity"
, testSolution' Default "Testing/2240-overridden-entity-capabilities" CheckForBadErrors $ \g -> do
let msgs = g ^.. robotInfo . robotMap . traverse . robotLog . to logToText . traverse
assertBool "Error message should mention tank treads but not treads" $
not (any ("- treads" `T.isInfixOf`) msgs)
&& any ("- tank treads" `T.isInfixOf`) msgs
]
where
-- expectFailIf :: Bool -> String -> TestTree -> TestTree
Expand Down

0 comments on commit 79ba1b7

Please sign in to comment.