-
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
9 changed files
with
1,196 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,4 @@ teleport.yaml | |
2048.yaml | ||
hanoi.yaml | ||
Mazes | ||
Ranching |
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 @@ | ||
gated-paddock.yaml |
115 changes: 115 additions & 0 deletions
115
data/scenarios/Challenges/Ranching/_gated-paddock/bridged-gap.sw
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,115 @@ | ||
def isFenced = s <- scan forward; return (case s (\_. false) (\x. x == "gate")); end; | ||
def isBlockedOrFenced = b <- blocked; f <- isFenced; return (b || f); end; | ||
def boolToInt = \b. if (b) {return 1} {return 0}; end; | ||
|
||
/** If one is standing on a fence, that means the fence has just been placed, | ||
because it is not possible to move onto a fence that already exists. | ||
We then inspect the 8 surrounding tiles. If at least two of them are "blocked" | ||
or are a "gate", then we know that we have just closed a gap. | ||
It may not have been that final gap, but it's a good time to run the full | ||
enclosure test. | ||
Invoke as follows: | ||
countAdjacentBlockagesBroken 4 | ||
FIXME: This has VERY strange behavior. | ||
The values of 'recVal' and 'total' are often inconsistent. | ||
*/ | ||
def countAdjacentBlockagesBroken = \i. | ||
if (i > 0) { | ||
turn left; | ||
say "======"; | ||
say $ format i; | ||
say "------"; | ||
amBlocked <- isBlockedOrFenced; | ||
|
||
say $ "amBlocked: " ++ format amBlocked; | ||
|
||
val <- boolToInt amBlocked; | ||
say $ "val:" ++ format val; | ||
recVal <- countAdjacentBlockagesBroken (i - 1); | ||
|
||
say $ "recVal: " ++ format recVal; | ||
|
||
let total = val + recVal in | ||
say $ "total: " ++ format total; | ||
return total; | ||
} { | ||
return 0; | ||
}; | ||
end; | ||
|
||
|
||
def countAdjacentBlockages = | ||
|
||
turn left; | ||
b1 <- isBlockedOrFenced; | ||
c1 <- boolToInt b1; | ||
|
||
turn left; | ||
b2 <- isBlockedOrFenced; | ||
c2 <- boolToInt b2; | ||
|
||
turn left; | ||
b3 <- isBlockedOrFenced; | ||
c3 <- boolToInt b3; | ||
|
||
turn left; | ||
b4 <- isBlockedOrFenced; | ||
c4 <- boolToInt b4; | ||
|
||
return $ c1 + c2 + c3 + c4; | ||
end; | ||
|
||
// Step forward, observing left and right. | ||
def observeLeftAndRight = | ||
move; | ||
turn left; | ||
amBlockedLeft <- isBlockedOrFenced; | ||
val1 <- boolToInt amBlockedLeft; | ||
|
||
turn back; | ||
amBlockedRight <- isBlockedOrFenced; | ||
val2 <- boolToInt amBlockedRight; | ||
|
||
turn right; | ||
move; | ||
return $ val1 + val2; | ||
end; | ||
|
||
|
||
/** If the four cardinal directions have at most | ||
one blockage, then there will exist an orientation | ||
where both that direction and its opposite direction | ||
are clear. | ||
So we can step that direction, check to the left and | ||
right of us, then step in the opposite direction | ||
and do the same. This allows us to check the 4 | ||
blocks that touch the corners of the center block. | ||
*/ | ||
def countDiagonalBlockages = | ||
// First, orient to the clear front-to-back path | ||
amBlocked <- isBlockedOrFenced; | ||
if amBlocked {turn left;} {}; | ||
|
||
// Second, step to both sides | ||
fwdCount <- observeLeftAndRight; | ||
backCount <- observeLeftAndRight; | ||
return $ fwdCount + backCount; | ||
end; | ||
|
||
def isStandingOnBridge = | ||
onFence <- ishere "fence"; | ||
if (onFence) { | ||
adjCount <- countAdjacentBlockages; | ||
if (adjCount > 1) { | ||
return true; | ||
} { | ||
diagCount <- countDiagonalBlockages; | ||
return $ (adjCount + diagCount) > 1; | ||
}; | ||
} {return false}; | ||
end; | ||
|
||
isStandingOnBridge; |
234 changes: 234 additions & 0 deletions
234
data/scenarios/Challenges/Ranching/_gated-paddock/enclosure-checking.sw
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,234 @@ | ||
// Algorithm: | ||
// ---------- | ||
// Maintain current direction until a wall is encountered. | ||
// Then enter "wall-following mode". | ||
// This mode presumes the wall is not a loop. | ||
// Wall-following mode exploits recursion to keep track of how many left turns were made | ||
// and then unwinds them again by ensuring each is paired with a right turn. | ||
// Once the recursion is fully unwound, the robot proceeds along its original direction | ||
// (though it may now be laterally displaced). | ||
// | ||
// (If it was a loop, then an "oriented breadcrumb" would need to be left. | ||
// The breadcrumb is oriented in case a single-width passage is backtracked | ||
// along the opposite wall.) | ||
|
||
/** A "gate" is walkable, so we need to supplement the "blocked" check with this function. | ||
Since fences are "unwalkable", they do not need to be mentioned in this function. | ||
*/ | ||
def isFenced = | ||
s <- scan forward; | ||
return ( | ||
case s | ||
(\_. false) | ||
(\x. x == "gate") | ||
); | ||
end; | ||
|
||
def isBlockedOrFenced = | ||
b <- blocked; | ||
f <- isFenced; | ||
return (b || f); | ||
end; | ||
|
||
// Returns true if we've already placed two | ||
// breadcrumbs on a given tile, false otherwise. | ||
def leaveBreadcrumbs = | ||
|
||
let bc1 = "fresh breadcrumb" in | ||
let bc2 = "treaded breadcrumb" in | ||
|
||
wasTraversedOnce <- ishere bc1; | ||
if wasTraversedOnce { | ||
_crumb <- grab; | ||
make bc2; | ||
place bc2; | ||
return false; | ||
} { | ||
wasTraversedTwice <- ishere bc2; | ||
if wasTraversedTwice { | ||
return true; | ||
} { | ||
// Make sure nothing's in the way before we place | ||
// our breadcrumb: | ||
x <- scan down; | ||
case x return (\y. | ||
// If we're on a water tile, get rid of | ||
// it with our special "drilling" recipe | ||
if (y == "water") { | ||
drill down; | ||
// Nothing will remain on the ground. | ||
// after making the "steam" via | ||
// the drilling recipe. | ||
} { | ||
grab; | ||
return (); | ||
}; | ||
); | ||
|
||
make bc1; | ||
place bc1; | ||
return false; | ||
}; | ||
}; | ||
end; | ||
|
||
def goForwardToPatrol = \wasBlocked. | ||
b <- isBlockedOrFenced; | ||
if b { | ||
turn left; | ||
goForwardToPatrol true; | ||
turn right; | ||
goForwardToPatrol false; | ||
} { | ||
if wasBlocked { | ||
isLoop <- leaveBreadcrumbs; | ||
if isLoop { | ||
fail "loop"; | ||
} {}; | ||
} {}; | ||
move; | ||
}; | ||
end; | ||
|
||
/** | ||
There should only be one place in the | ||
code where an exception is thrown: that is, | ||
if a treaded breadcrumb is encountered. | ||
*/ | ||
def checkIsEnclosedInner = | ||
try { | ||
goForwardToPatrol false; | ||
// Water is the outer boundary | ||
hasWater <- ishere "water"; | ||
if hasWater { | ||
return false; | ||
} { | ||
checkIsEnclosedInner; | ||
}; | ||
} { | ||
return true; | ||
}; | ||
end; | ||
|
||
def checkIsEnclosed = | ||
|
||
// The "evaporator" drill is used | ||
// to clear water tiles. | ||
let specialDrill = "evaporator" in | ||
create specialDrill; | ||
install self specialDrill; | ||
|
||
// NOTE: System robots can walk on water | ||
// so we only need this if we want to | ||
// demo the algorithm with a player robot. | ||
// create "boat"; | ||
// install self "boat"; | ||
|
||
checkIsEnclosedInner; | ||
end; | ||
|
||
def boolToInt = \b. if (b) {return 1} {return 0}; end; | ||
|
||
def countAdjacentBlockages = | ||
|
||
turn left; | ||
b1 <- isBlockedOrFenced; | ||
c1 <- boolToInt b1; | ||
|
||
turn left; | ||
b2 <- isBlockedOrFenced; | ||
c2 <- boolToInt b2; | ||
|
||
turn left; | ||
b3 <- isBlockedOrFenced; | ||
c3 <- boolToInt b3; | ||
|
||
turn left; | ||
b4 <- isBlockedOrFenced; | ||
c4 <- boolToInt b4; | ||
|
||
return $ c1 + c2 + c3 + c4; | ||
end; | ||
|
||
// Step forward, observing left and right. | ||
def observeLeftAndRight = | ||
move; | ||
turn left; | ||
amBlockedLeft <- isBlockedOrFenced; | ||
val1 <- boolToInt amBlockedLeft; | ||
|
||
turn back; | ||
amBlockedRight <- isBlockedOrFenced; | ||
val2 <- boolToInt amBlockedRight; | ||
|
||
turn right; | ||
move; | ||
return $ val1 + val2; | ||
end; | ||
|
||
|
||
/** If the four cardinal directions have at most | ||
one blockage, then there will exist an orientation | ||
where both that direction and its opposite direction | ||
are clear. | ||
So we can step that direction, check to the left and | ||
right of us, then step in the opposite direction | ||
and do the same. This allows us to check the 4 | ||
blocks that touch the corners of the center block. | ||
*/ | ||
def countDiagonalBlockages = | ||
// First, orient to the clear front-to-back path | ||
amBlocked <- isBlockedOrFenced; | ||
if amBlocked {turn left;} {}; | ||
|
||
// Second, step to both sides | ||
fwdCount <- observeLeftAndRight; | ||
backCount <- observeLeftAndRight; | ||
return $ fwdCount + backCount; | ||
end; | ||
|
||
def isStandingOnBridge = | ||
onFence <- ishere "fence"; | ||
onGate <- ishere "gate"; | ||
if (onFence || onGate) { | ||
adjCount <- countAdjacentBlockages; | ||
if (adjCount > 1) { | ||
return true; | ||
} { | ||
diagCount <- countDiagonalBlockages; | ||
return $ (adjCount + diagCount) > 1; | ||
}; | ||
} {return false}; | ||
end; | ||
|
||
|
||
/** | ||
There are 3 sheep. | ||
They have indices 1, 2, 3. | ||
(The base has index 0). | ||
*/ | ||
def allSheep = \predicateCmd. \i. | ||
|
||
if (i > 0) { | ||
r <- robotnumbered i; | ||
didSucceed <- as r {predicateCmd}; | ||
if didSucceed { | ||
allSheep predicateCmd $ i - 1; | ||
} { | ||
return false; | ||
}; | ||
} { | ||
return true; | ||
} | ||
end; | ||
|
||
|
||
justFilledGap <- as base { | ||
isStandingOnBridge; | ||
}; | ||
|
||
if (justFilledGap) { | ||
allSheep checkIsEnclosed 3; | ||
} { | ||
return false; | ||
} |
Oops, something went wrong.