Skip to content

Commit

Permalink
Meeting other robots (#920)
Browse files Browse the repository at this point in the history
Closes #306. Closes #931.

- Renamed `robot` type to `actor` in anticipation of meeting other things besides robots.
- `meet : cmd (unit + actor)` returns an arbitrary actor within Manhattan distance 1, if any.
- `meetAll : (b -> actor -> cmd b) -> b -> cmd b` will run on every nearby actor.
- Added `antenna` device to provide the commands.
- Added "make a friend" challenge that requires the use of `meet`.
  • Loading branch information
byorgey authored Dec 22, 2022
1 parent 56eea86 commit 926cede
Show file tree
Hide file tree
Showing 22 changed files with 388 additions and 57 deletions.
39 changes: 32 additions & 7 deletions data/entities.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
char: 'Å'
priority: 11
description:
- A tunnel in a mountain through which robots can freely move.
- A tunnel in a mountain through which anything can freely move.
properties: []

- name: copper ore
Expand Down Expand Up @@ -710,10 +710,10 @@
place. The item is removed from the robot's inventory and placed
in the robot's current cell (which must be empty). Raises an
exception if the operation fails.
- "The `give` command takes two arguments: the robot to
- "The `give` command takes two arguments: the actor to
give an item to (which can be at most 1 cell away), and the name
of the item to give. Raises an exception if the operation fails."
- "The `install` command takes two arguments: the robot
- "The `install` command takes two arguments: the actor
on which to install a device (which can be at most 1 cell away),
and the name of the device to install."
capabilities: [grab, give, place, install]
Expand Down Expand Up @@ -966,9 +966,9 @@
attr: device
char: '@'
description:
- "Allows a robot to hear what nearby robots are saying."
- "Allows a robot to hear anything being said nearby."
- "Simply having this device installed will automatically
add messages said by nearby robots to this robot's log,
add messages said by nearby actors to this robot's log,
assuming it has a logger installed."
- "That way you can view any heard message later either in
the logger or the message window."
Expand Down Expand Up @@ -1076,7 +1076,7 @@
attr: device
char: 'Ю'
description:
- An I/O cable can be used to communicate with an adjacent robot.
- An I/O cable can be used to communicate with adjacent actors.
properties: [portable]

- name: rubber band
Expand All @@ -1093,7 +1093,7 @@
- "This seems like a safe way to execute `grab` only when there is a
rock to grab. However, it is actually possible for the `grab` to
fail, if some other robot B snatches the rock right after robot A sensed
it and before robot A got around to grab it on the next game tick."
it and before robot A got around to grabbing it on the next game tick."
- "This will make robot A very sad and it will crash."
- "To prevent this situation, robot A can wrap the commands in `atomic`, like so:"
- |
Expand All @@ -1114,3 +1114,28 @@
- will attempt to move, but if that fails, turn left instead.
properties: [portable]
capabilities: [try]

- name: antenna
display:
attr: silver
char: 'Y'
description:
- A device for transforming electric current into radio waves, and
vice versa.
- |
It can be used to locate nearby actors, by bouncing radio
waves off them and listening for the echo. This capability can be
accessed via two commands:
- |
`meet : cmd (() + actor)` tries to locate a
nearby actor (a robot, or... something else?) up to one cell away.
It returns a reference to the nearest actor, or a unit value if
none are found.
- |
`meetAll : (b -> actor -> cmd b) -> b -> cmd b` runs a command on
every nearby actor (other than oneself), folding over the results
to compute a final result of type `b`. For example, if `x`, `y`,
and `z` are nearby actors, then `meetAll f b0` is equivalent to
`b1 <- f b0 x; b2 <- f b1 y; f b2 z`.
properties: [portable]
capabilities: [meet]
6 changes: 6 additions & 0 deletions data/recipes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,12 @@
out:
- [1, mirror]

- in:
- [2, silver]
- [2, copper wire]
out:
- [1, antenna]

#########################################
## LAMBDA ##
#########################################
Expand Down
1 change: 1 addition & 0 deletions data/scenarios/Challenges/00-ORDER.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ teleport.yaml
2048.yaml
hanoi.yaml
bucket-brigade.yaml
friend.yaml
Mazes
Ranching
75 changes: 75 additions & 0 deletions data/scenarios/Challenges/_friend/cat.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
def forever : cmd unit -> cmd unit = \c. c ; forever c end

def repeat : int -> cmd unit -> cmd unit =
\n. \c. if (n == 0) {} {c ; repeat (n-1) c}
end

def elif = \t. \then. \else. {if t then else} end
def else = \t. t end

def abs = \n. if (n < 0) {-n} {n} end

def randdir : cmd dir =
d <- random 4;
return (
if (d == 0) {north}
$ elif (d == 1) {east}
$ elif (d == 2) {south}
$ else {west}
)
end

def chooseWait : cmd int =
t <- random (16*2);
return (16 + t)
end

def wander =
d <- randdir;
turn d;
dist <- random 2;
try {repeat dist move} {};
r <- random 5;
if (r == 0) { say "meow" } {}
end

def disappointed = \cat. say "meow??"; cat end

def follow : cmd unit -> actor -> cmd unit = \cat. \r.
rLoc <- as r {whereami};
myLoc <- whereami;
let dx = fst rLoc - fst myLoc in
let dy = snd rLoc - snd myLoc in
if (abs dx > abs dy)
{ if (dx < 0) {turn west} {turn east} }
{ if (dy < 0) {turn south} {turn north} };
if (abs dx != 0 || abs dy != 0) {try { move } { disappointed cat }} {};
wait 4;
follow cat r
end

def love = \cat.
say "purr";
fishGiver <- meet;
case fishGiver
(\_. disappointed cat)
(\r. follow cat r)
end

def cat = \start. \fishCount. \waitTime.
if (waitTime == 0) { wander; start } { wait 1 };
n <- count "fish";
if (n > fishCount)
{ say "yum!";
if (n >= 3) { love start } { cat start n (waitTime - 1) }
}
{ cat start fishCount (waitTime - 1) }
end

def startCat =
n <- count "fish";
w <- chooseWait;
cat startCat n w
end;

startCat
18 changes: 18 additions & 0 deletions data/scenarios/Challenges/_friend/friend-solution.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
def m2 = move; move end
def m5 = m2; m2; move end
def m10 = m5; m5 end
def m20 = m10; m10 end

def give_fish = \n.
if (n == 0) {}
{ mcat <- meet;
case mcat (\_. give_fish n) (\cat. give cat "fish"; give_fish (n-1))
}
end;

build {
require 3 "fish";
m2; turn left; m20;
give_fish 3;
turn back; m20; turn right; m2
}
94 changes: 94 additions & 0 deletions data/scenarios/Challenges/friend.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
version: 1
name: Make a Friend
author: Brent Yorgey
description: |
Win the trust of a furry companion.
creative: false
robots:
- name: base
display:
char: 'Ω'
attr: robot
heavy: true
dir: [0, 1]
devices:
- 3D printer
- ADT calculator
- antenna
- branch predictor
- clock
- comparator
- counter
- dictionary
- grabber
- hearing aid
- lambda
- logger
- mirror
- net
- scanner
- strange loop
- string
- toolkit
- workbench
inventory:
- [10, ADT calculator]
- [10, antenna]
- [10, treads]
- [10, branch predictor]
- [10, fish]
- [10, solar panel]
- [10, grabber]
- [10, lambda]
- [10, strange loop]
- [10, logger]
- [10, clock]
- [10, comparator]
- [10, calculator]
- name: cat
system: true
dir: [-1, 0]
display:
invisible: false
char: 'c'
attr: sand
devices:
- logger
program: |
run "scenarios/Challenges/_friend/cat.sw"
objectives:
- goal:
- There's a cat wandering around in the field. Bring it back to
your base. If you give it something it likes, perhaps you can
get it to follow you.
condition: |
c <- robotNamed "cat";
catLoc <- as c {whereami};
baseLoc <- as base {whereami};
return (catLoc == baseLoc)
solution: |
run "scenarios/Challenges/_friend/friend-solution.sw"
entities:
- name: fish
display:
char: 'f'
description:
- A smelly fish. Rather unappetizing to a robot.
properties: [known, portable]

known: [fish]
seed: 0
world:
offset: true
palette:
'Ω': [grass, null, base]
'.': [stone]
',': [grass]
'c': [grass, null, cat]
'*': [grass, flower]
'@': [stone, boulder]
upperleft: [-20, 2]
map: |-
c,..,,,,,,..,,,,...,.
,..,,,,,,,...........
*,.,@,,,,,,,.....,..Ω
1 change: 1 addition & 0 deletions data/scenarios/Testing/00-ORDER.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
699-movement-fail
858-inventory
710-multi-robot.yaml
920-meet.yaml
52 changes: 52 additions & 0 deletions data/scenarios/Testing/920-meet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
version: 1
name: Test meet and meetAll commands
description: |
Make sure meet prefers a robot on the same cell, and test meetAll
by giving everyone a boat.
objectives:
- condition: |
r0 <- robotNamed "other0";
b0 <- as r0 { has "boat" };
teleport self (0,0);
b1 <- meetAll (\b. \r. b0 <- as r {has "boat"}; return (b && b0)) true;
n2 <- as r0 { count "boat" };
return (b0 && b1 && (n2 == 2))
solution: |
mr0 <- meet;
case mr0 (\_. return ()) (\r0. give r0 "boat");
meetAll (\_. \r. give r "boat") ()
robots:
- name: base
loc: [0,0]
dir: [1,0]
devices:
- logger
- antenna
- ADT calculator
- grabber
inventory:
- [7, boat]
- name: other0
loc: [0,0]
dir: [1,0]
- name: other
dir: [1,0]
world:
default: [blank]
palette:
'.': [grass]
'Ω': [grass, null]
'o': [grass, null, other]
'': [stone, upper left corner]
'': [stone, upper right corner]
'': [stone, lower left corner]
'': [stone, lower right corner]
'': [stone, horizontal wall]
'': [stone, vertical wall]
upperleft: [-2, 2]
map: |
┌───┐
│.o.│
│oΩo│
│.o.│
└───┘
4 changes: 2 additions & 2 deletions data/scenarios/Tutorials/crash-secret.sw
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ def iterate = \state.\com.
end;

// At the beginning all robots can be given Win.
def allOK: robot -> bool = \rob.
def allOK: actor -> bool = \rob.
true
end;

// Try to give a robot a Win, filtering out those that were already given a Win.
// The robot will also receive instructions, so it **must have a logger!**
def tryGive: text -> (robot -> bool) -> int -> cmd (robot -> bool) = \msg.\f.\i.
def tryGive: text -> (actor -> bool) -> int -> cmd (actor -> bool) = \msg.\f.\i.
r <- try {
robotNumbered i;
} {
Expand Down
2 changes: 1 addition & 1 deletion data/scenarios/Tutorials/farming.sw
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ end;
def while : cmd bool -> {cmd a} -> cmd unit = \test. \body.
ifC test {force body ; while test body} {}
end;
def giveall : robot -> text -> cmd unit = \r. \thing.
def giveall : actor -> text -> cmd unit = \r. \thing.
while (has thing) {give r thing}
end;
def x4 = \c. c; c; c; c end;
Expand Down
4 changes: 3 additions & 1 deletion editors/emacs/swarm-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@
"scan"
"upload"
"ishere"
"meet"
"meetall"
"whoami"
"setname"
"random"
Expand All @@ -104,7 +106,7 @@
"west"
"down"
))
(x-types '("int" "text" "dir" "bool" "cmd" "void" "unit"))
(x-types '("int" "text" "dir" "bool" "cmd" "void" "unit" "actor"))

(x-keywords-regexp (regexp-opt x-keywords 'words))
(x-builtins-regexp (regexp-opt x-builtins 'words))
Expand Down
Loading

0 comments on commit 926cede

Please sign in to comment.