Skip to content

Commit

Permalink
Merge branch 'main' into lsp-unused-vars
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Jan 18, 2023
2 parents 71a4296 + 22eb0c9 commit f5e9334
Show file tree
Hide file tree
Showing 7 changed files with 534 additions and 48 deletions.
162 changes: 138 additions & 24 deletions data/scenarios/Challenges/_word-search/create-puzzle.sw
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
/**
Note: we are being a bit devious here;
There actually will never be a horizontal solution.
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;

We know epirically that our chosen seed does
contain at least one vertical solution.
*/
def intersperse = \n. \f2. \f1. if (n > 0) {
f1;
if (n > 1) {
Expand All @@ -14,6 +9,31 @@ def intersperse = \n. \f2. \f1. if (n > 0) {
} {};
end;

def whichOrdinal = \str.
if (str == "capital C") {
return 0;
} {
if (str == "capital O") {
return 1;
} {
if (str == "capital W") {
return 2;
} {
return (-1);
}
}
}
end;

/**
Returns -1 if not a recognized letter.
*/
def getAdjacentOrdinal = \d.
maybeEntity <- scan d;
str <- case maybeEntity (\_. return "") (\s. return s);
whichOrdinal str;
end;

/**
Call a function repeatedly with the numeric argument,
in descending order.
Expand All @@ -39,37 +59,95 @@ def chooseLetter = \i.
end;

/**
We may have selected the last letter to complete
the word COW.
We only need to probe further if
the letter above us is an O.
Then we need to check whether the letter
above that is a C or a W.
*/
def getExcludedVerticalLetter =
northOrdinal <- getAdjacentOrdinal north;
if (northOrdinal == 1) {
currentLoc <- whereami;
teleport self (fst currentLoc, snd currentLoc + 1);
doubleNorthOrdinal <- getAdjacentOrdinal north;
teleport self currentLoc;

if (doubleNorthOrdinal == 2) {
return 0;
} {
if (doubleNorthOrdinal == 0) {
return 2;
} {
return (-1);
}
}
} {
return (-1);
}
end;

/**
To ensure there are limited numbers of solutions
(TODO: preferably exactly one),
(preferably exactly one),
make sure we're not completing a word
horizontally (foward or backward)
(TODO: except if we
are in the pre-designated location).
If we would be completing
a word, select a different random letter.
or vertically (upward or downward), except if we
are in the designated location.
*/
def reRoll = \expectedFwdOrdinal. \expectedBkwdOrdinal.
def reRoll = \excludedVertical. \expectedFwdOrdinal. \expectedBkwdOrdinal.

// NOTE: excludeTwo and excludeZero
// are mutually exclusive!
let excludeTwo = expectedFwdOrdinal == 2 in
let excludeZero = expectedBkwdOrdinal == 0 in

// NOTE: Excluded letters can only be 0 or 2.
// 1 is always a valid option.

letterIndex <- random 3;
let completingFwd = letterIndex == expectedFwdOrdinal && expectedFwdOrdinal == 2 in
let completingBkwd = letterIndex == expectedBkwdOrdinal && expectedBkwdOrdinal == 0 in
if (completingFwd || completingBkwd) {
if (completingFwd && completingBkwd) {
if excludeZero {
if (excludedVertical == 2) {
return 1;
} {
reRoll expectedFwdOrdinal expectedBkwdOrdinal;
// Zero is the only excluded value,
// so just offset a choice between 0 and 1 upward by 1,
// to make it a choice between 1 and 2.
val <- random 2;
return $ val + 1;
};
} {
return letterIndex;
if excludeTwo {
if (excludedVertical == 0) {
return 1;
} {
// Two is the only excluded value,
// so make it a choice between 0 and 1.
random 2;
};
} {
if (excludedVertical == 0) {
// Zero is the only excluded value,
// so just offset a choice between 0 and 1 upward by 1,
// to make it a choice between 1 and 2.
val <- random 2;
return $ val + 1;
} {
if (excludedVertical == 2) {
// Two is the only excluded value,
// so make it a choice between 0 and 1.
random 2;
} {
// No values are excluded, so select random from
// the full range.
random 3;
}
};
};
};
end;

def singleTile = \expectedFwdOrdinal. \expectedBkwdOrdinal.
letterIndex <- reRoll expectedFwdOrdinal expectedBkwdOrdinal;
excludedVertical <- getExcludedVerticalLetter;
letterIndex <- reRoll excludedVertical expectedFwdOrdinal expectedBkwdOrdinal;
chosenLetter <- chooseLetter letterIndex;
place chosenLetter;
return letterIndex;
Expand Down Expand Up @@ -125,8 +203,44 @@ def removeBoulder =
selfdestruct;
end;

def createPuzzle = \width. \height.
def createImpossiblePuzzle = \width. \height.
intersperse height (crossBack width) (layTilesRow 0 2 width);
end;

/**
This word center is padded by
one cell from the vertical and horizontal
edges of the playfield.
This means that the word will not exist
horizontally at either the top or bottom edge,
nor will it exist vertically at the left or
right edge of the playfield.
*/
def overwriteWithWord = \width. \height.

randX <- random $ width - 2;
randY <- random $ height - 2;
let insertionX = 1 + randX in
let insertionY = 1 + randY in
teleport self (insertionX, -insertionY);

// Rotate to random orientation
turnCount <- random 3;
doN turnCount $ turn left;

move;
turn back;

// Place all three letters of the word
iterN 3 $ \x.
chosenLetter <- chooseLetter x;
swap chosenLetter;
move;
end;

def createPuzzle = \width. \height.
createImpossiblePuzzle width height;
overwriteWithWord width height;
removeBoulder;
end;

Expand Down
119 changes: 109 additions & 10 deletions data/scenarios/Challenges/_word-search/verify-solution.sw
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,27 @@ def whichOrdinal =
}
}
end;



def whichHighlightedOrdinal = \str.
if (str == "lowercase c") {
return 0;
} {
if (str == "lowercase o") {
return 1;
} {
if (str == "lowercase w") {
return 2;
} {
return (-1);
}
}
}
end;

def countConsecutive = \expectedOrdinal. \n.

thisOrdinal <- whichOrdinal;

nextOrdinal <- if (thisOrdinal == expectedOrdinal) {
return $ expectedOrdinal + 1;
} {
Expand All @@ -39,17 +54,14 @@ def countConsecutive = \expectedOrdinal. \n.
if (nextOrdinal == 3) {
return true;
} {

if (n > 0) {
if (n > 1) {
move;
countConsecutive nextOrdinal (n - 1);
countConsecutive nextOrdinal $ n - 1;
} {
return false;
};
};

end;


def checkBackAndForth =

Expand All @@ -62,11 +74,10 @@ def checkBackAndForth =
}
end;


def checkDirections = \n.
if (n > 0) {
wasFound <- checkBackAndForth;
if (wasFound) {
if wasFound {
return true;
} {
turn left;
Expand All @@ -77,8 +88,96 @@ def checkDirections = \n.
}
end;

def isMarkedInDirection = \d.
scanResult <- scan d;
ordinalNum <- case scanResult
(\_. return (-1))
whichHighlightedOrdinal;
return $ ordinalNum >= 0;
end;

/**
It's possible we could be one cell away from
a marked cell after finishing, either due
to using a directional `drill` command instead of
`drill down`, or due to an apparent bug which
does not evaluate the goal condition between the
`drill` and a `move` command.
*/
def moveToMarkedCell = \n.
if (n > 0) {
isMarkedAhead <- isMarkedInDirection forward;
if isMarkedAhead {
move;
return true;
} {
turn left;
moveToMarkedCell $ n - 1;
};
} {
return false;
};
end;

/**
Orient ourselves such that
a marked cell is behind us.
*/
def findMarkBehind = \n.
if (n > 0) {
isMarkedBehind <- isMarkedInDirection back;
if isMarkedBehind {
return true;
} {
turn left;
findMarkBehind $ n - 1;
};
} {
return false;
};
end;

/**
The cell we're on might be in the middle of a word,
rather than the end. Determine the orientation of
the line, then move along it until reaching the end.
Algorithm:
0. Assumption: we are currently on a marked cell.
1. Turn in all all four directions to `scan back`
for a second marked cell. Stop turning if
we encounter one.
If none found after 4 turns, abort.
2. `scan forward` to see if there is a marked cell in
the opposite direction.
`move` (foward) once if there is. Since the word
is only three cells long, this will be the other
end of it.
*/
def moveToWordExtrema =
foundCellBehind <- findMarkBehind 4;
if foundCellBehind {
isMarkedAhead <- isMarkedInDirection forward;
if isMarkedAhead {
move;
} {};
} {};
end;

def checkSoln =
checkDirections 4;
isMarkedHere <- isMarkedInDirection down;
atMarkedCell <- if isMarkedHere {
return true;
} {
moveToMarkedCell 4;
};

if atMarkedCell {
moveToWordExtrema;
checkDirections 4;
} {
return false;
}
end;

as base {checkSoln};
Loading

0 comments on commit f5e9334

Please sign in to comment.