packages feed

swarm-0.4: data/scenarios/Challenges/Ranching/_capture/opponent.sw

/**
If any blocking entity is touching me, escape.
*/

def elif = \t. \then. \else. {if t then else} end
def else = \t. t end
def abs = \n. if (n < 0) {-n} {n} end;
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;
def until = \p. \c. q <- p; if q {} {c; until p c} 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;

def boolToInt = \b.
    if b {1} {0}
    end;

/**
Iterate 4 times (once for each direction)
*/
def countBlocked = \n.
    if (n > 0) {
        isBlocked <- blocked;
        // This assignment has to happen before the recursive
        // "countBlocked" call due to #1032
        let localBlockCount = boolToInt isBlocked in
        turn left;
        lastCount <- countBlocked $ n - 1;
        return $ lastCount + localBlockCount;
    } {
        return 0;
    }
    end;

def reWatch =
    watchDir 4;
    end;

def locationIsOpen =
    emptyHere <- isempty;
    blockedCount <- countBlocked 4;
    return $ emptyHere && blockedCount == 0;
    end;

def faceAwayFrom = \loc.
    myLoc <- whereami;
    let x = fst loc - fst myLoc in
    let y = snd loc - snd myLoc in
    let d = if (abs x > abs y) {
        if (x > 0) {west} {east}
    } {
        if (y > 0) {south} {north}
    } in
    turn d;
    end;

/**
Move in opposite direction from base to
find a cross-shaped region that has zero blockages.
*/
def findOpenArea =
    baseLoc <- as base {whereami};
    faceAwayFrom baseLoc;
    until locationIsOpen move;
    end;

def relocateAway =
    marker <- grab;
    findOpenArea;
    try {
        swap marker;
        return ();
    } {
        place marker;
    };
    end;

def handleBlockage =
    blockedCount <- countBlocked 4;
    if (blockedCount > 0) {
        if (blockedCount < 4) {
            relocateAway;
        } {
            selfdestruct;
        }
    } {};
    end;

def go =
    instant reWatch;
    wait 1000;
    instant handleBlockage;
    go;
    end;

go;