packages feed

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;