Compare commits

...
11 Commits
Author SHA1 Message Date
adamandClaude Opus 5.5 8dfebaa9f8 zero pad decimal part of average guesses
An average of 3.04 was shown as 3.4 because the hundredths weren't
padded. Pad with parameter expansion to keep the script bash-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:24:24 +00:00
adamandClaude Opus 5.5 f29d81e932 keep hard mode hints when resuming a game
hard_mode_check uses the previous row's greens and yellows, but these
weren't written to the progress file, so after resuming a game the next
guess could drop known green and yellow letters. Save them alongside
the rest of the game state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:19:24 +00:00
adamandClaude Opus 5.5 73f403693a save progress after every guess
Progress was only saved at the start of a game and on Ctrl-C, so a
dropped connection lost every guess made so far. Ctrl-C during the
reveal also saved the scored row without advancing ROW, which gave the
player that guess back on resume.

Save straight after each guess is scored (before the reveal) with the
next row, record the result before the final reveal, and make the
SIGINT trap only tidy up the terminal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:17:20 +00:00
abrown38andClaude Opus 5.5 1f6a5b4a44 validate username in online mode
Usernames are used in file names and URLs, so a '/' could write files
outside the game directory and a space broke the share links. Only
allow a-z, 0-9 and _ (max 32 chars) and re-prompt otherwise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:12:44 +00:00
abrown38 437d46e975 add colour to keyboard 2026-09-29 17:07:46 +00:00
adam 7621938f04 set program name in help message
Deploy game to server / deploy (push) Successful in 8s
2026-02-11 21:43:00 +00:00
adam 1a9a440509 fix duplicate path in URL
Deploy game to server / deploy (push) Successful in 6s
2026-01-21 12:48:48 +00:00
adam d9a7c94125 add link to website
Deploy game to server / deploy (push) Successful in 7s
2025-11-29 03:50:26 +00:00
adam efa709e34e add online mode flag to help message
Deploy game to server / deploy (push) Successful in 8s
2025-11-23 21:22:10 +00:00
adam a7cdb712fd fix typo in function name
Deploy game to server / deploy (push) Successful in 7s
2025-09-27 21:14:39 +00:00
adam 75074d8e84 add stats url to online mode
Deploy game to server / deploy (push) Successful in 7s
2025-08-28 09:59:26 +00:00
+59 -22
View File
@@ -33,6 +33,7 @@ function main() {
declare -g ANSWER
declare -g POOL='QWERTYUIOPASDFGHJKLZXCVBNM'
declare -Ag YELLOWS
declare -Ag KEYS
ANSWER=$(select_random_word)
set_options "$@"
@@ -50,23 +51,31 @@ function main() {
init_board
fi
[[ "${ONLINE}" == 1 ]] && save_game "NO_EXIT"
[[ "${ONLINE}" == 1 ]] && save_game "${ROW}"
render_board
for (( ROW; ROW<HEIGHT; ROW++ )); do
declare GUESS
[[ "${KEYBOARD}" == 1 ]] && render_keyboard
GUESS=$(retrive_guess)
GUESS=$(retrieve_guess)
check_guess "${GUESS}" "${ROW}" ; WIN=$?
# Save before the reveal so quitting or disconnecting can't undo a guess
if [[ $WIN == 5 ]] || (( ROW+1 == HEIGHT )); then
save_result
elif [[ "${ONLINE}" == 1 ]]; then
save_game "$(( ROW+1 ))"
fi
reveal_row "${ROW}"
if [[ $WIN == 5 ]]; then
save_result
echo -e "${CLEAR_DOWN}YOU WIN"
if [[ "${ONLINE}" == 1 && "${DAILY_DONE}" != 1 ]]; then
echo "Share/view your game with -> curl \"${URL_BASE}/${RESULT_FILE}\""
echo "Share/view your stats with -> curl \"${URL_BASE}/stats/${USER}\""
echo "Check out the new homepage in your browser -> ${URL_BASE}"
while read -r board_line; do echo "${board_line//[A-Z]/ }"; done < "${RESULT_FILE}"
fi
echo "Guess - $(( ROW+1 ))/6"
@@ -81,9 +90,10 @@ function main() {
done
echo -en "${NEWLINE}${RESET}"
save_result
if [[ "${ONLINE}" == 1 && "${DAILY_DONE}" != 1 ]]; then
if [[ "${ONLINE}" == 1 && "${DAILY_DONE}" != 1 ]]; then
echo "Share/view your game with -> curl \"${URL_BASE}/${RESULT_FILE}\""
echo "Share/view your stats with -> curl \"${URL_BASE}/stats/${USER}\""
echo "Check out the new homepage in your browser -> ${URL_BASE}"
while read -r board_line; do echo "${board_line//[A-Z]/ }"; done < "${RESULT_FILE}"
fi
exit 0
@@ -135,9 +145,15 @@ function set_options() {
echo -en "${CLEAR_SCREEN}"
declare -g USER
read -r -p "Username: " USER
read -r -p "Username: " USER || exit 1
USER="${USER,,}"
# Username is used in file names and URLs so only allow safe characters
while [[ -z "${USER}" || "${USER}" == *[!a-z0-9_]* || ${#USER} -gt 32 ]]; do
read -r -p "${CLEAR_UP1}Username (letters, numbers and _ only): " USER || exit 1
USER="${USER,,}"
done
declare -g DAY
DAY=$(( EPOCHSECONDS / 86400 ))
@@ -171,14 +187,15 @@ function set_options() {
fi
fi
trap save_game SIGINT
# Progress is saved after every guess so Ctrl-C only needs to tidy the terminal
trap 'echo -en "${SHOW_CURSOR}${RESET}"; exit 0' SIGINT
;;
d)
DELAY=0
;;
h)
echo -e \
"Usage: <program_name> [OPTIONS]
"Usage: wordle [OPTIONS]
Play a game for Wordle
Options:
@@ -187,6 +204,7 @@ Options:
-H Enable hard mode
-S Enable strict hard mode (Cannot reuse grey letters)
-k disable on screen keyboard
-o Enable online mode
-d Enable debug mode (no delay during letter reveal)
-h Show this help message and exit"
@@ -225,7 +243,7 @@ function render_board() {
[[ "${BORDER}" == 1 ]] && echo -e "└─────────────────┘"
}
function retrive_guess() {
function retrieve_guess() {
if [[ -n $1 ]]; then
read -r -p "${CLEAR_UP1}$1: " GUESS
else
@@ -238,12 +256,12 @@ function retrive_guess() {
declare valid_guess
validate_guess "${GUESS}" ; valid_guess=$?
[[ ${valid_guess} == 1 ]] && GUESS=$(retrive_guess "Not A Valid Word")
[[ ${valid_guess} == 2 ]] && GUESS=$(retrive_guess "Not A Valid Guess")
[[ ${valid_guess} == 3 ]] && GUESS=$(retrive_guess "GREEN Issue")
[[ ${valid_guess} == 4 ]] && GUESS=$(retrive_guess "YELLOW Issue")
[[ ${valid_guess} == 5 ]] && GUESS=$(retrive_guess "POOL Issue")
[[ ${valid_guess} == 6 ]] && GUESS=$(retrive_guess "NEW Issue")
[[ ${valid_guess} == 1 ]] && GUESS=$(retrieve_guess "Not A Valid Word")
[[ ${valid_guess} == 2 ]] && GUESS=$(retrieve_guess "Not A Valid Guess")
[[ ${valid_guess} == 3 ]] && GUESS=$(retrieve_guess "GREEN Issue")
[[ ${valid_guess} == 4 ]] && GUESS=$(retrieve_guess "YELLOW Issue")
[[ ${valid_guess} == 5 ]] && GUESS=$(retrieve_guess "POOL Issue")
[[ ${valid_guess} == 6 ]] && GUESS=$(retrieve_guess "NEW Issue")
echo -n "${GUESS^^}"
}
@@ -257,7 +275,12 @@ function render_keyboard() {
elif [[ $i == 19 ]]; then
echo -en "${NEWLINE} "
fi
echo -n "${POOL:$i:1} "
declare key="${POOL:$i:1}"
if [[ -n "${KEYS[$key]}" ]]; then
echo -n "${KEYS[$key]}${BOLD}${LETTER}${key}${RESET} "
else
echo -n "${key} "
fi
done
echo -en "${NEWLINE}"
}
@@ -328,6 +351,7 @@ function check_guess() {
if [[ "${_char}" == "${_answer:$c:1}" ]]; then
greens[c]="${_char}"
KEYS[$_char]="${GREEN}"
BOARD[$_row,$c]="${GREEN}${BOLD}${LETTER} ${_char} ${UNBOLD}"
continue
fi
@@ -336,6 +360,7 @@ function check_guess() {
chars="${chars/${_char}/}"
yellows[c]="${_char}" # volatile - stores previous row yellows
YELLOWS[$_row,$c]="${_char}" # stores all yellow from all rounds
[[ "${KEYS[$_char]}" != "${GREEN}" ]] && KEYS[$_char]="${YELLOW}"
BOARD[$_row,$c]="${YELLOW}${BOLD}${LETTER} ${_char} ${UNBOLD}"
fi
[[ "${ANSWER}" =~ ${_char} ]] && continue
@@ -367,8 +392,9 @@ function load_game() {
source "${PROGRESS_FILE}"
}
# shellcheck disable=SC2317 # Don't warn about unreachable commands in this function
# Takes the row the game should resume from
function save_game() {
declare -r row=$1
: > "${PROGRESS_FILE}"
for key in "${!BOARD[@]}"; do
@@ -379,19 +405,29 @@ function save_game() {
echo "YELLOWS[$key]='${YELLOWS[$key]}'" >> "${PROGRESS_FILE}"
done
for key in "${!KEYS[@]}"; do
echo "KEYS[$key]='${KEYS[$key]}'" >> "${PROGRESS_FILE}"
done
# Previous row's hints, needed by hard_mode_check after a resume
for key in "${!greens[@]}"; do
echo "greens[$key]='${greens[$key]}'" >> "${PROGRESS_FILE}"
done
for key in "${!yellows[@]}"; do
echo "yellows[$key]='${yellows[$key]}'" >> "${PROGRESS_FILE}"
done
{
echo "ROW=${ROW}"
echo "ROW=${row}"
echo "POOL=${POOL}"
echo "HARD_MODE=${HARD_MODE}"
echo "STRICT_HARD_MODE=${STRICT_HARD_MODE}"
echo "WIN=${WIN}"
echo "ANSWER=${ANSWER}"
echo "IN_PROGRESS=1"
[[ "${PLAYED}" == 1 ]] && echo 'PLAYED=1'
[[ "${PLAYED}" == 1 ]] && echo 'PLAYED=1'
} >> "${PROGRESS_FILE}"
echo -en "${RESET}"
[[ -z $1 ]] && exit 0
}
function save_result() {
@@ -448,6 +484,7 @@ function update_stats() {
integer_part=$(( result / 100 ))
decimal_part=$(( result % 100 ))
[[ ${decimal_part} -lt 10 ]] && decimal_part="0${decimal_part}"
AVERAGE="${integer_part}.${decimal_part}"
fi