Skip to content

Instantly share code, notes, and snippets.

@kostmo
Last active November 15, 2022 05:00
Show Gist options
  • Save kostmo/1bbcc9308889fa14a9315a2b9fdb7a31 to your computer and use it in GitHub Desktop.
Save kostmo/1bbcc9308889fa14a9315a2b9fdb7a31 to your computer and use it in GitHub Desktop.
Gosling simulator

To run this script:

  1. Download this gist as a zip file and extract
  2. Execute the following:
    stack run -- --scenario /path/to/goslings.yaml
    
def hasItemInDirection = \item. \direction.
x <- scan direction;
case x
(\_. return false)
(\y. return $ y == item);
end;
def elifM = \p.\t.\e. {p2 <- p; if p2 t e} end;
def getItemDirection : text -> cmd (unit + dir) = \item.
isFwd <- hasItemInDirection item forward;
if (isFwd) {
return $ inr forward;
} $ elifM (hasItemInDirection item left) {
return $ inr left;
} $ elifM (hasItemInDirection item right) {
return $ inr right;
} $ elifM (hasItemInDirection item back) {
return $ inr back;
} {
return $ inl ();
}
end;
def elif = \p.\t.\e. {if p t e} end;
def rememberDirection = \isStranded. \itemToFollow. \prevDir.
let goDirection= \d.
turn d;
f <- grab;
move;
place f;
rememberDirection false itemToFollow $ inl ();
in
maybeFeather <- getItemDirection itemToFollow;
case maybeFeather
(\_. case prevDir
(\_.
if isStranded {} {
say $ "Mama! Lost track of " ++ itemToFollow;
return ();
};
rememberDirection true itemToFollow $ inl ();
)
(\d. goDirection d)
)
(\d.
if isStranded {say "Reunited!"} {};
rememberDirection false itemToFollow $ inr d;
);
end;
def determineItemToFollow : cmd (unit + text) =
x <- scan down;
case x (\_. return $ inl ();) (\n.
return $ if (n == "feather1") {
inr "feather0"
} $ elif (n == "feather2") {
inr "feather1"
} $ elif (n == "feather3") {
inr "feather2"
} $ elif (n == "feather4") {
inr "feather3"
} {
inl ();
}
);
end;
itemToFollow <- determineItemToFollow;
case itemToFollow
(\_. say "Staying here.")
(\item. rememberDirection false item $ inl ())
version: 1
name: Goose caravan
author: Karl Ostmo
description: |
Geese
creative: false
robots:
- name: goose
description:
- mother goose
display:
invisible: false
char: 'G'
system: true
devices:
- logger
dir: [0, 1]
program: |
run "scenarios/Challenges/Ranching/_goslings/mother.sw";
- name: gosling
description:
- baby goose
display:
invisible: false
char: 'g'
system: true
dir: [0, 1]
program: |
run "scenarios/Challenges/Ranching/_goslings/gosling.sw";
entities:
- name: feather0
display:
char: 'f'
description:
- Scannable item carried by mother goose
properties: [known, portable]
- name: feather1
display:
char: 'f'
description:
- Scannable item carried by first baby goose
properties: [known, portable]
- name: feather2
display:
char: 'f'
description:
- Scannable item carried by second baby goose
properties: [known, portable]
- name: feather3
display:
char: 'f'
description:
- Scannable item carried by third baby goose
properties: [known, portable]
- name: feather4
display:
char: 'f'
description:
- Scannable item carried by fourth baby goose
properties: [known, portable]
known: [mountain, tree, water]
seed: 0
world:
palette:
'.': [grass]
'G': [grass, feather0, goose]
'g': [grass, feather1, gosling]
'h': [grass, feather2, gosling]
'i': [grass, feather3, gosling]
'j': [grass, feather4, gosling]
upperleft: [0, 0]
map: |-
.................
.................
.................
......Gghij......
.................
.................
.................
def elif = \p.\t.\e. {if p t e} end;
def decideDirection =
let randdir : cmd dir =
d <- random 3;
return $ if (d == 0) {
left
} $ elif (d == 1) {
right
} {
forward
}
in
d <- randdir;
turn d;
end;
def blockedByItem = \d.
x <- scan d;
case x
(\_. return false)
(\_. return true);
end;
def moveOneStep =
f <- grab;
move;
place f;
wait 12;
end;
let forever : cmd unit -> cmd unit = \c. c ; forever c in
let repeat : int -> cmd unit -> cmd unit =
\n. \c. if (n == 0) {} {c ; repeat (n-1) c} in
forever (
n <- random 10;
wait (16 + n);
decideDirection;
dist <- random 3;
repeat dist (
blockedForward <- blockedByItem forward;
if (blockedForward) {
blockedLeft <- blockedByItem left;
blockedRight <- blockedByItem right;
if (blockedLeft && blockedRight)
{
blockedBack <- blockedByItem back;
if blockedBack {
fail "My goose is cooked.";
} {
say "Let's go back...";
turn back;
}
}
{};
return ();
} {
moveOneStep
}
);
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment