packages feed

swarm-0.7.0.0: data/scenarios/Challenges/Ranching/_beekeeping/solution.sw

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

def intersperse = \n. \f2. \f1. if (n > 0) {
        f1;
        if (n > 1) {
            f2;
        } {};
        intersperse (n - 1) f2 f1;
    } {};
    end;

def abs = \n. if (n < 0) {-n} {n} end;

def λcase = \f. \g. \s. case s f g end
def λmatch = \f. \p. match p f end

def mapTuple = \f. λmatch \a. \b. (f a, f b) end;

def sumTuples = λmatch \t11. \t12. λmatch \t21. \t22.
    (t11 + t21, t12 + t22);
    end;

def negateTuple = \t.
    mapTuple (\x. -x) t;
    end;

def subtractTuple = \t1. \t2.
    sumTuples t1 $ negateTuple t2;
    end;

def moveTuple = λmatch \x. \y.
    turn $ if (x > 0) {east} {west};
    doN (abs x) move;

    turn $ if (y > 0) {north} {south};
    doN (abs y) move;
    end;

def nextRow = \d.
    intersperse 2 move $ turn d;
    end;

def harvestTrees =
    turn back;
    doN 14 move;
    turn left;

    intersperse 4 (nextRow left;) (
        intersperse 15 move harvest;
        nextRow right;
        intersperse 15 move harvest;
    );
    end;

def slatRow =
    let item = "honey frame" in
    intersperse 3 move $ place item;
    end;

def buildHive =
    // Make 16 boards
    doN 4 (make "log"; make "board");

    // Make 9 honey frames
    doN 3 $ make "log";
    doN 3 (make "board"; make "honey frame");

    doN 4 (intersperse 4 move (place "board"); turn right; move;);
    turn right;
    move;

    slatRow;
    nextRow left;
    slatRow;
    nextRow right;
    slatRow;
    end;

def moveToNextHive =
    doN 7 move;
    end;

/* Makes 8 staves */
def makeStaveBatch =
    // 1 per tree
    make "log";

    // 4 per log
    make "board";

    // 2 per board
    doN 4 $ make "stave";
    end;

def buildCasks = \caskCount.
    // 40 staves
    doN 5 makeStaveBatch;
    doN 4 $ make "steel hoop";
    doN caskCount $ make "cask";
    end;

/*
Moves forward until finding objective
item, stops when a gap is reached.
*/
def collectContiguous = \maxdist. \item. \hadFound. \dist.
    if (dist <= maxdist) {
        honeycombHere <- ishere item;
        if honeycombHere {
            grab;
            move;
            collectContiguous maxdist item true $ dist + 1;
        } {
            if hadFound {
                pure dist;
            } {
                move;
                collectContiguous maxdist item false $ dist + 1;
            }
        }
    } {
        pure dist;
    }
    end;

def collectHoneycomb =
    distTravelled <- collectContiguous 10 "honeycomb" false 0;
    turn back;
    doN distTravelled move;
    end;

def collectAllHoneycombs = \targetCount.

    honeycombHere <- ishere "honeycomb";
    if honeycombHere {} {
        watch down;
        wait 2000;
    };

    intersperse 4 (turn left; doN 9 move; turn left;) collectHoneycomb;

    currentCount <- count "honeycomb";
    if (currentCount < targetCount) {
        turn right;
        doN 27 move;
        turn right;

        collectAllHoneycombs targetCount;
    } {
        pure currentCount;
    };
    end;

def moveUntilBlocked =
    thing <- scan forward;
    let isBlocked = case thing (\_. false) (\x. x == "lakewater") in
    if isBlocked {} {
        move;
        moveUntilBlocked;
    }
    end;

def getLakewater = \caskCount.
    turn right;
    doN 2 move;
    turn left;
    doN 5 move;
    turn right;
    moveUntilBlocked;

    doN caskCount $ use "siphon" forward;
    end;

def pickRock =
    isRock <- ishere "rock";
    if isRock {
        grab;
        pure ();
    } {};
    end;

def collectRocks =
    doN 22 move;
    turn right;
    doN 59 move;
    turn left;

    doN 7 (
        intersperse 15 move pickRock;
        nextRow right;
        intersperse 15 move pickRock;
        nextRow left;
    );
    end;

def makeTables =

    doN 18 (make "log"; make "board";);
    doN 36 $ make "table";

    turn right;
    move;
    turn right;
    doN 2 move;
    doN 9 (swap "table"; move);
    doN 8 move;
    doN 9 (swap "table"; move);
    turn left;
    doN 2 move;
    turn left;
    move;
    doN 9 (swap "table"; move);
    doN 8 move;
    doN 9 (swap "table"; move);
    end;

def buildTavern =

    // x16 per rock = 
    doN 12 $ make "stone tile";

    doN 2 (
        intersperse 30 move $ place "stone tile";
        nextRow left;
        intersperse 30 move $ place "stone tile";
        nextRow right;
    );
    intersperse 30 move $ place "stone tile";

    makeTables;

    // hearth
    nextRow right;
    doN 12 move;
    intersperse 4 move (make "hearth"; swap "hearth");
    turn right;
    doN 6 move;
    turn right;
    intersperse 4 move (make "archway"; place "archway");
    nextRow right;
    intersperse 4 move (make "archway"; place "archway");
    move;

    // Make enough logs for 70 wall pieces
    doN 35 (make "log"; make "wall");
    
    intersperse 14 move (place "wall");
    turn left;
    doN 6 (move; place "wall");
    turn left;
    doN 31 (move; place "wall";);
    turn left;
    doN 6 (move; place "wall");
    turn left;
    doN 13 (move; place "wall");
    end;

def combCollectionLoop = \targetCount.

    currentCount <- count "honeycomb";
    if (currentCount < targetCount) {
        watch down;
        wait 2000;
        collectHoneycomb;
        turn back;
        combCollectionLoop targetCount;
    } {}
    end;

def buildRobot = \targetCount. \meetingLoc.

    // Unpack the "botkit"
    make "solar panel";

    build {
        stock 8 "tree";
        buildHive;

        // Move to northwest corner
        turn back;
        doN 3 move;
        turn left;
        doN 4 move;
        turn left;

        combCollectionLoop targetCount;

        currLoc <- whereami;
        let delta = subtractTuple meetingLoc currLoc in
        moveTuple delta;

        // Assume that the base has already arrived
        // at the rendezvous point
        honeycombCount <- count "honeycomb";
        doN honeycombCount $ give parent "honeycomb";
    };
    end;

def placeHives = \targetCount. \meetingLoc.
    buildRobot targetCount meetingLoc;
    doN 38 move;
    buildRobot targetCount meetingLoc;
    doN 56 move;
    turn right;
    doN 15 move;
    turn left;
    buildRobot targetCount meetingLoc;
    doN 2 move;
    turn right;
    doN 26 move;
    turn left;
    buildRobot targetCount meetingLoc;
    end;

def acceptHoneyDeliveries =
    currentCount <- count "honeycomb";
    if (currentCount < 60) {
        wait 32;
        acceptHoneyDeliveries;
    } {
        // Use the "honey extractor"
        doN currentCount $ make "honey";
    }
    end;

def go =
    harvestTrees;
    turn east;
    doN 19 move;
    
    let meetingLoc = (0, -12) in
    placeHives 15 meetingLoc;

    turn right;

    buildCasks 2;
    getLakewater 2;

    turn right;

    collectRocks;

    doN 7 move;
    turn left;
    doN 80 move;
    buildTavern;

    nextRow right;
    
    currLoc <- whereami;
    let delta = subtractTuple meetingLoc currLoc in
    moveTuple delta;

    acceptHoneyDeliveries;
    doN 4 salvage;

    doN 2 $ make "mead";

    end;

go;