swarm-0.4: data/scenarios/Challenges/word-search.yaml
version: 1
name: Word search
author: Karl Ostmo
description: |
Find the word
seed: 2
creative: false
objectives:
- goal:
- Use the `drill` command (e.g. "drill down" when on top of the
intended letter) to mark the sequence of letters that
spells COW within the designated playfield.
- |
The sequence may appear horizontally in either the
leftward or rightward direction,
or vertically in either the upward or downward direction.
Diagonal appearances are not valid.
condition: |
/**
Algorithm:
We only need to check the base's
current position: if we find three contiguous highlights,
then we know that the player has just completed their
third highlight.
*/
def whichOrdinal =
isC <- ishere "lowercase c";
if (isC) {
return 0;
} {
isO <- ishere "lowercase o";
if (isO) {
return 1;
} {
isW <- ishere "lowercase w";
if (isW) {
return 2;
} {
return (-1);
}
}
}
end;
def whichHighlightedOrdinal = \str.
if (str == "lowercase c") {
return 0;
} {
if (str == "lowercase o") {
return 1;
} {
if (str == "lowercase w") {
return 2;
} {
return (-1);
}
}
}
end;
def countConsecutive = \expectedOrdinal. \n.
thisOrdinal <- whichOrdinal;
nextOrdinal <- if (thisOrdinal == expectedOrdinal) {
return $ expectedOrdinal + 1;
} {
return 0;
};
if (nextOrdinal == 3) {
return true;
} {
if (n > 1) {
move;
countConsecutive nextOrdinal $ n - 1;
} {
return false;
};
};
end;
def checkBackAndForth =
foundBackward <- countConsecutive 0 3;
if (foundBackward) {
return true;
} {
turn back;
countConsecutive 0 3;
}
end;
def checkDirections = \n.
if (n > 0) {
wasFound <- checkBackAndForth;
if wasFound {
return true;
} {
turn left;
checkDirections $ n - 1;
}
} {
return false;
}
end;
def isMarkedInDirection = \d.
scanResult <- scan d;
ordinalNum <- case scanResult
(\_. return (-1))
whichHighlightedOrdinal;
return $ ordinalNum >= 0;
end;
/**
It's possible we could be one cell away from
a marked cell after finishing, either due
to using a directional `drill` command instead of
`drill down`, or due to an apparent bug which
does not evaluate the goal condition between the
`drill` and a `move` command.
*/
def moveToMarkedCell = \n.
if (n > 0) {
isMarkedAhead <- isMarkedInDirection forward;
if isMarkedAhead {
move;
return true;
} {
turn left;
moveToMarkedCell $ n - 1;
};
} {
return false;
};
end;
/**
Orient ourselves such that
a marked cell is behind us.
*/
def findMarkBehind = \n.
if (n > 0) {
isMarkedBehind <- isMarkedInDirection back;
if isMarkedBehind {
return true;
} {
turn left;
findMarkBehind $ n - 1;
};
} {
return false;
};
end;
/**
The cell we're on might be in the middle of a word,
rather than the end. Determine the orientation of
the line, then move along it until reaching the end.
Algorithm:
0. Assumption: we are currently on a marked cell.
1. Turn in all all four directions to `scan back`
for a second marked cell. Stop turning if
we encounter one.
If none found after 4 turns, abort.
2. `scan forward` to see if there is a marked cell in
the opposite direction.
`move` (foward) once if there is. Since the word
is only three cells long, this will be the other
end of it.
*/
def moveToWordExtrema =
foundCellBehind <- findMarkBehind 4;
if foundCellBehind {
isMarkedAhead <- isMarkedInDirection forward;
if isMarkedAhead {
move;
} {};
} {};
end;
def checkSoln =
isMarkedHere <- isMarkedInDirection down;
atMarkedCell <- if isMarkedHere {
return true;
} {
moveToMarkedCell 4;
};
if atMarkedCell {
moveToWordExtrema;
checkDirections 4;
} {
return false;
}
end;
as base {checkSoln};
robots:
- name: base
display:
attr: flower
dir: [-1, 0]
devices:
- treads
- ADT calculator
- branch predictor
- GPS receiver
- clock
- comparator
- counter
- dictionary
- lambda
- logger
- mirror
- net
- scanner
- strange loop
- string
- highlighter
inventory:
- [3, ink]
- name: lettersetter
system: true
dir: [1, 0]
display:
invisible: true
inventory:
- [376, capital C]
- [376, capital O]
- [376, capital W]
program: |
run "scenarios/Challenges/_word-search/create-puzzle.sw"
solution: |
// Hard-coded for seed=2:
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;
def waitUntilUnblocked =
x <- blocked;
if x {
wait 1;
waitUntilUnblocked;
} {};
end;
waitUntilUnblocked;
doN 11 move;
turn right;
doN 2 move;
drill down;
move;
drill down;
move;
drill down;
// run "scenarios/Challenges/_word-search/solution.sw"
entities:
- name: capital C
display:
char: 'C'
description:
- C is for California
- name: capital O
display:
char: 'O'
description:
- O is for Oklahoma
- name: capital W
display:
char: 'W'
description:
- W is for Washington
- name: lowercase c
display:
char: 'c'
attr: gold
description:
- c is for cantaloupe
- name: lowercase o
display:
char: 'o'
attr: gold
description:
- o is for orange
- name: lowercase w
display:
char: 'w'
attr: gold
description:
- w is for watermelon
- name: highlighter
display:
char: 'P'
attr: gold
capabilities: [drill]
description:
- Instrument for marking found words
properties: [known, portable]
- name: ink
display:
char: 'K'
attr: gold
description:
- Ink for marking found words
properties: [known, portable]
recipes:
- in:
- [1, capital C]
- [1, ink]
out:
- [1, lowercase c]
required:
- [1, highlighter]
- in:
- [1, capital O]
- [1, ink]
out:
- [1, lowercase o]
required:
- [1, highlighter]
- in:
- [1, capital W]
- [1, ink]
out:
- [1, lowercase w]
required:
- [1, highlighter]
- in:
- [1, lowercase c]
out:
- [1, capital C]
- [1, ink]
required:
- [1, highlighter]
- in:
- [1, lowercase o]
out:
- [1, capital O]
- [1, ink]
required:
- [1, highlighter]
- in:
- [1, lowercase w]
out:
- [1, capital W]
- [1, ink]
required:
- [1, highlighter]
known: [boulder]
world:
dsl: |
{dirt}
upperleft: [0, 0]
offset: false
palette:
'@': [stone, boulder]
'.': [grass]
'a': [grass, null, lettersetter]
'#': [dirt]
Ω: [stone, null, base]
map: |
a........................###
.........................###
.........................###
.........................###
.........................###
.........................###
.........................###
.........................###
.........................###
.........................@@@
.........................@Ω@
.........................@@@
.........................###
.........................###
.........................###