swarm-0.4: data/scenarios/Challenges/_hackman/ghost.sw
/* Algorithm:
Go forward until along any straight passage until reaching
an intersection. Then randomly choose any available direction
(except backwards).
*/
def isItemInDirection = \direction. \item.
x <- scan direction;
return $ case x (\_. false) (\y. y == item);
end;
// A ghost is not blocked by a "gate" when it is leaving the "nursery".
def canCrossGate =
isGate <- isItemInDirection forward "gate";
loc <- whereami;
let amCentered = loc == (0, 0) in
return $ isGate && amCentered;
end;
def isBlockedAhead =
isBlockedByWall <- blocked;
ghostCanCrossGate <- canCrossGate;
return $ isBlockedByWall && not ghostCanCrossGate;
end;
def checkLeftBlocked =
turn left;
isBlocked <- isBlockedAhead;
turn right;
return isBlocked;
end;
def checkRightBlocked =
turn right;
isBlocked <- isBlockedAhead;
turn left;
return isBlocked;
end;
def chooseDirection : cmd dir =
leftBlocked <- checkLeftBlocked;
rightBlocked <- checkRightBlocked;
forwardBlocked <- isBlockedAhead;
if (leftBlocked && rightBlocked && forwardBlocked) {
say "Dead end; turning back";
return back;
} {
// Since we're in the "else" case of all three
// being blocked, we know that at least one
// direction is available. So we check all
// the combinations.
if (leftBlocked && rightBlocked) {
// Keep going straight
return forward;
} {
if (leftBlocked && forwardBlocked) {
return right;
} {
if (rightBlocked && forwardBlocked) {
return left;
} {
// Now we have exhaused all of the combinations
// of *two* directions being blocked, so we
// check single directions.
if leftBlocked {
// Decide whether to go right or straight
d <- random 2;
if (d == 0) {
return right;
} {
// go straight
return forward;
}
} {
if rightBlocked {
// Decide whether to go left or straight
d <- random 2;
if (d == 0) {
return left;
} {
// go straight
return forward;
}
} {
if forwardBlocked {
// Decide whether to go left or right
d <- random 2;
if (d == 0) {
return left;
} {
// go right
return right;
}
} {
// No directions are blocked, so we can
// go left, right, or straight with
// equal probability.
d <- random 3;
if (d == 0) {
return left;
} {
if (d == 1) {
return right;
} {
// go straight
return forward;
}
}
}
}
}
}
}
}
}
end;
// Ghosts must implement teleporting logic themselves.
// Hard-codes location of the teleporter.
def checkNeedsTeleport = \offset.
currentLoc <- whereami;
if (fst currentLoc < -offset) {
teleport self (offset, snd currentLoc)
} {
if (fst currentLoc > offset) {
teleport self (-offset, snd currentLoc)
} {}
}
end;
startPos <- whereami;
def go =
hasGift <- has "donut";
if hasGift {
teleport self startPos;
} {
move;
checkNeedsTeleport 11;
newDirection <- chooseDirection;
turn newDirection;
go;
}
end;
def waitToStart =
offset <- random 300;
let startDelay = 50 + offset in
wait startDelay;
teleport self (0, 0);
go;
end;
waitToStart;