Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faster sheep check #844

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,3 +3,4 @@ teleport.yaml
2048.yaml
hanoi.yaml
Mazes
Ranching
1 change: 1 addition & 0 deletions data/scenarios/Challenges/Ranching/00-ORDER.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gated-paddock.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// 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 (\_. 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;

def checkIsEnclosed =
try {
goForwardToPatrol false;
// Water is the outer boundary
hasWater <- ishere "water";
if hasWater {
return false;
} {
checkIsEnclosed;
};
} {
return true;
};
end;

checkIsEnclosed;
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;


def processTree =
grab;
make "log";
make "board";
doN 2 (make "fence");
end;


def grabTwoRows =
doN 7 (processTree; move);
processTree;
turn right;
move;
turn right;

doN 7 (processTree; move);
processTree;
end;


def grabTrees =
doN 7 move;
turn right;

grabTwoRows;

turn left;
move;
turn left;

grabTwoRows;

turn left;
move;
turn left;

grabTwoRows;

end;


def buildFence =
doN 6 move;
turn right;
doN 4 (place "fence"; move);
turn left;
doN 30 (place "fence"; move);
turn left;
doN 15 (place "fence"; move);
turn left;
doN 30 (place "fence"; move);
turn left;
doN 7 (place "fence"; move);
place "fence";
turn right;
doN 6 move;
end;

// buildFence;
grabTrees;
buildFence;
121 changes: 121 additions & 0 deletions data/scenarios/Challenges/Ranching/_gated-paddock/follow-circle.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
def elif = \p.\t.\e. {if p t e} end;

def go : cmd (unit + dir) -> cmd unit = \gps.
md <- gps;
case md (\_.
noop
) (\d.
turn d;
move;
go gps
)
end;

def scanIf: dir -> (unit + dir) -> text -> cmd (unit + dir) =
\d. \current. \e.
sc <- scan d;
if (sc == inr e) {
if (current == inl ()) {
// say ("I am going " ++ format d);
return $ inr d
} {
// say "Multiple paths!";
fail "Multiple paths!"
}
} {
return $ current
}
end;

def follow: text -> cmd (unit + dir) = \e.
let noDir: unit + dir = inl () in
f <- scanIf forward noDir e;
fl <- scanIf left f e;
flr <- scanIf right fl e;
return flr;
end;

// follow a path from that ends right next to starting location
def broken_circle_north: text -> cmd bool = \e.
turn north;
b <- try {
go (follow e); return true
} {
// say "failed to follow"; wait 8; selfdestruct;
return false
};
if b {
// end next to start
l <- whereami;
//say ("I am at" ++ format l);
//selfdestruct;
return $ l == (0,-1)
} {
return false
}
end;


def untilBaaad: dir -> cmd (unit + dir) = \d.
//bl <- blocked;
//if bl {
// return $ inl ()
//} {
sf <- scan forward;
if (sf == inr "water" || sf == inr "gate") {
return $ inl ()
} {
return $ inr d
}
//}
end;

def checkWaterR: int -> cmd int = \n.
try {
r <- robotNumbered n;
wN <- as r {go (untilBaaad north); sf <- scan forward; return $ sf == inr "water"};
wS <- as r {go (untilBaaad south); sf <- scan forward; return $ sf == inr "water"};
if (wS || wN) {return 0} {return 1}
} {
return 0;
}
end;

// WATCH PROOF OF CONCEPT
//
// this shows that waiting for entities in location saves most time
// -> checks only after the fence is connected to both sides
//
teleport self (1,2);
sd1 <- scan west;
teleport self (1,-2);
sd2 <- scan west;
teleport self (0,0);

if (sd1 == inr "fence" && sd2 == inr "fence") {
/**************************************/
// SHEEP CHECK
//
// one sheep has to be surrounded by the
// fence from top and bottom
//
sheepWater1 <- checkWaterR 1;
if (sheepWater1 == 1) {
broken_circle_north "fence"
} {
sheepWater2 <- checkWaterR 2;
if (sheepWater2 == 1) {
broken_circle_north "fence"
} {
sheepWater3 <- checkWaterR 3;
if (sheepWater3 == 1) {
broken_circle_north "fence"
} {
return false;
}
}
}
/**************************************/
} {
return false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// A "sheep" that wanders around randomly.

/** 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;

def elif = \p.\t.\e. {if p t e} 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
let randdir : cmd dir =
d <- random 4;
return $ if (d == 0) {
north
} $ elif (d == 1) {
east
} $ elif (d == 2) {
south
} {
west
}
in

forever (
n <- random 30;
wait (30 + n);
d <- randdir;
turn d;
dist <- random 3;
repeat dist (

b <- isBlockedOrFenced;
if b {} {
move;
};

// Sheep can drown.
hasWater <- ishere "water";
if hasWater {
say "whoops!";
selfdestruct;
} {};
);
r <- random 5;
if (r == 0) { say "baaa" } {}
)
Loading