-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Demos use of a string to maintain a queue of coordinates. ![Screenshot from 2024-01-02 10-34-05](https://github.com/swarm-game/swarm/assets/261693/eaa24d48-40dc-4294-8243-2977caf4b79f)
- Loading branch information
Showing
5 changed files
with
323 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
GoL.yaml | ||
logo-burst.yaml | ||
horton.yaml | ||
horton.yaml | ||
snake.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/** | ||
Uses a string to maintain a queue of coordinates. | ||
*/ | ||
|
||
def coordsToString : (int * int) -> text = \coords. | ||
format (fst coords) ++ "," ++ format (snd coords) | ||
end | ||
|
||
def indexOfRec : int -> text -> text -> (unit + int) = \pos. \inputString. \targetChar. | ||
if (pos >= chars inputString) { | ||
inL () | ||
} { | ||
if (toChar (charAt pos inputString) == targetChar) { | ||
inR pos | ||
} { | ||
indexOfRec (pos + 1) inputString targetChar | ||
} | ||
} | ||
end | ||
|
||
def indexOf : text -> text -> (unit + int) = | ||
indexOfRec 0 | ||
end | ||
|
||
// Drops the first character of a string | ||
def strTail : text -> text = \inputString. | ||
snd $ split 1 inputString | ||
end | ||
|
||
def splitOnFirstChar : text -> text -> (text * text) = \inputString. \splitChar. | ||
case (indexOf inputString splitChar) (\_. | ||
// Did not find the split character, so return the original string | ||
(inputString, "") | ||
) (\foundIdx. | ||
let parts = split foundIdx inputString in | ||
(fst parts, strTail $ snd parts) | ||
) | ||
end | ||
|
||
def getDecimalCharValue = \inputString. \idx. | ||
charAt idx inputString - charAt 0 "0" | ||
end | ||
|
||
// Works from right to left | ||
def parseDecimalRec : int -> text -> int = \charsRemaining. \inputString. | ||
if (charsRemaining > 0) { | ||
getDecimalCharValue inputString (charsRemaining - 1) + 10 * parseDecimalRec (charsRemaining - 1) inputString | ||
} {0} | ||
end | ||
|
||
def parseDecimal : text -> int = \inputString. | ||
let isNegative = toChar (charAt 0 inputString) == "-" in | ||
let negationMultiplier = if isNegative {-1} {1} in | ||
let modifiedString = if isNegative {strTail inputString} {inputString} in | ||
let stringLength = chars modifiedString in | ||
negationMultiplier * parseDecimalRec stringLength modifiedString; | ||
end | ||
|
||
// Comma (",") is the separator between abscissa and ordinate | ||
def stringToCoords : text -> (int * int) = \coordsString. | ||
let pair = splitOnFirstChar coordsString "," in | ||
(parseDecimal $ fst pair, parseDecimal $ snd pair) | ||
end | ||
|
||
// APPEND to string representation of a coordinate list | ||
def snoc : (int * int) -> text -> text = \coords. \strList. | ||
let delimiter = if (chars strList > 0) {";"} {""} in | ||
strList ++ delimiter ++ coordsToString coords; | ||
end | ||
|
||
// Extracts the first element and returns the shortened list | ||
def pop : text -> (unit + ((int * int) * text)) = \strList. | ||
if (chars strList > 0) { | ||
let pair = splitOnFirstChar strList ";" in | ||
inR (stringToCoords $ fst pair, snd pair) | ||
} { | ||
inL (); | ||
} | ||
end | ||
|
||
def getDir = \dest. | ||
path (inL ()) (inL dest); | ||
end; | ||
|
||
def doAtLoc = \currLoc. \targetLoc. \func. | ||
teleport self targetLoc; | ||
x <- func; | ||
teleport self currLoc; | ||
return x; | ||
end; | ||
|
||
def moveTail = \tailList. | ||
emptyHere <- isempty; | ||
if emptyHere { | ||
let maybeShifted = pop tailList in | ||
case maybeShifted (\_. | ||
// Nothing to pick up or replace | ||
return tailList; | ||
|
||
) (\newPair. | ||
|
||
let farthestTail = fst newPair in | ||
let newInit = snd newPair in | ||
newLoc <- whereami; | ||
grabbedItem <- doAtLoc newLoc farthestTail grab; | ||
place grabbedItem; | ||
|
||
return $ snoc newLoc newInit; | ||
); | ||
} { | ||
return tailList; | ||
} | ||
end; | ||
|
||
def moveOneStep = \tailList. | ||
|
||
// This robot will always be sitting atop the apple | ||
r <- robotnamed "spawn"; | ||
targetLoc <- as r {whereami}; | ||
|
||
maybeD <- getDir targetLoc; | ||
case maybeD (\_. say "Dead!"; return "") (\d. | ||
turn $ fst d; | ||
newList <- moveTail tailList; | ||
move; | ||
return newList | ||
); | ||
end | ||
|
||
// Invariant: No tail pieces shall ever be moved underneath the | ||
// snake robot, unless an apple was just picked up. | ||
def moveToApple = \tailList. | ||
|
||
myLoc <- whereami; | ||
|
||
appleHere <- ishere "apple"; | ||
if appleHere { | ||
|
||
modifiedTailList <- try { | ||
make "tail"; | ||
swap "tail"; | ||
return $ snoc myLoc tailList; | ||
} { | ||
grab; | ||
return tailList; | ||
}; | ||
// Need to move here so that we get out of the way | ||
// if the tail gets elongated | ||
moveOneStep modifiedTailList; | ||
} { | ||
moveOneStep tailList; | ||
} | ||
end; | ||
|
||
def go = \tailList. | ||
newList <- instant $ moveToApple tailList; | ||
go newList; | ||
end; | ||
|
||
go ""; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
def waitForConsumption = | ||
watch down; | ||
wait 2000; | ||
appleHere <- ishere "apple"; | ||
if appleHere { | ||
waitForConsumption; | ||
} {} | ||
end; | ||
|
||
// TODO Ensure we don't spawn inside a coil of the tail | ||
def placeAtOpenLocation = \range. | ||
randX <- random range; | ||
randY <- random range; | ||
let x = range/2 - randX in | ||
let y = range/2 - randY in | ||
teleport self (x, y); | ||
emptyHere <- isempty; | ||
if emptyHere { | ||
place "apple"; | ||
} { | ||
placeAtOpenLocation range; | ||
} | ||
end; | ||
|
||
def repeatedlyPlaceApple = \range. | ||
placeAtOpenLocation range; | ||
waitForConsumption; | ||
end; | ||
|
||
def go = | ||
instant $ repeatedlyPlaceApple 20; | ||
go; | ||
end; | ||
|
||
go; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
version: 1 | ||
name: Snake | ||
author: Karl Ostmo | ||
seed: 1 | ||
description: | | ||
Watch the snake eat the apples | ||
creative: false | ||
objectives: | ||
- goal: | ||
- | | ||
Eat and "digest" many apples | ||
condition: | | ||
r <- robotnamed "snake"; | ||
as r { | ||
appleCoreCount <- count "apple core"; | ||
return $ appleCoreCount >= 40; | ||
} | ||
robots: | ||
- name: base | ||
dir: north | ||
devices: | ||
- ADT calculator | ||
- branch predictor | ||
- clock | ||
- comparator | ||
- compass | ||
- dictionary | ||
- grabber | ||
- hourglass | ||
- hearing aid | ||
- keyboard | ||
- lambda | ||
- logger | ||
- net | ||
- scanner | ||
- strange loop | ||
- string | ||
- treads | ||
- wayfinder | ||
- name: snake | ||
dir: north | ||
system: true | ||
display: | ||
attr: green | ||
invisible: false | ||
devices: | ||
- rattle | ||
program: | | ||
run "scenarios/Fun/_snake/snake.sw" | ||
- name: spawn | ||
dir: north | ||
system: true | ||
display: | ||
invisible: true | ||
inventory: | ||
- [100, apple] | ||
program: | | ||
run "scenarios/Fun/_snake/spawn.sw" | ||
solution: | | ||
noop | ||
entities: | ||
- name: wayfinder | ||
display: | ||
char: 'w' | ||
description: | ||
- | | ||
Enables the `path` command | ||
properties: [known, portable] | ||
capabilities: [path] | ||
- name: apple | ||
display: | ||
char: 'a' | ||
attr: red | ||
description: | ||
- | | ||
Tasty snack | ||
properties: [known, portable] | ||
- name: apple core | ||
display: | ||
char: 'I' | ||
attr: wood | ||
description: | ||
- | | ||
Remains of an eaten apple | ||
properties: [known, portable] | ||
- name: rattle | ||
display: | ||
char: 'r' | ||
attr: green | ||
description: | ||
- | | ||
Device unique to a snake | ||
properties: [known] | ||
- name: tail | ||
display: | ||
char: '@' | ||
attr: green | ||
description: | ||
- | | ||
Segment of snake's tail | ||
properties: [known, unwalkable] | ||
recipes: | ||
- in: | ||
- [3, apple] | ||
out: | ||
- [1, tail] | ||
- [3, apple core] | ||
required: | ||
- [1, rattle] | ||
known: [] | ||
world: | ||
dsl: | | ||
{grass} | ||
upperleft: [0, 0] | ||
palette: | ||
'B': [grass, erase, base] | ||
'S': [grass, erase, snake] | ||
's': [grass, erase, spawn] | ||
'.': [grass, erase] | ||
map: | | ||
B.. | ||
s.S |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters