Skip to content

Commit

Permalink
Whack-a-mole scenario
Browse files Browse the repository at this point in the history
  • Loading branch information
kostmo committed Jan 22, 2023
1 parent d96405b commit 1b9def6
Show file tree
Hide file tree
Showing 5 changed files with 405 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 @@ -2,6 +2,7 @@ chess_horse.yaml
teleport.yaml
2048.yaml
word-search.yaml
gopher.yaml
ice-cream.yaml
hanoi.yaml
bucket-brigade.yaml
Expand Down
146 changes: 146 additions & 0 deletions data/scenarios/Challenges/_gopher/gopher.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;
def abs = \n. if (n < 0) {-n} {n} end;

def randSign = \x.
opposite <- random 2;
if (opposite == 1) {
return (-x);
} {
return x;
}
end;

def converge = \dest. \currentLoc.

let xDist = fst currentLoc - fst dest in
let yDist = snd currentLoc - snd dest in

if (xDist < 0) {
turn east;
} {
if (xDist > 0) {
turn west;
} {};
};
doN (abs xDist) move;

if (yDist < 0) {
turn north;
} {
if (yDist > 0) {
turn south;
} {};
};
doN (abs yDist) move;
end;

/**
TODO: Randomly alternate between horizontal and vertical
movement.
*/
def navigateTo = \destTuple.
loc <- whereami;
converge destTuple loc;
end;

def arrive = \fieldWidth. \fieldHeight.

let leadDist = 20 in

newDestinationX <- random fieldWidth;
newDestinationYtemp <- random fieldHeight;
let newDestinationY = -newDestinationYtemp in

offsetXrand <- random $ leadDist / 2;

// The manhattan-distance of the offset
// must total some preset amount.
let offsetXunsigned = (leadDist / 2) + offsetXrand in
let offsetYunsigned = leadDist - offsetXunsigned in

offsetX <- randSign offsetXunsigned;
offsetY <- randSign offsetYunsigned;

let startX = newDestinationX + offsetX in
let startY = newDestinationY + offsetY in

teleport self (startX, startY);
navigateTo (newDestinationX, newDestinationY);
turn down;
end;

def getTauntStage = \startingAmount. \newCount.
if ((newCount * 5) / startingAmount < 1) {
return (0, "Hey, maybe we can work this out?");
} {
if ((newCount * 5) / startingAmount < 2) {
return (1, "I didn't hear no bell!");
} {
if ((newCount * 5) / startingAmount < 3) {
return (2, "Why don't you just give up?");
} {
if ((newCount * 5) / startingAmount < 4) {
return (3, "Close one!");
} {
if (newCount < startingAmount - 2) {
return (4, "OK, no more Mr. Nice Gopher!");
} {
if (newCount < startingAmount - 1) {
return (5, "Bet you can't do that again!");
} {
if (newCount < startingAmount) {
return (6, "Beginner's luck!");
} {
return (7, "You'll never catch me!");
};
};
};
};
};
};
};
end;

def waitWhileHere = \e.
here <- isHere e;
if here {
wait 1;
waitWhileHere e;
} {};
end;

def go = \lastTauntIndex. \startingAmount. \dropping.
newCount <- count dropping;
if (newCount > 0) {
tauntStage <- getTauntStage startingAmount newCount;
let tauntIndex = fst tauntStage in
if (tauntIndex != lastTauntIndex) {
say $ snd tauntStage;
} {};

appear "o";
arrive 48 18;

place dropping;
appear "G";
waitWhileHere dropping;
go tauntIndex startingAmount dropping;
} {
say "Argh! I give up.";

// Allow the player to salvage their robots
let reward = "toolkit" in
try {
place reward;
} {
swap reward;
return ();
};

selfdestruct;
};
end;

let dropping = "mound" in
startingAmount <- count dropping;
go (-1) startingAmount dropping;
121 changes: 121 additions & 0 deletions data/scenarios/Challenges/_gopher/solution.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;

def makeSigned = \b. \x.
if b {
return (-x);
} {
return x;
}
end;

def getDirection = \n.
if (n == 0) {
return forward;
} {
if (n == 1) {
return right;
} {
if (n == 2) {
return back;
} {
if (n == 3) {
return left;
} {
return down;
}
}
}
}
end;

/**
Loops forever
*/
def scanDirections = \n.
d <- getDirection n;
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;
} {
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 = \offset. \cellCount.
if (isDivisibleBy (cellCount + offset) 5) {
deploySensor;
} {};
if (cellCount > 1) {
move;
deployRow offset $ cellCount - 1;
} {};
end;

def isEven = \x.
isDivisibleBy x 2
end;

def deployGrid = \width. \height.

if (height > 0) {

let nowEven = isEven height in

offsetVal <- makeSigned nowEven $ height * 2;
extraOffset <- if nowEven {
return (-1);
} {
return 0;
};
deployRow (offsetVal + extraOffset) width;

d <- if nowEven {
return right;
} {
return left;
};

turn d;
move;
turn d;

deployGrid width $ height - 1;
} {};
end;

def recenter = \height.
turn left;
doN (height / 2) move;
end;

def go = \width. \height.
deployGrid width height;
recenter height;
end;

go 50 20;
Loading

0 comments on commit 1b9def6

Please sign in to comment.