Unsurprisingly, Wordle is a game about words, so we need to have a section of the code dedicated to them.
DAILY
Each day the players are allowed to guess a single word which is automatically selected by the script.
I didn’t want to make a fully functioning Wordle clone with a vast set of words, so the set here is quite small and is stored in a single string. The words are base64-encoded to obfuscate the words from people seeing the code like yourself.
%%[
/* Select the word for the day in the encoded form */
set @words = 'U1RFQU0=|T1BFUkE=|Q0xPQUs=|Q0xFQVI=|TklHSFQ=|R0hPU1Q=|U1RBRkY=|U1RPVVQ=|UElMT1Q=|S0VCQUI=|QUJZU1M=|Uk9VR0U=|V09STEQ=|UVVFUlk=|VUxDRVI=|U0lFR0U=|QkxPS0U=|RlJBTUU=|Q0hFQVQ=|RVBPQ0g=|U1BJQ1k=|RUxERVI=|RkVJR04=|Q1JBVEU=|VElNSUQ=|U1BJTEw=|QlJFQUs=|UEFVU0U=|R1JJTUU=|Q0hBTVA=|TllNUEg='
set @rowset = BuildRowsetFromString(@words, '|')
set @day = DatePart(@now, 'D')
set @row = Row(@rowset, @day)
set @theWordEncoded = Field(@row, 1)
set @theWord = Base64Decode(@theWordEncoded, "UTF-8")
The processing is quite simple:
- We use the
BuildRowsetFromString()
function to make our string work as an array of words - We get the number representing the
@day
of the month - This number is used to select the corresponding row from our
@rowset
of words) - The encoded word is retrieved using the
Field
function - Finally, we decode the string obtained in the last step to get the daily word
Consider this example:
- I’m writing this on April 12 2022
- This means the
@day
variable would get the value of 12 - The 12th word is
Uk9VR0U=
which decoded means ROUGE
VOCAB
To ensure players don’t submit non-existing words to easily find the letters from the searched word, we need to have a data extension with a list of allowed words:
- I’m using the
Wordle - Allowed Word List
name in my script - The DE has just a single column called
Words
with the obvious text data type and length of 5 characters - You can see the allowed word list here – this txt file stores 12.972 words
NOTE Why do we need this? We want to prevent players from optimizing their search for the daily word by using strings like EAIOU or NRSTC allow them to eliminate letters without flexing their knowledge of the English vocabulary.
CHECK
If the player has submitted a word, we perform a validation to see if we can accept this @lastGuess
.
Words are accepted if they fulfill the following conditions:
- they were not submitted before
- they exist in our dictionary data extension
/* Validation of incoming words*/
IF
IndexOf(@guesses, @lastGuess) < 1
AND
Empty(@lastGuess) == false
THEN
set @lookup = RowCount(LookupRows('Wordle - Allowed Word List', 'Word', @lastGuess))
IF
@lookup == 1
AND
Empty(@guesses) == true
THEN
set @guesses = @lastGuess
ELSEIF
@lookup == 1
AND
Empty(@guesses) == false
THEN
set @guesses = Concat(@guesses, '|', @lastGuess)
ELSE
set @feedback = Concat("'", @lastGuess, "' is not an allowed word")
ENDIF
ELSEIF
IndexOf(@guesses, @lastGuess) > 0
THEN
set @feedback = 'Repeat guesses are not allowed'
ENDIF
Submitted words are validated in two ways:
- we check if they exist in our data extension with allowed words
- if the word is found by the
lookupRows
fucntion, the@lastGuess
variable is added to the@guesses
string conditionally:- if it is the first submitted word, it becomes the
@guesses
value - any words submitted later are delimited with the
|
separator
- if it is the first submitted word, it becomes the
- if the word is found by the
- we check if the word was submitted previously
INPUT
You might have thought that there’s a flaw in the validation of the submitted word – the submitted @lastGuess
is never checked for length or if it only contains letters. That part of the validation is done entirely client-side by HTML form validation and the properties of the main input.
The submited word needs to fit with the [A-Za-z]{5}
pattern: must have 5 letters (case insensitive). If the input value does not match this value, the browser will display the message: This needs to be a 5-letter word.
RESET
The following block checks if the daily word has expired in the middle of our session:
/* Check if the last word has expired */
IF
Empty(@previousWord) == false
AND
@theWord != Base64Decode(@previousWord)
THEN
set @feedback = 'The daily word has reset'
set @guesses = ''
set @lastGuess = ''
ENDIF
While the script is running, we check if the current run is a reaction to a form submission event (the @previousWord
values is not empty) and later compare the current daily word with the one that was submitted in the @previousWord
in the encoded form. If those conditions are met:
- we remove all
@guesses
which resets the progress - the
@lastGuess
is removed so that a lucky guess from the last try does not accidentally count as a submission for a new day