declare -a B=( e e e  e e e  e e e )  

function show(){  
  local -i p POS=${1:-9}; local UL BOLD="\e[1m" GREEN="\e[32m" DIM="\e[2m" OFF="\e[m" ULC="\e[4m"
  for p in 0 1 2 3 4 5 6 7 8; do
    [[ p%3 -eq 0 ]] && printf "  "                             
    UL=""; [[ p/3 -lt 2 ]] && UL=$ULC                          
    [[ p -eq POS ]]   && printf "$BOLD$GREEN"                  
    [[ ${B[p]} = e ]] && printf "$UL$DIM%d$OFF" $p || printf "$UL%s$OFF" ${B[p]}  
    { [[ p%3 -lt 2 ]] && printf "$UL | $OFF"; } || printf "\n" 
  done
};

function win(){  
  local ME=$1; local -i p=$2
  [[ ${B[p/3*3]} = $ME && ${B[p/3*3+1]} = $ME && ${B[p/3*3+2]} = $ME ]] && return 0  
  [[ ${B[p]}     = $ME && ${B[(p+3)%9]} = $ME && ${B[(p+6)%9]} = $ME ]] && return 0  
  [[ ${B[4]} != $ME ]] && return 1                                                   
  [[ p%4 -eq 0 && ${B[0]} = $ME && ${B[8]} = $ME ]] && return 0                      
  [[ p%4 -eq 2 || p -eq 4 ]] && [[ ${B[2]} = $ME && ${B[6]} = $ME ]]                 
};

function bestMove(){  
  local ME=$1 OP=$2; local -i o s p
  local -ia S=( -9 -9 -9  -9 -9 -9  -9 -9 -9 )  
  local -a SB                                   
  [[ ${B[*]//[!e]} = "" ]] && return 9          
  SB=( ${B[*]} )                                
  for p in 0 1 2 3 4 5 6 7 8; do                          
    [[ ${B[p]} != e ]] && continue                        
    B[p]=$ME                                              
    win $ME $p && { S[p]=2; B=( ${SB[*]} ); return $p; }  
    bestMove $OP $ME; o=$?                                
    [[ o -le 8 ]] && { B[o]=$OP; win $OP $o; s=$?; }      
    S[p]=${s:-1}                                          
    B=( ${SB[*]} )                                        
  done
  local -i best=-1; local -ia MOV=()
  for p in 0 1 2 3 4 5 6 7 8; do                     
    [[ S[p] -lt 0 ]] && continue                     
    [[ S[p] -eq S[best] ]] && { MOV+=(p); best=p; }  
    [[ S[p] -gt S[best] ]] && { MOV=(p); best=p; }   
  done
  return ${MOV[ RANDOM%${
};

function getMove(){  
  [[ $ME = X ]] && { bestMove $ME $OP; return $?; }     
  read -p "O move: " -n 1; printf "\n"; return $REPLY   
};

function turn(){  
  local -i p; local ME=$1 OP=$2
  getMove; p=$?; [[ p -gt 8 ]] && { printf "Draw!\n"; show; return 1; }  
  B[p]=$ME; printf "%s moves%d\n" $ME $p                                
  win $ME $p && { printf "%s wins!\n" $ME; show $p; [[ $ME = X ]] && return 2; return 0; }
  [[ ${B[*]//[!e]} = "" ]] && { printf "Draw!\n"; show; return 1; }      
  show $p; turn $OP $ME                                                  
};

printf "Bic Bash Bow\n"
show; [[ RANDOM%2 -eq 0 ]] && { turn O X; exit $?; } || turn X O