#!/usr/local/bin/bash ############################################################################## # # # Author : Martin "BruXy" Bruchanov, bruxy at regnet.cz # # URL : http://bruxy.regnet.cz # # Version: 1.01 (Wed Jan 9 20:04:26 CET 2013) # # # ############################################################################## MW=$(tput cols) MH=$(tput lines) MH=$[MH-1] # bottom line is used for info and score CONFIG=~/.housenka DEFAULT_FOOD_NUMBER=2 # reset after game over in func. new_level FOOD_NUMBER=0 DEATH=0 SCORE=0 TIMING=0.1 # delay constant, lower value => faster moves C=2 # game cycle declare -A FOOD _STTY=$(stty -g) # Save current terminal setup printf "\e[?25l" # Turn of cursor printf "\e]0;HOUSENKA\007" stty -echo -icanon USER=$(whoami) NAME=$(grep $USER /etc/passwd | cut -d : -f 5) ############# # ANSI data # ############# GAME_OVER[0]="\e[1;35m╥┌ ╓─╖ ╥ ╥ ╥─┐ ╥─┐ ╥ ╥ ╥┐ ╥ ┬\e[0m" GAME_OVER[1]="\e[0;31m╟┴┐ ║ ║ ║\║ ╟┤ ║ ╟─╢ ╟┴┐ ╨╥┘\e[0m" GAME_OVER[2]="\e[1;31m╨ ┴ ╙─╜ ╨ ╨ ╨─┘ ╨─┘ ╨ ╨ ╨ ┴ ╨ \e[0m" GAME_OVER[3]="\e[0;32m╥────────────────────────────────╥\e[0m" GAME_OVER[4]="\e[1;32m║ Presione INTRO par Jugar! ║\e[0m" GAME_OVER[5]="\e[1;36m╨────────────────────────────────╨\e[0m" ############# # FUNCTIONS # ############# function at_exit() { printf "\e[?9l" # Turn off mouse reading printf "\e[?12l\e[?25h" # Turn on cursor stty "$_STTY" # reinitialize terminal settings tput sgr0 clear } function get_first() { # Return: first index of array eval echo \${!$1[@]} | cut -d ' ' -f 1 } function gen_food() { local x y food for ((i=0; i<$[2*$FOOD_NUMBER]; i++)) do x=$[RANDOM % (MW-2) + 2] y=$[RANDOM % (MH-2) + 2] # check if leaf position is unique if [ $(echo ${!FOOD[@]} | tr ' ' '\n' | grep -c "^$y;$x$") -gt 0 ] then : $[i--] continue fi food=$[i & 1] # 0 -- poison, 1 -- leaf FOOD["$y;$x"]=$food if [ $food -eq 1 ] ; then printf "\e[$y;${x}f\e[1;32m♠\e[0m"; else printf "\e[$y;${x}f\e[1;31m♣\e[0m"; fi done } function check_food() { local first # check what was eaten in garden if [ "${FOOD["$HY;$HX"]}" == "1" ] ; then unset FOOD["$HY;$HX"] : $[FOOD_NUMBER--] $[SCORE++] ((FOOD_NUMBER==0)) && return elif [ "${FOOD["$HY;$HX"]}" == "0" ] ; then DEATH=1 else first=$(get_first HOUSENKA) printf "\e[${HOUSENKA[$first]}f " unset HOUSENKA[$first] fi # do not break into wall if [ $HY -le 1 ] || [ $HY -ge $MH ] || [ $HX -le 1 ] || [ $HX -ge $MW ] then DEATH=2 fi # check if Housenka does not bite herself if [ ! -z "$KEY" -a $C -gt 4 ] ; then local last last=${#HOUSENKA[@]} if [ $(echo ${HOUSENKA[@]} | tr ' ' '\n' | \ head -n $[last-2] | grep -c "^$HY;$HX$") -gt 0 ] ; then DEATH=3 fi fi } function game_over() { trap : ALRM # disable interupt printf "\a" centered_window 34 ${#GAME_OVER[@]} GAME_OVER if [ $SCORE -gt $TOP_SCORE ] ; then echo $SCORE > $CONFIG TOP_SCORE=$SCORE fi read DEATH=0 SCORE=0 DEFAULT_FOOD_NUMBER=2 new_level } function centered_window() { # $1 width $2 height $3 content w=$1 h=$2 x=$[(MW-w)/2] y=$[(MH-h)/2] ul=$y";"$x bl=$[y+h+1]";"$x printf "\e[${ul}f┌"; printf '─%.0s' $(eval echo {1..$w}); printf '┐\n' for i in $(eval echo {0..$h}); do printf "\e[$[y+i+1];${x}f│"; echo -en "$(eval printf \"%s\" \"\${$3[\$i]}\")" printf "\e[$[y+i+1];$[x+w+1]f│"; done printf "\e[${bl}f└"; printf '─%.0s' $(eval echo {1..$w}); printf '┘\n' } function move() { check_food if [ $DEATH -gt 0 ] ; then game_over; fi if [ $FOOD_NUMBER -eq 0 ] ; then new_level; fi echo -en "\e[$HY;${HX}f\e[1;33;42m☻\e[0m" ( sleep $TIMING; kill -ALRM $$ ) & case "$KEY" in A) HY=$[HY-1] ;; # Arriba B) HY=$[HY+1] ;; # Abajo C) HX=$[HX+1] ;; # Derecha D) HX=$[HX-1] ;; # Izquierda esac HOUSENKA[$C]="$HY;$HX" : $[C++] game_info } function draw_area() { # draw play area printf "\e[31m" local x y o="█" for ((x=0;x<=$MW;x++)) do printf "\e[1;${x}f$o\e[$MH;${x}f$o" sleep 0.005 done for ((y=0;y<=$MH;y++)) do printf "\e[${y};1f$o\e[${y};${MW}f$o" sleep 0.01 done } function new_level() { unset HOUSENKA for i in ${!FOOD[@]}; do unset FOOD[$i]; done # erase leaves and poison clear draw_area FOOD_NUMBER=$[DEFAULT_FOOD_NUMBER*=2] gen_food HX=$[MW/2] HY=$[MH/2] # start position in the middle of the screen # body initialization HOUSENKA=([0]="$[HY-2];$HX" [1]="$[HY-1];$HX" [2]="$HY;$HX") KEY='' C=2 trap move ALRM } function title_screen() { TITLE="QlpoOTFBWSZTWWMw1D8AAnd//X38AIhAA/24Cg2UCD7H13BVRH9ktkYEBAgAEABQ BHgAEQBSlBJEQhqaA0ZDQBoA0ABpoBo9Rk0Ghw00wQyGmmRkwgGmgDCaNMmABA0E KRJCTTIDIAAAAAyBkNDQNNHqHDTTBDIaaZGTCAaaAMJo0yYAEDQ4aaYIZDTTIyYQ DTQBhNGmTAAgadZFPhSv08GL4IDbz4ctYPMQnUncHF0csCYaeprXNsFiBI3jqAqr eZINIEZYBM0vKFjDLrT3O9d7u0YdyNmszDTqrCoaow3YRJGmq1mpO9ZAbqoXLRBc sNPFvNGSbnbbDlhVhwUxhQ2lyXlxhssjLVysN8tVGpyiODkVooK4kzcZBVBBouKq K4k3RKUuppicgMDWCYG23aU3vWmMOHN8HBjaSTYb43vjg4bTqDizjjW5iojfdt7O DhnoedhCmSaWgoUq6IyuzGTVFAUs66ujrbwJmIp54zi8U0Jvl2dG7jlOcZy0IU8Q HY32Ojyejm45lswDjSi5KwUwUUlAIQ01SRKUtKU1Hjwg4A7BIMFZ3MMYMQHc2nHg Fi88aPlyBeYkZTTyRgUml+nl5p3CxSMeGHDUCBTstZpOZckIU8f7lIckxlKZ53hT YzK0p+YzytGd2hNg2ZCrUpkv09fqowZ9vLuiQCDnIRUPoBDAIVRIZkQO0AKOpQ0o msRVHATFQU7vc7/1AfWSlJFEkFIrRKQUlVRCSlVNUlLQDMCxBAlAlIkEQTMFMkTM KkKVBJARFVEBD9hI9tR52USwDECnHMMIoyMqxgMsg0BodaBnMaMbCUaR1ZLkoYFR EgUFAFNBEoxRgYJqQNQg9r4/g7vn+99/Gsj4bVxAAJfFf177dEjRn5b+cAhI82SQ jRPNoFhdnAMJcvMkDUJEOiRqlRWaGSUhKgJZGIkiEkGS/jv9e9m2vitRmRjm0T38 FrpAS4kkIYQliBkCQnEYYP80AEjqXFAyVSw1tRWIFcZFUcAwaeljJUjJfQ8Ph9X1 Q+3t/mIXWLjCLuLwg1WEYiUo038wzoqSHpSaSOKUde7LhfHRdQzqlxs3rJKmOROc o6Y6ZDm+THkzMzIdPXzUOo4RVH/xdyRThQkGMw1D8A==" SCR=`echo "$TITLE" | base64 -d | bzcat` #unpack main screen local i j IFS=$'\n' clear # center on screen for ((j=0;j<$[(MH-25)/2];j++)) do echo; done for i in $SCR do for ((j=0;j<$[(MW-63)/2];j++)) do echo -n " "; done printf "%s\n" $i done read } function game_info() { printf "\e[$[MH+1];0fNombre: $USER (Récord histórico: $TOP_SCORE)" printf "\e[$[MH+1];$[MW-12]fPuntaje: %5d" $SCORE } ######## # MAIN # ######## exec 2>/dev/null trap at_exit ERR EXIT if [ -f $CONFIG ] ; then TOP_SCORE=$(cat $CONFIG) else TOP_SCORE=0 fi title_screen new_level move while : do read -rsn3 -d '' PRESS KEY=${PRESS:2} done