From b477c8ad8e3db8d207d628b5694122afd7bda7a7 Mon Sep 17 00:00:00 2001 From: Karl Ostmo Date: Sun, 11 Jun 2023 20:21:12 -0700 Subject: [PATCH] traffic vignette --- data/scenarios/00-ORDER.txt | 1 + data/scenarios/Vignettes/00-ORDER.txt | 1 + .../Vignettes/_roadway/coordinator.sw | 55 +++++ data/scenarios/Vignettes/_roadway/drone.sw | 200 ++++++++++++++++ data/scenarios/Vignettes/roadway.yaml | 219 ++++++++++++++++++ 5 files changed, 476 insertions(+) create mode 100644 data/scenarios/Vignettes/00-ORDER.txt create mode 100644 data/scenarios/Vignettes/_roadway/coordinator.sw create mode 100644 data/scenarios/Vignettes/_roadway/drone.sw create mode 100644 data/scenarios/Vignettes/roadway.yaml diff --git a/data/scenarios/00-ORDER.txt b/data/scenarios/00-ORDER.txt index 25406667f..b8f3c6815 100644 --- a/data/scenarios/00-ORDER.txt +++ b/data/scenarios/00-ORDER.txt @@ -6,3 +6,4 @@ Challenges Fun Speedruns Testing +Vignettes diff --git a/data/scenarios/Vignettes/00-ORDER.txt b/data/scenarios/Vignettes/00-ORDER.txt new file mode 100644 index 000000000..01d295798 --- /dev/null +++ b/data/scenarios/Vignettes/00-ORDER.txt @@ -0,0 +1 @@ +roadway.yaml \ No newline at end of file diff --git a/data/scenarios/Vignettes/_roadway/coordinator.sw b/data/scenarios/Vignettes/_roadway/coordinator.sw new file mode 100644 index 000000000..fff00786f --- /dev/null +++ b/data/scenarios/Vignettes/_roadway/coordinator.sw @@ -0,0 +1,55 @@ +def forever : cmd unit -> cmd unit = \c. c ; forever c end + +/** Teleports to a new location to execute a function + then returns to the original location before + returning the function's output value. +*/ +def atLocation = \newLoc. \f. + prevLoc <- whereami; + teleport self newLoc; + retval <- f; + teleport self prevLoc; + return retval; + end; + +def swapItem = \ent. + create ent; + emptyHere <- isempty; + if emptyHere {} {grab; return ()}; + place ent; + end; + +def setRedPixel = + instant $ ( + swapItem "pixel (R)"; + ); + end; + +def setGreenPixel = + instant $ ( + swapItem "pixel (G)"; + ); + end; + +def changeToRed = + say "Red light"; + make "bit (0)"; + setRedPixel; + atLocation (17, 2) setGreenPixel; + wait 50; + end; + +def changeToGreen = + say "Green light"; + make "bit (1)"; + setGreenPixel; + atLocation (17, 2) setRedPixel; + wait 100; + end; + +def alternate = + changeToGreen; + changeToRed; + end; + +forever alternate; \ No newline at end of file diff --git a/data/scenarios/Vignettes/_roadway/drone.sw b/data/scenarios/Vignettes/_roadway/drone.sw new file mode 100644 index 000000000..ae24925cf --- /dev/null +++ b/data/scenarios/Vignettes/_roadway/drone.sw @@ -0,0 +1,200 @@ +def elif = \t. \then. \else. {if t then else} end +def else = \t. t end + +def sumTuples = \t1. \t2. + (fst t1 + fst t2, snd t1 + snd t2); + end; + +def max = \a. \b. + if (a > b) {a} {b}; + end; + +def mapTuple = \f. \t. + (f $ fst t, f $ snd t) + end; + +// modulus function (%) +def mod : int -> int -> int = \i.\m. + i - m * (i / m) +end + +def abs = \n. if (n < 0) {-n} {n} end + +def isEven = \n. + mod n 2 == 0; + end + +/* +Decide where to initially teleport to based on the initial coords. +*/ +def init : + [xMin : int, xMax : int, yMin : int, yMax : int] + -> [yWest : int, yEast : int, xSouth : int, xNorth : int] + -> cmd (bool * int) = \extents. \lanes. + let topCorner = (-18, 30) in + absloc <- whereami; + let loc = sumTuples absloc $ mapTuple (\x. -x) topCorner in + let xloc = abs $ fst loc in + let idx = xloc / 2 in + + let yloc = abs (snd loc) in + + randoffset <- random 5; + let baseoffset = 10 * idx in + let offset = randoffset + baseoffset in + let isLongitudinal = not $ isEven yloc in + let locdir = if isLongitudinal { + if (isEven xloc) { + (south, (lanes.xSouth, extents.yMax - offset)) + } { + (north, (lanes.xNorth, extents.yMin + offset)) + } + } { + if (isEven xloc) { + (east, (extents.xMin + offset, lanes.yEast)) + } { + (west, (extents.xMax - offset, lanes.yWest)) + } + } in + turn $ fst locdir; + teleport self $ snd locdir; + return (isLongitudinal, idx); + end; + +def isGreenLight = \isLongitudinal. + r <- robotnamed "stoplight"; + isGreen <- as r {has "bit (1)"}; + return $ isLongitudinal != isGreen; + end; + +def getCanMove : + [xWest : int, xEast : int, ySouth : int, yNorth : int] + -> bool + -> cmd bool + = \stoplines. \hasGreenLight. + + d <- heading; + loc <- whereami; + let atStopLine = if (d == north) { + snd loc == stoplines.yNorth; + } $ elif (d == south) { + snd loc == stoplines.ySouth; + } $ elif (d == east) { + fst loc == stoplines.xEast; + } $ else { + // west + fst loc == stoplines.xWest; + } in + + eitherNeighbor <- meet; + // TODO: Make sure we only consider the neighbor directly in front of us. + neighborIsStopped <- case eitherNeighbor + (\_. return false) + (\r. as r {has "bit (0)"}); // zero-bit means stopped + + return $ hasGreenLight || not (atStopLine || neighborIsStopped); + end; + +def doTunnelWrap : [xMin : int, xMax : int, yMin : int, yMax : int] -> cmd bool = \extents. + myloc <- whereami; + didWrap <- if (fst myloc < extents.xMin) { + teleport self (extents.xMax, snd myloc); + return true; + } $ elif (fst myloc > extents.xMax) { + teleport self (extents.xMin, snd myloc); + return true; + } $ elif (snd myloc < extents.yMin) { + teleport self (fst myloc, extents.yMax); + return true; + } $ elif (snd myloc > extents.yMax) { + teleport self (fst myloc, extents.yMin); + return true; + } $ else { + return false; + }; + return didWrap; + end; + +def moveWithWrap : + [xWest : int, xEast : int, ySouth : int, yNorth : int] + -> [xMin : int, xMax : int, yMin : int, yMax : int] // extents + -> bool + -> cmd (bool * bool) + = \stoplines. \extents. \isLongitudinal. + + hasGreenLight <- isGreenLight isLongitudinal; + canMove <- getCanMove stoplines hasGreenLight; + + wentThroughTunnel <- if canMove { + move; + doTunnelWrap extents; + } { + return false; + }; + + try { + // Makes the "stopped" state queryable by other robots + if canMove {make "bit (1)"} {make "bit (0)"} + } {}; + + return (canMove, wentThroughTunnel); + end; + +def getNewDelayState : + bool + -> [moveDelay : int, transitionCountdown : int] + -> [moveDelay : int, transitionCountdown : int] + = \canGo. \delayState. + if (not canGo) { + // reset to max delay and pause the countdown at max + [moveDelay=5, transitionCountdown=2]; + } $ elif (delayState.moveDelay <= 0) { + // unchanged + delayState + } $ elif (delayState.transitionCountdown > 0) { + // decrement countdown + [moveDelay=delayState.moveDelay, transitionCountdown=delayState.transitionCountdown - 1]; + } $ else { + // Decrement the delay and reset the countdown. + [moveDelay=max 0 $ delayState.moveDelay - 1, transitionCountdown=2]; + } + end; + +/** +Initially we wait several ticks between movements. +Then we continually decrease the delay by 1, until reaching no delay. +*/ +def advance : + int + -> bool + -> [xWest : int, xEast : int, ySouth : int, yNorth : int] + -> [xMin : int, xMax : int, yMin : int, yMax : int] + -> [moveDelay : int, transitionCountdown : int] + -> cmd unit + = \idx. \isLongitudinal. \stoplines. \extents. \delayState. + + wait delayState.moveDelay; + + result <- instant $ moveWithWrap stoplines extents isLongitudinal; + let canGo = fst result in + let wentThroughTunnel = snd result in + if wentThroughTunnel { + r <- random 50; + wait $ idx * 10 + r; + } {}; + + let newDelay = getNewDelayState canGo delayState in + advance idx isLongitudinal stoplines extents newDelay; + end; + +def go = + let extents = [xMin = -12, xMax=53, yMin = -15, yMax = 26] in + let lanes = [yWest = 7, yEast = 5, xSouth = 20, xNorth = 22] in + let stoplines = [xWest = 24, xEast = 17, ySouth = 9, yNorth = 2] in + result <- instant $ init extents lanes; + let isLongitudinal = fst result in + let idx = snd result in + advance idx isLongitudinal stoplines extents [moveDelay=5, transitionCountdown=2]; + end; + +go; \ No newline at end of file diff --git a/data/scenarios/Vignettes/roadway.yaml b/data/scenarios/Vignettes/roadway.yaml new file mode 100644 index 000000000..87525c880 --- /dev/null +++ b/data/scenarios/Vignettes/roadway.yaml @@ -0,0 +1,219 @@ +creative: true +description: Commuting robots meet at an intersection +entities: [] +name: Traffic simulation +robots: + # We include a base robot to stabilize the screen at a fixed position. + - name: base + display: + char: Ω + attr: robot + dir: [1, 0] + loc: [10, 3] + devices: + - logger + - hearing aid + - treads + - name: drone + system: true + display: + invisible: false + dir: [1, 0] + devices: + - lodestone + inventory: + - [1, bit (0)] + program: | + run "data/scenarios/Vignettes/_roadway/drone.sw" + - name: stoplight + system: true + display: + invisible: true + dir: [0, 1] + loc: [24, 9] + devices: + - lodestone + inventory: + - [1, bit (0)] + program: | + run "data/scenarios/Vignettes/_roadway/coordinator.sw" +version: 1 +world: + default: [blank] + palette: + '.': [grass] + 'd': [grass, null, drone] + structures: + - name: road segment + structure: + palette: + 'S': + - stone + 'w': + - ice + '█': + - stone + - sand + map: | + SSSSSS + SSSSSS + ███SSS + SSSSSS + SSSSSS + wwwwww + - name: tunnel + structure: + mask: '.' + palette: + '@': [stone, boulder] + 'b': [blank] + map: | + ..@@@@.. + .@bbbb@. + @@bbbb@@ + @bbbbbb@ + - name: intersection + structure: + palette: + 'S': + - stone + 'w': + - ice + '█': + - stone + - sand + map: | + SSSSSS + SSSSSS + SSSSSS + SSSSSS + SSSSSS + SSSSSS + placements: + - src: tunnel + offset: [3, -21] + orient: + up: "DWest" + - src: tunnel + offset: [71, -21] + orient: + up: "DEast" + - src: road segment + offset: [6, -22] + orient: + up: "DSouth" + flip: true + - src: road segment + offset: [12, -22] + orient: + up: "DSouth" + flip: true + - src: road segment + offset: [18, -22] + orient: + up: "DSouth" + flip: true + - src: road segment + offset: [24, -22] + orient: + up: "DSouth" + flip: true + - src: road segment + offset: [30, -22] + orient: + up: "DSouth" + flip: true + - src: intersection + offset: [36, -22] + - src: road segment + offset: [42, -22] + - src: road segment + offset: [48, -22] + - src: road segment + offset: [54, -22] + - src: road segment + offset: [60, -22] + - src: road segment + offset: [66, -22] + - src: road segment + offset: [36, -28] + orient: + up: "DEast" + - src: road segment + offset: [36, -34] + orient: + up: "DEast" + - src: road segment + offset: [36, -40] + orient: + up: "DEast" + - src: road segment + offset: [36, -16] + orient: + up: "DWest" + flip: true + - src: road segment + offset: [36, -10] + orient: + up: "DWest" + flip: true + - src: road segment + offset: [36, -4] + orient: + up: "DWest" + flip: true + upperleft: + - -18 + - 30 + map: | + dddddddddd.................................................................... + dddddddd...................................................................... + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. + .............................................................................. \ No newline at end of file