Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make structures, waypoints, and tagmembers commands return lists #2260

Merged
merged 13 commits into from
Jan 6, 2025
8 changes: 4 additions & 4 deletions data/entities.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -596,15 +596,15 @@
attr: blue
char: 'B'
description:
- This enables the `structure` and `floorplan` commands to locate and analyze structures placed in the world.
- This enables the `structures` and `floorplan` commands to locate and analyze structures placed in the world.
- |
`structure : Text -> Int -> Cmd (Unit + (Int * (Int * Int)))`
- Gets the x, y coordinates of the southwest corner of a constructed structure, by name and index.
`structures : Text -> Cmd (rec l. Unit + (Int * Int) * l)`
- Gets the x, y coordinates of the southwest corner of every constructed structure with a given name.
- |
`floorplan : Text -> Cmd (Int * Int)`
- Gets the dimensions of a structure template.
properties: [pickable]
capabilities: [structure, floorplan]
capabilities: [structures, floorplan]
- name: drill bit
display:
attr: entity
Expand Down
118 changes: 38 additions & 80 deletions data/scenarios/Challenges/Ranching/_beekeeping/queenbee.sw
Original file line number Diff line number Diff line change
Expand Up @@ -152,65 +152,29 @@ def takeStepTowardItem = \item.
}
end;

/**
Searches through the existing instances of
a given structure template, starting at a supplied
index.
Either returns the (potentially new) index of the structure
(in the case that more had been built since the last check),
or unit. Re-using the newly found index amortizes the "search"
within the structure list over many ticks to constant time
rather than linear time.
*/
def findStructureNewIndex = \remainingCount. \structureLoc. \lastIdx.
if (remainingCount > 0) {
foundStructure <- structure "beehive" lastIdx;
case foundStructure (\_. return $ inL ()) (\fs.
if (structureLoc == snd fs) {
return $ inR lastIdx;
} {
findStructureNewIndex (remainingCount - 1) structureLoc $ lastIdx + 1;
}
);
def workerProgram = \structureLoc.
try {make "honeycomb";} {};
hasHoneycomb <- has "honeycomb";
if hasHoneycomb {
goToHive structureLoc;
} {
return $ inL ();
}
end;

def workerProgram = \hiveIdx. \structureLoc.
eitherFoundStructure <- structure "beehive" hiveIdx;
case eitherFoundStructure return (\fs.
let hasSameStructure = structureLoc == snd fs in
if hasSameStructure {
try {make "honeycomb";} {};
hasHoneycomb <- has "honeycomb";
if hasHoneycomb {
goToHive structureLoc;
} {
takeStepTowardItem "wildflower";
return ();
};
workerProgram hiveIdx structureLoc;
} {
eitherNewIdx <- findStructureNewIndex (fst fs) structureLoc hiveIdx;
case eitherNewIdx
(\_. selfdestruct)
(\newIdx. workerProgram newIdx structureLoc);
}
);
takeStepTowardItem "wildflower";
return ();
};
workerProgram structureLoc;
end;

def mkBeeName = \structureLoc.
"bee" ++ format structureLoc;
end;

def workerProgramInit = \beename. \hiveIdx. \structureLoc.
def workerProgramInit = \beename. \structureLoc.
setname beename;
appear "B" (inl ());
workerProgram hiveIdx structureLoc;
workerProgram structureLoc;
end;

def createWorkerForStructure = \structureIdx. \fs.
def createWorkerForStructure = \loc.
// Build worker bee, assign ID, location
create "wax gland";
create "proboscis";
Expand All @@ -236,38 +200,36 @@ def createWorkerForStructure = \structureIdx. \fs.
create "treads";
create "workbench";

teleport self $ snd fs;
let beename = mkBeeName (snd fs) in
teleport self $ loc;
let beename = mkBeeName loc in
build {
require 1 "wax gland";
workerProgramInit beename structureIdx $ snd fs;
workerProgramInit beename loc;
};
return ();
end;

def associateAllHives = \remainingCount. \idx.
if (remainingCount > 0) {

foundStructure <- structure "beehive" idx;
case foundStructure return (\fs.
let beename = mkBeeName (snd fs) in
try {
// Fails if the robot does not exist
robotnamed beename;
return ();
} {
createWorkerForStructure idx fs;

// Give the child robot time to register its new
// name so that we don't end up spawning multiple
// bees for the same location
wait 1;
};

associateAllHives (remainingCount - 1) (idx + 1);
);
} {}
end;
def associateHive = \loc.
let beename = mkBeeName loc in
try {
// Fails if the robot does not exist
robotnamed beename;
return ();
} {
createWorkerForStructure loc;

// Give the child robot time to register its new
// name so that we don't end up spawning multiple
// bees for the same location
wait 1;
};
end;

def mapM_ : (a -> Cmd b) -> (rec l. Unit + a * l) -> Cmd Unit = \f. \l.
case l
(\_. return ())
(\cons. f (fst cons); mapM_ f (snd cons))
end;

/**
Each tick, iterates through all hives,
Expand All @@ -278,12 +240,8 @@ creates a bee named after the location.
*/
def observeHives =

// This invocation is just to get the total structure count.
// We will invoke it again once per iteration of 'associateAllHives'.
foundStructure <- structure "beehive" 0;
case foundStructure return (\fs.
associateAllHives (fst fs) 0;
);
beehives <- structures "beehive";
mapM_ associateHive beehives;

// Wait at least 1 tick so that we do not spin infinitely until
// we saturate our computation quota for the tick.
Expand Down
40 changes: 20 additions & 20 deletions data/scenarios/Challenges/Ranching/_fishing/hauler.sw
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,29 @@ def intersperse = \n. \f2. \f1. if (n > 0) {
} {};
end;

def isEnclosureFull = \idx.
foundBox <- structure "rubbish enclosure" idx;
case foundBox (\_. return false) (\enclosure.
let boxPos = snd enclosure in

prevLoc <- whereami;

dims <- floorplan "rubbish enclosure";
teleport self boxPos;

c <- density ((0, 0), dims);
let area = fst dims * snd dims in
let notFull = c < area in

teleport self prevLoc;
return $ not notFull;
);
def isEnclosureFull : Int * Int -> Cmd Bool = \encl.
prevLoc <- whereami;

dims <- floorplan "rubbish enclosure";
teleport self encl;

c <- density ((0, 0), dims);
let area = fst dims * snd dims in
let notFull = c < area in

teleport self prevLoc;
return $ not notFull;
end;

def any : (a -> Cmd Bool) -> (rec l. Unit + a * l) -> Cmd Bool = \p. \l.
case l
(\_. return false)
(\c. b <- p (fst c); if b {return true} {any p (snd c)})
end;

def isEitherEnclosureFull =
full1 <- isEnclosureFull 0;
full2 <- isEnclosureFull 1;
return $ full1 || full2;
enclosures <- structures "rubbish enclosure";
any isEnclosureFull enclosures
end;

def tryGrab =
Expand Down
24 changes: 6 additions & 18 deletions data/scenarios/Challenges/Ranching/_fishing/solution.sw
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,11 @@ def harvestIngredients =
move;
end;

def getJunkItem = \idx.
result <- tagmembers "junk" idx;
let totalCount = fst result in
let member = snd result in
let nextIdx = idx + 1 in

hasProhibited <- has member;
if hasProhibited {
return $ inr member;
} {
if (nextIdx < totalCount) {
getJunkItem nextIdx;
} {
return $ inl ();
}
}
end;
def find : (a -> Cmd Bool) -> (rec l. Unit + a * l) -> Cmd (Unit + a) = \p. \l.
case l
(\_. return (inl ()))
(\cons. h <- p (fst cons); if h {return $ inr (fst cons)} {find p (snd cons)})
end

def tryPlace = \item.
try {
Expand Down Expand Up @@ -131,7 +119,7 @@ def returnToCorner =
def unloadTrash =
try {
placeSerpentine (
item <- getJunkItem 0;
item <- find has (tagmembers "junk");
case item (\_. fail "done") (\item. place item);
);
watch down;
Expand Down
6 changes: 3 additions & 3 deletions data/scenarios/Challenges/Ranching/beekeeping.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ objectives:
judicious placement is essential for efficient
`honeycomb`{=entity} production.
condition: |
foundStructure <- structure "beehive" 0;
foundStructure <- structures "beehive";
return $ case foundStructure (\_. false) (\_. true);
- teaser: Collect honeycomb
goal:
Expand Down Expand Up @@ -75,7 +75,7 @@ objectives:
- |
Construct a `mead hall`{=structure}.
condition: |
foundStructure <- structure "mead hall" 0;
foundStructure <- structures "mead hall";
return $ case foundStructure (\_. false) (\_. true);
robots:
- name: base
Expand Down Expand Up @@ -193,7 +193,7 @@ entities:
description:
- Senses direction to nectar-producing flowers
properties: [known, pickable]
capabilities: [chirp, structure]
capabilities: [chirp, structures]
- name: honey
display:
char: 'h'
Expand Down
68 changes: 27 additions & 41 deletions data/scenarios/Challenges/Ranching/fishing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,26 +59,14 @@ objectives:
Otherwise, when the enclosure becomes full, the trash
hauler will come to empty it.
condition: |
// Returns true if prohibited item is in inventory.
def checkProhibited = \idx.
result <- tagmembers "junk" idx;
let totalCount = fst result in
let member = snd result in
let nextIdx = idx + 1 in
def hasAny : (rec l. Unit + Text * l) -> Cmd Bool = \items.
case items
(\_. return false)
(\c. b <- has (fst c); if b {return true} {hasAny (snd c)})
end;

hasProhibited <- as base {has member};
if hasProhibited {
return false;
} {
if (nextIdx < totalCount) {
checkProhibited nextIdx;
} {
return true;
}
}
end;

checkProhibited 0;
let prohibited = tagmembers "junk" in
h <- hasAny prohibited; return (not h)
- teaser: No littering
id: littered
hidden: true
Expand All @@ -89,33 +77,33 @@ objectives:
- |
Note that certain items can be burned with a `torch`{=entity} to make room.
condition: |
def locIsInsideEnclosure = \loc. \dims. \idx.
foundBox <- structure "rubbish enclosure" idx;
case foundBox (\_. return false) (\enclosure.
let boxPos = snd enclosure in
return $ snd loc >= snd boxPos
&& snd loc < snd dims + snd boxPos
&& fst loc >= fst boxPos
&& fst loc < fst dims + fst boxPos;
);
def locIsInsideEnclosure = \loc. \dims. \boxPos.
return $ snd loc >= snd boxPos
&& snd loc < snd dims + snd boxPos
&& fst loc >= fst boxPos
&& fst loc < fst dims + fst boxPos;
end;

def junkOutsideEnclosure =
result <- scan down;
case result (\_. return false) (\item.
isJunk <- hastag item "junk";
let isJunk = hastag item "junk" in
if isJunk {
foundBox <- structure "rubbish enclosure" 0;
enclosures <- structures "rubbish enclosure";

case foundBox (\_. return false) (\enclosure.
case enclosures (\_. return false) (\cons0.
let enclosure0 = fst cons0 in
case (snd cons0) (\_. return false) (\cons1.
let enclosure1 = fst cons1 in

dims <- floorplan "rubbish enclosure";
loc <- whereami;
dims <- floorplan "rubbish enclosure";
loc <- whereami;

insideFirst <- locIsInsideEnclosure loc dims 0;
insideSecond <- locIsInsideEnclosure loc dims 1;
return $ not $ insideFirst || insideSecond;
);
insideFirst <- locIsInsideEnclosure loc dims enclosure0;
insideSecond <- locIsInsideEnclosure loc dims enclosure1;
return $ not $ insideFirst || insideSecond;
)
)
} {
return false;
};
Expand Down Expand Up @@ -208,13 +196,11 @@ entities:
description:
- |
Can tell you if something is `junk`{=tag}
via the `hastag` command. E.g.:
via the `hastag` function. E.g.:
- |
`hastag "car tire" "junk"`
- |
Also allows you to iterate over the list of junk, e.g.:
- |
`tagmembers "junk" 0`
Also allows you to get the list of all junk items with `tagmembers "junk"`.
capabilities: [hastag, tagmembers]
- name: torch
display:
Expand Down
Loading
Loading