From a687d54c76f4b33b41b2cab170d3b11006ffd3db Mon Sep 17 00:00:00 2001 From: Brent Yorgey Date: Tue, 25 Jun 2024 16:31:43 -0500 Subject: [PATCH] Fix world DSL coordinate bug (#1988) The special variables `x` and `y` in the world DSL did not refer to the correct thing --- in the interpreter apparently I forgot to convert from `Coords` to `Location` and just used the row, column in `Coords` as the `x` and `y`. I have also fixed up all the scenarios which used `x` and `y` in their world description so that they now look identical to before, by replacing every use of `x` with `-y` and every use of `y` with `x` (though in some cases where the result would be algebraically equal I did not literally do this replacement, *e.g.* `(x + y) % 2` is equal to `((-y) + x) % 2`, so I left it alone). --- .../Challenges/Ranching/beekeeping.yaml | 2 +- data/scenarios/Challenges/gallery.yaml | 4 ++-- data/scenarios/Challenges/wave.yaml | 2 +- data/scenarios/Fun/horton.yaml | 2 +- .../Testing/1320-world-DSL/00-ORDER.txt | 1 + .../Testing/1320-world-DSL/coords.yaml | 22 +++++++++++++++++++ .../Testing/1535-ping/1535-in-range.yaml | 4 ++-- .../Testing/1535-ping/1535-out-of-range.yaml | 4 ++-- .../Swarm/Game/World/Interpret.hs | 7 ++++-- 9 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 data/scenarios/Testing/1320-world-DSL/coords.yaml diff --git a/data/scenarios/Challenges/Ranching/beekeeping.yaml b/data/scenarios/Challenges/Ranching/beekeeping.yaml index 4872dc067..4625126ce 100644 --- a/data/scenarios/Challenges/Ranching/beekeeping.yaml +++ b/data/scenarios/Challenges/Ranching/beekeeping.yaml @@ -430,7 +430,7 @@ world: in overlay [ {grass} - , mask (flowers && (x + y) % 3 == 0) {wildflower} + , mask (flowers && (x - y) % 3 == 0) {wildflower} , mask (rubble && (x + y) % 2 == 0) {rock} , mask rock {rock} , mask trees {tree} diff --git a/data/scenarios/Challenges/gallery.yaml b/data/scenarios/Challenges/gallery.yaml index 5dffa219c..69d8cf7c9 100644 --- a/data/scenarios/Challenges/gallery.yaml +++ b/data/scenarios/Challenges/gallery.yaml @@ -241,8 +241,8 @@ world: dsl: | overlay [ {terrain: stone} - , if (x/5 + y/5) % 2 == 0 then {terrain: dirt} else {blank} - , if (((x + 3) % 20)/11 + ((y + 3) % 20)/11) == 0 then {terrain: grass} else {blank} + , if (x/5 + (-y)/5) % 2 == 0 then {terrain: dirt} else {blank} + , if (((3 - y) % 20)/11 + ((x + 3) % 20)/11) == 0 then {terrain: grass} else {blank} ] upperleft: [0, 11] offset: false diff --git a/data/scenarios/Challenges/wave.yaml b/data/scenarios/Challenges/wave.yaml index 6c183db31..70693a0b9 100644 --- a/data/scenarios/Challenges/wave.yaml +++ b/data/scenarios/Challenges/wave.yaml @@ -68,7 +68,7 @@ world: dsl: | overlay [ {dirt, water} - , if (x + y / 2) % 5 == 0 then {dirt, wavy water} else {blank} + , if (x / 2 - y) % 5 == 0 then {dirt, wavy water} else {blank} ] upperleft: [-3, 6] offset: false diff --git a/data/scenarios/Fun/horton.yaml b/data/scenarios/Fun/horton.yaml index 24987c3ad..027ae5a65 100644 --- a/data/scenarios/Fun/horton.yaml +++ b/data/scenarios/Fun/horton.yaml @@ -76,7 +76,7 @@ world: [ {dirt} , mask (patch) {boulder} , mask (prize) {flower} - , mask (y < -80 || y > 80 || x < -60 || x > 60) (overlay [{water}]) + , mask (x < -80 || x > 80 || y < -60 || y > 60) (overlay [{water}]) ] upperleft: [-4, 4] offset: false diff --git a/data/scenarios/Testing/1320-world-DSL/00-ORDER.txt b/data/scenarios/Testing/1320-world-DSL/00-ORDER.txt index 8a46bc0af..b8b093e30 100644 --- a/data/scenarios/Testing/1320-world-DSL/00-ORDER.txt +++ b/data/scenarios/Testing/1320-world-DSL/00-ORDER.txt @@ -1,3 +1,4 @@ constant.yaml erase.yaml override.yaml +coords.yaml diff --git a/data/scenarios/Testing/1320-world-DSL/coords.yaml b/data/scenarios/Testing/1320-world-DSL/coords.yaml new file mode 100644 index 000000000..d1bc97a51 --- /dev/null +++ b/data/scenarios/Testing/1320-world-DSL/coords.yaml @@ -0,0 +1,22 @@ +version: 1 +name: Coordinate test +description: | + Ensure x and y are handled correctly in the world DSL +creative: false +objectives: + - goal: + - Must pick up a rock + condition: | + as base {has "rock"} +solution: | + grab +robots: + - name: base + loc: [1, 2] + dir: east + devices: + - logger + - grabber +world: + dsl: | + mask (x == 1) (mask (y == 2) {rock,dirt}) diff --git a/data/scenarios/Testing/1535-ping/1535-in-range.yaml b/data/scenarios/Testing/1535-ping/1535-in-range.yaml index 37bbb7acd..f42462d05 100644 --- a/data/scenarios/Testing/1535-ping/1535-in-range.yaml +++ b/data/scenarios/Testing/1535-ping/1535-in-range.yaml @@ -75,8 +75,8 @@ world: dsl: | overlay [ {terrain: stone} - , if (x/5 + y/5) % 2 == 0 then {terrain: dirt} else {blank} - , if ((x + 3) % 19)/12 + (y % 19)/12 == 0 then {terrain: grass} else {blank} + , if (x/5 + (-y)/5) % 2 == 0 then {terrain: dirt} else {blank} + , if ((3 - y) % 19)/12 + (x % 19)/12 == 0 then {terrain: grass} else {blank} ] palette: 'B': [blank, null, base] diff --git a/data/scenarios/Testing/1535-ping/1535-out-of-range.yaml b/data/scenarios/Testing/1535-ping/1535-out-of-range.yaml index fed61705d..96352c712 100644 --- a/data/scenarios/Testing/1535-ping/1535-out-of-range.yaml +++ b/data/scenarios/Testing/1535-ping/1535-out-of-range.yaml @@ -54,8 +54,8 @@ world: dsl: | overlay [ {terrain: blank} - , if (x/4 + y/4) % 2 == 0 then {terrain: dirt} else {blank} - , if ((x + 3) % 19)/12 + (y % 19)/12 == 0 then {terrain: grass} else {blank} + , if (x/4 + (-y)/4) % 2 == 0 then {terrain: dirt} else {blank} + , if ((3 - y) % 19)/12 + (x % 19)/12 == 0 then {terrain: grass} else {blank} ] palette: 'B': [stone, null, base] diff --git a/src/swarm-scenario/Swarm/Game/World/Interpret.hs b/src/swarm-scenario/Swarm/Game/World/Interpret.hs index 3437af9c8..552455bf2 100644 --- a/src/swarm-scenario/Swarm/Game/World/Interpret.hs +++ b/src/swarm-scenario/Swarm/Game/World/Interpret.hs @@ -1,4 +1,6 @@ {-# LANGUAGE GADTs #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE ViewPatterns #-} -- | -- SPDX-License-Identifier: BSD-3-Clause @@ -16,8 +18,9 @@ import Data.ByteString (ByteString) import Data.Hash.Murmur (murmur3) import Data.Tagged (unTagged) import Numeric.Noise.Perlin (noiseValue, perlin) +import Swarm.Game.Location (pattern Location) import Swarm.Game.World.Abstract (BTerm (..)) -import Swarm.Game.World.Coords (Coords (..)) +import Swarm.Game.World.Coords (Coords (..), coordsToLoc) import Swarm.Game.World.Gen (Seed) import Swarm.Game.World.Syntax (Axis (..), Rot (..)) import Swarm.Game.World.Typecheck (Const (..), Empty (..), Over (..)) @@ -55,7 +58,7 @@ interpConst seed = \case CGeq -> (>=) CMask -> \b x c -> if b c then x c else empty CSeed -> fromIntegral seed - CCoord ax -> \(Coords (x, y)) -> fromIntegral (case ax of X -> x; Y -> y) + CCoord ax -> \(coordsToLoc -> Location x y) -> fromIntegral (case ax of X -> x; Y -> y) CHash -> \(Coords ix) -> fromIntegral . murmur3 0 . unTagged . from @String @(Encoding.UTF_8 ByteString) . show $ ix CPerlin -> \s o k p -> let noise = perlin (fromIntegral s) (fromIntegral o) k p