packages feed

swarm-0.4: data/scenarios/Challenges/_gopher/solution.sw

def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;
def elif = \t. \then. \else. {if t then else} end
def else = \t. t end

def makeSigned = \b. \x.
    if b {-x} {x};
    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;

/**
Loops forever
*/
def scanDirections = \n.
    let d = getDirection n in
    out <- scan d;
    shouldContinue <- case out
        (\_. return true)
        (\x. if (x == "mound") {
            drill d;
            return true;
        } {
            // A "flower" shall serve as
            // a semaphore to terminate the loop,
            // so that the base can `salvage` us.
            return $ x != "flower";
        });

    if shouldContinue {
        if (n > 0) {
            scanDirections $ n - 1;
        } {
            watchDir 4;
            wait 1000;
            scanDirections 4;
        };
    } {};
    end;

def deploySensor =
    _s <- build {scanDirections 0};
    return ();
    end;

def isDivisibleBy = \dividend. \divisor.
    (dividend / divisor) * divisor == dividend;
    end;

// stagger at every fifth cell
def deployRow = \f. \offset. \cellCount.
    if (isDivisibleBy (cellCount + offset) 5) {
        f;
    } {};
    if (cellCount > 1) {
        move;
        deployRow f offset $ cellCount - 1;
    } {};
    end;

def isEven = \x.
   isDivisibleBy x 2
   end;

def deployGrid = \f. \width. \height.

    if (height > 0) {

        let nowEven = isEven height in
        let offsetVal = makeSigned nowEven $ height * 2 in
        let extraOffset = if nowEven {-1} {0} in
        deployRow f (offsetVal + extraOffset) width;

        let d = if nowEven {right} {left} in
        turn d;
        move;
        turn d;
        deployGrid f width $ height - 1;
    } {};
    end;

def pickupToolkit =
    x <- scan down;
    case x
        (\_. return false)
        (\y. if (y == "toolkit") {
            tk <- grab;
            equip tk;
            return true
        } {
            return false
        });
    end;

def searchToolkitSingleRow = \colCount.

    _found <- pickupToolkit;
    if (colCount > 1) {
        move;
        searchToolkitSingleRow $ colCount - 1;
    } {};
    end;    

def searchToolkitRows = \width. \rowCount.
    searchToolkitSingleRow width;
    if (rowCount > 1) {

        let nowEven = isEven rowCount in
        let d = if nowEven {right} {left} in

        turn d;
        move;
        turn d;

        searchToolkitRows width $ rowCount - 1;
    } {};
    end;

def listenForDefeat =
    // Block until the gopher is defeated
    m <- has "serenity";
    if m {} {
        listenForDefeat;
    };
    end;

def searchForToolkit = \width. \height.
    searchToolkitRows width height;

    turn right;
    doN (height - 1) move;
    turn right;
    doN (width - 1) move;
    turn right;
    end;

def go = \width. \height.
    deployGrid deploySensor width height;
    turn left;
    move;

    listenForDefeat;
    searchForToolkit height width;

    deployGrid (place "flower") width height;
    turn left;
    doN height move;
    turn right;
    deployGrid salvage width height;
    end;

go 30 20;