Compare commits

...
5 Commits
Author SHA1 Message Date
adamandClaude Opus 5.5 8e62094a6f treat Ctrl-D at the guess prompt like Enter
Ctrl-D doesn't move the cursor to a new line, but the retry prompts
move up a line assuming Enter was pressed, so each Ctrl-D climbed up
the screen over the keyboard and board. It also quit the game, losing
an offline game to a stray key press.

On a terminal, print the missing newline and carry on as if Enter was
pressed. Only exit when input has really ended (not a terminal), so a
closed pipe still can't spin the retry loop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:39:02 +00:00
adamandClaude Opus 5.5 0f8640e9e8 explain hard mode errors in guess prompt
Replace "GREEN Issue", "YELLOW Issue" and "POOL Issue" with messages
that say which letter broke which rule:

  3rd letter must be A
  Must contain R
  1st letter can't be R   (was yellow there before)
  S is not in the word    (strict mode, grey letter reused)

hard_mode_check now records the failing position, and a yellow letter
reused in the same spot gets its own code (6, previously the unused
"NEW Issue"). Drop the unused "Not A Valid Guess" code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:35:38 +00:00
adamandClaude Opus 5.5 6b07093d68 write the same answer line to both board files
On a loss the answer line was written to RESULT_FILE with the border
indent and bold, but CUR_RESULT_FILE only got the letters. Move the
answer line into render_answer and use it for the terminal and both
files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:32:28 +00:00
adamandClaude Opus 5.5 a3f9ae6a17 quit when input ends at the guess prompt
At end of input (Ctrl-D, or stdin closed) read returns straight away
with an empty guess, so the "Must be 5 letters" loop spun forever at
full CPU. If the game's parent process was killed first, the subshell
was left orphaned and spinning.

Exit retrieve_guess when read hits EOF, pass that back through the
retry prompts with a single recursive call, and quit from main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:31:21 +00:00
adamandClaude Opus 5.5 d34d98c15d only update stats for the daily game
update_stats ran for every online game, so practice games played after
the daily counted towards played/wins/losses and a practice loss reset
the streak. Move it inside the DAILY_DONE check with the board files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:27:24 +00:00
+43 -27
View File
@@ -58,7 +58,7 @@ function main() {
for (( ROW; ROW<HEIGHT; ROW++ )); do
declare GUESS
[[ "${KEYBOARD}" == 1 ]] && render_keyboard
GUESS=$(retrieve_guess)
GUESS=$(retrieve_guess) || { echo -en "${NEWLINE}"; exit 0; }
check_guess "${GUESS}" "${ROW}" ; WIN=$?
# Save before the reveal so quitting or disconnecting can't undo a guess
@@ -83,12 +83,7 @@ function main() {
fi
done
[[ "${BORDER}" == 1 ]] && echo -en "${CLEAR_DOWN}${INDENT}${INDENT}"
echo -en "${CLEAR_LINE}${BOLD}"
for (( i=0; i<WIDTH; i++ )); do
echo -en " ${ANSWER:$i:1} "
done
echo -en "${NEWLINE}${RESET}"
render_answer
if [[ "${ONLINE}" == 1 && "${DAILY_DONE}" != 1 ]]; then
echo "Share/view your game with -> curl \"${URL_BASE}/${RESULT_FILE}\""
@@ -243,29 +238,54 @@ function render_board() {
[[ "${BORDER}" == 1 ]] && echo -e "└─────────────────┘"
}
function render_answer() {
[[ "${BORDER}" == 1 ]] && echo -en "${CLEAR_DOWN}${INDENT}${INDENT}"
echo -en "${CLEAR_LINE}${BOLD}"
for (( i=0; i<WIDTH; i++ )); do
echo -en " ${ANSWER:$i:1} "
done
echo -en "${NEWLINE}${RESET}"
}
# Exits non-zero when input has ended so the caller can quit
function retrieve_guess() {
if [[ -n $1 ]]; then
read -r -p "${CLEAR_UP1}$1: " GUESS
read -r -p "${CLEAR_UP1}$1: " GUESS || end_of_input
else
read -r -p "${CLEAR_2END}Enter Guess: " GUESS
read -r -p "${CLEAR_2END}Enter Guess: " GUESS || end_of_input
fi
while [[ ${#GUESS} -ne 5 ]] || [[ ! "${GUESS,,}" =~ ^[a-z]{5}$ ]]; do
read -r -p "${CLEAR_UP1}Must be 5 letters: " GUESS
done
read -r -p "${CLEAR_UP1}Must be 5 letters: " GUESS || end_of_input
done
declare valid_guess
validate_guess "${GUESS}" ; valid_guess=$?
[[ ${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")
declare message
declare -r pos="${HARD_MODE_POS}"
declare -r letter="${GUESS:pos:1}"
declare -ra ordinals=(1st 2nd 3rd 4th 5th)
[[ ${valid_guess} == 1 ]] && message="Not A Valid Word"
[[ ${valid_guess} == 3 ]] && message="${ordinals[pos]} letter must be ${greens[pos]}"
[[ ${valid_guess} == 4 ]] && message="Must contain ${yellows[pos]}"
[[ ${valid_guess} == 5 ]] && message="${letter^^} is not in the word"
[[ ${valid_guess} == 6 ]] && message="${ordinals[pos]} letter can't be ${letter^^}"
if [[ -n "${message}" ]]; then
GUESS=$(retrieve_guess "${message}") || exit 1
fi
echo -n "${GUESS^^}"
}
# Called when read gets Ctrl-D. On a terminal treat it like Enter, but if
# input has really ended (closed pipe) exit, or the retry loop spins forever
function end_of_input() {
[[ -t 0 ]] || exit 1
# Ctrl-D doesn't move to a new line like Enter, which the prompts expect
echo -en "${NEWLINE}" >&2
}
function render_keyboard() {
declare pos=$(( BORDER*2+7 ))
echo -en "${RESET}\e[$pos;0H"
@@ -306,6 +326,8 @@ function hard_mode_check() {
declare GUESS=$1
for (( i=0; i<WIDTH; i++ )); do
HARD_MODE_POS=$i # letter position that failed, for the error message
if [[ "${STRICT_HARD_MODE}" == 1 ]]; then
[[ "${POOL}" == *${GUESS:i:1}* ]] || return 5
fi
@@ -321,7 +343,7 @@ function hard_mode_check() {
for (( r=ROW-1; r>=0; r-- )); do
CHAR="${GUESS:i:1}"
PREV_CHAR="${YELLOWS[$r,$i]}"
[[ "${CHAR}" == "${PREV_CHAR}" ]] && return 4
[[ "${CHAR}" == "${PREV_CHAR}" ]] && return 6
done
done
@@ -432,19 +454,13 @@ function save_game() {
function save_result() {
[[ "${ONLINE}" == 0 ]] && return 0
[[ "${ONLINE}" == 1 ]] && update_stats
if [[ "${ONLINE}" == 1 ]] && [[ "${DAILY_DONE}" != 1 ]]; then
update_stats
render_board > "${RESULT_FILE}"
render_board > "${CUR_RESULT_FILE}"
if [[ $WIN != 5 ]]; then
[[ "${BORDER}" == 1 ]] && echo -en "${CLEAR_DOWN}${INDENT}${INDENT}" >> "${RESULT_FILE}"
echo -en "${CLEAR_LINE}${BOLD}" >> "${RESULT_FILE}"
for (( i=0; i<WIDTH; i++ )); do
echo -en " ${ANSWER:$i:1} " >> "${RESULT_FILE}"
echo -en " ${ANSWER:$i:1} " >> "${CUR_RESULT_FILE}"
done
echo -en "${NEWLINE}${RESET}" >> "${RESULT_FILE}"
echo -en "${NEWLINE}${RESET}" >> "${CUR_RESULT_FILE}"
render_answer >> "${RESULT_FILE}"
render_answer >> "${CUR_RESULT_FILE}"
fi
fi
echo 'PLAYED=1' > "${PROGRESS_FILE}"