-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
454 additions
and
0 deletions.
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
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,27 @@ | ||
# Synchronized capture | ||
|
||
Two approaches to implement the goal-checking of this scenario were considered. | ||
In both, the goal is reached when the "pig" is surrounded on all four sides by barriers. | ||
|
||
The difference is is when the barriers are not synchronized: | ||
1. In the first approach, a goal condition is defined that detects if any barrier is adjacent to the pig without being surrounded on all sides. The primary goal condition treats this as a negated prerequisite, so that the scenario is instantly lost. | ||
2. In the second (adopted) approach, this secondary goal was preserved, but only as an optional achievement. Instead, the pig as a system robot implements the detection of an un-synchronized approach. The pig retreats a short distance, providing another opportunity for the player to attempt a synchronized approach (though players may simply choose to restart the scenario). | ||
|
||
In implementing this second approach, it is essential that the pig react to barrier placement within a single tick. We do not want to allow the player to place one barrier later than the others and simply be too slow to detect this un-synchronized state, counting it as a win. This single-tick reaction is accomplished with the `instant` command. | ||
|
||
## Retreat behavior | ||
If a barrier comes in contact with the pig without surrounding on all sides, the pig "runs away" in a straight line opposite from the "base" robot, irrespective of any entities or impassible terrain, until no barriers are adjacent. This may entail traversing multiple cells, which happens instantaneously, due to the single-tick reaction requirement described above. | ||
|
||
This escape strategy is simplified by finite availability of `unwalkable`, `portable` entities in this scenario. | ||
|
||
## Alternative game mechanic applications | ||
|
||
Other physical phenomena could rationalize this "squeezing" game mechanic. | ||
|
||
* The synchronized "squeeze" from all sides is evocative of the ["implosion method" of a fission weapon](https://en.wikipedia.org/wiki/Fizzle_(nuclear_explosion)). A [PNE](https://en.wikipedia.org/wiki/Peaceful_nuclear_explosion) has applications in: | ||
* [nuclear synthesis](https://en.wikipedia.org/wiki/Synthesis_of_precious_metals) | ||
* [space travel](https://en.wikipedia.org/wiki/Nuclear_pulse_propulsion) | ||
* [asteroid redirection](https://en.wikipedia.org/wiki/Asteroid_impact_avoidance) | ||
* Instead of an explosion, the barriers could serve as [neutron reflectors](https://en.wikipedia.org/wiki/Neutron_reflector) for a fission reaction. See [demon core](https://en.wikipedia.org/wiki/Demon_core) for consequences of uncontrolled (un-synchronized) reflectors | ||
* A high-pressure squeeze could create [artificial diamonds](https://en.wikipedia.org/wiki/Synthetic_diamond) (HPHT method). | ||
|
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,114 @@ | ||
/** | ||
If any blocking entity is touching me, escape. | ||
*/ | ||
|
||
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 doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end; | ||
def until = \p. \c. q <- p; if q {} {c; until p c} end; | ||
|
||
def getDirection = \n. | ||
if (n == 0) { | ||
forward; | ||
} $ elif (n == 1) { | ||
right; | ||
} $ elif (n == 2) { | ||
back; | ||
} $ elif (n == 3) { | ||
left; | ||
} $ else { | ||
down; | ||
}; | ||
end; | ||
|
||
def watchDir = \n. | ||
watch $ getDirection n; | ||
if (n > 0) { | ||
watchDir $ n - 1; | ||
} {}; | ||
end; | ||
|
||
def boolToInt = \b. | ||
if b {1} {0} | ||
end; | ||
|
||
/** | ||
Iterate 4 times (once for each direction) | ||
*/ | ||
def countBlocked = \n. | ||
if (n > 0) { | ||
isBlocked <- blocked; | ||
// This assignment has to happen before the recursive | ||
// "countBlocked" call due to #1032 | ||
let localBlockCount = boolToInt isBlocked in | ||
turn left; | ||
lastCount <- countBlocked $ n - 1; | ||
return $ lastCount + localBlockCount; | ||
} { | ||
return 0; | ||
} | ||
end; | ||
|
||
def reWatch = | ||
watchDir 4; | ||
end; | ||
|
||
def locationIsOpen = | ||
emptyHere <- isempty; | ||
blockedCount <- countBlocked 4; | ||
return $ emptyHere && blockedCount == 0; | ||
end; | ||
|
||
def faceAwayFrom = \loc. | ||
myLoc <- whereami; | ||
let x = fst loc - fst myLoc in | ||
let y = snd loc - snd myLoc in | ||
let d = if (abs x > abs y) { | ||
if (x > 0) {west} {east} | ||
} { | ||
if (y > 0) {south} {north} | ||
} in | ||
turn d; | ||
end; | ||
|
||
/** | ||
Move in opposite direction from base to | ||
find a cross-shaped region that has zero blockages. | ||
*/ | ||
def findOpenArea = | ||
baseLoc <- as base {whereami}; | ||
faceAwayFrom baseLoc; | ||
until locationIsOpen move; | ||
end; | ||
|
||
def relocateAway = | ||
marker <- grab; | ||
findOpenArea; | ||
try { | ||
swap marker; | ||
return (); | ||
} { | ||
place marker; | ||
}; | ||
end; | ||
|
||
def handleBlockage = | ||
blockedCount <- countBlocked 4; | ||
if (blockedCount > 0) { | ||
if (blockedCount < 4) { | ||
relocateAway; | ||
} { | ||
selfdestruct; | ||
} | ||
} {}; | ||
end; | ||
|
||
def go = | ||
instant reWatch; | ||
wait 1000; | ||
instant handleBlockage; | ||
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,123 @@ | ||
/** | ||
Need to synchronize pushes so that in the same tick | ||
that the first boulder comes into contact with the | ||
opponent, there is no escape route. | ||
*/ | ||
|
||
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end; | ||
|
||
def intersperse = \n. \f2. \f1. if (n > 0) { | ||
f1; | ||
if (n > 1) { | ||
f2; | ||
} {}; | ||
intersperse (n - 1) f2 f1; | ||
} {}; | ||
end; | ||
|
||
def walkAround = \d1. \d2. | ||
turn d1; | ||
doN 3 move; | ||
turn d2; | ||
|
||
doN 3 move; | ||
turn d2; | ||
end; | ||
|
||
def buildBot = \initialTurn. | ||
_r1 <- build { | ||
watch back; | ||
wait 200; | ||
doN 2 move; | ||
turn initialTurn; | ||
walkAround right left; | ||
push; | ||
}; | ||
|
||
_r2 <- build { | ||
watch back; | ||
wait 200; | ||
doN 2 move; | ||
turn initialTurn; | ||
walkAround left right; | ||
push; | ||
}; | ||
end; | ||
|
||
def arrangeBoulders = | ||
// First boulder | ||
turn right; | ||
move; | ||
turn left; | ||
doN 7 move; | ||
turn left; | ||
push; | ||
turn right; | ||
move; | ||
turn left; | ||
move; | ||
turn left; | ||
doN 4 push; | ||
|
||
// Second boulder | ||
turn back; | ||
doN 7 move; | ||
turn left; | ||
doN 2 move; | ||
turn left; | ||
doN 5 push; | ||
|
||
// Third boulder | ||
turn right; | ||
doN 4 move; | ||
turn left; | ||
doN 7 move; | ||
turn left; | ||
move; | ||
turn left; | ||
doN 3 push; | ||
turn left; | ||
move; | ||
turn right; | ||
move; | ||
turn right; | ||
push; | ||
|
||
// Fourth boulder | ||
turn right; | ||
doN 3 move; | ||
turn left; | ||
doN 2 push; | ||
turn right; | ||
move; | ||
turn left; | ||
move; | ||
turn left; | ||
push; | ||
end; | ||
|
||
def go = | ||
|
||
doN 3 move; | ||
obj <- grab; | ||
|
||
arrangeBoulders; | ||
|
||
turn right; | ||
doN 2 move; | ||
turn back; | ||
buildBot right; | ||
turn back; | ||
move; | ||
|
||
turn left; | ||
move; | ||
buildBot left; | ||
turn back; | ||
move; | ||
|
||
place obj; | ||
move; | ||
end; | ||
|
||
go; |
Oops, something went wrong.