#!/bin/bash
MAX_H=8
MAX_H_1=$(( MAX_H -1 ))
MAX_W=8
MAX_W_1=$(( MAX_W -1 ))
TOTAL=$(( MAX_H * MAX_W ))
res=$TOTAL
MINUS_NUM=10
cur_x=0
cur_y=0
map=( m m m m m m m m
      m m 0 0 0 0 0 0
      0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0)

map2=( u u u u u u u u
       u u u u u u u u
       u u u u u u u u
       u u u u u u u u
       u u u u u u u u
       u u u u u u u u
       u u u u u u u u
       u u u u u u u u)
draw(){
  tput cup $(($MAX_H+1)) 0
  for(( i=0; i<TOTAL; i+=MAX_W ))
  do
    printf "%s %s %s %s %s %s %s %s\n" "${map[@]:$i:8}"
  done
}
draw2(){
  local c=$(($cur_y * MAX_W + $cur_x))
  tput cup 0 0
  for(( i=0; i<TOTAL; i+=MAX_W ))
  do
    printf "%s %s %s %s %s %s %s %s\n" "${map2[@]:$i:8}"
  done
  tput cup $cur_y $(($cur_x<<1))
  echo -ne "\033[1;47m${map2[$c]}\033[m"
}
random(){
  local tmp i j
  for (( i=0; i<MINUS_NUM; i++))
  do
    (( j = $RANDOM % TOTAL))
    tmp=${map[$i]}
    map[$i]=${map[$j]}
    map[$j]=$tmp
  done
}
modify(){
 local i j c u d l r ul ur dl dr
 for (( i=0; i<MAX_W; i++))
 do
   for (( j=0; j<MAX_H; j++))
   do
     c=$((j * MAX_W + i))

     if (( j != 0 )) ; then
       u=$((c - MAX_W))
       (( i != 0 ))      && ul=$((u - 1 )) || ul=
       (( i < MAX_W_1 )) && ur=$((u + 1 )) || ur=
     else u= ul= ur=
     fi
     if (( j < MAX_H_1 )) ; then
       d=$((c + MAX_W))
       (( i != 0 ))      && dl=$((d - 1 )) || ul=
       (( i < MAX_W_1 )) && dr=$((d + 1 )) || ur=
     else d= dl= dr=
     fi
     (( i != 0 ))      && l=$((c - 1 )) || l=
     (( i < MAX_W_1 )) && r=$((c + 1 )) || r=


     if [ ${map[$c]} = m ] ; then
        [ -n "$u" ] && [[ "${map[$u]}" =~ [0-8] ]] && (( map[$u]++ ))
        [ -n "$d" ] && [[ "${map[$d]}" =~ [0-8] ]] && (( map[$d]++ ))
        [ -n "$l" ] && [[ "${map[$l]}" =~ [0-8] ]] && (( map[$l]++ ))
        [ -n "$r" ] && [[ "${map[$r]}" =~ [0-8] ]] && (( map[$r]++ ))
        [ -n "$ul" ] && [[ "${map[$ul]}" =~ [0-8] ]] && (( map[$ul]++ ))
        [ -n "$ur" ] && [[ "${map[$ur]}" =~ [0-8] ]] && (( map[$ur]++ ))
        [ -n "$dl" ] && [[ "${map[$dl]}" =~ [0-8] ]] && (( map[$dl]++ ))
        [ -n "$dr" ] && [[ "${map[$dr]}" =~ [0-8] ]] && (( map[$dr]++ ))
     fi
   done
 done
}
modify2(){
  # cur_x
  # cur_y
#  echo \($1, $2\)
  local c=$(( $2 * MAX_W + $1 )) u d l r ul ur dl dr
  if [[ "${map2[$c]}" = u ]] ; then

     if (( $2 != 0 )) ; then
       u=$((c - MAX_W))
       (( $1 != 0 ))      && ul=$((u - 1 )) || ul=
       (( $1 < MAX_W_1 )) && ur=$((u + 1 )) || ur=
     else u= ul= ur=
     fi
     if (( $2 < MAX_H_1 )) ; then
       d=$((c + MAX_W))
       (( $1 != 0 ))      && dl=$((d - 1 )) || dl=
       (( $1 < MAX_W_1 )) && dr=$((d + 1 )) || dr=
     else d= dl= dr=
     fi
     (( $1 != 0 ))      && l=$((c - 1 )) || l=
     (( $1 < MAX_W_1 )) && r=$((c + 1 )) || r=


     if [[ "${map[$c]}" = m ]] ; then
       draw
       echo you dead. && exit
     elif [[ "${map[$c]}" =~ [1-8] ]] ; then
       map2[$c]=${map[$c]}
       (( res-- ))
     elif [[ "${map[$c]}" = 0 ]] ; then
        map2[$c]=' '
        (( res-- ))
        [ -n "$u" ] && [[ "${map2[$u]}" = u ]] && modify2 $1 $(( $2-1 ))
        [ -n "$ul" ] && [[ "${map2[$ul]}" = u ]] && modify2 $(( $1-1 )) $(( $2-1 ))
        [ -n "$ur" ] && [[ "${map2[$ur]}" = u ]] && modify2 $(( $1+1 )) $(( $2-1 ))

        [ -n "$d" ] && [[ "${map2[$d]}" = u ]] && modify2 $1 $(( $2+1 ))
        [ -n "$dl" ] && [[ "${map2[$dl]}" = u ]] && modify2 $(( $1-1 )) $(( $2+1 ))
        [ -n "$dr" ] && [[ "${map2[$dr]}" = u ]] && modify2 $(( $1+1 )) $(( $2+1 ))

        [ -n "$l" ] && [[ "${map2[$l]}" = u ]] && modify2 $(( $1-1 )) $2
        [ -n "$r" ] && [[ "${map2[$r]}" = u ]] && modify2 $(( $1+1 )) $2
     fi
  fi
}
open_all(){
  local c=$(( $2 * MAX_W + $1 )) tmp

  if [[ "${map[$c]}" = m ]] ; then
    draw
    echo $1, $2
    echo you dead. && exit
  fi
  tmp=${map[$c]}
  map[$c]=0
  if [[ ${map2[$c]} != u ]] ; then
    ((++res))
    map2[$c]=u
  fi
  modify2 $1 $2
  map[$c]=$tmp
  [[ $tmp = 0 ]] && map2[$c]=' ' || map2[$c]=$tmp
}
check(){
 [[ $res = $MINUS_NUM ]]
}
input(){
  echo -ne "\033[?25l"
  local aKey=(0 0 0 0)
  local cESC=`echo -ne "\033"`
  local index c
  while :
  do
    read -s -n 1 key
    aKey=( "${aKey[@]:1}" "$key")
    if [[ $key${aKey[2]} == $cESC$cESC ]] ; then break
    elif [ "${aKey[@]:1:2}$key" = "${cESC} [A" -a $cur_y != 0 ] ; then  (( cur_y-- )) # up
    elif [ "${aKey[@]:1:2}$key" = "${cESC} [B" -a $cur_y != $MAX_H_1 ] ; then (( cur_y++ )) # down
    elif [ "${aKey[@]:1:2}$key" = "${cESC} [C" -a $cur_x != $MAX_W_1 ] ; then (( cur_x++ )) # right
    elif [ "${aKey[@]:1:2}$key" = "${cESC} [D" -a $cur_x != 0 ] ; then (( cur_x-- )) # left
    elif [ "$key" = "" ] ; then modify2 $cur_x $cur_y # space
    elif [ "$key" = "a" ] ; then open_all $cur_x $cur_y
    elif [ "$key" = "m" ] ; then
      c=$((cur_y*MAX_W+cur_x))
      if [[ ${map2[$c]} = u ]] ; then
        map2[$c]=M
      elif [[ ${map2[$c]} = M ]] ; then
        map2[$c]='?'
      elif [[ ${map2[$c]} = '?' ]] ; then
        map2[$c]=u
      fi
    else continue
    fi
    draw2
    #draw
    check && break
  done
  echo -ne "\033[?25h"
}
clear
random
modify
draw2
#draw
input
draw2
draw
tput cup $(( (MAX_H<<1) + 2 )) 0
check && echo Clear time is ${SECONDS}s. || echo Quit by user.

