Way back while learning BASH scripting I made a tetris clone, as is common practice when learning a new language. Being a C++ guy, the result was horrible to look at. You can also tell that I got lazy with comments. Plenty of unfinished things as well. Behold:
#!/bin/bash
#-----------------------------------------------------------------------------
# A tetromino stacking game written entirely in BASH script! =D
#
# Because I can...
#
#-----------------------------------------------------------------------------
# Version 0.1 Beta:
# - The game is functional
# - Todo:
# - Overtime bonus to score after all 10 lines of level 10 are cleared
# - Highscores
#=============================================================================
#=============================================================================
#-----------------------------------------------------------------------------
# [ Global Variables ]
#-----------------------------------------------------------------------------
#=============================================================================
declare -r TETRIBASHTITLE="TetriBASH"
declare -ri TETRIBASHVERSION=0
declare -ri TETRIBASHSUBVERS=1
declare -r TETRIBASHRELEASE="Beta"
declare -r TETRIBASHDATE="2010 - 2012"
declare -r TETRIBASHINFO="A tetromino stacking game written entirely in"
declare -r TETRIBASHINFO2="BASH script! =D"
declare -r TETRIBASHINFO3="Because I can..."
declare -i TETRIBASHSTATE=0 # Indicates the current game state
declare -i TETRIBASHDEBUG=0 # Value of 1 enables debug mode
declare TIMESTART="0.0" # Start time of a frame
declare TIMEEND="0.0" # End time of a frame
declare DELTATIME="0.0" # Time elapsed for the frame
declare ACCUMULATOR="0.0" # Primary gameplay accumulator
declare -ri TERMULT=2 # and chaos # Multiplier to determin tetromino block width in characters (Do not change!)
declare -ri TERMWIDTH=$(tput cols) # Character width of the terminal
declare -ri TERMHEIGHT=$(tput lines) # Character height of the terminal
declare -ri GAMEWIDTH=34 # Width of the game area
declare -ri GAMEOFFSETX=$((($TERMWIDTH / 2) - ($GAMEWIDTH / 2))) # X offset of the game area
declare -ri GAMEOFFSETY=2 # Y offset of the game area
declare -ri GAMEBLOCKSIZE=4 # Width and height of the game block array
declare -ri GAMEBLOCKAREA=$(($GAMEBLOCKSIZE * $GAMEBLOCKSIZE)) # Size of the game block array
declare -i GAMESCORE=0 # Game score
declare -i GAMESCOREMULTDEF=33 # Score Multiplier Default
declare -i GAMESCOREMULT=33 # Score Multiplier
declare -i GAMESCOREMULTINC=100 # Score Multiplier increase per level
declare -i GAMELEVEL=0 # Game level
declare -i GAMELINES=0 # Number of lines cleared
declare -i GAMELINESPERLEVEL=10 # Number of lines that need to be cleared to advance in level
declare -i GAMELEVELLINES=0 # Number of lines cleared this level
declare -i GAMEFAILUREMAX=10 # NUmber of blocks to place after failure before showing Game Over message
declare -i GAMEFAILURECOUNT=0 # Number of blocks placed on top of eachother
declare -i GAMEFAILURE=0 # Indicates a game is determined to be lost
declare -i GAMECURRENT=0 # Current active block ID
declare -i GAMECURRENTROT=0 # Current active block rotation
declare -i GAMENEXT=0 # The next block ID
declare -i GAMERUNNING=0 # Indicates the game is running
declare -a GAMECURRENTARRAY # Current active block array
declare -a GAMENEXTARRAY # Next block array
declare -a GAMEBLOCKBUFFER # Current active block rotation buffer
declare -i GAMECLEARINPROGRESS=0 # Indicates a line clear is in progress
declare -i GAMEOVERINPROGRESS=0 # Indicates game over is in progress
declare -i GAMELINESTOCLEAR=0 # Number of lines that need clearing
declare -a GAMELINESBUFFER # Lists of lines that need clearing
declare -i GAMECLEARANIMFRAMES=3 # Number of frames of clearing animation
declare -r GAMECLEARCHAR=":"
declare -i GAMEBLOCKX=0 # X position of active game block relative to terminal
declare -i GAMEBLOCKY=0 # Y position of active game block relative to terminal
declare -i GAMEBLOCKAPX=0 # X position of active game block relative to the play area
declare -i GAMEBLOCKAPY=0 # Y position of active game block relative to the play area
declare GAMEINTERVAL="0.5" # Fall rate in seconds
declare GAMECLEARINTERVAL="0.2" # Clear rate in seconds
declare GAMEOVERINTERVAL="5.0" # Game Over message interval in seconds
declare -i FRAMEUPDATED=0 # Indicates drawing has been done in the current frame
declare -ri TBASHW=10 # Width of the play area in blocks
declare -ri TBASHH=20 # Height of the play area in blocks
declare -ri TBASHSIZE=$(($TBASHW * $TBASHH)) # Size of the play area array
declare -ri TBASHAREAOFFSETX=$GAMEOFFSETX # X offset of play area including border
declare -ri TBASHAREAOFFSETY=$GAMEOFFSETY # Y offset of play area including border
declare -ri TBASHAREAW=$((($TBASHW * $TERMULT) + 2)) # Width of play area including border
declare -ri TBASHAREAH=$(($TBASHH + 2)) # Height of play area including border
declare -ri TBASHOFFSETX=$(($TBASHAREAOFFSETX + 1)) # X offset of play area
declare -ri TBASHOFFSETY=$(($TBASHAREAOFFSETY + 1)) # Y offset of play area
declare -ri TBASHGAMEOVEROFFSETX=$(($TBASHAREAOFFSETX + 2))
declare -ri TBASHGAMEOVEROFFSETY=$(($TBASHAREAOFFSETY + ($TBASHAREAH / 2) - 2))
declare -ri TBASHGAMEOVERWIDTH=$(($TBASHAREAW - 4))
declare -ri TBASHGAMEOVERHEIGHT=3
declare -ri TBASHSCOREW=10
declare -ri TBASHSCOREH=3
declare -ri TBASHSCOREOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX))
declare -ri TBASHSCOREOFFSETY=$GAMEOFFSETY
declare -ri TBASHSCOREVALUEX=$(($TBASHSCOREOFFSETX + 1))
declare -ri TBASHSCOREVALUEY=$(($TBASHSCOREOFFSETY + 1))
declare -ri TBASHLEVELW=10
declare -ri TBASHLEVELH=3
declare -ri TBASHLEVELOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX))
declare -ri TBASHLEVELOFFSETY=$(($GAMEOFFSETY + 1 + $TBASHSCOREH))
declare -ri TBASHLEVELVALUEX=$(($TBASHLEVELOFFSETX + 1))
declare -ri TBASHLEVELVALUEY=$(($TBASHLEVELOFFSETY + 1))
declare -ri TBASHLINESW=10
declare -ri TBASHLINESH=3
declare -ri TBASHLINESOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX))
declare -ri TBASHLINESOFFSETY=$(($GAMEOFFSETY + 1 + $TBASHSCOREH + 1 + $TBASHLEVELH))
declare -ri TBASHLINESVALUEX=$(($TBASHLINESOFFSETX + 1))
declare -ri TBASHLINESVALUEY=$(($TBASHLINESOFFSETY + 1))
declare -ri TBASHNEXTW=10
declare -ri TBASHNEXTH=6
declare -ri TBASHNEXTOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX))
declare -ri TBASHNEXTOFFSETY=$(($GAMEOFFSETY + $TBASHAREAH - $TBASHNEXTH))
declare -ri TBASHNEXTVALUEX=$(($TBASHNEXTOFFSETX + 1))
declare -ri TBASHNEXTVALUEY=$(($TBASHNEXTOFFSETY + 1))
declare -ri MAINTITLEW=49
declare -ri MAINTITLEH=5
declare -ri MAINTITLEX=$((($TERMWIDTH / 2) - ($MAINTITLEW / 2)))
declare -ri MAINTITLEY=1
declare -r MAINTITLELINE1="\e[0;31m ______ __ _ ____ ___ _____ __ __\e[0m"
declare -r MAINTITLELINE2="\e[1;31m /_ __/___ / /______(_) __ )/ | / ___// / / /\e[0m"
declare -r MAINTITLELINE3="\e[0;33m / / / _ \\/ __/ ___/ / __ / /| | \\__ \\/ /_/ / \e[0m"
declare -r MAINTITLELINE4="\e[1;33m / / / __/ /_/ / / / /_/ / ___ |___/ / __ / \e[0m"
declare -r MAINTITLELINE5="\e[1;37m/_/ \\___/\\__/_/ /_/_____/_/ |_/____/_/ /_/ \e[0m"
declare -ri TBASHABOUTW=49
declare -ri TBASHABOUTH=7
declare -ri TBASHABOUTX=$((($TERMWIDTH / 2) - ($TBASHABOUTW / 2)))
declare -ri TBASHABOUTY=$(($MAINTITLEH + 5))
declare -ri MAINMENUW=15
declare -ri MAINMENUH=4
declare -ri MAINMENUX=$((($TERMWIDTH / 2) - ($MAINMENUW / 2)))
declare -ri MAINMENUY=$(($MAINTITLEH + $MAINTITLEY + 3))
declare -ri MAINMENUITEMCOUNT=4
declare -a MAINMENUITEMS
MAINMENUITEMS[0]="New Game\e[0m"
MAINMENUITEMS[1]="High Scores\e[0m"
MAINMENUITEMS[2]="About\e[0m"
MAINMENUITEMS[3]="Exit\e[0m"
declare -a MAINMENUITEMY
MAINMENUITEMY[0]=$MAINMENUY
MAINMENUITEMY[1]=$(($MAINMENUY + 2))
MAINMENUITEMY[2]=$(($MAINMENUY + 4))
MAINMENUITEMY[3]=$(($MAINMENUY + 6))
declare -i MAINMENUSELECTION=0
declare -r MAINMENUITEMNOTSEL=" \e[0;33m"
declare -r MAINMENUITEMSELECT="\e[1;37m??> \e[1;33m"
declare -ri MENUBOTTOMDECORX=$MAINTITLEX
declare -ri MENUBOTTOMDECORY=$(($TERMHEIGHT - 5))
declare -r SCREENINFOSTRING=$(printf "%s %d.%d %s" "$TETRIBASHTITLE" $TETRIBASHVERSION $TETRIBASHSUBVERS "$TETRIBASHRELEASE")
declare -ri SCREENINFOSTRINGX=$((($TERMWIDTH / 2) - (${#SCREENINFOSTRING} / 2)))
declare -ri SCREENINFOSTRINGY=$(($TERMHEIGHT - 1))
declare -r BH="?"
declare -r BV="?"
declare -r BTL="?"
declare -r BTR="?"
declare -r BBL="?"
declare -r BBR="?"
declare -r BLK1="\e[43m\e[1;33m[]"
declare -r BLK2="\e[42m\e[1;32m()"
declare -r BLK3="\e[46m\e[1;36m::"
declare -r BLK4="\e[41m\e[1;31m[]"
declare -r BLK5="\e[44m\e[1;34m{}"
declare -r BLK6="\e[47m\e[1;37m++"
declare -r BLK7="\e[45m\e[1;35m<>"
declare -a TBASHARRAY
#================================== Block 1 ==================================
declare -a BLK1ARRAY=(0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0)
declare -a BLK1ARRAYR2=(0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0)
declare -a BLK1ARRAYR3=(0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0)
declare -a BLK1ARRAYR4=(0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0)
#================================== Block 2 ==================================
declare -a BLK2ARRAY=(0 0 0 0 0 2 2 0 0 2 2 0 0 0 0 0)
#================================== Block 3 ==================================
declare -a BLK3ARRAY=(0 0 0 0 3 3 3 3 0 0 0 0 0 0 0 0)
declare -a BLK3ARRAYR2=(0 0 3 0 0 0 3 0 0 0 3 0 0 0 3 0)
declare -a BLK3ARRAYR3=(0 3 0 0 0 3 0 0 0 3 0 0 0 3 0 0)
#================================== Block 4 ==================================
declare -a BLK4ARRAY=(0 0 0 0 4 4 0 0 0 4 4 0 0 0 0 0)
declare -a BLK4ARRAYR2=(0 4 0 0 4 4 0 0 4 0 0 0 0 0 0 0)
#================================== Block 5 ==================================
declare -a BLK5ARRAY=(0 0 0 0 0 5 5 0 5 5 0 0 0 0 0 0)
declare -a BLK5ARRAYR2=(5 0 0 0 5 5 0 0 0 5 0 0 0 0 0 0)
#================================== Block 6 ==================================
declare -a BLK6ARRAY=(0 0 0 0 6 6 6 0 0 0 6 0 0 0 0 0)
declare -a BLK6ARRAYR2=(0 6 0 0 0 6 0 0 6 6 0 0 0 0 0 0)
declare -a BLK6ARRAYR3=(6 0 0 0 6 6 6 0 0 0 0 0 0 0 0 0)
declare -a BLK6ARRAYR4=(0 6 6 0 0 6 0 0 0 6 0 0 0 0 0 0)
#================================== Block 7 ==================================
declare -a BLK7ARRAY=(0 0 0 0 7 7 7 0 7 0 0 0 0 0 0 0)
declare -a BLK7ARRAYR2=(7 7 0 0 0 7 0 0 0 7 0 0 0 0 0 0)
declare -a BLK7ARRAYR3=(0 0 7 0 7 7 7 0 0 0 0 0 0 0 0 0)
declare -a BLK7ARRAYR4=(0 7 0 0 0 7 0 0 0 7 7 0 0 0 0 0)
#=============================================================================
#-----------------------------------------------------------------------------
# [ Function Declarations ]
#-----------------------------------------------------------------------------
#=============================================================================
function ZeroTetriBashArray()
{
for((i=0; i<TBASHSIZE; i++)); do
{
TBASHARRAY[$i]=0
}
done
}
function GameOverClearTetriBashArray()
{
for((i=0; i<TBASHSIZE; i++)); do
{
TBASHARRAY[$i]=8
}
done
}
function ZeroBlockBuffer()
{
for((i=0; i<GAMEBLOCKAREA; i++)); do
{
GAMEBLOCKBUFFER[$i]=0
}
done
}
function ZeroLinesBuffer()
{
for((i=0; i<TBASHH; i++)); do
{
GAMELINESBUFFER[$i]=0
}
done
}
function DrawBorder()
{
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then
{
return 1
}
fi
local BWIDTH=$(($3 - 2))
local BHEIGHT=$(($4 - 2))
local BVERTVPOS=$(($2 + 1))
local BVERTHPOS=$1
printf "\e[%d;%dH${BTL}" $2 $1
for((i=0; i<BWIDTH; i++)); do
{
printf "${BH}"
}
done
printf "${BTR}"
for((i=0; i<BHEIGHT; i++)); do
{
printf "\e[%d;%dH${BV}" $BVERTVPOS $BVERTHPOS
BVERTVPOS=$(($BVERTVPOS + 1))
}
done
BVERTVPOS=$(($2 + 1))
BVERTHPOS=$(($1 + $3 - 1))
for((i=0; i<BHEIGHT; i++)); do
{
printf "\e[%d;%dH${BV}" $BVERTVPOS $BVERTHPOS
BVERTVPOS=$(($BVERTVPOS + 1))
}
done
printf "\e[%d;%dH${BBL}" $(($2 + $4 - 1)) $1
for((i=0; i<BWIDTH; i++)); do
{
printf "${BH}"
}
done
printf "${BBR}"
return 0
}
function DrawTetriBashArray()
{
local BLAPOS=0
for((i=0; i<TBASHH; i++)); do
{
for((j=0; j<TBASHW; j++)); do
{
BLAPOS=$((($i * $TBASHW) + $j))
case ${TBASHARRAY[$BLAPOS]} in
1) printf "\e[%d;%dH${BLK1}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
2) printf "\e[%d;%dH${BLK2}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
3) printf "\e[%d;%dH${BLK3}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
4) printf "\e[%d;%dH${BLK4}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
5) printf "\e[%d;%dH${BLK5}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
6) printf "\e[%d;%dH${BLK6}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
7) printf "\e[%d;%dH${BLK7}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
8) printf "\e[%d;%dH::\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
esac
}
done
}
done
FRAMEUPDATED=1
}
function DrawTetriBashArrayEx()
{
local BLAPOS=0
for((i=0; i<TBASHH; i++)); do
{
for((j=0; j<TBASHW; j++)); do
{
BLAPOS=$((($i * $TBASHW) + $j))
case ${TBASHARRAY[$BLAPOS]} in
0) printf "\e[%d;%dH \e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
1) printf "\e[%d;%dH${BLK1}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
2) printf "\e[%d;%dH${BLK2}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
3) printf "\e[%d;%dH${BLK3}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
4) printf "\e[%d;%dH${BLK4}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
5) printf "\e[%d;%dH${BLK5}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
6) printf "\e[%d;%dH${BLK6}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
7) printf "\e[%d;%dH${BLK7}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));;
esac
}
done
}
done
FRAMEUPDATED=1
}
function HUDDrawArea()
{
DrawBorder $TBASHAREAOFFSETX $TBASHAREAOFFSETY $TBASHAREAW $TBASHAREAH
FRAMEUPDATED=1
}
function HUDDrawGameOver()
{
DrawBorder $TBASHGAMEOVEROFFSETX $TBASHGAMEOVEROFFSETY $TBASHGAMEOVERWIDTH $TBASHGAMEOVERHEIGHT
printf "\e[%d;%dH\e[1;31m Game Over! \e[0m" $(($TBASHGAMEOVEROFFSETY + 1)) $(($TBASHGAMEOVEROFFSETX + 1))
FRAMEUPDATED=1
}
function HUDDrawScore()
{
DrawBorder $TBASHSCOREOFFSETX $TBASHSCOREOFFSETY $TBASHSCOREW $TBASHSCOREH
printf "\e[%d;%dH\e[1;33mScore\e[0m" $(($TBASHSCOREOFFSETY + 0)) $(($TBASHSCOREOFFSETX + 2))
FRAMEUPDATED=1
}
function HUDDrawLevel()
{
DrawBorder $TBASHLEVELOFFSETX $TBASHLEVELOFFSETY $TBASHLEVELW $TBASHLEVELH
printf "\e[%d;%dH\e[1;33mLevel\e[0m" $(($TBASHLEVELOFFSETY + 0)) $(($TBASHLEVELOFFSETX + 2))
FRAMEUPDATED=1
}
function HUDDrawLines()
{
DrawBorder $TBASHLINESOFFSETX $TBASHLINESOFFSETY $TBASHLINESW $TBASHLINESH
printf "\e[%d;%dH\e[1;33mLines\e[0m" $(($TBASHLINESOFFSETY + 0)) $(($TBASHLINESOFFSETX + 2))
FRAMEUPDATED=1
}
function HUDDrawNext()
{
DrawBorder $TBASHNEXTOFFSETX $TBASHNEXTOFFSETY $TBASHNEXTW $TBASHNEXTH
printf "\e[%d;%dH\e[1;33mNext\e[0m" $(($TBASHNEXTOFFSETY + 0)) $(($TBASHNEXTOFFSETX + 2))
FRAMEUPDATED=1
}
function HUDUpdateScore()
{
printf "\e[%d;%dH\e[1;36m%d\e[0m" $TBASHSCOREVALUEY $TBASHSCOREVALUEX $GAMESCORE
FRAMEUPDATED=1
}
function HUDUpdateLevel()
{
printf "\e[%d;%dH\e[1;36m%d\e[0m" $TBASHLEVELVALUEY $TBASHLEVELVALUEX $GAMELEVEL
FRAMEUPDATED=1
}
function HUDUpdateLines()
{
printf "\e[%d;%dH\e[1;36m%d\e[0m" $TBASHLINESVALUEY $TBASHLINESVALUEX $GAMELINES
FRAMEUPDATED=1
}
function HUDUpdateNext()
{
local BLAPOS=0;
local VY=$TBASHNEXTVALUEY;
case $GAMENEXT in
0) GAMENEXTARRAY=("${BLK1ARRAY[@]}");;
1) GAMENEXTARRAY=("${BLK2ARRAY[@]}");;
2) GAMENEXTARRAY=("${BLK3ARRAY[@]}");;
3) GAMENEXTARRAY=("${BLK4ARRAY[@]}");;
4) GAMENEXTARRAY=("${BLK5ARRAY[@]}");;
5) GAMENEXTARRAY=("${BLK6ARRAY[@]}");;
6) GAMENEXTARRAY=("${BLK7ARRAY[@]}");;
esac
printf "\e[%d;%dH" $TBASHNEXTVALUEY $TBASHNEXTVALUEX
for((i=0; i<GAMEBLOCKSIZE; i++)); do
{
for((j=0; j<GAMEBLOCKSIZE; j++)); do
{
BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
case ${GAMENEXTARRAY[$BLAPOS]} in
0) printf "\e[0m ";;
1) printf "${BLK1}";;
2) printf "${BLK2}";;
3) printf "${BLK3}";;
4) printf "${BLK4}";;
5) printf "${BLK5}";;
6) printf "${BLK6}";;
7) printf "${BLK7}";;
*) printf "\e[0m ";;
esac
}
done
VY=$(($VY + 1))
printf "\e[%d;%dH" $VY $TBASHNEXTVALUEX
}
done
FRAMEUPDATED=1
}
function DrawTetriBashHUD()
{
HUDDrawArea
HUDDrawScore
HUDDrawLevel
HUDDrawLines
HUDDrawNext
HUDUpdateScore
HUDUpdateLevel
HUDUpdateLines
HUDUpdateNext
FRAMEUPDATED=1
}
function FillArrayDemoBlocks()
{
TBASHARRAY[15]=1
TBASHARRAY[16]=1
TBASHARRAY[17]=1
TBASHARRAY[26]=1
TBASHARRAY[21]=2
TBASHARRAY[22]=2
TBASHARRAY[31]=2
TBASHARRAY[32]=2
TBASHARRAY[38]=3
TBASHARRAY[48]=3
TBASHARRAY[58]=3
TBASHARRAY[68]=3
TBASHARRAY[51]=4
TBASHARRAY[52]=4
TBASHARRAY[62]=4
TBASHARRAY[63]=4
TBASHARRAY[75]=5
TBASHARRAY[76]=5
TBASHARRAY[84]=5
TBASHARRAY[85]=5
TBASHARRAY[103]=6
TBASHARRAY[113]=6
TBASHARRAY[114]=6
TBASHARRAY[115]=6
TBASHARRAY[138]=7
TBASHARRAY[146]=7
TBASHARRAY[147]=7
TBASHARRAY[148]=7
}
function DrawTetriBashTitle()
{
printf "\e[%d;%dH${MAINTITLELINE1}" $MAINTITLEY $MAINTITLEX
printf "\e[%d;%dH${MAINTITLELINE2}" $(($MAINTITLEY + 1)) $MAINTITLEX
printf "\e[%d;%dH${MAINTITLELINE3}" $(($MAINTITLEY + 2)) $MAINTITLEX
printf "\e[%d;%dH${MAINTITLELINE4}" $(($MAINTITLEY + 3)) $MAINTITLEX
printf "\e[%d;%dH${MAINTITLELINE5}" $(($MAINTITLEY + 4)) $MAINTITLEX
FRAMEUPDATED=1
}
function DrawTetriBashMenuDecor()
{
printf "\e[%d;%dH \e[0m" $MENUBOTTOMDECORY $MENUBOTTOMDECORX
printf "\e[%d;%dH \e[0m" $(($MENUBOTTOMDECORY + 1)) $MENUBOTTOMDECORX
printf "\e[%d;%dH \e[0m" $(($MENUBOTTOMDECORY + 2)) $MENUBOTTOMDECORX
printf "\e[%d;%dH \e[0m" $(($MENUBOTTOMDECORY + 3)) $MENUBOTTOMDECORX
FRAMEUPDATED=1
}
function DrawTetriBashVersionString()
{
printf "\e[%d;%dH%s\e[0m" $SCREENINFOSTRINGY $SCREENINFOSTRINGX "$SCREENINFOSTRING"
FRAMEUPDATED=1
}
function DrawTetriBashMainMenu()
{
for((i=0; i<MAINMENUITEMCOUNT; i++)); do
{
if [ $i -eq $MAINMENUSELECTION ]; then
{
printf "\e[%d;%dH${MAINMENUITEMSELECT}${MAINMENUITEMS[$i]}" ${MAINMENUITEMY[$i]} $MAINMENUX
}
else
{
printf "\e[%d;%dH${MAINMENUITEMNOTSEL}${MAINMENUITEMS[$i]}" ${MAINMENUITEMY[$i]} $MAINMENUX
}
fi
}
done
FRAMEUPDATED=1
}
function SetMainMenuSelection()
{
if [ -z "$1" ]; then
{
return 1
}
fi
if [ $1 -lt 0 ] || [ $1 -ge $MAINMENUITEMCOUNT ]; then
{
return 1
}
fi
if [ $1 -eq $MAINMENUSELECTION ]; then
{
return 0
}
fi
printf "\e[%d;%dH${MAINMENUITEMNOTSEL}${MAINMENUITEMS[$MAINMENUSELECTION]}" ${MAINMENUITEMY[$MAINMENUSELECTION]} $MAINMENUX
MAINMENUSELECTION=$1
printf "\e[%d;%dH${MAINMENUITEMSELECT}${MAINMENUITEMS[$MAINMENUSELECTION]}" ${MAINMENUITEMY[$MAINMENUSELECTION]} $MAINMENUX
FRAMEUPDATED=1
return 0
}
function ChangeMainMenuSelectionUp()
{
local NEXTITEM=$MAINMENUSELECTION
if [ $NEXTITEM -eq 0 ]; then
{
NEXTITEM=$(($MAINMENUITEMCOUNT - 1))
}
else
{
NEXTITEM=$(($NEXTITEM - 1))
}
fi
SetMainMenuSelection $NEXTITEM
}
function ChangeMainMenuSelectionDown()
{
local NEXTITEM=$MAINMENUSELECTION
if [ $NEXTITEM -eq $(($MAINMENUITEMCOUNT - 1)) ]; then
{
NEXTITEM=0
}
else
{
NEXTITEM=$(($NEXTITEM + 1))
}
fi
SetMainMenuSelection $NEXTITEM
}
function GameSetCurrentBlock()
{
case $GAMECURRENT in
0) GAMECURRENTARRAY=("${BLK1ARRAY[@]}");;
1) GAMECURRENTARRAY=("${BLK2ARRAY[@]}");;
2) GAMECURRENTARRAY=("${BLK3ARRAY[@]}");;
3) GAMECURRENTARRAY=("${BLK4ARRAY[@]}");;
4) GAMECURRENTARRAY=("${BLK5ARRAY[@]}");;
5) GAMECURRENTARRAY=("${BLK6ARRAY[@]}");;
6) GAMECURRENTARRAY=("${BLK7ARRAY[@]}");;
esac
GAMEBLOCKX=$(($TBASHOFFSETX + ($GAMEBLOCKSIZE * 2) - 2))
GAMEBLOCKY=$TBASHOFFSETY
GAMEBLOCKAPX=3
GAMEBLOCKAPY=0
}
function GameDrawCurrentBlock()
{
local BLAPOS=0
for((i=0; i<GAMEBLOCKSIZE; i++)); do
{
for((j=0; j<GAMEBLOCKSIZE; j++)); do
{
BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
case ${GAMECURRENTARRAY[$BLAPOS]} in
1) printf "\e[%d;%dH${BLK1}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
2) printf "\e[%d;%dH${BLK2}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
3) printf "\e[%d;%dH${BLK3}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
4) printf "\e[%d;%dH${BLK4}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
5) printf "\e[%d;%dH${BLK5}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
6) printf "\e[%d;%dH${BLK6}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
7) printf "\e[%d;%dH${BLK7}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
esac
}
done
}
done
FRAMEUPDATED=1
}
function GameClearCurrentBlock()
{
local BLAPOS=0
for((i=0; i<GAMEBLOCKSIZE; i++)); do
{
for((j=0; j<GAMEBLOCKSIZE; j++)); do
{
BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
case ${GAMECURRENTARRAY[$BLAPOS]} in
1) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
2) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
3) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
4) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
5) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
6) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
7) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));;
esac
}
done
}
done
FRAMEUPDATED=1
}
function GameGenerateBlock()
{
GAMECURRENTROT=0
GAMECURRENT=$GAMENEXT
GAMENEXT=$(($RANDOM % 7))
GameSetCurrentBlock
GameDrawCurrentBlock
HUDUpdateNext
}
function GameCommitBlock()
{
local BLAPOS=0
local BLKX=0
local BLKY=0
for((i=0; i<GAMEBLOCKSIZE; i++)); do
{
for((j=0; j<GAMEBLOCKSIZE; j++)); do
{
BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
BLKX=$(($j + $GAMEBLOCKAPX))
BLKY=$(($i + $GAMEBLOCKAPY))
if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then
{
continue
}
fi
if [ $BLKY -gt $(($TBASHH - 1)) ]; then
{
continue
}
fi
if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then
{
if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX))]} -gt 0 ]; then
{
GAMEFAILURE=1
}
fi
TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX))]=${GAMECURRENTARRAY[$BLAPOS]}
}
fi
}
done
}
done
if [ $GAMEFAILURE -eq 0 ]; then
{
GAMESCORE=$(($GAMESCORE + 1))
HUDUpdateScore
}
fi
}
function GameEraseLine()
{
local BLAPOS=0
local YPOSSTART=0
if [ -z "$1" ]; then
{
return 0
}
fi
YPOSSTART=$1
if [ $1 -gt $(($TBASHH - 1)) ]; then
{
return 0
}
fi
for((k=YPOSSTART; k>0; k--)); do
{
for((j=0; j<TBASHW; j++)); do
{
BLAPOS=$((($k * $TBASHW) + $j))
TBASHARRAY[$BLAPOS]=${TBASHARRAY[$(($BLAPOS - $TBASHW))]}
}
done
}
done
return 1
}
function GameClearLines()
{
local BLAPOS=0
for((i=0; i<GAMELINESTOCLEAR; i++)); do
{
GameEraseLine ${GAMELINESBUFFER[$i]}
}
done
DrawTetriBashArrayEx
GAMESCORE=$(($GAMESCORE + (($GAMELINESTOCLEAR * ($GAMELEVEL + 1)) * ($GAMESCOREMULT * ($GAMELEVEL + 1)))))
GAMELINES=$(($GAMELINES + $GAMELINESTOCLEAR))
GAMELEVELLINES=$(($GAMELEVELLINES + $GAMELINESTOCLEAR))
if [ $GAMELEVELLINES -ge $GAMELINESPERLEVEL ] && [ $GAMELEVEL -lt 10 ]; then
{
GAMELEVELLINES=$(($GAMELEVELLINES - $GAMELINESPERLEVEL))
GAMELEVEL=$(($GAMELEVEL + 1))
GAMESCOREMULT=$(($GAMESCOREMULTDEF + ($GAMELEVEL * $GAMESCOREMULTINC)))
GAMEINTERVAL=$(echo "$GAMEINTERVAL - 0.03" | bc)
HUDUpdateLevel
}
fi
HUDUpdateScore
HUDUpdateLines
}
function GameDetectLines()
{
local BLAPOS=0
local BLKCOUNT=0
local LINECLEARS=0
ZeroLinesBuffer
for((i=0; i<TBASHH; i++)); do
{
BLKCOUNT=0
for((j=0; j<TBASHW; j++)); do
{
BLAPOS=$((($i * $TBASHW) + $j))
if [ ${TBASHARRAY[$BLAPOS]} -gt 0 ]; then
{
BLKCOUNT=$(($BLKCOUNT + 1))
}
fi
}
done
if [ $BLKCOUNT -eq $TBASHW ]; then
{
GAMELINESBUFFER[$LINECLEARS]=$i
LINECLEARS=$(($LINECLEARS + 1))
}
fi
}
done
if [ $LINECLEARS -gt 0 ]; then
{
GAMELINESTOCLEAR=$LINECLEARS
GAMECLEARINPROGRESS=1
ACCUMULATOR="0.0"
GameDrawLineClear
return 1
}
fi
return 0
}
function GameDrawLineClear()
{
local BLAPOS=0
for((i=0; i<GAMELINESTOCLEAR; i++)); do
{
for((j=0; j<TBASHW; j++)); do
{
BLAPOS=$(((${GAMELINESBUFFER[$i]} * $TBASHW) + $j))
printf "\e[%d;%dH${GAMECLEARCHAR}${GAMECLEARCHAR}\e[0m" $(($TBASHOFFSETY + ${GAMELINESBUFFER[$i]})) $(($TBASHOFFSETX + ($j * 2)))
}
done
}
done
FRAMEUPDATED=1
}
function GameCheckMoveLeft()
{
local BLAPOS=0
local BLKX=0
local BLKY=0
for((i=0; i<GAMEBLOCKSIZE; i++)); do
{
for((j=0; j<GAMEBLOCKSIZE; j++)); do
{
BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
BLKX=$(($j + $GAMEBLOCKAPX))
BLKY=$(($i + $GAMEBLOCKAPY))
if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then
{
continue
}
fi
if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then
{
if [ $(($BLKX - 1)) -lt 0 ]; then
{
return 0
}
fi
if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX - 1))]} -gt 0 ]; then
{
return 0
}
fi
}
fi
}
done
}
done
return 1
}
function GameCheckMoveRight()
{
local BLAPOS=0
local BLKX=0
local BLKY=0
for((i=0; i<GAMEBLOCKSIZE; i++)); do
{
for((j=0; j<GAMEBLOCKSIZE; j++)); do
{
BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
BLKX=$(($j + $GAMEBLOCKAPX))
BLKY=$(($i + $GAMEBLOCKAPY))
if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then
{
continue
}
fi
if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then
{
if [ $(($BLKX + 1)) -gt $(($TBASHW - 1)) ]; then
{
return 0
}
fi
if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX + 1))]} -gt 0 ]; then
{
return 0
}
fi
}
fi
}
done
}
done
return 1
}
function GameCheckMoveDown()
{
local BLAPOS=0
local BLKX=0
local BLKY=0
for((i=0; i<GAMEBLOCKSIZE; i++)); do
{
for((j=0; j<GAMEBLOCKSIZE; j++)); do
{
BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
BLKX=$(($j + $GAMEBLOCKAPX))
BLKY=$(($i + $GAMEBLOCKAPY))
if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then
{
continue
}
fi
if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then
{
if [ $(($BLAPOS + $GAMEBLOCKSIZE)) -lt $GAMEBLOCKAREA ]; then
{
if [ ${GAMECURRENTARRAY[$(($BLAPOS + $GAMEBLOCKSIZE))]} -gt 0 ]; then
{
continue
}
fi
}
fi
if [ $(($BLKY + 1)) -gt $(($TBASHH - 1)) ]; then
{
return 0
}
fi
if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX + $TBASHW))]} -gt 0 ]; then
{
return 0
}
fi
}
fi
}
done
}
done
return 1
}
function GameMoveBlockLeft()
{
GameCheckMoveLeft
if [ $? -eq 1 ]; then
{
GameClearCurrentBlock
GAMEBLOCKAPX=$(($GAMEBLOCKAPX - 1))
GAMEBLOCKX=$(($GAMEBLOCKX - 2))
GameDrawCurrentBlock
}
fi
}
function GameMoveBlockRight()
{
GameCheckMoveRight
if [ $? -eq 1 ]; then
{
GameClearCurrentBlock
GAMEBLOCKAPX=$(($GAMEBLOCKAPX + 1))
GAMEBLOCKX=$(($GAMEBLOCKX + 2))
GameDrawCurrentBlock
}
fi
}
function GameMoveBlockDown()
{
if [ ! -z "$1" ]; then
{
if [ $1 -eq 1 ]; then
{
if [ $GAMEFAILURE -eq 0 ]; then
{
ACCUMULATOR="0.0"
}
else
{
return
}
fi
}
fi
}
fi
GameCheckMoveDown
if [ $? -eq 1 ]; then
{
GameClearCurrentBlock
GAMEBLOCKAPY=$(($GAMEBLOCKAPY + 1))
GAMEBLOCKY=$(($GAMEBLOCKY + 1))
GameDrawCurrentBlock
}
else
{
GameCommitBlock
GameDetectLines
if [ $? -eq 0 ]; then
{
GameGenerateBlock
}
fi
}
fi
}
function GameCheckRotate()
{
local NEWROT=0
local BLAPOS=0
local BLKX=0
local BLKY=0
if [ -z "$1" ]; then
{
return 0
}
fi
if [ $1 -eq 0 ]; then
{
if [ $GAMECURRENTROT -eq 0 ]; then
{
NEWROT=3
}
else
{
NEWROT=$(($GAMECURRENTROT - 1))
}
fi
}
else
{
if [ $GAMECURRENTROT -eq 3 ]; then
{
NEWROT=0
}
else
{
NEWROT=$(($GAMECURRENTROT + 1))
}
fi
}
fi
ZeroBlockBuffer
if [ $GAMECURRENT -eq 0 ]; then
{
case $NEWROT in
0) GAMEBLOCKBUFFER=("${BLK1ARRAY[@]}");;
1) GAMEBLOCKBUFFER=("${BLK1ARRAYR2[@]}");;
2) GAMEBLOCKBUFFER=("${BLK1ARRAYR3[@]}");;
3) GAMEBLOCKBUFFER=("${BLK1ARRAYR4[@]}");;
esac
}
elif [ $GAMECURRENT -eq 1 ]; then
{
GAMEBLOCKBUFFER=("${BLK2ARRAY[@]}")
return 1
}
elif [ $GAMECURRENT -eq 2 ]; then
{
case $NEWROT in
0) GAMEBLOCKBUFFER=("${BLK3ARRAY[@]}");;
1) GAMEBLOCKBUFFER=("${BLK3ARRAYR2[@]}");;
2) GAMEBLOCKBUFFER=("${BLK3ARRAY[@]}");;
3) GAMEBLOCKBUFFER=("${BLK3ARRAYR3[@]}");;
esac
}
elif [ $GAMECURRENT -eq 3 ]; then
{
case $NEWROT in
0) GAMEBLOCKBUFFER=("${BLK4ARRAY[@]}");;
1) GAMEBLOCKBUFFER=("${BLK4ARRAYR2[@]}");;
2) GAMEBLOCKBUFFER=("${BLK4ARRAY[@]}");;
3) GAMEBLOCKBUFFER=("${BLK4ARRAYR2[@]}");;
esac
}
elif [ $GAMECURRENT -eq 4 ]; then
{
case $NEWROT in
0) GAMEBLOCKBUFFER=("${BLK5ARRAY[@]}");;
1) GAMEBLOCKBUFFER=("${BLK5ARRAYR2[@]}");;
2) GAMEBLOCKBUFFER=("${BLK5ARRAY[@]}");;
3) GAMEBLOCKBUFFER=("${BLK5ARRAYR2[@]}");;
esac
}
elif [ $GAMECURRENT -eq 5 ]; then
{
case $NEWROT in
0) GAMEBLOCKBUFFER=("${BLK6ARRAY[@]}");;
1) GAMEBLOCKBUFFER=("${BLK6ARRAYR2[@]}");;
2) GAMEBLOCKBUFFER=("${BLK6ARRAYR3[@]}");;
3) GAMEBLOCKBUFFER=("${BLK6ARRAYR4[@]}");;
esac
}
elif [ $GAMECURRENT -eq 6 ]; then
{
case $NEWROT in
0) GAMEBLOCKBUFFER=("${BLK7ARRAY[@]}");;
1) GAMEBLOCKBUFFER=("${BLK7ARRAYR2[@]}");;
2) GAMEBLOCKBUFFER=("${BLK7ARRAYR3[@]}");;
3) GAMEBLOCKBUFFER=("${BLK7ARRAYR4[@]}");;
esac
}
fi
for((i=0; i<GAMEBLOCKSIZE; i++)); do
{
for((j=0; j<GAMEBLOCKSIZE; j++)); do
{
BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j))
BLKX=$(($j + $GAMEBLOCKAPX))
BLKY=$(($i + $GAMEBLOCKAPY))
if [ ${GAMEBLOCKBUFFER[$BLAPOS]} -gt 0 ]; then
{
if [ $BLKY -gt $(($TBASHH - 1)) ] || [ $BLKX -gt $(($TBASHW - 1)) ] || [ $BLKX -lt 0 ]; then
{
return 0
}
fi
if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX))]} -gt 0 ]; then
{
return 0
}
fi
}
fi
}
done
}
done
GAMECURRENTROT=$NEWROT
return 1
}
function GameRotateBlockLeft()
{
GameCheckRotate 0
if [ $? -eq 1 ]; then
{
GameClearCurrentBlock
GAMECURRENTARRAY=("${GAMEBLOCKBUFFER[@]}")
GameDrawCurrentBlock
}
fi
}
function GameRotateBlockRight()
{
GameCheckRotate 1
if [ $? -eq 1 ]; then
{
GameClearCurrentBlock
GAMECURRENTARRAY=("${GAMEBLOCKBUFFER[@]}")
GameDrawCurrentBlock
}
fi
}
function InitGame()
{
GAMESCORE=0
GAMELEVEL=0
GAMELINES=0
GAMEFAILURE=0
GAMEFAILURECOUNT=0
GAMEOVERINPROGRESS=0
GAMECLEARINPROGRESS=0
GAMELINESTOCLEAR=0
GAMESCOREMULT=$(($GAMESCOREMULTDEF + ($GAMELEVEL * $GAMESCOREMULTINC)))
GAMECURRENT=$(($RANDOM % 7))
GAMENEXT=$(($RANDOM % 7))
GAMEINTERVAL="0.5"
ACCUMULATOR="0.0"
ZeroTetriBashArray
DrawTetriBashArray
GameSetCurrentBlock
GameDrawCurrentBlock
}
function SetGameStateMenu()
{
TETRIBASHSTATE=1
GAMERUNNING=0
clear
DrawTetriBashTitle
DrawTetriBashMainMenu
DrawTetriBashMenuDecor
DrawTetriBashVersionString
}
function SetGameStatePlay()
{
clear
TETRIBASHSTATE=2
GAMERUNNING=1
InitGame
DrawTetriBashHUD
}
function SetGameStateAbout()
{
clear
TETRIBASHSTATE=3
GAMERUNNING=0
DrawTetriBashTitle
DrawTetriBashVersionString
DrawBorder $TBASHABOUTX $TBASHABOUTY $TBASHABOUTW $TBASHABOUTH
printf "\e[%d;%dH\e[1;32m${TETRIBASHINFO}\e[0m" $(($TBASHABOUTY + 1)) $(($TBASHABOUTX + 1))
printf "\e[%d;%dH\e[1;32m${TETRIBASHINFO2}\e[0m" $(($TBASHABOUTY + 2)) $(($TBASHABOUTX + 1))
printf "\e[%d;%dH\e[1;32m${TETRIBASHINFO3}\e[0m" $(($TBASHABOUTY + 4)) $(($TBASHABOUTX + 1))
}
function SetGameStatePause()
{
clear
TETRIBASHSTATE=4
GAMERUNNING=0
}
function SetGameStateExit()
{
clear
TETRIBASHSTATE=0
GAMERUNNING=0
}
function ExecuteMainMenuSelection()
{
case $MAINMENUSELECTION in
0) SetGameStatePlay;;
2) SetGameStateAbout;;
3) SetGameStateExit;;
esac
}
#=============================================================================
#-----------------------------------------------------------------------------
# [ TetriBASH Script ]
#-----------------------------------------------------------------------------
#=============================================================================
# Clear Screen
clear
stty -echo -icanon time 0 min 0
SetGameStateMenu
# Game Loop
while true; do
{
TIMESTART=$(date +%s.%N)
KEY=$(dd bs=1 count=1 2> /dev/null; echo ".")
KEY=${KEY%.}
if [ $TETRIBASHSTATE -eq 1 ]; then
{
case $KEY in
q) SetGameStateExit;;
w) ChangeMainMenuSelectionUp;;
a) ChangeMainMenuSelectionUp;;
s) ChangeMainMenuSelectionDown;;
d) ChangeMainMenuSelectionDown;;
k) ExecuteMainMenuSelection;;
# ?) printf "$KEY" ;;
esac
}
elif [ $TETRIBASHSTATE -eq 2 ]; then
{
if [ $GAMERUNNING -eq 1 ]; then
{
if [ $GAMECLEARINPROGRESS -eq 1 ]; then
{
case $KEY in
q) SetGameStateMenu;;
esac
if [[ $(echo "if (${ACCUMULATOR} > ${GAMECLEARINTERVAL}) 1" | bc) -eq 1 ]]; then
{
GameClearLines
GAMECLEARINPROGRESS=0
GAMELINESTOCLEAR=0
GameGenerateBlock
}
fi
}
elif [ $GAMEOVERINPROGRESS -eq 1 ]; then
{
case $KEY in
q) SetGameStateMenu;;
esac
if [[ $(echo "if (${ACCUMULATOR} > ${GAMEOVERINTERVAL}) 1" | bc) -eq 1 ]]; then
{
SetGameStateMenu
}
fi
}
else
{
case $KEY in
q) SetGameStateMenu;;
w) DrawTetriBashArray;;
a) GameMoveBlockLeft;;
s) GameMoveBlockDown 1;;
d) GameMoveBlockRight;;
j) GameRotateBlockLeft;;
l) GameRotateBlockRight;;
# ?) printf "%d\n" "'$KEY" ;;
esac
if [[ $(echo "if (${ACCUMULATOR} > ${GAMEINTERVAL}) 1" | bc) -eq 1 ]]; then
{
GameMoveBlockDown
if [ $GAMEFAILURE -eq 1 ]; then
{
GAMEFAILURECOUNT=$(($GAMEFAILURECOUNT + 1))
if [ $GAMEFAILURECOUNT -eq $GAMEFAILUREMAX ]; then
{
GAMEOVERINPROGRESS=1
ACCUMULATOR="0.0"
GameOverClearTetriBashArray
DrawTetriBashArray
HUDDrawGameOver
}
fi
GAMEINTERVAL=$(echo "$GAMEINTERVAL - 0.05" | bc)
}
fi
ACCUMULATOR=$(echo "$ACCUMULATOR - $GAMEINTERVAL" | bc)
}
fi
}
fi
}
fi
}
elif [ $TETRIBASHSTATE -eq 3 ]; then
{
case $KEY in
q) SetGameStateMenu;;
esac
}
elif [ $TETRIBASHSTATE -eq 4 ]; then
{
case $KEY in
q) SetGameStateExit ;;
w) DrawTetriBashArray ;;
a) DrawBorder 4 2 10 10 ;;
s) DrawTetriBashHUD ;;
d) DrawTetriBashTitle;;
?) printf "%d\n" "'$KEY" ;;
esac
}
else
{
break
}
fi
if [ $FRAMEUPDATED -eq 1 ]; then
{
if [ $TETRIBASHDEBUG -eq 1 ]; then
{
if [ $TETRIBASHSTATE -eq 2 ]; then
{
printf "\e[1;2H\e[1;32mDebug:BlkPos(%d,%d) BlkTerm(%d,%d) Delta(%2.3g) Accu(%2.3g) LC(%d) \e[0m" $GAMEBLOCKAPX $GAMEBLOCKAPY $GAMEBLOCKX $GAMEBLOCKY $DELTATIME $ACCUMULATOR $GAMECLEARINPROGRESS
}
fi
}
fi
printf "\e[1;1H"
FRAMEUPDATED=0
}
fi
TIMEEND=$(date +%s.%N)
DELTATIME=$(echo "$TIMEEND - $TIMESTART" | bc)
if [ $TETRIBASHSTATE -eq 2 ] && [ $GAMERUNNING -eq 1 ]; then
{
ACCUMULATOR=$(echo "$ACCUMULATOR + $DELTATIME" | bc)
}
fi
}
done
# Clean Up
printf "\e[0m"
clear
stty sane
exit 0
I attached the script file as well, just drop the .txt.
The controls are as follows:
K - Select menu item
Q - quit or back
WASD - menu nav and block movement
J and L - rotate piece
Don't hold down keys too long or the key buffer will sometimes fill up quicker than it gets emptied (does not seem to happen as quickly while running slower in a VM) .