Compare commits

...
Author SHA1 Message Date
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
adam 3487adf34c exit save_result if not in online mode
Deploy game to server / deploy (push) Successful in 30s
2025-04-23 21:22:03 +00:00
adam 2194d495e6 extra file for current board
Deploy game to server / deploy (push) Successful in 42s
2025-03-03 12:07:43 +00:00
adam 005a129919 change help message format
Deploy game to server / deploy (push) Successful in 6s
2025-02-22 20:00:30 +00:00
adam bdb3d4e4d1 Move signal trap initialization after game mode questions - Prevent progress files after incorrect username 2025-02-22 19:41:46 +00:00
adam 6bbcc5229b save progress at start of a game 2025-02-22 19:38:06 +00:00
adam 4029c00edc remove $ where not needed 2025-02-22 19:22:45 +00:00
adam 8327678209 only show board on daily win
Deploy game to server / deploy (push) Successful in 6s
2025-02-21 13:21:04 +00:00
adam d496319361 Add guess count out of 6 on win
Deploy game to server / deploy (push) Successful in 7s
2025-02-21 13:12:19 +00:00
adam 107fd30b00 print spoiler free board after a game 2025-02-21 13:07:03 +00:00
adam 0a5d0be050 change spacing on math
Deploy game to server / deploy (push) Successful in 7s
2025-02-20 12:50:17 +00:00
adam 357c74cf08 calculate average guesses and fix divide by 0 bug
Deploy game to server / deploy (push) Successful in 8s
2025-02-16 17:05:57 +00:00
adam e138f71a62 start games played at 0
Deploy game to server / deploy (push) Successful in 6s
2025-02-14 16:31:02 +00:00
adam 064b85aac2 add 1 to graph axis to match number of guesses
Deploy game to server / deploy (push) Successful in 7s
2025-02-14 16:27:01 +00:00
adam fba5cc07ae fix pool issue bug
Deploy game to server / deploy (push) Successful in 5s
2025-02-14 16:14:31 +00:00
adam ce2a14fbe6 track stat
Deploy game to server / deploy (push) Successful in 6s
2025-02-14 16:00:39 +00:00
adam 138c254591 initalise stats to 0 and always update
Deploy game to server / deploy (push) Successful in 7s
2025-02-14 14:43:07 +00:00
adam dfe8ea7f13 track user stats 2025-02-14 14:05:45 +00:00
adam 1ee78db9bf only print share URL after daily wordle
Deploy game to server / deploy (push) Successful in 7s
2025-02-13 23:43:14 +00:00
adam da696e5df2 display share URL with online mode
Deploy game to server / deploy (push) Successful in 7s
2025-02-13 23:37:03 +00:00
adam 00490f53c7 Merge branch 'feature/online_mode'
Deploy game to server / deploy (push) Successful in 7s
2025-02-12 19:42:35 +00:00
adam 8d92cfe57d fix strict hard mode pool bug with double letters 2025-02-12 19:21:14 +00:00
adam a7a19d33b6 uncomment epoch thing 2025-02-12 13:50:06 +00:00
adam 2dc552c74e after daily word complete new words can be played 2025-02-12 13:36:01 +00:00
adam 556c1ec598 working, may still be bugs 2025-02-12 11:30:38 +00:00
adam ab97bcea65 resume partially working 2025-02-11 20:43:28 +00:00
adam 7d14d5dae9 use proper newline
Deploy game to server / deploy (push) Successful in 7s
2025-02-11 19:57:08 +00:00
adam f73667b6a9 change format order 2025-02-10 19:12:35 +00:00
adam 47ab1d243e only bold for letters 2025-02-10 16:38:47 +00:00
adam 1cbdfe5858 go to start of terminal outside of render board 2025-02-10 16:24:28 +00:00
adam 31a7332af1 divide instead to get number of day since epoch
Deploy game to server / deploy (push) Successful in 8s
2025-02-10 16:09:13 +00:00
adam 7c3b695737 output user results
Deploy game to server / deploy (push) Successful in 6s
2025-02-10 16:00:30 +00:00
adam e6b5a3da7a Interactive prompt for online mode
Deploy game to server / deploy (push) Successful in 6s
2025-02-10 13:05:06 +00:00
adam c530058c9b hard mode now check all previous rounds for yellow placement
Deploy game to server / deploy (push) Successful in 7s
2025-02-10 13:00:11 +00:00
adam fa2fdf80b7 fix filename
Deploy game to server / deploy (push) Successful in 5s
2025-02-08 20:12:34 +00:00
adam 2ff11722b4 add deploy workflow
Deploy game to server / deploy (push) Failing after 4s
2025-02-08 20:11:31 +00:00
adam 26e4eeb356 remove output 2025-02-07 16:19:06 +00:00
adam 7e280ce64b fix win logic error 2025-02-07 15:39:05 +00:00
adam 0cf5a68052 reset before restoring cursor position 2025-02-07 15:26:06 +00:00
adam 6733031ed9 test fix for mac terminal 2025-02-07 15:20:40 +00:00
adam 9745876be1 remove extra space 2025-01-30 00:07:47 +00:00
adam 5640a28b5b remove unused variable 2025-01-30 00:06:17 +00:00
adam cf7f5da7e5 keyboard toggle option 2025-01-29 22:41:04 +00:00
adam 2ee79b85db basic keyboard function 2025-01-29 22:41:04 +00:00
adam 1e6942c5b7 combine into one line 2025-01-29 21:21:24 +00:00
adam b31e0442e3 save correct position 2025-01-29 21:21:24 +00:00
adam 9218601b52 fix logic for hard mode and strict hard mode
Reviewed-on: #2
2025-01-29 13:19:30 +00:00
adam c925f66e4d Debug mode to remove delay on letter reveal 2025-01-28 18:17:50 +00:00
adam 828c9190b1 clear screen after options are processed 2025-01-28 18:05:20 +00:00
adam 8122eab5b4 strict hard mode and help message 2025-01-27 09:20:10 +00:00
adam a179fed550 Initial implementation of hard mode 2025-01-27 08:46:12 +00:00
adam 0c2b212c72 reorder function declaration order 2025-01-26 21:09:58 +00:00
adam 22a02a6dcf set execute permission 2025-01-22 23:15:56 +00:00
adam 88a4761538 fix win condition 2025-01-22 20:33:49 +00:00
adam 08f51a6a92 change spacing of text on loss 2025-01-22 17:54:21 +00:00
2 changed files with 492 additions and 118 deletions

No files matched your search

+30
View File
@@ -0,0 +1,30 @@
name: Deploy game to server
on:
workflow_dispatch: # Allows manual execution
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H "${{ vars.REMOTE_SERVER }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: Transfer file via SCP
run: |
scp -i ~/.ssh/id_rsa wordle ${{ vars.REMOTE_USER }}@${{ vars.REMOTE_SERVER }}:${{ vars.REMOTE_DEST }}
- name: Clean up SSH key
run: rm -rf ~/.ssh
Regular → Executable
+462 -118
View File
@@ -6,98 +6,89 @@ declare -gr HEIGHT=6
declare -gr LETTER=$'\e[97m' declare -gr LETTER=$'\e[97m'
declare -gr GREY=$'\e[48;5;8m' declare -gr GREY=$'\e[48;5;8m'
declare -gr GREEN=$'\e[48;5;10m' declare -gr GREEN=$'\e[48;5;10m'
declare -gr LETTER_GR=$'\e[32m'
declare -gr YELLOW=$'\e[48;5;3m' declare -gr YELLOW=$'\e[48;5;3m'
declare -gr RESET=$'\e[0m' declare -gr RESET=$'\e[0m'
declare -gr BOLD=$'\e[1m' declare -gr BOLD=$'\e[1m'
declare -gr CLEAR_LINE=$'\e[1F\e[K' declare -gr UNBOLD=$'\e[22m'
declare -gr CLEAR_UP1=$'\e[1F\e[K'
declare -gr CLEAR_LINE=$'\e[K'
declare -gr CLEAR_2END=$'\e[0K' declare -gr CLEAR_2END=$'\e[0K'
declare -gr CLEAR_SCREEN=$'\e[H\e[J' declare -gr CLEAR_SCREEN=$'\e[H\e[J'
declare -gr CLEAR_DOWN=$'\e[0J'
declare -gr NEWLINE=$'\n'
declare -gr SAVE=$'\e[s' declare -gr SAVE=$'\e[s'
declare -gr RESTORE=$'\e[u' declare -gr RESTORE=$'\e[u'
declare -gr UP1=$'\e[1F' declare -gr UP1=$'\e[1F'
declare -gr HIDE_CURSOR=$'\e[?25l' declare -gr HIDE_CURSOR=$'\e[?25l'
declare -gr SHOW_CURSOR=$'\e[?25h' declare -gr SHOW_CURSOR=$'\e[?25h'
declare -gr GOHOME=$'\e[H' declare -gr GOHOME=$'\e[H'
declare -gr DOWN1=$'\e[1E' declare -gr INDENT=$'\e[1C'
function reveal_row() { function main() {
echo -en "${SAVE}"
echo -en "${HIDE_CURSOR}"
# Must increment by 1 Row as 0 == 1 for escape code
declare RNUM=$(( $1+1+BORDER ))
declare OFFSET=$(( BORDER * 3 ))
echo -en "\e[${RNUM};${OFFSET}H" declare -Ag BOARD
for (( C=0; C<WIDTH; C++ )); do declare -g ROW=0
echo -n "${BOARD[$1,$C]}" declare -g WIN=0
read -r -s -t 0.5 declare -g ANSWER
done declare -g POOL='QWERTYUIOPASDFGHJKLZXCVBNM'
echo -en "${SHOW_CURSOR}" declare -Ag YELLOWS
echo -en "${RESTORE}${UP1}" ANSWER=$(select_random_word)
}
function check_guess() { set_options "$@"
declare -r _guess=$1
declare -r _row=$2
declare -r _answer="${ANSWER}"
declare green_count=0
declare chars=""
for (( i=0; i<WIDTH; i++ )); do echo -en "${CLEAR_SCREEN}"
[[ "${_answer:i:1}" != "${_guess:i:1}" ]] && chars+=${_answer:i:1} echo -en "${GOHOME}"
done
for (( c=0; c<WIDTH; c++ )); do if [[ "${RESUME}" == 1 ]]; then
BOARD[$_row,$c]="${BOLD}${LETTER}${GREY} ${_guess:$c:1} " load_game
if [[ "${PLAYED}" == 1 ]] && [[ "${IN_PROGRESS}" != 1 ]]; then
declare _char=${_guess:$c:1} ANSWER=$(select_random_word)
init_board
if [[ "${_char}" == "${_answer:$c:1}" ]]; then
green_count=$(( green_count+1 ))
BOARD[$_row,$c]="${BOLD}${LETTER}${GREEN} ${_char} "
[[ $green_count == 5 ]] && return 5
continue
fi fi
if [[ "${chars}" == *${_char}* ]]; then
chars="${chars/${_char}/}"
BOARD[$_row,$c]="${BOLD}${LETTER}${YELLOW} ${_char} "
fi
done
}
function validate_guess() {
declare GUESS=$1
for WORD in ${VALID_GUESSES}; do
if [[ "${WORD}" == "${GUESS,,}" ]]; then
return 0
fi
done
return 1
}
function retrive_guess() {
if [[ -n $1 ]]; then
read -r -p "${CLEAR_LINE}$1: " GUESS
else else
read -r -p "${CLEAR_2END}Enter Guess: " GUESS init_board
fi fi
while [[ ${#GUESS} -ne 5 ]] || [[ ! "${GUESS,,}" =~ ^[a-z]{5}$ ]]; do [[ "${ONLINE}" == 1 ]] && save_game "NO_EXIT"
read -r -p "${CLEAR_LINE}Must be 5 letters: " GUESS
done
declare valid_guess render_board
validate_guess "${GUESS}" &
declare validation_pid=$!
wait $validation_pid
valid_guess=$?
[[ ${valid_guess} != 0 ]] && GUESS=$(retrive_guess "Not A Valid Word") for (( ROW; ROW<HEIGHT; ROW++ )); do
declare GUESS
[[ "${KEYBOARD}" == 1 ]] && render_keyboard
GUESS=$(retrieve_guess)
check_guess "${GUESS}" "${ROW}" ; WIN=$?
echo -n "${GUESS^^}" 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}\""
while read -r board_line; do echo "${board_line//[A-Z]/ }"; done < "${RESULT_FILE}"
fi
echo "Guess - $(( ROW+1 ))/6"
exit 0
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}"
save_result
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}\""
while read -r board_line; do echo "${board_line//[A-Z]/ }"; done < "${RESULT_FILE}"
fi
exit 0
} }
function select_random_word() { function select_random_word() {
@@ -106,37 +97,17 @@ function select_random_word() {
echo "${answers[random_index]^^}" echo "${answers[random_index]^^}"
} }
function render_board() {
echo -en "${GOHOME}"
declare row
declare char
[[ "${BORDER}" == 1 ]] && echo -e "┌─────────────────┐"
for (( row=0; row<HEIGHT; row++ )); do
[[ "${BORDER}" == 1 ]] && echo -en "│ "
for (( char=0; char<WIDTH; char++ )); do
echo -n "${BOARD[${row},${char}]}${RESET}"
done
[[ "${BORDER}" == 1 ]] && echo -en " │ "
echo -en "${DOWN1}"
done
[[ "${BORDER}" == 1 ]] && echo -e "└─────────────────┘"
}
function init_board() {
declare -Ag BOARD
for (( row=0; row<HEIGHT; row++ )); do
for (( char=0; char<WIDTH; char++ )); do
BOARD[${row},${char}]="${GREY} "
done
done
}
function set_options() { function set_options() {
declare -g BORDER=1
while getopts "bw:h" OPT; do declare -g BORDER=1
declare -g HARD_MODE=0
declare -g STRICT_HARD_MODE=0
declare -g DELAY=0.5
declare -g KEYBOARD=1
declare -g ONLINE=0
declare -g RESUME=0
while getopts "bw:HSkodh" OPT; do
case "${OPT}" in case "${OPT}" in
b) b)
BORDER=0 BORDER=0
@@ -149,40 +120,413 @@ function set_options() {
exit 1 exit 1
fi fi
;; ;;
H)
HARD_MODE=1
;;
S)
HARD_MODE=1
STRICT_HARD_MODE=1
;;
k)
KEYBOARD=0
;;
o)
ONLINE=1
declare -gr URL_BASE="https://www.adbraun.lol/wordle"
echo -en "${CLEAR_SCREEN}"
declare -g USER
read -r -p "Username: " USER
USER="${USER,,}"
declare -g DAY
DAY=$(( EPOCHSECONDS / 86400 ))
declare -gr PROGRESS_FILE=".${USER}-${DAY}.progress"
declare -gr RESULT_FILE="${USER}-${DAY}.board"
declare -gr CUR_RESULT_FILE="${USER}.board"
declare -gr STATS_SOURCE=".${USER}.stats"
declare -gr STATS_FILE="${USER}.stats"
if [[ -f "${PROGRESS_FILE}" ]] && [[ -s "${PROGRESS_FILE}" ]]; then
load_game
RESUME=1
[[ "${PLAYED}" == 1 ]] && declare -g DAILY_DONE=1
fi
if [[ -z "${IN_PROGRESS}" ]]; then
declare HM
read -r -p "Do you want to enable hard mode [y/N]? " -n 1 HM
if [[ "${HM}" =~ ^[Yy]$ ]]; then
HARD_MODE=1
echo -en "${NEWLINE}"
read -r -p "Do you want to enable strict hard mode [y/N]? " -n 1 HM
[[ "${HM}" =~ ^[Yy]$ ]] && STRICT_HARD_MODE=1
fi
fi
trap save_game SIGINT
;;
d)
DELAY=0
;;
h) h)
exit # add help message echo -e \
"Usage: <program_name> [OPTIONS]
Play a game for Wordle
Options:
-b Toggle borderless mode
-w Set target word
-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"
exit
;; ;;
*) *)
;; ;;
esac esac
done done
shift $((OPTIND - 1))
} }
function main() { function init_board() {
echo -en "${CLEAR_SCREEN}" for (( row=0; row<HEIGHT; row++ )); do
declare -g ANSWER for (( char=0; char<WIDTH; char++ )); do
ANSWER=$(select_random_word) BOARD[${row},${char}]="${GREY} "
done
done
}
set_options "$@" function render_board() {
init_board
render_board
declare row declare row
for (( row=0; row<HEIGHT; row++ )); do declare char
declare GUESS
GUESS=$(retrive_guess)
check_guess "${GUESS}" "${row}"
win=$?
reveal_row "${row}" [[ "${BORDER}" == 1 ]] && echo -e "┌─────────────────┐"
[[ $win == 5 ]] && echo -e "\n${CLEAR_LINE}YOU WIN" && exit 0 for (( row=0; row<HEIGHT; row++ )); do
[[ "${BORDER}" == 1 ]] && echo -en "│ "
for (( char=0; char<WIDTH; char++ )); do
echo -n "${BOARD[${row},${char}]}${RESET}"
done
[[ "${BORDER}" == 1 ]] && echo -en " │"
echo -en "${NEWLINE}"
done
[[ "${BORDER}" == 1 ]] && echo -e "└─────────────────┘"
}
function retrieve_guess() {
if [[ -n $1 ]]; then
read -r -p "${CLEAR_UP1}$1: " GUESS
else
read -r -p "${CLEAR_2END}Enter Guess: " GUESS
fi
while [[ ${#GUESS} -ne 5 ]] || [[ ! "${GUESS,,}" =~ ^[a-z]{5}$ ]]; do
read -r -p "${CLEAR_UP1}Must be 5 letters: " GUESS
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")
echo -n "${GUESS^^}"
}
function render_keyboard() {
declare pos=$(( BORDER*2+7 ))
echo -en "${RESET}\e[$pos;0H"
for (( i=0; i<${#POOL}; i++ )); do
if [[ $i == 10 ]]; then
echo -en "${NEWLINE}${INDENT}"
elif [[ $i == 19 ]]; then
echo -en "${NEWLINE} "
fi
echo -n "${POOL:$i:1} "
done
echo -en "${NEWLINE}"
}
function validate_guess() {
declare GUESS=$1
for WORD in ${VALID_GUESSES}; do
if [[ "${WORD}" == "${GUESS,,}" ]]; then
if [[ "${HARD_MODE}" == 1 ]]; then
hard_mode_check "${GUESS^^}" || return $?
fi
return 0
fi
done done
result="${ANSWER//?/& }" return 1
result=${result%} }
echo -e "\n${CLEAR_LINE}YOU LOSE\n${result} ${RESET}" && exit 0
function hard_mode_check() {
[[ -z "${ROW}" || "${ROW}" == 0 ]] && return 0
declare GUESS=$1
for (( i=0; i<WIDTH; i++ )); do
if [[ "${STRICT_HARD_MODE}" == 1 ]]; then
[[ "${POOL}" == *${GUESS:i:1}* ]] || return 5
fi
if [[ -n "${greens[i]}" ]]; then
[[ "${greens[i]}" != "${GUESS:i:1}" ]] && return 3
fi
if [[ -n "${yellows[i]}" ]]; then
[[ ! "${GUESS}" == *"${yellows[i]}"* ]] && return 4
fi
for (( r=ROW-1; r>=0; r-- )); do
CHAR="${GUESS:i:1}"
PREV_CHAR="${YELLOWS[$r,$i]}"
[[ "${CHAR}" == "${PREV_CHAR}" ]] && return 4
done
done
return 0
}
function check_guess() {
declare -r _guess=$1
declare -r _row=$2
declare -r _answer="${ANSWER}"
declare chars=""
declare -ga yellows=()
declare -ga greens=()
for (( i=0; i<WIDTH; i++ )); do
[[ "${_answer:i:1}" != "${_guess:i:1}" ]] && chars+=${_answer:i:1}
done
for (( c=0; c<WIDTH; c++ )); do
BOARD[$_row,$c]="${GREY}${BOLD}${LETTER} ${_guess:$c:1} ${UNBOLD}"
declare _char=${_guess:$c:1}
if [[ "${_char}" == "${_answer:$c:1}" ]]; then
greens[c]="${_char}"
BOARD[$_row,$c]="${GREEN}${BOLD}${LETTER} ${_char} ${UNBOLD}"
continue
fi
if [[ "${chars}" == *${_char}* ]]; then
chars="${chars/${_char}/}"
yellows[c]="${_char}" # volatile - stores previous row yellows
YELLOWS[$_row,$c]="${_char}" # stores all yellow from all rounds
BOARD[$_row,$c]="${YELLOW}${BOLD}${LETTER} ${_char} ${UNBOLD}"
fi
[[ "${ANSWER}" =~ ${_char} ]] && continue
[[ " ${yellows[*]} " =~ ${_char} ]] && continue
[[ " ${greens[*]} " =~ ${_char} ]] && continue
POOL="${POOL/${_char}/_}"
done
[[ "${#greens[*]}" == 5 ]] && return 5
}
function reveal_row() {
echo -en "${UP1}${SAVE}"
echo -en "${HIDE_CURSOR}"
# Must increment by 1 Row as 0 == 1 for escape code
declare RNUM=$(( $1+1+BORDER ))
declare OFFSET=$(( BORDER * 3 ))
echo -en "\e[${RNUM};${OFFSET}H"
for (( C=0; C<WIDTH; C++ )); do
echo -n "${BOARD[$1,$C]}"
read -r -s -t $DELAY
done
echo -en "${SHOW_CURSOR}${RESET}${RESTORE}"
}
function load_game() {
# shellcheck source=/dev/null
source "${PROGRESS_FILE}"
}
# shellcheck disable=SC2317 # Don't warn about unreachable commands in this function
function save_game() {
: > "${PROGRESS_FILE}"
for key in "${!BOARD[@]}"; do
echo "BOARD[$key]='${BOARD[$key]}'" >> "${PROGRESS_FILE}"
done
for key in "${!BOARD[@]}"; do
echo "YELLOWS[$key]='${YELLOWS[$key]}'" >> "${PROGRESS_FILE}"
done
{
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'
} >> "${PROGRESS_FILE}"
echo -en "${RESET}"
[[ -z $1 ]] && exit 0
}
function save_result() {
[[ "${ONLINE}" == 0 ]] && return 0
[[ "${ONLINE}" == 1 ]] && update_stats
if [[ "${ONLINE}" == 1 ]] && [[ "${DAILY_DONE}" != 1 ]]; then
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}"
fi
fi
echo 'PLAYED=1' > "${PROGRESS_FILE}"
}
function update_stats() {
if [[ -f "${STATS_SOURCE}" ]]; then
# shellcheck source=/dev/null
source "${STATS_SOURCE}"
else
create_stats
# shellcheck source=/dev/null
source "${STATS_SOURCE}"
fi
GAMES_PLAYED=$(( GAMES_PLAYED+1 ))
[[ $WIN == 5 ]] && WINS=$(( WINS+1 ))
[[ $WIN != 5 ]] && LOSSES=$(( LOSSES+1 ))
[[ $WIN == 5 ]] && SCORE="${GAME_HIST[$ROW]}"
[[ $WIN == 5 ]] && SCORE=$(( SCORE+1 ))
[[ $WIN == 5 ]] && GAME_HIST[ROW]="${SCORE}"
[[ $WIN == 5 ]] && STREAK=$(( STREAK+1 ))
[[ $WIN != 5 ]] && STREAK=0
[[ $LONGEST_STREAK -lt $STREAK ]] && LONGEST_STREAK=$(( LONGEST_STREAK+1 ))
declare num=0
declare den=0
for (( i=0; i<${#GAME_HIST[@]}; i++)); do
(( den += ${GAME_HIST[$i]} ))
(( num += ${GAME_HIST[$i]}*(i+1) ))
done
if [[ "${den}" != 0 ]]; then
result=$(( (num * 100) / den ))
integer_part=$(( result / 100 ))
decimal_part=$(( result % 100 ))
AVERAGE="${integer_part}.${decimal_part}"
fi
: > "${STATS_SOURCE}"
{
echo "GAMES_PLAYED=${GAMES_PLAYED}"
echo "WINS=${WINS}"
echo "LOSSES=${LOSSES}"
echo "GAME_HIST=(${GAME_HIST[*]})"
echo "STREAK=${STREAK}"
echo "LONGEST_STREAK=${LONGEST_STREAK}"
echo "AVERAGE=${AVERAGE}"
} >> "${STATS_SOURCE}"
render_stats
}
function create_stats() {
{
echo "GAMES_PLAYED=0"
echo "WINS=0"
echo "LOSSES=0"
echo "GAME_HIST=(0 0 0 0 0 0)"
echo "STREAK=0"
echo "LONGEST_STREAK=0"
echo "AVERAGE=0"
} >> "${STATS_SOURCE}"
}
function render_stats() {
[[ -f "${STATS_SOURCE}" ]] || return
# shellcheck source=/dev/null
# https://www.shellcheck.net/wiki/SC1091 https://www.shellcheck.net/wiki/SC1090
source "${STATS_SOURCE}"
declare highest=0
declare -r max_width=20
declare axis
for (( i=0; i<HEIGHT; i++ )); do
[[ "${GAME_HIST[$i]}" -gt "${highest}" ]] && highest="${GAME_HIST[$i]}"
done
for (( i=0; i<HEIGHT; i++ )); do
value="${GAME_HIST[$i]}"
if [[ "${highest}" == 0 ]]; then
bar_length=0
else
bar_length=$(( value * max_width / highest ))
fi
bar='▇'
for (( j=0; j<bar_length; j++)); do
bar+='▇'
done
axis=$(( i+1 ))
if [[ "${ROW}" == "${i}" ]]; then
echo "$axis│${LETTER_GR}$bar${RESET} $value"
else
echo "$axis│$bar $value"
fi
done > "${STATS_FILE}"
{
echo
echo "Played: ${GAMES_PLAYED}"
echo "Wins: ${WINS}"
echo "Losses: ${LOSSES}"
echo "Streak: ${STREAK}"
echo "Longest Streak: ${LONGEST_STREAK}"
echo "Average: ${AVERAGE}"
} >> "${STATS_FILE}"
} }
declare -gr VALID_GUESSES="aahed aalii aapas aargh aarti abaca abaci aback abacs abaft abaht abaka abamp aband abase abash abask abate abaya abbas abbed abbes abbey abbot abcee abeam abear abeat abeer abele abeng abers abets abeys abhor abide abies abius abjad abjud abled abler ables ablet ablow abmho abnet abode abohm aboil aboma aboon abord abore aborn abort about above abram abray abrim abrin abris absey absit abuna abune abura aburn abuse abuts abuzz abyes abysm abyss acais acara acari accas accha accoy accra acedy acene acerb acers aceta achar ached acher aches achey achoo acids acidy acies acing acini ackee acker acmes acmic acned acnes acock acoel acold acone acorn acral acred acres acrid acron acros acryl actas acted actin acton actor actus acute acyls adage adapt adats adawn adaws adays adbot addas addax added adder addin addio addle addra adead adeem adept adhan adhoc adieu adios adits adlib adman admen admin admit admix adnex adobe adobo adoon adopt adorb adore adorn adown adoze adrad adraw adred adret adrip adsum aduki adult adunc adust advew advts adyta adyts adzed adzes aecia aedes aeger aegis aeons aerie aeros aesir aevum afald afanc afara afars afear affix affly afion afire afizz aflaj aflap aflow afoam afoot afore afoul afret afrit afros after aftos again agals agama agami agamy agape agars agasp agast agate agaty agave agaze agbas agene agent agers aggag agger aggie aggri aggro aggry aghas agidi agila agile aging agios agism agist agita aglee aglet agley agloo aglow aglus agmas agoge agogo agone agons agony agood agora agree agria agrin agros agrum agued agues aguey aguna agush aguti ahead aheap ahent ahigh ahind ahing ahint ahold ahole ahull ahuru aidas aided aider aides aidoi aidos aiery aigas aight ailed aimag aimak aimed aimer ainee ainga aioli aired airer airns airth airts aisle aitch aitus aiver aixes aiyah aiyee aiyoh aiyoo aizle ajies ajiva ajuga ajupa ajwan akara akees akela akene aking akita akkas akker akoia akoja akoya aksed akses alaap alack alala alamo aland alane alang alans alant alapa alaps alarm alary alata alate alays albas albee albid album alcea alces alcid alcos aldea alder aldol aleak aleck alecs aleem alefs aleft aleph alert alews aleye alfas algae algal algas algid algin algor algos algum alias alibi alick alien alifs align alike alims aline alios alist alive aliya alkie alkin alkos alkyd alkyl allan allay allee allel allen aller alley allin allis allod allot allow alloy allus allyl almah almas almeh almes almud almug alods aloed aloes aloft aloha aloin alone along aloof aloos alose aloud alowe alpha altar alter altho altos alula alums alumy alure alurk alvar alway amahs amain amari amaro amass amate amaut amaze amban amber ambit amble ambos ambry ameba ameer amend amene amens ament amias amice amici amide amido amids amies amiga amigo amine amino amins amirs amiss amity amlas amman ammas ammon ammos amnia amnic amnio amoks amole among amore amort amour amove amowt amped ample amply ampul amrit amuck amuse amyls anana anata ancho ancle ancon andic andro anear anele anent angas angel anger angle anglo angry angst anigh anile anils anima anime animi anion anise anker ankhs ankle ankus anlas annal annan annas annat annex annoy annul annum annus anoas anode anole anomy ansae ansas antae antar antas anted antes antic antis antra antre antsy anura anvil anyon aorta apace apage apaid apart apayd apays apeak apeek apers apert apery apgar aphid aphis apian aping apiol apish apism apnea apode apods apols apoop aport appal appam appay appel apple apply appro appts appui appuy apres apron apses apsis apsos apted apter aptly aquae aquas araba araks arame arars arbah arbas arbor arced archi arcos arcus ardeb ardor ardri aread areae areal arear areas areca aredd arede arefy areic arena arene arepa arere arete arets arett argal argan argil argle argol argon argot argue argus arhat arias ariel ariki arils ariot arise arish arith arked arled arles armed armer armet armil armor arnas arnis arnut aroba aroha aroid aroma arose arpas arpen arrah arras array arret arris arrow arroz arsed arses arsey arsis arson artal artel arter artic artis artly artsy aruhe arums arval arvee arvos aryls asada asana ascon ascot ascus asdic ashed ashen ashes ashet aside asity askar asked asker askew askoi askos aspen asper aspic aspie aspis aspro assai assam assay assed asses asset assez assot aster astir astun asura asway aswim asyla ataps ataxy atigi atilt atimy atlas atman atmas atmos atocs atoke atoks atoll atoms atomy atone atony atopy atria atrip attap attar attas atter attic atuas aucht audad audax audio audit augen auger auges aught augur aulas aulic auloi aulos aumil aunes aunts aunty aurae aural aurar auras aurei aures auric auris aurum autos auxin avail avale avant avast avels avens avers avert avgas avian avine avion avise aviso avize avoid avows avyze await awake award aware awari awarn awash awato awave aways awdls aweel aweto awful awing awkin awmry awned awner awoke awols awork axels axiaLine truncated declare -gr VALID_GUESSES="aahed aalii aapas aargh aarti abaca abaci aback abacs abaft abaht abaka abamp aband abase abash abask abate abaya abbas abbed abbes abbey abbot abcee abeam abear abeat abeer abele abeng abers abets abeys abhor abide abies abius abjad abjud abled abler ables ablet ablow abmho abnet abode abohm aboil aboma aboon abord abore aborn abort about above abram abray abrim abrin abris absey absit abuna abune abura aburn abuse abuts abuzz abyes abysm abyss acais acara acari accas accha accoy accra acedy acene acerb acers aceta achar ached acher aches achey achoo acids acidy acies acing acini ackee acker acmes acmic acned acnes acock acoel acold acone acorn acral acred acres acrid acron acros acryl actas acted actin acton actor actus acute acyls adage adapt adats adawn adaws adays adbot addas addax added adder addin addio addle addra adead adeem adept adhan adhoc adieu adios adits adlib adman admen admin admit admix adnex adobe adobo adoon adopt adorb adore adorn adown adoze adrad adraw adred adret adrip adsum aduki adult adunc adust advew advts adyta adyts adzed adzes aecia aedes aeger aegis aeons aerie aeros aesir aevum afald afanc afara afars afear affix affly afion afire afizz aflaj aflap aflow afoam afoot afore afoul afret afrit afros after aftos again agals agama agami agamy agape agars agasp agast agate agaty agave agaze agbas agene agent agers aggag agger aggie aggri aggro aggry aghas agidi agila agile aging agios agism agist agita aglee aglet agley agloo aglow aglus agmas agoge agogo agone agons agony agood agora agree agria agrin agros agrum agued agues aguey aguna agush aguti ahead aheap ahent ahigh ahind ahing ahint ahold ahole ahull ahuru aidas aided aider aides aidoi aidos aiery aigas aight ailed aimag aimak aimed aimer ainee ainga aioli aired airer airns airth airts aisle aitch aitus aiver aixes aiyah aiyee aiyoh aiyoo aizle ajies ajiva ajuga ajupa ajwan akara akees akela akene aking akita akkas akker akoia akoja akoya aksed akses alaap alack alala alamo aland alane alang alans alant alapa alaps alarm alary alata alate alays albas albee albid album alcea alces alcid alcos aldea alder aldol aleak aleck alecs aleem alefs aleft aleph alert alews aleye alfas algae algal algas algid algin algor algos algum alias alibi alick alien alifs align alike alims aline alios alist alive aliya alkie alkin alkos alkyd alkyl allan allay allee allel allen aller alley allin allis allod allot allow alloy allus allyl almah almas almeh almes almud almug alods aloed aloes aloft aloha aloin alone along aloof aloos alose aloud alowe alpha altar alter altho altos alula alums alumy alure alurk alvar alway amahs amain amari amaro amass amate amaut amaze amban amber ambit amble ambos ambry ameba ameer amend amene amens ament amias amice amici amide amido amids amies amiga amigo amine amino amins amirs amiss amity amlas amman ammas ammon ammos amnia amnic amnio amoks amole among amore amort amour amove amowt amped ample amply ampul amrit amuck amuse amyls anana anata ancho ancle ancon andic andro anear anele anent angas angel anger angle anglo angry angst anigh anile anils anima anime animi anion anise anker ankhs ankle ankus anlas annal annan annas annat annex annoy annul annum annus anoas anode anole anomy ansae ansas antae antar antas anted antes antic antis antra antre antsy anura anvil anyon aorta apace apage apaid apart apayd apays apeak apeek apers apert apery apgar aphid aphis apian aping apiol apish apism apnea apode apods apols apoop aport appal appam appay appel apple apply appro appts appui appuy apres apron apses apsis apsos apted apter aptly aquae aquas araba araks arame arars arbah arbas arbor arced archi arcos arcus ardeb ardor ardri aread areae areal arear areas areca aredd arede arefy areic arena arene arepa arere arete arets arett argal argan argil argle argol argon argot argue argus arhat arias ariel ariki arils ariot arise arish arith arked arled arles armed armer armet armil armor arnas arnis arnut aroba aroha aroid aroma arose arpas arpen arrah arras array arret arris arrow arroz arsed arses arsey arsis arson artal artel arter artic artis artly artsy aruhe arums arval arvee arvos aryls asada asana ascon ascot ascus asdic ashed ashen ashes ashet aside asity askar asked asker askew askoi askos aspen asper aspic aspie aspis aspro assai assam assay assed asses asset assez assot aster astir astun asura asway aswim asyla ataps ataxy atigi atilt atimy atlas atman atmas atmos atocs atoke atoks atoll atoms atomy atone atony atopy atria atrip attap attar attas atter attic atuas aucht audad audax audio audit augen auger auges aught augur aulas aulic auloi aulos aumil aunes aunts aunty aurae aural aurar auras aurei aures auric auris aurum autos auxin avail avale avant avast avels avens avers avert avgas avian avine avion avise aviso avize avoid avows avyze await awake award aware awari awarn awash awato awave aways awdls aweel aweto awful awing awkin awmry awned awner awoke awols awork axels axiaLine truncated