Skip to content

Commit

Permalink
DNA copying challenge (#1031)
Browse files Browse the repository at this point in the history
A challenge that utilizes a stack.
Closes #932.

Demo:
```
scripts/play.sh --scenario data/scenarios/Challenges/dna.yaml --autoplay
```
![Screenshot from 2024-10-13 17-06-06](https://github.com/user-attachments/assets/678984b0-f83d-4e0d-8958-dfcd33461ce6)
  • Loading branch information
kostmo authored Oct 14, 2024
1 parent 3c03a24 commit 0fda99f
Show file tree
Hide file tree
Showing 8 changed files with 1,288 additions and 0 deletions.
1 change: 1 addition & 0 deletions data/scenarios/Challenges/00-ORDER.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ wave.yaml
gallery.yaml
wolf-goat-cabbage.yaml
blender.yaml
dna.yaml
friend.yaml
pack-tetrominoes.yaml
dimsum.yaml
Expand Down
177 changes: 177 additions & 0 deletions data/scenarios/Challenges/_dna/lab.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;

def getBaseForNumber = \n.
if (n == 0) {
"guanine";
} {
if (n == 1) {
"cytosine";
} {
if (n == 2) {
"adenine";
} {
"thymine";
};
};
};
end;

def getNumberForBase = \n.
if (n == "guanine") {
0;
} {
if (n == "cytosine") {
1;
} {
if (n == "adenine") {
2;
} {
3;
};
};
};
end;

/** Toggle the lowest bit */
def getComplementNumber = \n.
if (n == 0) {
1;
} {
if (n == 1) {
0;
} {
if (n == 2) {
3;
} {
2;
};
};
};
end;

def waitUntilSomethingExists =
maybeItemHere <- scan down;
case maybeItemHere (\_.
watch down;
wait 1000;
waitUntilSomethingExists;
) return;
end;

def waitUntilHere = \item.
hereNow <- ishere item;
if hereNow {} {
watch down;
wait 1000;
waitUntilHere item;
};
end;

def waitUntilOccupied =
stillEmpty <- isempty;
if stillEmpty {
watch down;
wait 1000;
waitUntilOccupied;
} {};
end;

def myStandby = \receptacleLoc.
teleport self receptacleLoc;
entToClone <- grab;
teleport self (36, -11);
turn back;
return $ inR entToClone;
end;

def placeBase = \standbyFunc. \n.

if (n > 0) {
idx <- random 4;
let entTemp = getBaseForNumber idx in
let ent = entTemp in
create ent;
place ent;
move;

clonedOrganism <- placeBase standbyFunc $ n - 1;

// Unwinds the stack; verifies the original placement order
placedEnt <- instant waitUntilSomethingExists;
let isGood = ent == placedEnt in
move;

if isGood {
return clonedOrganism;
} {
return $ inL ();
}
} {
// Returns the clonedOrganism
standbyFunc;
};
end;

def makeDnaStrand = \receptacleLoc.
teleport self (5, -2);

dims <- floorplan "DNA decoder";
let decoderWidth = fst dims in
eitherClonedOrganism <- placeBase (myStandby receptacleLoc) decoderWidth;

case eitherClonedOrganism (\_.
create "pixel (R)";
) (\clonedItem.
instant $ (
teleport self (0, -11);
waitUntilHere "switch (on)";

bottomWaypointQuery <- waypoint "receiver" 1;
let receptacleLoc2 = snd bottomWaypointQuery in
teleport self receptacleLoc2;

sow clonedItem;
create clonedItem;
k <- robotnamed "keeper";
give k clonedItem;

let slideBox = "slide box" in
create slideBox;
give base slideBox;
say $ "You got a new \"" ++ slideBox ++ "\"";
);
);
end;

def waitForCloneableOrganism =

waypointQuery <- waypoint "receiver" 0;
let receptacleLoc = snd waypointQuery in
organism <- instant (
teleport self receptacleLoc;

waitUntilOccupied;

thingHere <- scan down;
case thingHere (\x. return $ inL x) (\item.
isOrganism <- hastag item "organism";
return $ inR item;
);
);

case organism (\_.
say "Not a cloneable organism!";
waitForCloneableOrganism;
) (\item.
create "pixel (G)";
makeDnaStrand receptacleLoc;
);
end;

def go =
waitForCloneableOrganism;
turn east;
go;
end;

go;
99 changes: 99 additions & 0 deletions data/scenarios/Challenges/_dna/mirrorbot.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;

def getBaseForNumber = \n.
if (n == 0) {
"guanine";
} {
if (n == 1) {
"cytosine";
} {
if (n == 2) {
"adenine";
} {
"thymine";
};
};
};
end;

def getNumberForBase = \n.
if (n == "guanine") {
0;
} {
if (n == "cytosine") {
1;
} {
if (n == "adenine") {
2;
} {
if (n == "thymine") {
3;
} {-1};
};
};
};
end;

/** Toggle the lowest bit */
def getComplementNumber = \n.
if (n == 0) {
1;
} {
if (n == 1) {
0;
} {
if (n == 2) {
3;
} {
2;
};
};
};
end;

def placeComplementOf = \item.
let baseNumber = getNumberForBase item in
if (baseNumber >= 0) {
let complementNumber = getComplementNumber baseNumber in
let newItem = getBaseForNumber complementNumber in
move;
create newItem;
place newItem;
} {
let sludge = "organic sludge" in
create sludge;
place sludge;
}
end;

def waitUntilHere =
watch down;
wait 1000;

maybeItemDown <- scan down;
case maybeItemDown (\_. waitUntilHere) (\itemHere.
placeComplementOf itemHere;
);
end;

def waitUntilEmpty =
watch down;
wait 1000;
emptyHere <- isempty;
if emptyHere {
// reset the position
turn back;
move;
turn back;
} {
waitUntilEmpty;
}
end;

def go =
instant waitUntilHere;
waitUntilEmpty;
go;
end;

go;
48 changes: 48 additions & 0 deletions data/scenarios/Challenges/_dna/resetter.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;

/**
Assumes we are on the left edge of a row of nucleobases
*/
def resetPlayfieldRow =
dims <- floorplan "DNA decoder";
let decoderWidth = fst dims in
doN decoderWidth (grab; move;);
end;

def resetPlayfield =
teleport self (5, -2);
resetPlayfieldRow;
teleport self (5, -3);
resetPlayfieldRow;

teleport self (5, -11);
resetPlayfieldRow;
teleport self (5, -12);
resetPlayfieldRow;
end;

def watchSwitch = \lastState.
watch down;
wait 1000;
found <- scan down;
case found return (\item.
if (item != lastState) {
if (item == "switch (off)") {
loc <- whereami;
resetPlayfield;
teleport self loc;
} {
};
} {};
watchSwitch item;
);
end;

def go =
instant $ (
found <- scan down;
case found return watchSwitch;
);
end;

go;
Loading

0 comments on commit 0fda99f

Please sign in to comment.