From b2cba349e18aff8b803ddc7df716efa8333eed24 Mon Sep 17 00:00:00 2001 From: Karl Ostmo Date: Tue, 14 Nov 2023 21:21:36 -0800 Subject: [PATCH] fishing scenario --- .../Challenges/Ranching/00-ORDER.txt | 1 + .../Challenges/Ranching/_fishing/hauler.sw | 68 +++ .../Challenges/Ranching/_fishing/shark.sw | 24 + .../Challenges/Ranching/_fishing/solution.sw | 138 +++++ .../Challenges/Ranching/fishing.yaml | 509 ++++++++++++++++++ test/integration/Main.hs | 1 + 6 files changed, 741 insertions(+) create mode 100644 data/scenarios/Challenges/Ranching/_fishing/hauler.sw create mode 100644 data/scenarios/Challenges/Ranching/_fishing/shark.sw create mode 100644 data/scenarios/Challenges/Ranching/_fishing/solution.sw create mode 100644 data/scenarios/Challenges/Ranching/fishing.yaml diff --git a/data/scenarios/Challenges/Ranching/00-ORDER.txt b/data/scenarios/Challenges/Ranching/00-ORDER.txt index 8bdbff6478..f3f14650b1 100644 --- a/data/scenarios/Challenges/Ranching/00-ORDER.txt +++ b/data/scenarios/Challenges/Ranching/00-ORDER.txt @@ -1,4 +1,5 @@ beekeeping.yaml capture.yaml powerset.yaml +fishing.yaml gated-paddock.yaml diff --git a/data/scenarios/Challenges/Ranching/_fishing/hauler.sw b/data/scenarios/Challenges/Ranching/_fishing/hauler.sw new file mode 100644 index 0000000000..4dc0740c54 --- /dev/null +++ b/data/scenarios/Challenges/Ranching/_fishing/hauler.sw @@ -0,0 +1,68 @@ +def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end; + +def isEnclosureFull = + foundBox <- structure "rubbish enclosure" 0; + case foundBox (\_. return false) (\enclosure. + let boxPos = snd enclosure in + + prevLoc <- whereami; + + dims <- floorplan "rubbish enclosure"; + teleport self boxPos; + + c <- density ((0, 0), dims); + let area = fst dims * snd dims in + let notFull = c < area in + + teleport self prevLoc; + return $ not notFull; + ); + end; + +def tryGrab = + try { + grab; + return () + } {}; + end; + +def waitUntilEnclosureFull = + + isFull <- instant isEnclosureFull; + if isFull { + turn south; + doN 13 move; + turn right; + doN 3 move; + turn right; + doN 2 move; + turn left; + + doN 2 (tryGrab; move;); + tryGrab; + turn left; + move; + turn left; + doN 2 (tryGrab; move;); + tryGrab; + + // Leave again + turn right; + move; + turn left; + doN 3 move; + turn left; + doN 13 move; + turn back; + } { + wait 10; + waitUntilEnclosureFull; + } + end; + +def go = + waitUntilEnclosureFull; + go; + end; + +go; diff --git a/data/scenarios/Challenges/Ranching/_fishing/shark.sw b/data/scenarios/Challenges/Ranching/_fishing/shark.sw new file mode 100644 index 0000000000..14e1efd62c --- /dev/null +++ b/data/scenarios/Challenges/Ranching/_fishing/shark.sw @@ -0,0 +1,24 @@ +/** +Swims back and forth forever. +*/ + +def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end; + +def swim = + appear "^"; + doN 3 (move; wait 3); + turn back; + wait 15; + doN 3 (move; wait 3); + turn back; + appear " "; + end; + +def go = + waitR <- random 100; + wait $ 50 + waitR; + swim; + go; + end; + +go; diff --git a/data/scenarios/Challenges/Ranching/_fishing/solution.sw b/data/scenarios/Challenges/Ranching/_fishing/solution.sw new file mode 100644 index 0000000000..6b6ae9719f --- /dev/null +++ b/data/scenarios/Challenges/Ranching/_fishing/solution.sw @@ -0,0 +1,138 @@ +def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end; + +def makeRoll = + make "nori"; + make "california roll"; + end; + +def checkIngredients = + hasTuna <- has "crab"; + hasSeaweed <- has "seaweed"; + return $ hasTuna && hasSeaweed; + end; + +def catchFish = \rod. + use rod forward; + ready <- checkIngredients; + if ready { + makeRoll; + } { + catchFish rod; + }; + end; + +def harvestIngredients = + turn back; + doN 4 move; + turn right; + move; + harvest; + turn back; + doN 2 move; + harvest; + doN 3 move; + harvest; + turn left; + doN 7 move; + turn left; + end; + +def getJunkItem = \idx. + result <- tagmembers "junk" idx; + let totalCount = fst result in + let member = snd result in + let nextIdx = idx + 1 in + + hasProhibited <- has member; + if hasProhibited { + return $ inr member; + } { + if (nextIdx < totalCount) { + getJunkItem nextIdx; + } { + return $ inl (); + } + } + end; + +def tryPlace = \item. + try { + place item; + } {}; + end; + +/** +Precondition: facing north in lower-left corner of enclosure + +Navigates a serpentine pattern through the space to +place items. +*/ +def placeSerpentine = \placeFunc. + placeFunc; + move; + placeFunc; + turn right; + move; + placeFunc; + turn right; + move; + placeFunc; + turn left; + move; + placeFunc; + turn left; + move; + placeFunc; + end; + +def returnToCorner = + turn back; + move; move; + turn right; + move; move; + turn right; + end; + +def unloadTrash = + try { + placeSerpentine ( + item <- getJunkItem 0; + case item (\_. fail "done") (\item. place item); + ); + watch forward; + wait 1000; + + wait 50; + unloadTrash; + } {}; + end; + +def disposeTrash = + turn back; + doN 5 move; + turn left; + doN 11 move; + turn left; + move; + + doN 2 ( + placeSerpentine $ tryPlace "car tire"; + returnToCorner; + ignite forward; + wait 80; + move; + ); + + unloadTrash; + end; + +def go = + harvestIngredients; + let rod = "fishing tackle" in + make rod; + equip rod; + catchFish rod; + disposeTrash; + end; + +go; diff --git a/data/scenarios/Challenges/Ranching/fishing.yaml b/data/scenarios/Challenges/Ranching/fishing.yaml new file mode 100644 index 0000000000..5152d040c5 --- /dev/null +++ b/data/scenarios/Challenges/Ranching/fishing.yaml @@ -0,0 +1,509 @@ +version: 1 +name: Fishing trip +author: Karl Ostmo +description: | + Catch a the appropriate seafood to make lunch. + + If you haul any trash out of the lake, you + must throw it away in the enclosure to the southeast. + No littering! +creative: false +seed: 0 +attrs: + - name: shark + bg: "#2040bb" +objectives: + - teaser: Hot rod + goal: + - | + `equip` your `fishing tackle`{=entity}, i.e. a rod and its accoutrements. + condition: | + as base { + equipped "fishing tackle"; + } + - teaser: Sushi chef + id: made_sushi + goal: + - | + Make a `california roll`{=entity} + condition: | + as base { + has "california roll" + } + - teaser: Waste disposal + prerequisite: + logic: + and: + - made_sushi + - not: littered + goal: + - | + Inventory must be free of all `junk`{=tag} + condition: | + // Returns true if prohibited item is in inventory. + def checkProhibited = \idx. + result <- tagmembers "junk" idx; + let totalCount = fst result in + let member = snd result in + let nextIdx = idx + 1 in + + hasProhibited <- as base {has member}; + if hasProhibited { + return false; + } { + if (nextIdx < totalCount) { + checkProhibited nextIdx; + } { + return true; + } + } + end; + + checkProhibited 0; + - teaser: No littering + id: littered + optional: true + goal: + - | + Dispose of `junk`{=tag} only in designated enclosure. + - | + Certain items can be burned to make room. + Good thing you brought your `torch`{=entity}! + - | + Otherwise, when the enclosure becomes full, the trash + hauler will come to empty it. + condition: | + def junkOutsideEnclosure = + result <- scan down; + case result (\_. return false) (\item. + isJunk <- hastag item "junk"; + if isJunk { + foundBox <- structure "rubbish enclosure" 0; + case foundBox (\_. return false) (\enclosure. + let boxPos = snd enclosure in + dims <- floorplan "rubbish enclosure"; + loc <- whereami; + + return $ not $ snd loc >= snd boxPos + && snd loc < snd dims + snd boxPos + && fst loc >= fst boxPos + && fst loc < fst dims + fst boxPos; + ); + } { + return false; + }; + ); + end; + + // If a junk entity was placed on the ground, + // it will be in the same cell as the base robot. + as base { + junkOutsideEnclosure; + } +robots: + - name: base + dir: [1, 0] + devices: + - branch predictor + - ADT calculator + - hourglass + - comparator + - dictionary + - grabber + - harvester + - keyboard + - lambda + - logger + - net + - pawn star + - rolex + - scanner + - strange loop + - torch + - treads + - welder + - workbench + inventory: + - [1, branch] + - [1, string] + - [1, fish hook] + - [1, lead weight] + - name: hauler + dir: [1, 0] + system: true + display: + char: W + invisible: false + program: | + run "scenarios/Challenges/Ranching/_fishing/hauler.sw" + - name: shark + dir: [1, 0] + system: true + display: + char: ' ' + attr: shark + invisible: false + program: | + run "scenarios/Challenges/Ranching/_fishing/shark.sw" +solution: | + run "scenarios/Challenges/Ranching/_fishing/solution.sw" +structures: + - name: rubbish enclosure + recognize: [north] + structure: + palette: + 'j': [grass, concrete wall] + '.': [stone, null] + map: | + jjjjj + j...j + j...j +entities: + - name: concrete wall + display: + attr: rock + char: '-' + description: + - Enclosure for rubbish + properties: [known, unwalkable] + - name: lakewater + display: + attr: water + char: ' ' + description: + - Potable water from a lake + properties: [known, infinite, liquid] + - name: pawn star + display: + attr: gold + char: '*' + description: + - | + Can tell you if something is `junk`{=tag} + via the `hastag` command. E.g.: + - | + `hastag "car tire" "junk"` + - | + Also allows you to iterate over the list of junk, e.g.: + - | + `tagmembers "junk" 0` + capabilities: [hastag, tagmembers] + - name: torch + display: + attr: wood + char: 't' + description: + - Can set things on fire + properties: [known, pickable] + capabilities: [ignite] + - name: fishing tackle + display: + char: 'r' + attr: wood + description: + - A fishing rod equipped with hook, line and sinker. + - Use on `water`{=entity} to catch fish + properties: [known, pickable] + - name: lead weight + display: + char: 'w' + attr: device + description: + - Used as a fishing sinker + properties: [known, pickable] + - name: fish hook + display: + char: 'j' + attr: device + description: + - Use to catch fish + properties: [known, pickable] + - name: california roll + display: + char: 'c' + description: + - Delicious + properties: [known, pickable] + - name: rice + display: + char: 'i' + attr: plant + description: + - Perfect for sushi + properties: [known, pickable, growable] + - name: avocado + display: + char: 'A' + attr: plant + description: + - Perfect for sushi + properties: [known, pickable, growable] + - name: cucumber + display: + char: 'u' + attr: plant + description: + - Perfect for sushi + properties: [known, pickable, growable] + - name: tuna + display: + char: 't' + description: + - Edible fish + properties: [known, pickable] + - name: crab + display: + char: 'c' + description: + - Perfect for sushi + properties: [known, pickable] + - name: pufferfish + display: + char: 'p' + description: + - Poisonous + properties: [known, pickable] + - name: trout + display: + char: 't' + description: + - Good to eat + properties: [known, pickable] + - name: salmon + display: + char: 't' + description: + - Good to eat + properties: [known, pickable] + - name: oarfish + display: + char: 'r' + description: + - Too long + properties: [known, pickable] + - name: narwhal + display: + char: 'n' + description: + - Too big + properties: [known, pickable] + - name: marlin + display: + char: 'm' + description: + - Pointy + properties: [known, pickable] + - name: seaweed + display: + char: 'w' + description: + - Inedible...? + properties: [known, pickable] + - name: nori + display: + char: 'n' + description: + - Dried seaweed wrap for sushi rolls + properties: [known, pickable] + - name: car tire + display: + char: 'o' + description: + - Rubber waste. Flammable. + tags: [junk] + properties: [known, pickable, combustible] + combustion: + ignition: 0.5 + duration: [40, 80] + product: null + - name: kitchen sink + display: + char: 'i' + description: + - Everything but! + tags: [junk] + properties: [known, pickable] + - name: boot + display: + char: 'b' + description: + - A soggy, worn-out boot. + tags: [junk] + properties: [known, pickable] + - name: rusty bicycle + display: + char: '8' + description: + - Its riding days are over. + tags: [junk, metal] + properties: [known, pickable] +recipes: + - in: + - [1, lakewater] + out: + - [1, rusty bicycle] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, car tire] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 6 + - in: + - [1, lakewater] + out: + - [1, boot] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, kitchen sink] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, seaweed] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, tuna] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, salmon] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, narwhal] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, oarfish] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, trout] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, marlin] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, pufferfish] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, lakewater] + out: + - [1, crab] + - [1, lakewater] + required: + - [1, fishing tackle] + time: 10 + weight: 1 + - in: + - [1, seaweed] + out: + - [1, nori] + - in: + - [1, crab] + - [1, rice] + - [1, nori] + - [1, cucumber] + - [1, avocado] + out: + - [1, california roll] + - in: + - [1, branch] + - [1, fish hook] + - [1, string] + - [1, lead weight] + out: + - [1, fishing tackle] +known: [] +world: + dsl: | + {grass} + upperleft: [0, 0] + placements: + - src: rubbish enclosure + offset: [19, -10] + palette: + 'B': [grass, erase, base] + '.': [grass] + 'w': [grass, lakewater] + 's': [grass, lakewater, shark] + 'A': [grass, avocado] + 'i': [grass, rice] + 'c': [grass, cucumber] + 'r': [dirt, erase] + 'h': [dirt, erase, hauler] + map: | + .........................h. + .........................r. + .AA......................r. + .AA........wwwwww........r. + ......B...wwwwwwww.......r. + .ii.......wwswwwww.......r. + .ii......wwwwwwwww.......r. + .........wwwwwwww........r. + .cc........wwww..........r. + .cc......................r. + .........................r. + .........................r. + .........................r. + ....................rrrrrr. diff --git a/test/integration/Main.hs b/test/integration/Main.hs index d1e086e5b0..5c950f5388 100644 --- a/test/integration/Main.hs +++ b/test/integration/Main.hs @@ -254,6 +254,7 @@ testScenarioSolutions rs ui = [ testSolution Default "Challenges/Ranching/capture" , testSolution (Sec 60) "Challenges/Ranching/beekeeping" , testSolution (Sec 10) "Challenges/Ranching/powerset" + , testSolution (Sec 10) "Challenges/Ranching/fishing" , testSolution (Sec 30) "Challenges/Ranching/gated-paddock" ] , testGroup