#!/bin/bash
# Copyright 2010 Alicia Cathryn Coder
stty -echo
# Get the terminal size
width="`stty size | sed -e "s/.* //;"`"
height="`stty size | sed -e "s/ .*//;"`"
let width_n="${width}-1"
let height_n="${height}-1"
let scorepos="${width}-8"
body[0]="5 10"
body[1]="5 9"
body[2]="5 8"
body[3]="5 7"
body[4]="5 6"
body[5]="5 5"
body[6]="5 4"
dir="1"
score=0
lives=3
pid="$$"

if ! which seq > /dev/null 2> /dev/null; then
seq()
{
  x="$1"
  y="$2"
  while [ "$x" -lt "$y" ]; do
    echo "$x"
    x="`expr "$x" + 1`"
  done
  if [ "$x" = "$y" ]; then echo "$x"; fi
}
fi

# Clear the controls
echo > "/tmp/.gamecontrols"

# Draw the world
echo -ne "\033[1H/-- q=quit "
for j in `seq 13 $width`; do
  echo -n "-"
done
echo -n "\\"
for i in `seq 2 $height_n`; do
  echo -ne "\033[${i}H|"
  for j in `seq 3 $width`; do
    echo -n " "
  done
  echo -n "|"
done
echo -ne "\033[${height}H\\"
for j in `seq 3 $width`; do
  echo -n "-"
done
echo -n "/"

# Draw the snake
echo -ne "\033[10H\033[5GO"
echo -ne "\033[9H\033[5GO"
echo -ne "\033[8H\033[5GO"
echo -ne "\033[7H\033[5GO"
echo -ne "\033[6H\033[5GO"
echo -ne "\033[5H\033[5GO"

echo -ne "\033[${height}H\033[${width}G"

function random {
  a="$RANDOM"
  while [ "$a" -ge "$1" ]; do let a="${a}-${1}"; done
  if [ "$a" -lt "2" ]; then let a="${1}-1"; fi
  echo "$a"
}

function die {
  # Clear the screen
  for i in `seq 2 $height_n`; do
    echo -ne "\033[${i}H|"
    for j in `seq 3 $width`; do
      echo -n " "
    done
    echo -n "|"
  done
  let lives-=1
  echo > "/tmp/.gamecontrols"
  dir=1
  x=5
  y=10
  body[0]="5 10"
  echo -ne "\033[10H\033[5GO"
  body[1]="5 9"
  echo -ne "\033[9H\033[5GO"
  body[2]="5 8"
  echo -ne "\033[8H\033[5GO"
  body[3]="5 7"
  echo -ne "\033[7H\033[5GO"
  body[4]="5 6"
  echo -ne "\033[6H\033[5GO"
  body[5]="5 5"
  echo -ne "\033[5H\033[5GO"
  body[6]="5 4"
  body[7]=""
  echo -ne "\033[${foody}H\033[${foodx}G\033[42mX\033[00m"
  if [ "$lives" -lt "0" ]; then
    rm -f "/tmp/.gamecontrols"
    clear
    echo "GAME OVER"
    kill "$pid"
    exit
  fi
}

foodx="`random "$width"`"
foody="`random "$height"`"
echo -ne "\033[${foody}H\033[${foodx}G\033[42mX\033[00m"

# Main game loop
(while true; do
  action="`if [ -e /tmp/.gamecontrols ]; then cat /tmp/.gamecontrols; fi`"
  if [ "$action" = "A" ]; then dir=0; fi
  if [ "$action" = "B" ]; then dir=1; fi
  if [ "$action" = "C" ]; then dir=2; fi
  if [ "$action" = "D" ]; then dir=3; fi
  if [ "$action" = "quit" ]; then rm -f "/tmp/.gamecontrols"; exit; fi
  # Print lives and score
  echo -ne "\033[3H\033[3G${lives} "
  echo -ne "\033[3H\033[${scorepos}G${score} "
  if [ "$dir" = "0" ]; then
    let x="${body[0]% *}"
    let y="${body[0]#* }-1"
  elif [ "$dir" = "1" ]; then
    let x="${body[0]% *}"
    let y="${body[0]#* }+1"
  elif [ "$dir" = "2" ]; then
    let x="${body[0]% *}+1"
    let y="${body[0]#* }"
  elif [ "$dir" = "3" ]; then
    let x="${body[0]% *}-1"
    let y="${body[0]#* }"
  fi
  tmp="${body[0]}"
  body[0]="${x} ${y}"
  x1="$x"
  y1="$y"
  i=1
  while [ ! -z "${body[$i]}" ]; do
    tmp2="${body[$i]}"
    body[$i]="$tmp"
    tmp="$tmp2"
    x="${body[$i]% *}"
    y="${body[$i]#* }"
    if [ "$x" = "$x1" -a "$y" = "$y1" ]; then die; break; fi
if [ "$i" = "1" ]; then    echo -ne "\033[${y}H\033[${x}GO"; fi
    let i="${i}+1"
  done
  if [ "$x1" -lt "2" -o "$x1" -gt "$width_n" -o "$y1" -lt "2" -o "$y1" -gt "$height_n" ]; then die; fi
  if [ "$x1" = "$foodx" -a "$y1" = "$foody" ]; then
    let score+=1
    foodx="`random "$width"`"
    foody=3
    while [ "$foody" = "3" ]; do
      foody="`random "$height"`"
    done
    echo -ne "\033[${foody}H\033[${foodx}G\033[42mX\033[00m"
    body[$i]="$tmp"; let i+=1; body[$i]=""
  fi
  if [ "$x" = "$foodx" -a "$y" = "$foody" ]; then
    echo -ne "\033[${y}H\033[${x}G\033[42mX\033[00m"
  else
    echo -ne "\033[${y}H\033[${x}G "
  fi
  echo -ne "\033[${height}H\033[${width}G"
  sleep 0.1
done) &

while true; do
  read -n 1 key
  if [ "$key" = "q" ]; then echo "quit" > "/tmp/.gamecontrols"; stty echo; echo; clear; exit; fi
  if [ "$key" = "`echo -ne '\033'`" ]; then
    read -t 1 -n 2 dirkey
    if [ "$dirkey" = "[A" ]; then echo "A" > "/tmp/.gamecontrols"; fi
    if [ "$dirkey" = "[B" ]; then echo "B" > "/tmp/.gamecontrols"; fi
    if [ "$dirkey" = "[C" ]; then echo "C" > "/tmp/.gamecontrols"; fi
    if [ "$dirkey" = "[D" ]; then echo "D" > "/tmp/.gamecontrols"; fi
  fi
done

kill %1
stty echo
