21 game

You are encouraged to solve this task according to the task description, using any language you may know.
21 is a two player game, the game is played by choosing
a number (1, 2, or 3) to be added to the running total.

The game is won by the player whose chosen number causes the running total
to reach exactly 21.

The running total starts at zero.
One player will be the computer.

Players alternate supplying a number to be added to the running total.



Task

Write a computer program that will:

 do the prompting (or provide a button menu), 
 check for errors and display appropriate error messages, 
 do the additions (add a chosen number to the running total), 
 display the running total, 
 provide a mechanism for the player to quit/exit/halt/stop/close the program,
 issue a notification when there is a winner, and
 determine who goes first (maybe a random or user choice, or can be specified when the game begins). 


shopt -s expand_aliases
alias bind_variables='
{
  local -ri goal_count=21
  local -ri player_human=0
  local -ri player_computer=1
  local -i turn=1
  local -i total_count=0
  local -i input_number=0
  local -i choose_turn=0
}
'
whose_turn() {
  case $(( ( turn + choose_turn ) % 2 )) in
   ${player_human}) echo "player";;
   ${player_computer}) echo "computer";;
  esac
}
next_turn() {
  let turn++
}
validate_number() {
  ! test ${input_number} -ge 1 -a ${input_number} -le $( max_guess )
}
prompt_number() {
  local prompt_str
  test $( max_guess ) -eq 1 && {
    prompt_str="enter the number 1 to win"
  true
  } || {
    prompt_str="enter a number between 1 and $( max_guess )"
  }
  while [ ! ]
  do
   read -p "${prompt_str} (or quit): "
   input_number=${REPLY}
   case ${REPLY} in
    "quit") {
      false
      return
    } ;;
   esac
   validate_number || break
   echo "try again"
  done
}
update_count() {
  let total_count+=input_number
}
remaining_count() {
  echo $(( goal_count - total_count ))
}
max_guess() {
  local -i remaining_count
  remaining_count=$( remaining_count )
  case $( remaining_count ) in
    1|2|3) echo ${remaining_count} ;;
    *) echo 3 ;;
  esac
}
iter() {
  update_count
  next_turn
}
on_game_over() {
  test ! ${input_number} -eq $( remaining_count ) || {
    test ! "$( whose_turn )" = "player" && {
      echo -ne "\nYou won!\n\n"
    true
    } || {
      echo -ne "\nThe computer won!\nGAME OVER\n\n"
    }
    false
  }
}
on_game_start() {
  echo 21 Game
  read -p "Press enter key to start"
}
choose_turn() {
  let choose_turn=${RANDOM}%2
}
choose_number() {
  local -i remaining_count
  remaining_count=$( remaining_count )
  case ${remaining_count} in
   1|2|3) {  
     input_number=${remaining_count}
   } ;;
   5|6|7) {  
     let input_number=remaining_count-4
   } ;;
   *) {  
     let input_number=${RANDOM}%$(( $( max_guess ) - 1 ))+1
   }
  esac
}
game_play() {
  choose_turn
  while [ ! ]
  do
    echo "Total now ${total_count} (remaining: $( remaining_count ))"
    echo -ne "Turn: ${turn} ("
    test ! "$( whose_turn )" = "player" && {
      echo -n "Your"
    true
    } || {
      echo -n "Computer"
    }
    echo " turn)"
    test ! "$( whose_turn )" = "player" && {
      prompt_number || break
    true
    } || {
      choose_number
      sleep 2
      echo "Computer chose ${input_number}"
    }
    on_game_over || break
    sleep 1
    iter
  done
}
21_Game() {
  bind_variables
  on_game_start
  game_play
}
if [ ${#} -eq 0 ] 
then
 true
else
 exit 1
fi
21_Game
 