#!/bin/sh
case "`echo -e`" in
-e)
ECHO() { echo "$@"; }
;;
*)
ECHO() { echo -e "$@"; }
;;
esac
case "`ECHO '\r'`" in
'\r')
case "`(print X) 2> /dev/null`" in
X)
ECHO() { print "$@"; }
;;
*)
PATH=/usr/5bin:$PATH
export PATH
;;
esac
;;
esac
case "$((1))" in
1)
expr()
{
echo "$(($*))"
}
;;
esac 2> /dev/null
cls()
{
ECHO '\033[H\033[2J\c'
}
cursor()
{
ECHO '\033['$2';'$1'H\c'
}
beep()
{
ECHO '\07\c'
}
new_screen()
{
ECHO '\033\067\033[?47h\c'
}
exit_screen()
{
ECHO '\033[?47l\033\070\c'
}
init_tty()
{
stty -icanon -echo min 1 -ixon
new_screen
cls
}
quit_tty()
{
cls
exit_screen
stty icanon echo eof '^d' ixon
}
getchar()
{
dd bs=1 count=1 2> /dev/null
}
# trap
if (trap '' INT) 2> /dev/null
then
SIGINT=INT SIGQUIT=QUIT SIGTERM=TERM SIGTSTP=TSTP
else
SIGINT=2 SIGQUIT=3 SIGTERM=15 SIGTSTP=18
fi
# random
if [ "$RANDOM" != "$RANDOM" ]
then
random_short()
{
eval $1=$RANDOM
}
elif [ -c /dev/urandom ]
then
random_short()
{
rand_s=`(
set \`dd if=/dev/urandom bs=2 count=1 2> /dev/null | od -d\`
echo "$2"
)`
eval $1=$rand_s
}
else
seed=$$
random_short()
{
seed=`expr $seed \* 256 % 32768 + \
\( $seed / 16384 + $seed / 8192 \) % 2 \* 128 + \
\( $seed / 8192 + $seed / 4096 \) % 2 \* 64 + \
\( $seed / 4096 + $seed / 2048 \) % 2 \* 32 + \
\( $seed / 2048 + $seed / 1024 \) % 2 \* 16 + \
\( $seed / 1024 + $seed / 512 \) % 2 \* 8 + \
\( $seed / 512 + $seed / 256 \) % 2 \* 4 + \
\( $seed / 256 + $seed / 128 \) % 2 \* 2 + \
\( $seed / 128 + $seed / 64 \) % 2`
eval $1=$seed
}
fi
rand()
{
random_short rand_val
rand_val=`expr $rand_val % 256 \* \( "$3" - "$2" + 1 \) / 256 + "$2"`
eval $1=$rand_val
}
# scroll
partial_scroll()
{
ECHO '\033['$1';'$2'r\c'
}
partial_scroll_off()
{
ECHO '\033[r\c'
}
scroll_up()
{
ECHO '\033M\c'
}
# program
piece_face_b='B' piece_face_c='C' piece_face_d='D' piece_face_e='E'
piece_face_f='F' piece_face_g='G' piece_face_h='H' piece_face_i='I'
piece_face_j='J' piece_face_k='K' piece_face_l='L' piece_face_m='M'
piece_face_n='N' piece_face_o='O' piece_face_p='P' piece_face_q='Q'
piece_face_r='R' piece_face_s='S' piece_face_t='T' piece_face_u='U'
piece_face_v='V' piece_face_w='W' piece_face_x='X' piece_face_y='Y'
piece_face_z='Z'
pkey_1=b pkey_2=c pkey_3=d pkey_4=e pkey_5=f pkey_6=g pkey_7=h pkey_8=i
pkey_9=j pkey_10=k pkey_11=l pkey_12=m pkey_13=n pkey_14=o pkey_15=p
pkey_16=q pkey_17=r pkey_18=s pkey_19=t pkey_20=u pkey_21=v pkey_22=w
pkey_23=x pkey_24=y pkey_25=z
init_map()
{
cursor 25 24
ECHO 'SCORE:\c'
cursor 40 23
ECHO '┷\c'
cursor 1 24
ECHO '[A]←LEFT─\c'
cursor 41 24
ECHO '([Shift] +[Q]-quit) ─RIGHT→[;]\c'
cursor 80 24
}
put_score()
{
cursor 31 24
printf %8d $1
}
add_score()
{
score=`expr $score + $1`
if [ $score -lt 0 ]; then
score=0
fi
put_score $score
}
piece_down()
{
cursor 1 1
scroll_up
}
put_piece()
{
eval piece_face=\$piece_face_$3
px=`expr $1 - 2`
py=$2
cursor $px $py
ECHO '┏━┓\c'
py=`expr $py + 1`
cursor $px $py
ECHO '┃'"$piece_face"'┃\c'
py=`expr $py + 1`
cursor $px $py
ECHO '┗━┛\c'
}
remove_piece()
{
px=`expr $1 - 2`
py=$2
cursor $px $py
ECHO ' \c'
py=`expr $py + 1`
cursor $px $py
ECHO ' \c'
py=`expr $py + 1`
cursor $px $py
ECHO ' \c'
}
put_cannon()
{
cursor $1 $2
ECHO '┷\c'
}
remove_cannon()
{
cursor $1 $2
ECHO ' \c'
}
fire()
{
i=$2
while [ $i -gt $3 ]; do
i=`expr $i - 1`
cursor $1 $i
ECHO '│\c'
done
cursor $1 $2
i=$2
while [ $i -gt $3 ]; do
i=`expr $i - 1`
cursor $1 $i
ECHO ' \c'
done
}
# main
trap '' $SIGINT $SIGQUIT $SIGTSTP
trap : $SIGTERM
init_tty
init_map
partial_scroll 1 22
cannon_x=40
old_cannon_x=$cannon_x
draw=1
score=0
put_score $score
seq_20='1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20'
for i in $seq_20
do
eval piece_x_$i=0 piece_y_$i=0
done
(
while :
do
sleep 1
ECHO '~\c'
done &
/bin/cat
) | while :
do
if [ "$draw" ]; then
draw=
remove_cannon $old_cannon_x 23
put_cannon $cannon_x 23
old_cannon_x=$cannon_x
fi
cursor $cannon_x 23
key=`getchar`
case "$key" in
'~')
for i in $seq_20
do
eval y=\$piece_y_$i
if [ $y -gt 0 ]; then
y=`expr $y + 1`
eval piece_y_$i=$y
fi
done
piece_down
for i in $seq_20
do
eval y=\$piece_y_$i
if [ $y -eq 0 ]; then
rand x 1 13
x=`expr $x \* 6 - 2`
y_min=99
for j in $seq_20
do
eval xx=\$piece_x_$j
if [ $xx -eq $x ]; then
eval yy=\$piece_y_$j
if [ $yy -lt $y_min ]; then
y_min=$yy
fi
fi
done
if [ $y_min -ge 4 ]; then
eval piece_x_$i=$x
eval piece_y_$i=1
rand k 1 25
eval k=\$pkey_$k
eval piece_key_$i=$k
put_piece $x 1 $k
fi
break
fi
done
for i in $seq_20
do
eval y=\$piece_y_$i
if [ $y -ge 21 ]; then
cursor 1 1
ECHO 'Game Over\nHit [Shift]+[Q] to quit...\c'
while :
do
case "`getchar`" in
Q)
break
;;
esac
done
kill -TERM 0
break 2
fi
done
;;
Q)
kill -TERM 0
break
;;
a|D|4)
cannon_x=`expr $cannon_x - 6`
if [ $cannon_x -lt 4 ]; then
cannon_x=$old_cannon_x
else
draw=1
fi
;;
';'|C|6)
cannon_x=`expr $cannon_x + 6`
if [ $cannon_x -gt 76 ]; then
cannon_x=$old_cannon_x
else
draw=1
fi
;;
[b-z])
y_max=0
for i in $seq_20
do
eval x=\$piece_x_$i
eval y=\$piece_y_$i
if [ $x -eq $cannon_x -a $y -gt 0 ]; then
if [ $y -gt $y_max ]; then
y_max=$y
j=$i
fi
fi
done
if [ $y_max -gt 0 ]; then
eval k=\$piece_key_$j
if [ "$key" = $k ]; then
fire $cannon_x 23 $y_max
remove_piece $cannon_x $y_max
eval piece_x_$j=0
eval piece_y_$j=0
add_score 10
else
y=`expr $y_max + 3`
fire $cannon_x 23 $y
beep
add_score -1
fi
else
fire $cannon_x 23 1
beep
add_score -1
fi
;;
esac
done
partial_scroll_off
quit_tty
exit