xref: /titanic_51/usr/src/cmd/ast/libshell/common/scripts/gnaw.sh (revision b4dd7d09880f14016feece03929a224eca1cf39a)
1*b4dd7d09SAndy Fiddaman#!/usr/bin/ksh93
2*b4dd7d09SAndy Fiddaman
3*b4dd7d09SAndy Fiddaman#
4*b4dd7d09SAndy Fiddaman# CDDL HEADER START
5*b4dd7d09SAndy Fiddaman#
6*b4dd7d09SAndy Fiddaman# The contents of this file are subject to the terms of the
7*b4dd7d09SAndy Fiddaman# Common Development and Distribution License (the "License").
8*b4dd7d09SAndy Fiddaman# You may not use this file except in compliance with the License.
9*b4dd7d09SAndy Fiddaman#
10*b4dd7d09SAndy Fiddaman# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11*b4dd7d09SAndy Fiddaman# or http://www.opensolaris.org/os/licensing.
12*b4dd7d09SAndy Fiddaman# See the License for the specific language governing permissions
13*b4dd7d09SAndy Fiddaman# and limitations under the License.
14*b4dd7d09SAndy Fiddaman#
15*b4dd7d09SAndy Fiddaman# When distributing Covered Code, include this CDDL HEADER in each
16*b4dd7d09SAndy Fiddaman# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17*b4dd7d09SAndy Fiddaman# If applicable, add the following below this CDDL HEADER, with the
18*b4dd7d09SAndy Fiddaman# fields enclosed by brackets "[]" replaced with your own identifying
19*b4dd7d09SAndy Fiddaman# information: Portions Copyright [yyyy] [name of copyright owner]
20*b4dd7d09SAndy Fiddaman#
21*b4dd7d09SAndy Fiddaman# CDDL HEADER END
22*b4dd7d09SAndy Fiddaman#
23*b4dd7d09SAndy Fiddaman
24*b4dd7d09SAndy Fiddaman#
25*b4dd7d09SAndy Fiddaman# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
26*b4dd7d09SAndy Fiddaman#
27*b4dd7d09SAndy Fiddaman
28*b4dd7d09SAndy Fiddaman#
29*b4dd7d09SAndy Fiddaman# gnaw - a simple ksh93 technology demo
30*b4dd7d09SAndy Fiddaman#
31*b4dd7d09SAndy Fiddaman# Note that this script has been written with the main idea to show
32*b4dd7d09SAndy Fiddaman# many of ksh93's new features (comparing to ksh88/bash) and not
33*b4dd7d09SAndy Fiddaman# as an example of efficient&&clean script code (much of the code
34*b4dd7d09SAndy Fiddaman# could be done more efficient using compound variables, this script
35*b4dd7d09SAndy Fiddaman# focus is the usage of associative arrays).
36*b4dd7d09SAndy Fiddaman#
37*b4dd7d09SAndy Fiddaman
38*b4dd7d09SAndy Fiddaman# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
39*b4dd7d09SAndy Fiddamanexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
40*b4dd7d09SAndy Fiddaman
41*b4dd7d09SAndy Fiddaman# Make sure all math stuff runs in the "C" locale to avoid problems
42*b4dd7d09SAndy Fiddaman# with alternative # radix point representations (e.g. ',' instead of
43*b4dd7d09SAndy Fiddaman# '.' in de_DE.*-locales). This needs to be set _before_ any
44*b4dd7d09SAndy Fiddaman# floating-point constants are defined in this script).
45*b4dd7d09SAndy Fiddamanif [[ "${LC_ALL}" != "" ]] ; then
46*b4dd7d09SAndy Fiddaman    export \
47*b4dd7d09SAndy Fiddaman        LC_MONETARY="${LC_ALL}" \
48*b4dd7d09SAndy Fiddaman        LC_MESSAGES="${LC_ALL}" \
49*b4dd7d09SAndy Fiddaman        LC_COLLATE="${LC_ALL}" \
50*b4dd7d09SAndy Fiddaman        LC_CTYPE="${LC_ALL}"
51*b4dd7d09SAndy Fiddaman        unset LC_ALL
52*b4dd7d09SAndy Fiddamanfi
53*b4dd7d09SAndy Fiddamanexport LC_NUMERIC=C
54*b4dd7d09SAndy Fiddaman
55*b4dd7d09SAndy Fiddamanfunction print_setcursorpos
56*b4dd7d09SAndy Fiddaman{
57*b4dd7d09SAndy Fiddaman    print -n -- "${vtcode[cup_${1}_${2}]}"
58*b4dd7d09SAndy Fiddaman}
59*b4dd7d09SAndy Fiddaman
60*b4dd7d09SAndy Fiddamanfunction beep
61*b4dd7d09SAndy Fiddaman{
62*b4dd7d09SAndy Fiddaman    ${quiet} || print -n -- "${vtcode["bel"]}"
63*b4dd7d09SAndy Fiddaman}
64*b4dd7d09SAndy Fiddaman
65*b4dd7d09SAndy Fiddamanfunction fatal_error
66*b4dd7d09SAndy Fiddaman{
67*b4dd7d09SAndy Fiddaman    print -u2 "${progname}: $*"
68*b4dd7d09SAndy Fiddaman    exit 1
69*b4dd7d09SAndy Fiddaman}
70*b4dd7d09SAndy Fiddaman
71*b4dd7d09SAndy Fiddaman# Get terminal size and put values into a compound variable with the integer
72*b4dd7d09SAndy Fiddaman# members "columns" and "lines"
73*b4dd7d09SAndy Fiddamanfunction get_term_size
74*b4dd7d09SAndy Fiddaman{
75*b4dd7d09SAndy Fiddaman	nameref rect=$1
76*b4dd7d09SAndy Fiddaman
77*b4dd7d09SAndy Fiddaman	rect.columns=${ tput cols ; } || return 1
78*b4dd7d09SAndy Fiddaman	rect.lines=${ tput lines ; }  || return 1
79*b4dd7d09SAndy Fiddaman
80*b4dd7d09SAndy Fiddaman	return 0
81*b4dd7d09SAndy Fiddaman}
82*b4dd7d09SAndy Fiddaman
83*b4dd7d09SAndy Fiddamanfunction print_levelmap
84*b4dd7d09SAndy Fiddaman{
85*b4dd7d09SAndy Fiddaman    integer screen_y_offset=$1
86*b4dd7d09SAndy Fiddaman    integer start_y_pos=$2 # start at this line in the map
87*b4dd7d09SAndy Fiddaman    integer max_numlines=$3 # maximum lines we're allowed to render
88*b4dd7d09SAndy Fiddaman    integer x
89*b4dd7d09SAndy Fiddaman    integer y
90*b4dd7d09SAndy Fiddaman    typeset line=""
91*b4dd7d09SAndy Fiddaman
92*b4dd7d09SAndy Fiddaman    print_setcursorpos 0 ${screen_y_offset}
93*b4dd7d09SAndy Fiddaman
94*b4dd7d09SAndy Fiddaman    for (( y=start_y_pos; (y-start_y_pos) < max_numlines && y < levelmap["max_y"] ; y++ )) ; do
95*b4dd7d09SAndy Fiddaman        line=""
96*b4dd7d09SAndy Fiddaman        for (( x=0 ; x < levelmap["max_x"] ; x++ )) ; do
97*b4dd7d09SAndy Fiddaman            line+="${levelmap["${x}_${y}"]}"
98*b4dd7d09SAndy Fiddaman        done
99*b4dd7d09SAndy Fiddaman
100*b4dd7d09SAndy Fiddaman        print -- "${line} "
101*b4dd7d09SAndy Fiddaman    done
102*b4dd7d09SAndy Fiddaman
103*b4dd7d09SAndy Fiddaman    # print lines filled with spaces for each line not filled
104*b4dd7d09SAndy Fiddaman    # by the level map
105*b4dd7d09SAndy Fiddaman    line="${vtcode["spaceline"]:0:${levelmap["max_x"]}}"
106*b4dd7d09SAndy Fiddaman    for (( ; (y-start_y_pos) < max_numlines ; y++ )) ; do
107*b4dd7d09SAndy Fiddaman        print -- "${line} "
108*b4dd7d09SAndy Fiddaman    done
109*b4dd7d09SAndy Fiddaman    return 0
110*b4dd7d09SAndy Fiddaman}
111*b4dd7d09SAndy Fiddaman
112*b4dd7d09SAndy Fiddamanfunction level_completed
113*b4dd7d09SAndy Fiddaman{
114*b4dd7d09SAndy Fiddaman    integer i
115*b4dd7d09SAndy Fiddaman    typeset dummy
116*b4dd7d09SAndy Fiddaman    typeset render_buffer="$(
117*b4dd7d09SAndy Fiddaman    print -n -- "${vtcode["clear"]}"
118*b4dd7d09SAndy Fiddaman    cat <<ENDOFTEXT
119*b4dd7d09SAndy Fiddaman
120*b4dd7d09SAndy Fiddaman #       ######  #    #  ######  #
121*b4dd7d09SAndy Fiddaman #       #       #    #  #       #
122*b4dd7d09SAndy Fiddaman #       #####   #    #  #####   #
123*b4dd7d09SAndy Fiddaman #       #       #    #  #       #
124*b4dd7d09SAndy Fiddaman #       #        #  #   #       #
125*b4dd7d09SAndy Fiddaman ######  ######    ##    ######  ######
126*b4dd7d09SAndy Fiddaman
127*b4dd7d09SAndy Fiddaman             (Good job)
128*b4dd7d09SAndy Fiddaman
129*b4dd7d09SAndy Fiddaman     #####    ####   #    #  ######
130*b4dd7d09SAndy Fiddaman     #    #  #    #  ##   #  #
131*b4dd7d09SAndy Fiddaman     #    #  #    #  # #  #  #####
132*b4dd7d09SAndy Fiddaman     #    #  #    #  #  # #  #
133*b4dd7d09SAndy Fiddaman     #    #  #    #  #   ##  #
134*b4dd7d09SAndy Fiddaman     #####    ####   #    #  ######
135*b4dd7d09SAndy Fiddaman
136*b4dd7d09SAndy Fiddaman
137*b4dd7d09SAndy FiddamanENDOFTEXT
138*b4dd7d09SAndy Fiddaman
139*b4dd7d09SAndy Fiddaman    printf "    SCORE: --> %s <--\n" "${player["score"]}"
140*b4dd7d09SAndy Fiddaman    printf "    LIVES: --> %s <--\n" "${player["lives"]}"
141*b4dd7d09SAndy Fiddaman    )"
142*b4dd7d09SAndy Fiddaman    print -- "${render_buffer}${end_of_frame}"
143*b4dd7d09SAndy Fiddaman
144*b4dd7d09SAndy Fiddaman    # wait five seconds and swallow any user input
145*b4dd7d09SAndy Fiddaman    for (( i=0 ; i < 50 ; i++ )) ; do
146*b4dd7d09SAndy Fiddaman        read -r -t 0.1 -n 1 dummy
147*b4dd7d09SAndy Fiddaman    done
148*b4dd7d09SAndy Fiddaman
149*b4dd7d09SAndy Fiddaman    print "Press any key to continue...${end_of_frame}"
150*b4dd7d09SAndy Fiddaman    # wait five secs or for a key
151*b4dd7d09SAndy Fiddaman    read -r -t 5 -n 1 dummy
152*b4dd7d09SAndy Fiddaman    return 0
153*b4dd7d09SAndy Fiddaman}
154*b4dd7d09SAndy Fiddaman
155*b4dd7d09SAndy Fiddamanfunction game_over
156*b4dd7d09SAndy Fiddaman{
157*b4dd7d09SAndy Fiddaman    typeset dummy
158*b4dd7d09SAndy Fiddaman    typeset render_buffer="$(
159*b4dd7d09SAndy Fiddaman    print -n -- "${vtcode["clear"]}"
160*b4dd7d09SAndy Fiddaman    cat <<ENDOFTEXT
161*b4dd7d09SAndy Fiddaman
162*b4dd7d09SAndy Fiddaman  ####     ##    #    #  ######
163*b4dd7d09SAndy Fiddaman #    #   #  #   ##  ##  #
164*b4dd7d09SAndy Fiddaman #       #    #  # ## #  #####
165*b4dd7d09SAndy Fiddaman #  ###  ######  #    #  #
166*b4dd7d09SAndy Fiddaman #    #  #    #  #    #  #
167*b4dd7d09SAndy Fiddaman  ####   #    #  #    #  ######
168*b4dd7d09SAndy Fiddaman
169*b4dd7d09SAndy Fiddaman            (LOSER!)
170*b4dd7d09SAndy Fiddaman
171*b4dd7d09SAndy Fiddaman  ####   #    #  ######  #####
172*b4dd7d09SAndy Fiddaman #    #  #    #  #       #    #
173*b4dd7d09SAndy Fiddaman #    #  #    #  #####   #    #
174*b4dd7d09SAndy Fiddaman #    #  #    #  #       #####
175*b4dd7d09SAndy Fiddaman #    #   #  #   #       #   #
176*b4dd7d09SAndy Fiddaman  ####     ##    ######  #    #
177*b4dd7d09SAndy Fiddaman
178*b4dd7d09SAndy FiddamanENDOFTEXT
179*b4dd7d09SAndy Fiddaman
180*b4dd7d09SAndy Fiddaman    printf "\n    SCORE: --> %s <--\n" "${player["score"]}"
181*b4dd7d09SAndy Fiddaman    )"
182*b4dd7d09SAndy Fiddaman    print -r -- "${render_buffer}${end_of_frame}"
183*b4dd7d09SAndy Fiddaman
184*b4dd7d09SAndy Fiddaman    # wait five seconds and swallow any user input
185*b4dd7d09SAndy Fiddaman    for (( i=0 ; i < 50 ; i++ )) ; do
186*b4dd7d09SAndy Fiddaman        read -r -t 0.1 -n 1 dummy
187*b4dd7d09SAndy Fiddaman    done
188*b4dd7d09SAndy Fiddaman
189*b4dd7d09SAndy Fiddaman    print "Press any key to continue...${end_of_frame}"
190*b4dd7d09SAndy Fiddaman    # wait five secs or for a key
191*b4dd7d09SAndy Fiddaman    read -r -t 5 -n 1 dummy
192*b4dd7d09SAndy Fiddaman    return 0
193*b4dd7d09SAndy Fiddaman}
194*b4dd7d09SAndy Fiddaman
195*b4dd7d09SAndy Fiddamanfunction run_logo
196*b4dd7d09SAndy Fiddaman{
197*b4dd7d09SAndy Fiddaman    typeset render_buffer="$(
198*b4dd7d09SAndy Fiddaman    cat <<ENDOFTEXT
199*b4dd7d09SAndy Fiddaman
200*b4dd7d09SAndy Fiddaman #####  #     #    #    #     #   ###
201*b4dd7d09SAndy Fiddaman#     # ##    #   # #   #  #  #   ###
202*b4dd7d09SAndy Fiddaman#       # #   #  #   #  #  #  #   ###
203*b4dd7d09SAndy Fiddaman#  #### #  #  # #     # #  #  #    #
204*b4dd7d09SAndy Fiddaman#     # #   # # ####### #  #  #
205*b4dd7d09SAndy Fiddaman#     # #    ## #     # #  #  #   ###
206*b4dd7d09SAndy Fiddaman #####  #     # #     #  ## ##    ###
207*b4dd7d09SAndy FiddamanENDOFTEXT
208*b4dd7d09SAndy Fiddaman    )"
209*b4dd7d09SAndy Fiddaman    print -- "${vtcode["clear"]}${render_buffer}"
210*b4dd7d09SAndy Fiddaman
211*b4dd7d09SAndy Fiddaman    # wait two seconds and swallow any user input
212*b4dd7d09SAndy Fiddaman    for (( i=0 ; i < 20 ; i++ )) ; do
213*b4dd7d09SAndy Fiddaman        read -r -t 0.1 -n 1 dummy
214*b4dd7d09SAndy Fiddaman    done
215*b4dd7d09SAndy Fiddaman
216*b4dd7d09SAndy Fiddaman    print "\n   (The KornShell 93 maze game)"
217*b4dd7d09SAndy Fiddaman
218*b4dd7d09SAndy Fiddaman    attract_mode
219*b4dd7d09SAndy Fiddaman    return 0
220*b4dd7d09SAndy Fiddaman}
221*b4dd7d09SAndy Fiddaman
222*b4dd7d09SAndy Fiddamanfunction attract_mode
223*b4dd7d09SAndy Fiddaman{
224*b4dd7d09SAndy Fiddaman(
225*b4dd7d09SAndy Fiddaman    # Now present some info, line-by-line in an endless loop
226*b4dd7d09SAndy Fiddaman    # until the user presses a key (we turn the "magic" return
227*b4dd7d09SAndy Fiddaman    # code for that)
228*b4dd7d09SAndy Fiddaman    integer -r magic_return_code=69
229*b4dd7d09SAndy Fiddaman    typeset line
230*b4dd7d09SAndy Fiddaman    IFS='' ; # Make sure we do not swallow whitespaces
231*b4dd7d09SAndy Fiddaman
232*b4dd7d09SAndy Fiddaman    while true ; do
233*b4dd7d09SAndy Fiddaman        (
234*b4dd7d09SAndy Fiddaman            redirect 5<&0
235*b4dd7d09SAndy Fiddaman
236*b4dd7d09SAndy Fiddaman        (cat <<ENDOFTEXT
237*b4dd7d09SAndy Fiddaman
238*b4dd7d09SAndy Fiddaman
239*b4dd7d09SAndy Fiddaman
240*b4dd7d09SAndy Fiddaman
241*b4dd7d09SAndy Fiddaman
242*b4dd7d09SAndy Fiddaman         ################
243*b4dd7d09SAndy Fiddaman     ########################
244*b4dd7d09SAndy Fiddaman   ############################
245*b4dd7d09SAndy Fiddaman  #######     ######     #######
246*b4dd7d09SAndy Fiddaman  ######     ######     ########
247*b4dd7d09SAndy Fiddaman  #######     ######     #######
248*b4dd7d09SAndy Fiddaman  ##############################
249*b4dd7d09SAndy Fiddaman  ##############################
250*b4dd7d09SAndy Fiddaman  ##############################
251*b4dd7d09SAndy Fiddaman  ##############################
252*b4dd7d09SAndy Fiddaman  ##############################
253*b4dd7d09SAndy Fiddaman  #########  ########  #########
254*b4dd7d09SAndy Fiddaman  #  ####      ####      ####  #
255*b4dd7d09SAndy Fiddaman
256*b4dd7d09SAndy Fiddaman
257*b4dd7d09SAndy Fiddaman
258*b4dd7d09SAndy Fiddaman
259*b4dd7d09SAndy Fiddaman
260*b4dd7d09SAndy Fiddaman
261*b4dd7d09SAndy Fiddaman           Written by
262*b4dd7d09SAndy Fiddaman
263*b4dd7d09SAndy Fiddaman          Roland Mainz
264*b4dd7d09SAndy Fiddaman    (roland.mainz@nrubsig.org)
265*b4dd7d09SAndy Fiddaman
266*b4dd7d09SAndy Fiddaman
267*b4dd7d09SAndy Fiddaman
268*b4dd7d09SAndy Fiddaman
269*b4dd7d09SAndy Fiddaman
270*b4dd7d09SAndy Fiddaman
271*b4dd7d09SAndy Fiddaman           ##############
272*b4dd7d09SAndy Fiddaman      ########################
273*b4dd7d09SAndy Fiddaman   #################**############
274*b4dd7d09SAndy Fiddaman  ################################
275*b4dd7d09SAndy Fiddaman ############################
276*b4dd7d09SAndy Fiddaman ######################
277*b4dd7d09SAndy Fiddaman ################
278*b4dd7d09SAndy Fiddaman ######################
279*b4dd7d09SAndy Fiddaman ############################
280*b4dd7d09SAndy Fiddaman  ################################
281*b4dd7d09SAndy Fiddaman   ##############################
282*b4dd7d09SAndy Fiddaman      ########################
283*b4dd7d09SAndy Fiddaman           ##############
284*b4dd7d09SAndy Fiddaman
285*b4dd7d09SAndy Fiddaman
286*b4dd7d09SAndy Fiddaman
287*b4dd7d09SAndy Fiddaman
288*b4dd7d09SAndy Fiddaman
289*b4dd7d09SAndy Fiddaman
290*b4dd7d09SAndy Fiddaman
291*b4dd7d09SAndy Fiddaman             High scores:
292*b4dd7d09SAndy Fiddaman
293*b4dd7d09SAndy Fiddaman        * 'chin'      8200 pt
294*b4dd7d09SAndy Fiddaman        * 'gisburn'   7900 pt
295*b4dd7d09SAndy Fiddaman        * 'tpenta'    5520 pt
296*b4dd7d09SAndy Fiddaman        * 'kupfer'    5510 pt
297*b4dd7d09SAndy Fiddaman        * 'noname'    5000 pt
298*b4dd7d09SAndy Fiddaman        * 'noname'    4000 pt
299*b4dd7d09SAndy Fiddaman        * 'livad'     3120 pt
300*b4dd7d09SAndy Fiddaman        * 'noname'    3000 pt
301*b4dd7d09SAndy Fiddaman        * 'noname'    2000 pt
302*b4dd7d09SAndy Fiddaman        * 'noname'    1000 pt
303*b4dd7d09SAndy Fiddaman
304*b4dd7d09SAndy FiddamanENDOFTEXT
305*b4dd7d09SAndy Fiddaman
306*b4dd7d09SAndy Fiddaman        # clear screen, line-by-line
307*b4dd7d09SAndy Fiddaman        for (( i=0 ; i < termsize.lines ; i++ )) ; do print "" ; done
308*b4dd7d09SAndy Fiddaman        ) | (while read -r line ; do
309*b4dd7d09SAndy Fiddaman                read -r -t 0.3 -n 1 c <&5
310*b4dd7d09SAndy Fiddaman                [[ "$c" != "" ]] && exit ${magic_return_code}
311*b4dd7d09SAndy Fiddaman                print -- "${line}"
312*b4dd7d09SAndy Fiddaman            done)
313*b4dd7d09SAndy Fiddaman        (( $? == magic_return_code )) && exit ${magic_return_code}
314*b4dd7d09SAndy Fiddaman        )
315*b4dd7d09SAndy Fiddaman        (( $? == magic_return_code )) && return 0
316*b4dd7d09SAndy Fiddaman
317*b4dd7d09SAndy Fiddaman        sleep 2
318*b4dd7d09SAndy Fiddaman    done
319*b4dd7d09SAndy Fiddaman)
320*b4dd7d09SAndy Fiddaman}
321*b4dd7d09SAndy Fiddaman
322*b4dd7d09SAndy Fiddamanfunction run_menu
323*b4dd7d09SAndy Fiddaman{
324*b4dd7d09SAndy Fiddaman    integer numlevels=0
325*b4dd7d09SAndy Fiddaman    integer selected_level=0
326*b4dd7d09SAndy Fiddaman    typeset l
327*b4dd7d09SAndy Fiddaman
328*b4dd7d09SAndy Fiddaman    # built list of available levels based on the "function levelmap_.*"
329*b4dd7d09SAndy Fiddaman    # built into this script
330*b4dd7d09SAndy Fiddaman    typeset -f | egrep "^function.*levelmap_.*" | sed 's/^function //' |
331*b4dd7d09SAndy Fiddaman    while read -r l ; do
332*b4dd7d09SAndy Fiddaman        levellist[numlevels]="$l"
333*b4dd7d09SAndy Fiddaman        numlevels+=1
334*b4dd7d09SAndy Fiddaman    done
335*b4dd7d09SAndy Fiddaman
336*b4dd7d09SAndy Fiddaman    # swallow any queued user input (e.g. drain stdin)
337*b4dd7d09SAndy Fiddaman    read -r -t 0.1 -n 100 dummy
338*b4dd7d09SAndy Fiddaman
339*b4dd7d09SAndy Fiddaman    while true ; do
340*b4dd7d09SAndy Fiddaman        # menu loop with timeout (which switches to "attract mode")
341*b4dd7d09SAndy Fiddaman        while true ; do
342*b4dd7d09SAndy Fiddaman            print -n -- "${vtcode["clear"]}"
343*b4dd7d09SAndy Fiddaman
344*b4dd7d09SAndy Fiddaman    cat <<ENDOFTEXT
345*b4dd7d09SAndy Fiddaman>======================================\
346*b4dd7d09SAndy Fiddaman>  /-\     .--.                        |
347*b4dd7d09SAndy Fiddaman> | OO|   / _.-' .-.   .-.  .-.   .-.  |
348*b4dd7d09SAndy Fiddaman> |   |   \  '-. '-'   '-'  '-'   '-'  |
349*b4dd7d09SAndy Fiddaman> ^^^^^    '--'                        |
350*b4dd7d09SAndy Fiddaman>======\       /================\  .-. |
351*b4dd7d09SAndy Fiddaman>      |       |                |  '-' |
352*b4dd7d09SAndy Fiddaman ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
353*b4dd7d09SAndy FiddamanENDOFTEXT
354*b4dd7d09SAndy Fiddaman            print "    GNAW - the ksh93 maze game"
355*b4dd7d09SAndy Fiddaman            print "\n\tMenu:"
356*b4dd7d09SAndy Fiddaman
357*b4dd7d09SAndy Fiddaman            print "\t - [L]evels:"
358*b4dd7d09SAndy Fiddaman            for (( i=0 ; i < numlevels ; i++ )) ; do
359*b4dd7d09SAndy Fiddaman                printf "\t    %s %s \n" "$( (( i == selected_level )) && print -n "*" || print -n " ")" "${levellist[i]##levelmap_}"
360*b4dd7d09SAndy Fiddaman            done
361*b4dd7d09SAndy Fiddaman
362*b4dd7d09SAndy Fiddaman            print  "\t - Rendering options:"
363*b4dd7d09SAndy Fiddaman            printf "\t    [%s] Use [U]nicode\n" "$( (( game_use_unicode == 1 )) && print -n "x" || print -n "_" )"
364*b4dd7d09SAndy Fiddaman            printf "\t    [%s] Use [C]olors\n"  "$( (( game_use_colors  == 1 )) && print -n "x" || print -n "_" )"
365*b4dd7d09SAndy Fiddaman
366*b4dd7d09SAndy Fiddaman            print "\t - [S]tart - [Q]uit"
367*b4dd7d09SAndy Fiddaman
368*b4dd7d09SAndy Fiddaman            # wait 30 secs (before we switch to "attract mode")
369*b4dd7d09SAndy Fiddaman            c="" ; read -r -t 30 -n 1 c
370*b4dd7d09SAndy Fiddaman            case "$c" in
371*b4dd7d09SAndy Fiddaman                'l') (( selected_level=(selected_level+numlevels+1) % numlevels )) ;;
372*b4dd7d09SAndy Fiddaman                'L') (( selected_level=(selected_level+numlevels-1) % numlevels )) ;;
373*b4dd7d09SAndy Fiddaman                ~(Fi)s)
374*b4dd7d09SAndy Fiddaman                    (( game_use_colors == 1 )) && print -- "${vtcode["bg_black"]}"
375*b4dd7d09SAndy Fiddaman                    case "${game_use_colors}${game_use_unicode}" in
376*b4dd7d09SAndy Fiddaman                        "00") main_loop "${levellist[selected_level]}" ;;
377*b4dd7d09SAndy Fiddaman                        "01") main_loop "${levellist[selected_level]}" | map_filter 0 1 ;;
378*b4dd7d09SAndy Fiddaman                        "10") main_loop "${levellist[selected_level]}" | map_filter 1 0 ;;
379*b4dd7d09SAndy Fiddaman                        "11") main_loop "${levellist[selected_level]}" | map_filter 1 1 ;;
380*b4dd7d09SAndy Fiddaman                    esac
381*b4dd7d09SAndy Fiddaman                    print -- "${vtcode["vtreset"]}"
382*b4dd7d09SAndy Fiddaman                    ;;
383*b4dd7d09SAndy Fiddaman                ~(Fi)q | $'\E')
384*b4dd7d09SAndy Fiddaman                    # make sure we do not exit on a cursor key (e.g. <esc>[A,B,C,D)
385*b4dd7d09SAndy Fiddaman                    read -r -t 0.01 -n 1 c
386*b4dd7d09SAndy Fiddaman                    if [[ "$c" == "[" ]] ; then
387*b4dd7d09SAndy Fiddaman                        # this was a cursor key sequence, just eat the 3rd charcater
388*b4dd7d09SAndy Fiddaman                        read -r -t 0.01 -n 1 c
389*b4dd7d09SAndy Fiddaman                    else
390*b4dd7d09SAndy Fiddaman                        exit 0
391*b4dd7d09SAndy Fiddaman                    fi
392*b4dd7d09SAndy Fiddaman                    ;;
393*b4dd7d09SAndy Fiddaman                ~(Fi)u) (( game_use_unicode=(game_use_unicode+2+1) % 2)) ;;
394*b4dd7d09SAndy Fiddaman                ~(Fi)c) (( game_use_colors=(game_use_colors+2+1) % 2))   ;;
395*b4dd7d09SAndy Fiddaman                "") break ;; # timeout, switch to attract mode
396*b4dd7d09SAndy Fiddaman                *) beep ;;
397*b4dd7d09SAndy Fiddaman            esac
398*b4dd7d09SAndy Fiddaman        done
399*b4dd7d09SAndy Fiddaman
400*b4dd7d09SAndy Fiddaman        print -n -- "${vtcode["clear"]}"
401*b4dd7d09SAndy Fiddaman        attract_mode
402*b4dd7d09SAndy Fiddaman    done
403*b4dd7d09SAndy Fiddaman    return 0
404*b4dd7d09SAndy Fiddaman}
405*b4dd7d09SAndy Fiddaman
406*b4dd7d09SAndy Fiddamanfunction levelmap_stripes
407*b4dd7d09SAndy Fiddaman{
408*b4dd7d09SAndy Fiddamancat <<ENDOFLEVEL
409*b4dd7d09SAndy Fiddaman###################################
410*b4dd7d09SAndy Fiddaman#.......    ...............    P  #
411*b4dd7d09SAndy Fiddaman#########..#################..### #
412*b4dd7d09SAndy Fiddaman#########..#################..### #
413*b4dd7d09SAndy Fiddaman#.......    ..    ..............# #
414*b4dd7d09SAndy Fiddaman###############  ################ #
415*b4dd7d09SAndy Fiddaman###############  ################ #
416*b4dd7d09SAndy Fiddaman#............. M  ..............# #
417*b4dd7d09SAndy Fiddaman##..#####################  ###### #
418*b4dd7d09SAndy Fiddaman##..#####################  ###### #
419*b4dd7d09SAndy Fiddaman#.......  ...........    .......# #
420*b4dd7d09SAndy Fiddaman########  ############  ######### #
421*b4dd7d09SAndy Fiddaman#   ####  ############  ######### #
422*b4dd7d09SAndy Fiddaman# #..................     ......# #
423*b4dd7d09SAndy Fiddaman# ############################### #
424*b4dd7d09SAndy Fiddaman#                                 #
425*b4dd7d09SAndy Fiddaman###################################
426*b4dd7d09SAndy FiddamanENDOFLEVEL
427*b4dd7d09SAndy Fiddaman    return 0
428*b4dd7d09SAndy Fiddaman}
429*b4dd7d09SAndy Fiddaman
430*b4dd7d09SAndy Fiddamanfunction levelmap_livad
431*b4dd7d09SAndy Fiddaman{
432*b4dd7d09SAndy Fiddamancat <<ENDOFLEVEL
433*b4dd7d09SAndy Fiddaman#####################################################
434*b4dd7d09SAndy Fiddaman#                                                   #
435*b4dd7d09SAndy Fiddaman# ##############  ###############  ################ #
436*b4dd7d09SAndy Fiddaman# #............       P             ..............# #
437*b4dd7d09SAndy Fiddaman#  .#############################################.# #
438*b4dd7d09SAndy Fiddaman# #.#..........                     ............#.  #
439*b4dd7d09SAndy Fiddaman# #.#.##########  ###############  ############.#.# #
440*b4dd7d09SAndy Fiddaman# #...#........                     ..........#...# #
441*b4dd7d09SAndy Fiddaman# #...#.#####################################.#.#.# #
442*b4dd7d09SAndy Fiddaman# #...#.#......                     ........#...#.# #
443*b4dd7d09SAndy Fiddaman# #.#.#...######  #########################.#.#.#.# #
444*b4dd7d09SAndy Fiddaman#  .#.....#....          M          ......#...#.#.# #
445*b4dd7d09SAndy Fiddaman# #.#.#...#######################  ########.#.#.#.# #
446*b4dd7d09SAndy Fiddaman# #...#.#......                     ........#...#.# #
447*b4dd7d09SAndy Fiddaman# #...#.########  ###############  ##########.#.#.# #
448*b4dd7d09SAndy Fiddaman# #...#........                     ..........#...# #
449*b4dd7d09SAndy Fiddaman# #.#.#########################################.#.# #
450*b4dd7d09SAndy Fiddaman# #.#..........                     ............#.  #
451*b4dd7d09SAndy Fiddaman#  .############  ###############  ##############.# #
452*b4dd7d09SAndy Fiddaman# #............                     ..............# #
453*b4dd7d09SAndy Fiddaman# ################################################# #
454*b4dd7d09SAndy Fiddaman#                                                   #
455*b4dd7d09SAndy Fiddaman#####################################################
456*b4dd7d09SAndy FiddamanENDOFLEVEL
457*b4dd7d09SAndy Fiddaman    return 0
458*b4dd7d09SAndy Fiddaman}
459*b4dd7d09SAndy Fiddaman
460*b4dd7d09SAndy Fiddamanfunction levelmap_classic1
461*b4dd7d09SAndy Fiddaman{
462*b4dd7d09SAndy Fiddamancat <<ENDOFLEVEL
463*b4dd7d09SAndy Fiddaman#########################
464*b4dd7d09SAndy Fiddaman#.P.........#...........#
465*b4dd7d09SAndy Fiddaman#.####.####.#.####.####.#
466*b4dd7d09SAndy Fiddaman#.#  #.#  #.#.#  #.#  #.#
467*b4dd7d09SAndy Fiddaman#.#  #.#  #.#.#  #.#  #.#
468*b4dd7d09SAndy Fiddaman#.####.####.#.####.####.#
469*b4dd7d09SAndy Fiddaman#.......................#
470*b4dd7d09SAndy Fiddaman#.####.#.#######.#.####.#
471*b4dd7d09SAndy Fiddaman#.#  #.#.#     #.#.#  #.#
472*b4dd7d09SAndy Fiddaman#.####.#.#######.#.####.#
473*b4dd7d09SAndy Fiddaman#......#....#....#......#
474*b4dd7d09SAndy Fiddaman######.####.#.####.######
475*b4dd7d09SAndy Fiddaman###### #         # ######
476*b4dd7d09SAndy Fiddaman###### # ##   ## # ######
477*b4dd7d09SAndy Fiddaman###### # #     # # ######
478*b4dd7d09SAndy Fiddaman#        #  M  #        #
479*b4dd7d09SAndy Fiddaman###### # ####### # ######
480*b4dd7d09SAndy Fiddaman###### #         # ######
481*b4dd7d09SAndy Fiddaman###### # ####### # ######
482*b4dd7d09SAndy Fiddaman###### # #     # # ######
483*b4dd7d09SAndy Fiddaman######.#.#######.#.######
484*b4dd7d09SAndy Fiddaman#...........#...........#
485*b4dd7d09SAndy Fiddaman#.###.###...#...###.###.#
486*b4dd7d09SAndy Fiddaman#...#...............#...#
487*b4dd7d09SAndy Fiddaman###.#....#######....#.###
488*b4dd7d09SAndy Fiddaman# #.#..#.#     #.#..#.# #
489*b4dd7d09SAndy Fiddaman###....#.#######.#....###
490*b4dd7d09SAndy Fiddaman#......#....#....#......#
491*b4dd7d09SAndy Fiddaman#.#########.#.#########.#
492*b4dd7d09SAndy Fiddaman#.......................#
493*b4dd7d09SAndy Fiddaman#########################
494*b4dd7d09SAndy FiddamanENDOFLEVEL
495*b4dd7d09SAndy Fiddaman    return 0
496*b4dd7d09SAndy Fiddaman}
497*b4dd7d09SAndy Fiddaman
498*b4dd7d09SAndy Fiddamanfunction levelmap_classic2
499*b4dd7d09SAndy Fiddaman{
500*b4dd7d09SAndy Fiddamancat <<ENDOFLEVEL
501*b4dd7d09SAndy Fiddaman#######################
502*b4dd7d09SAndy Fiddaman#.P...#.........#.....#
503*b4dd7d09SAndy Fiddaman#.###.#.#######.#.###.#
504*b4dd7d09SAndy Fiddaman#.....................#
505*b4dd7d09SAndy Fiddaman###.#.####.#.####.#.###
506*b4dd7d09SAndy Fiddaman###.#......#......#.###
507*b4dd7d09SAndy Fiddaman###.###.#######.###.###
508*b4dd7d09SAndy Fiddaman###.................###
509*b4dd7d09SAndy Fiddaman###.###.### ###.###.###
510*b4dd7d09SAndy Fiddaman###.#...#M    #...#.###
511*b4dd7d09SAndy Fiddaman###.#.#.#######.#.#.###
512*b4dd7d09SAndy Fiddaman#.....#.........#.....#
513*b4dd7d09SAndy Fiddaman###.#####..#..#####.###
514*b4dd7d09SAndy Fiddaman###........#........###
515*b4dd7d09SAndy Fiddaman###.###.#######.###.###
516*b4dd7d09SAndy Fiddaman#.....................#
517*b4dd7d09SAndy Fiddaman#.###.####.#.####.###.#
518*b4dd7d09SAndy Fiddaman#.###.#....#....#.###.#
519*b4dd7d09SAndy Fiddaman#.###.#.#######.#.###.#
520*b4dd7d09SAndy Fiddaman#.....................#
521*b4dd7d09SAndy Fiddaman#######################
522*b4dd7d09SAndy FiddamanENDOFLEVEL
523*b4dd7d09SAndy Fiddaman    return 0
524*b4dd7d09SAndy Fiddaman}
525*b4dd7d09SAndy Fiddaman
526*b4dd7d09SAndy Fiddamanfunction levelmap_easy
527*b4dd7d09SAndy Fiddaman{
528*b4dd7d09SAndy Fiddamancat <<ENDOFLEVEL
529*b4dd7d09SAndy Fiddaman##################
530*b4dd7d09SAndy Fiddaman# .............. #
531*b4dd7d09SAndy Fiddaman# . ######       #
532*b4dd7d09SAndy Fiddaman# . #  M #       #
533*b4dd7d09SAndy Fiddaman# . #    #       #
534*b4dd7d09SAndy Fiddaman# . ### ##       #
535*b4dd7d09SAndy Fiddaman# .   #          #
536*b4dd7d09SAndy Fiddaman# .   ###        #
537*b4dd7d09SAndy Fiddaman# .              #
538*b4dd7d09SAndy Fiddaman# ..........     #
539*b4dd7d09SAndy Fiddaman# .......... P   #
540*b4dd7d09SAndy Fiddaman##################
541*b4dd7d09SAndy FiddamanENDOFLEVEL
542*b4dd7d09SAndy Fiddaman    return 0
543*b4dd7d09SAndy Fiddaman}
544*b4dd7d09SAndy Fiddaman
545*b4dd7d09SAndy Fiddamanfunction levelmap_sunsolaristext
546*b4dd7d09SAndy Fiddaman{
547*b4dd7d09SAndy Fiddamancat <<ENDOFLEVEL
548*b4dd7d09SAndy Fiddaman################################################
549*b4dd7d09SAndy Fiddaman# .####   .    #  #....#                       #
550*b4dd7d09SAndy Fiddaman# #       #    #  #....#                       #
551*b4dd7d09SAndy Fiddaman#  ####   #    #  #.#..#          M            #
552*b4dd7d09SAndy Fiddaman#      #  #    #  #..#.#                       #
553*b4dd7d09SAndy Fiddaman# #    #  #    #  #...##                       #
554*b4dd7d09SAndy Fiddaman#  ####    ####   #....#                       #
555*b4dd7d09SAndy Fiddaman#                                              #
556*b4dd7d09SAndy Fiddaman#  ####    ####  #       ##    #####  #  ####  #
557*b4dd7d09SAndy Fiddaman# #       #.  .# #      #  #   #....# # #      #
558*b4dd7d09SAndy Fiddaman#  ####   #    # #      # P #  #....# #  ####  #
559*b4dd7d09SAndy Fiddaman#      #  #    ###      #.#### #.###  #      # #
560*b4dd7d09SAndy Fiddaman# #   .#  #.  ..        #    # #...#  # #    # #
561*b4dd7d09SAndy Fiddaman#  ####    ####  ###### .    #  ....# #  ####. #
562*b4dd7d09SAndy Fiddaman################################################
563*b4dd7d09SAndy FiddamanENDOFLEVEL
564*b4dd7d09SAndy Fiddaman    return 0
565*b4dd7d09SAndy Fiddaman}
566*b4dd7d09SAndy Fiddaman
567*b4dd7d09SAndy Fiddamanfunction read_levelmap
568*b4dd7d09SAndy Fiddaman{
569*b4dd7d09SAndy Fiddaman    typeset map="$( $1 )"
570*b4dd7d09SAndy Fiddaman
571*b4dd7d09SAndy Fiddaman    integer y=0
572*b4dd7d09SAndy Fiddaman    integer x=0
573*b4dd7d09SAndy Fiddaman    integer maxx=0
574*b4dd7d09SAndy Fiddaman    integer numdots=0
575*b4dd7d09SAndy Fiddaman    typeset line
576*b4dd7d09SAndy Fiddaman    typeset c
577*b4dd7d09SAndy Fiddaman
578*b4dd7d09SAndy Fiddaman    while read -r line ; do
579*b4dd7d09SAndy Fiddaman        for (( x=0 ; x < ${#line} ; x++ )) ; do
580*b4dd7d09SAndy Fiddaman            c="${line:x:1}"
581*b4dd7d09SAndy Fiddaman
582*b4dd7d09SAndy Fiddaman            case $c in
583*b4dd7d09SAndy Fiddaman                ".") numdots+=1 ;;
584*b4dd7d09SAndy Fiddaman                "M")
585*b4dd7d09SAndy Fiddaman		    # log start position of monsters
586*b4dd7d09SAndy Fiddaman                    levelmap["monsterstartpos_x"]="$x"
587*b4dd7d09SAndy Fiddaman                    levelmap["monsterstartpos_y"]="$y"
588*b4dd7d09SAndy Fiddaman                    c=" "
589*b4dd7d09SAndy Fiddaman                    ;;
590*b4dd7d09SAndy Fiddaman                "P")
591*b4dd7d09SAndy Fiddaman		    # log start position of player
592*b4dd7d09SAndy Fiddaman                    levelmap["playerstartpos_x"]="$x"
593*b4dd7d09SAndy Fiddaman                    levelmap["playerstartpos_y"]="$y"
594*b4dd7d09SAndy Fiddaman                    c=" "
595*b4dd7d09SAndy Fiddaman                    ;;
596*b4dd7d09SAndy Fiddaman            esac
597*b4dd7d09SAndy Fiddaman
598*b4dd7d09SAndy Fiddaman            levelmap["${x}_${y}"]="$c"
599*b4dd7d09SAndy Fiddaman        done
600*b4dd7d09SAndy Fiddaman        (( maxx=x , y++ ))
601*b4dd7d09SAndy Fiddaman    done <<<"${map}"
602*b4dd7d09SAndy Fiddaman
603*b4dd7d09SAndy Fiddaman    levelmap["max_x"]=${maxx}
604*b4dd7d09SAndy Fiddaman    levelmap["max_y"]=${y}
605*b4dd7d09SAndy Fiddaman    levelmap["numdots"]=${numdots}
606*b4dd7d09SAndy Fiddaman
607*b4dd7d09SAndy Fiddaman    # consistency checks
608*b4dd7d09SAndy Fiddaman    if [[ "${levelmap["monsterstartpos_x"]}" == "" ]] ; then
609*b4dd7d09SAndy Fiddaman        fatal_error "read_levelmap: monsterstartpos_x is empty."
610*b4dd7d09SAndy Fiddaman    fi
611*b4dd7d09SAndy Fiddaman    if [[ "${levelmap["playerstartpos_x"]}" == "" ]] ; then
612*b4dd7d09SAndy Fiddaman        fatal_error "read_levelmap: playerstartpos_x is empty."
613*b4dd7d09SAndy Fiddaman    fi
614*b4dd7d09SAndy Fiddaman
615*b4dd7d09SAndy Fiddaman    return 0
616*b4dd7d09SAndy Fiddaman}
617*b4dd7d09SAndy Fiddaman
618*b4dd7d09SAndy Fiddamanfunction player.set
619*b4dd7d09SAndy Fiddaman{
620*b4dd7d09SAndy Fiddaman    case "${.sh.subscript}" in
621*b4dd7d09SAndy Fiddaman        pos_y)
622*b4dd7d09SAndy Fiddaman            if [[ "${levelmap["${player["pos_x"]}_${.sh.value}"]}" == "#" ]] ; then
623*b4dd7d09SAndy Fiddaman                .sh.value=${player["pos_y"]}
624*b4dd7d09SAndy Fiddaman                beep
625*b4dd7d09SAndy Fiddaman            fi
626*b4dd7d09SAndy Fiddaman            ;;
627*b4dd7d09SAndy Fiddaman
628*b4dd7d09SAndy Fiddaman        pos_x)
629*b4dd7d09SAndy Fiddaman            if [[ "${levelmap["${.sh.value}_${player["pos_y"]}"]}" == "#" ]] ; then
630*b4dd7d09SAndy Fiddaman                .sh.value=${player["pos_x"]}
631*b4dd7d09SAndy Fiddaman                beep
632*b4dd7d09SAndy Fiddaman            fi
633*b4dd7d09SAndy Fiddaman            ;;
634*b4dd7d09SAndy Fiddaman    esac
635*b4dd7d09SAndy Fiddaman    return 0
636*b4dd7d09SAndy Fiddaman}
637*b4dd7d09SAndy Fiddaman
638*b4dd7d09SAndy Fiddamanfunction monster.set
639*b4dd7d09SAndy Fiddaman{
640*b4dd7d09SAndy Fiddaman    case "${.sh.subscript}" in
641*b4dd7d09SAndy Fiddaman        *_pos_y)
642*b4dd7d09SAndy Fiddaman            if [[ "${levelmap["${monster[${currmonster}_"pos_x"]}_${.sh.value}"]}" == "#" ]] ; then
643*b4dd7d09SAndy Fiddaman                .sh.value=${monster[${currmonster}_"pos_y"]}
644*b4dd7d09SAndy Fiddaman                # turn homing off when the monster hit a wall
645*b4dd7d09SAndy Fiddaman                monster[${currmonster}_"homing"]=0
646*b4dd7d09SAndy Fiddaman            fi
647*b4dd7d09SAndy Fiddaman            ;;
648*b4dd7d09SAndy Fiddaman
649*b4dd7d09SAndy Fiddaman        *_pos_x)
650*b4dd7d09SAndy Fiddaman            if [[ "${levelmap["${.sh.value}_${monster[${currmonster}_"pos_y"]}"]}" == "#" ]] ; then
651*b4dd7d09SAndy Fiddaman                .sh.value=${monster[${currmonster}_"pos_x"]}
652*b4dd7d09SAndy Fiddaman                # turn homing off when the monster hit a wall
653*b4dd7d09SAndy Fiddaman                monster[${currmonster}_"homing"]=0
654*b4dd7d09SAndy Fiddaman            fi
655*b4dd7d09SAndy Fiddaman            ;;
656*b4dd7d09SAndy Fiddaman    esac
657*b4dd7d09SAndy Fiddaman    return 0
658*b4dd7d09SAndy Fiddaman}
659*b4dd7d09SAndy Fiddaman
660*b4dd7d09SAndy Fiddamanfunction render_game
661*b4dd7d09SAndy Fiddaman{
662*b4dd7d09SAndy Fiddaman    # render_buffer is some kind of "background buffer" to "double buffer"
663*b4dd7d09SAndy Fiddaman    # all output and combine it in one write to reduce flickering in the
664*b4dd7d09SAndy Fiddaman    # terminal
665*b4dd7d09SAndy Fiddaman    typeset render_buffer="$(
666*b4dd7d09SAndy Fiddaman        integer screen_y_offset=1
667*b4dd7d09SAndy Fiddaman        integer start_y_pos=0
668*b4dd7d09SAndy Fiddaman        integer render_num_lines=${levelmap["max_y"]}
669*b4dd7d09SAndy Fiddaman
670*b4dd7d09SAndy Fiddaman        if (( (termsize.lines-3) < levelmap["max_y"] )) ; then
671*b4dd7d09SAndy Fiddaman            (( start_y_pos=player["pos_y"] / 2))
672*b4dd7d09SAndy Fiddaman            (( render_num_lines=termsize.lines-5))
673*b4dd7d09SAndy Fiddaman        fi
674*b4dd7d09SAndy Fiddaman
675*b4dd7d09SAndy Fiddaman        #print -n -- "${vtcode["clear"]}"
676*b4dd7d09SAndy Fiddaman        print_setcursorpos 0 0
677*b4dd7d09SAndy Fiddaman
678*b4dd7d09SAndy Fiddaman        # print score (note the " " around "%d" are neccesary to clean up cruft
679*b4dd7d09SAndy Fiddaman        # when we overwrite the level
680*b4dd7d09SAndy Fiddaman        printf "SCORE: %05d  DOTS: %.3d  LIVES: %2.d " "${player["score"]}" "${levelmap["numdots"]}" "${player["lives"]}"
681*b4dd7d09SAndy Fiddaman        print_levelmap ${screen_y_offset} ${start_y_pos} ${render_num_lines}
682*b4dd7d09SAndy Fiddaman
683*b4dd7d09SAndy Fiddaman        # render player
684*b4dd7d09SAndy Fiddaman        print_setcursorpos ${player["pos_x"]} $((player["pos_y"]+screen_y_offset-start_y_pos))
685*b4dd7d09SAndy Fiddaman        print -n "@"
686*b4dd7d09SAndy Fiddaman
687*b4dd7d09SAndy Fiddaman        # render monsters
688*b4dd7d09SAndy Fiddaman        for currmonster in ${monsterlist} ; do
689*b4dd7d09SAndy Fiddaman            (( m_pos_x=monster[${currmonster}_"pos_x"] ))
690*b4dd7d09SAndy Fiddaman            (( m_pos_y=monster[${currmonster}_"pos_y"]+screen_y_offset-start_y_pos ))
691*b4dd7d09SAndy Fiddaman
692*b4dd7d09SAndy Fiddaman            if (( m_pos_y >= screen_y_offset && m_pos_y < render_num_lines )) ; then
693*b4dd7d09SAndy Fiddaman                print_setcursorpos ${m_pos_x} ${m_pos_y}
694*b4dd7d09SAndy Fiddaman                print -n "x"
695*b4dd7d09SAndy Fiddaman            fi
696*b4dd7d09SAndy Fiddaman        done
697*b4dd7d09SAndy Fiddaman
698*b4dd7d09SAndy Fiddaman        # status block
699*b4dd7d09SAndy Fiddaman        print_setcursorpos 0 $((render_num_lines+screen_y_offset))
700*b4dd7d09SAndy Fiddaman        emptyline="                                                            "
701*b4dd7d09SAndy Fiddaman        print -n " >> ${player["message"]} <<${emptyline:0:${#emptyline}-${#player["message"]}}"
702*b4dd7d09SAndy Fiddaman    )"
703*b4dd7d09SAndy Fiddaman    print -r -- "${render_buffer}${end_of_frame}"
704*b4dd7d09SAndy Fiddaman#    print "renderbuffersize=$(print "${render_buffer}" | wc -c) ${end_of_frame}"
705*b4dd7d09SAndy Fiddaman    return 0
706*b4dd7d09SAndy Fiddaman}
707*b4dd7d09SAndy Fiddaman
708*b4dd7d09SAndy Fiddamanfunction main_loop
709*b4dd7d09SAndy Fiddaman{
710*b4dd7d09SAndy Fiddaman    float   sleep_per_cycle=0.2
711*b4dd7d09SAndy Fiddaman    float   seconds_before_read
712*b4dd7d09SAndy Fiddaman    integer num_cycles=0
713*b4dd7d09SAndy Fiddaman    float   rs
714*b4dd7d09SAndy Fiddaman
715*b4dd7d09SAndy Fiddaman    print -n -- "${vtcode["clear"]}"
716*b4dd7d09SAndy Fiddaman
717*b4dd7d09SAndy Fiddaman    read_levelmap "$1"
718*b4dd7d09SAndy Fiddaman
719*b4dd7d09SAndy Fiddaman    # player init
720*b4dd7d09SAndy Fiddaman    player["pos_x"]=${levelmap["playerstartpos_x"]}
721*b4dd7d09SAndy Fiddaman    player["pos_y"]=${levelmap["playerstartpos_y"]}
722*b4dd7d09SAndy Fiddaman    player["score"]=0         # player score
723*b4dd7d09SAndy Fiddaman    player["lives"]=5         # number of lives
724*b4dd7d09SAndy Fiddaman    player["invulnerable"]=10 # cycles how long the player remains invulnerable
725*b4dd7d09SAndy Fiddaman    player["message"]="Go..."
726*b4dd7d09SAndy Fiddaman
727*b4dd7d09SAndy Fiddaman    monsterlist="maw claw jitterbug tentacle grendel"
728*b4dd7d09SAndy Fiddaman
729*b4dd7d09SAndy Fiddaman    for currmonster in ${monsterlist} ; do
730*b4dd7d09SAndy Fiddaman        monster[${currmonster}_"pos_x"]=${levelmap["monsterstartpos_x"]}
731*b4dd7d09SAndy Fiddaman        monster[${currmonster}_"pos_y"]=${levelmap["monsterstartpos_y"]}
732*b4dd7d09SAndy Fiddaman        monster[${currmonster}_"xstep"]=0
733*b4dd7d09SAndy Fiddaman        monster[${currmonster}_"ystep"]=0
734*b4dd7d09SAndy Fiddaman        monster[${currmonster}_"homing"]=0
735*b4dd7d09SAndy Fiddaman    done
736*b4dd7d09SAndy Fiddaman
737*b4dd7d09SAndy Fiddaman    # main game cycle loop
738*b4dd7d09SAndy Fiddaman    while true ; do
739*b4dd7d09SAndy Fiddaman        num_cycles+=1
740*b4dd7d09SAndy Fiddaman        seconds_before_read=${SECONDS}
741*b4dd7d09SAndy Fiddaman        c="" ; read -r -t ${sleep_per_cycle} -n 1 c
742*b4dd7d09SAndy Fiddaman
743*b4dd7d09SAndy Fiddaman        if [[ "$c" != "" ]] ; then
744*b4dd7d09SAndy Fiddaman            # special case handling for cursor keys which are usually composed
745*b4dd7d09SAndy Fiddaman            # of three characters (e.g. "<ESC>[D"). If only <ESC> is hit we
746*b4dd7d09SAndy Fiddaman            # quicky exit
747*b4dd7d09SAndy Fiddaman            if [[ "$c" == $'\E' ]] ; then
748*b4dd7d09SAndy Fiddaman                read -r -t 0.1 -n 1 c
749*b4dd7d09SAndy Fiddaman                if [[ "$c" != "[" ]] ; then
750*b4dd7d09SAndy Fiddaman                    return 0
751*b4dd7d09SAndy Fiddaman                fi
752*b4dd7d09SAndy Fiddaman
753*b4dd7d09SAndy Fiddaman                # we assume the user is using the cursor keys, this |read|
754*b4dd7d09SAndy Fiddaman                # should fetch the 3rd byte of the three-character sequence
755*b4dd7d09SAndy Fiddaman                # for the cursor keys
756*b4dd7d09SAndy Fiddaman                read -r -t 0.1 -n 1 c
757*b4dd7d09SAndy Fiddaman            fi
758*b4dd7d09SAndy Fiddaman
759*b4dd7d09SAndy Fiddaman            # if the user hit a key the "read" above was interrupted
760*b4dd7d09SAndy Fiddaman            # and didn't wait exactly |sleep_per_cycle| seconds.
761*b4dd7d09SAndy Fiddaman            # We wait here some moments (|rs|="remaining seconds") to
762*b4dd7d09SAndy Fiddaman            # avoid that the game gets "faster" when more user input
763*b4dd7d09SAndy Fiddaman            # is given.
764*b4dd7d09SAndy Fiddaman            (( rs=sleep_per_cycle-(SECONDS-seconds_before_read) ))
765*b4dd7d09SAndy Fiddaman            (( rs > 0.001 )) && sleep ${rs}
766*b4dd7d09SAndy Fiddaman
767*b4dd7d09SAndy Fiddaman            player["message"]=""
768*b4dd7d09SAndy Fiddaman
769*b4dd7d09SAndy Fiddaman            case "$c" in
770*b4dd7d09SAndy Fiddaman                j|D|4) (( player["pos_x"]-=1 )) ;;
771*b4dd7d09SAndy Fiddaman                k|C|6) (( player["pos_x"]+=1 )) ;;
772*b4dd7d09SAndy Fiddaman                i|A|8) (( player["pos_y"]-=1 )) ;;
773*b4dd7d09SAndy Fiddaman                m|B|2) (( player["pos_y"]+=1 )) ;;
774*b4dd7d09SAndy Fiddaman
775*b4dd7d09SAndy Fiddaman                q) return 0 ;;
776*b4dd7d09SAndy Fiddaman            esac
777*b4dd7d09SAndy Fiddaman
778*b4dd7d09SAndy Fiddaman            if [[ "${levelmap["${player["pos_x"]}_${player["pos_y"]}"]}" == "." ]] ; then
779*b4dd7d09SAndy Fiddaman                levelmap["${player["pos_x"]}_${player["pos_y"]}"]=" "
780*b4dd7d09SAndy Fiddaman                (( levelmap["numdots"]-=1 ))
781*b4dd7d09SAndy Fiddaman
782*b4dd7d09SAndy Fiddaman                (( player["score"]+=10 ))
783*b4dd7d09SAndy Fiddaman                player["message"]='GNAW!!'
784*b4dd7d09SAndy Fiddaman
785*b4dd7d09SAndy Fiddaman                if (( levelmap["numdots"] <= 0 )) ; then
786*b4dd7d09SAndy Fiddaman                    level_completed
787*b4dd7d09SAndy Fiddaman                    return 0
788*b4dd7d09SAndy Fiddaman                fi
789*b4dd7d09SAndy Fiddaman            fi
790*b4dd7d09SAndy Fiddaman        fi
791*b4dd7d09SAndy Fiddaman
792*b4dd7d09SAndy Fiddaman        # generic player status change
793*b4dd7d09SAndy Fiddaman        if (( player["invulnerable"] > 0 )) ; then
794*b4dd7d09SAndy Fiddaman            (( player["invulnerable"]-=1 ))
795*b4dd7d09SAndy Fiddaman        fi
796*b4dd7d09SAndy Fiddaman        if (( player["lives"] <= 0 )) ; then
797*b4dd7d09SAndy Fiddaman            game_over
798*b4dd7d09SAndy Fiddaman            return 0
799*b4dd7d09SAndy Fiddaman        fi
800*b4dd7d09SAndy Fiddaman
801*b4dd7d09SAndy Fiddaman        # move monsters
802*b4dd7d09SAndy Fiddaman        for currmonster in ${monsterlist} ; do
803*b4dd7d09SAndy Fiddaman            # make monster as half as slow then the others when it is following the user
804*b4dd7d09SAndy Fiddaman            if (( monster[${currmonster}_"homing"] > 0 )) ; then
805*b4dd7d09SAndy Fiddaman                (( (num_cycles%2) > 0 )) && continue
806*b4dd7d09SAndy Fiddaman            fi
807*b4dd7d09SAndy Fiddaman
808*b4dd7d09SAndy Fiddaman            if [[ ${monster[${currmonster}_"pos_x"]} == ${player["pos_x"]} ]] ; then
809*b4dd7d09SAndy Fiddaman                if (( (monster[${currmonster}_"pos_y"]-player["pos_y"]) > 0 )) ; then
810*b4dd7d09SAndy Fiddaman                    (( monster[${currmonster}_"xstep"]=+0 , monster[${currmonster}_"ystep"]=-1 ))
811*b4dd7d09SAndy Fiddaman                else
812*b4dd7d09SAndy Fiddaman                    (( monster[${currmonster}_"xstep"]=+0 , monster[${currmonster}_"ystep"]=+1 ))
813*b4dd7d09SAndy Fiddaman                fi
814*b4dd7d09SAndy Fiddaman                monster[${currmonster}_"homing"]=1
815*b4dd7d09SAndy Fiddaman                if (( player["invulnerable"] <= 0 )) ; then
816*b4dd7d09SAndy Fiddaman                    player["message"]="Attention: ${currmonster} is chasing you"
817*b4dd7d09SAndy Fiddaman                fi
818*b4dd7d09SAndy Fiddaman            elif (( monster[${currmonster}_"pos_y"] == player["pos_y"] )) ; then
819*b4dd7d09SAndy Fiddaman                if (( (monster[${currmonster}_"pos_x"]-player["pos_x"]) > 0 )) ; then
820*b4dd7d09SAndy Fiddaman                    (( monster[${currmonster}_"xstep"]=-1 , monster[${currmonster}_"ystep"]=-0 ))
821*b4dd7d09SAndy Fiddaman                else
822*b4dd7d09SAndy Fiddaman                    (( monster[${currmonster}_"xstep"]=+1 , monster[${currmonster}_"ystep"]=+0 ))
823*b4dd7d09SAndy Fiddaman                fi
824*b4dd7d09SAndy Fiddaman                monster[${currmonster}_"homing"]=1
825*b4dd7d09SAndy Fiddaman                if (( player["invulnerable"] <= 0 )) ; then
826*b4dd7d09SAndy Fiddaman                    player["message"]="Attention: ${currmonster} is chasing you"
827*b4dd7d09SAndy Fiddaman                fi
828*b4dd7d09SAndy Fiddaman            else
829*b4dd7d09SAndy Fiddaman                if (( monster[${currmonster}_"homing"] == 0 )) ; then
830*b4dd7d09SAndy Fiddaman                    case $((SECONDS % 6 + RANDOM % 4)) in
831*b4dd7d09SAndy Fiddaman                        0) (( monster[${currmonster}_"xstep"]=+0 , monster[${currmonster}_"ystep"]=+0 )) ;;
832*b4dd7d09SAndy Fiddaman                        2) (( monster[${currmonster}_"xstep"]=+0 , monster[${currmonster}_"ystep"]=+1 )) ;;
833*b4dd7d09SAndy Fiddaman                        3) (( monster[${currmonster}_"xstep"]=+1 , monster[${currmonster}_"ystep"]=+0 )) ;;
834*b4dd7d09SAndy Fiddaman                        5) (( monster[${currmonster}_"xstep"]=+0 , monster[${currmonster}_"ystep"]=-1 )) ;;
835*b4dd7d09SAndy Fiddaman                        6) (( monster[${currmonster}_"xstep"]=-1 , monster[${currmonster}_"ystep"]=+0 )) ;;
836*b4dd7d09SAndy Fiddaman                    esac
837*b4dd7d09SAndy Fiddaman                fi
838*b4dd7d09SAndy Fiddaman            fi
839*b4dd7d09SAndy Fiddaman
840*b4dd7d09SAndy Fiddaman            (( monster[${currmonster}_"pos_x"]=monster[${currmonster}_"pos_x"]+monster[${currmonster}_"xstep"] ))
841*b4dd7d09SAndy Fiddaman            (( monster[${currmonster}_"pos_y"]=monster[${currmonster}_"pos_y"]+monster[${currmonster}_"ystep"] ))
842*b4dd7d09SAndy Fiddaman
843*b4dd7d09SAndy Fiddaman            # check if a monster hit the player
844*b4dd7d09SAndy Fiddaman            if (( player["invulnerable"] <= 0 )) ; then
845*b4dd7d09SAndy Fiddaman                if (( monster[${currmonster}_"pos_x"] == player["pos_x"] && \
846*b4dd7d09SAndy Fiddaman                      monster[${currmonster}_"pos_y"] == player["pos_y"] )) ; then
847*b4dd7d09SAndy Fiddaman                     # if player was hit by a monster take one life and
848*b4dd7d09SAndy Fiddaman                     # make him invulnerable for 10 cycles to avoid that
849*b4dd7d09SAndy Fiddaman                     # the next cycle steals more lives
850*b4dd7d09SAndy Fiddaman                     player["message"]="Ouuuchhhh"
851*b4dd7d09SAndy Fiddaman                     player["invulnerable"]=10
852*b4dd7d09SAndy Fiddaman                     (( player["lives"]-=1 ))
853*b4dd7d09SAndy Fiddaman
854*b4dd7d09SAndy Fiddaman                     beep ; beep ; sleep 0.2 ; beep ; beep
855*b4dd7d09SAndy Fiddaman                fi
856*b4dd7d09SAndy Fiddaman            fi
857*b4dd7d09SAndy Fiddaman        done
858*b4dd7d09SAndy Fiddaman
859*b4dd7d09SAndy Fiddaman        render_game
860*b4dd7d09SAndy Fiddaman    done
861*b4dd7d09SAndy Fiddaman    return 0
862*b4dd7d09SAndy Fiddaman}
863*b4dd7d09SAndy Fiddaman
864*b4dd7d09SAndy Fiddamanfunction map_filter
865*b4dd7d09SAndy Fiddaman{
866*b4dd7d09SAndy Fiddaman    typeset ch_player ch_monster ch_wall var
867*b4dd7d09SAndy Fiddaman
868*b4dd7d09SAndy Fiddaman    if (( $1 == 1 )) ; then
869*b4dd7d09SAndy Fiddaman        ch_player="${vtcode["fg_yellow"]}"
870*b4dd7d09SAndy Fiddaman        ch_monster="${vtcode["fg_red"]}"
871*b4dd7d09SAndy Fiddaman        ch_wall="${vtcode["fg_blue"]}"
872*b4dd7d09SAndy Fiddaman    else
873*b4dd7d09SAndy Fiddaman        ch_player=""
874*b4dd7d09SAndy Fiddaman        ch_monster=""
875*b4dd7d09SAndy Fiddaman        ch_wall=""
876*b4dd7d09SAndy Fiddaman    fi
877*b4dd7d09SAndy Fiddaman
878*b4dd7d09SAndy Fiddaman    if (( $2 == 1 )) ; then
879*b4dd7d09SAndy Fiddaman        # unicode map
880*b4dd7d09SAndy Fiddaman        ch_player+="$(printf '\u[24d2]')"
881*b4dd7d09SAndy Fiddaman        ch_monster+="$(printf '\u[2605]')"
882*b4dd7d09SAndy Fiddaman        ch_wall+="$(printf '\u[25a6]')"
883*b4dd7d09SAndy Fiddaman    else
884*b4dd7d09SAndy Fiddaman        # ascii map
885*b4dd7d09SAndy Fiddaman        ch_player+="@"
886*b4dd7d09SAndy Fiddaman        ch_monster+="x"
887*b4dd7d09SAndy Fiddaman        ch_wall+="#"
888*b4dd7d09SAndy Fiddaman    fi
889*b4dd7d09SAndy Fiddaman
890*b4dd7d09SAndy Fiddaman    # note that this filter currently defeats the "double-buffering"
891*b4dd7d09SAndy Fiddaman    while IFS='' read -r -d "${end_of_frame}" var ; do
892*b4dd7d09SAndy Fiddaman        var="${var// /${vtcode["fg_grey"]} }"
893*b4dd7d09SAndy Fiddaman        var="${var//\./${vtcode["fg_lightred"]}.}"
894*b4dd7d09SAndy Fiddaman        var="${var//@/${ch_player}}"
895*b4dd7d09SAndy Fiddaman        var="${var//x/${ch_monster}}"
896*b4dd7d09SAndy Fiddaman        var="${var//#/${ch_wall}}"
897*b4dd7d09SAndy Fiddaman
898*b4dd7d09SAndy Fiddaman        print -r -- "${var}"
899*b4dd7d09SAndy Fiddaman    done
900*b4dd7d09SAndy Fiddaman    return 0
901*b4dd7d09SAndy Fiddaman}
902*b4dd7d09SAndy Fiddaman
903*b4dd7d09SAndy Fiddamanfunction exit_trap
904*b4dd7d09SAndy Fiddaman{
905*b4dd7d09SAndy Fiddaman    # restore stty settings
906*b4dd7d09SAndy Fiddaman    stty ${saved_stty}
907*b4dd7d09SAndy Fiddaman
908*b4dd7d09SAndy Fiddaman    print "bye."
909*b4dd7d09SAndy Fiddaman    return 0
910*b4dd7d09SAndy Fiddaman}
911*b4dd7d09SAndy Fiddaman
912*b4dd7d09SAndy Fiddamanfunction usage
913*b4dd7d09SAndy Fiddaman{
914*b4dd7d09SAndy Fiddaman    OPTIND=0
915*b4dd7d09SAndy Fiddaman    getopts -a "${progname}" "${gnaw_usage}" OPT '-?'
916*b4dd7d09SAndy Fiddaman    exit 2
917*b4dd7d09SAndy Fiddaman}
918*b4dd7d09SAndy Fiddaman
919*b4dd7d09SAndy Fiddaman# program start
920*b4dd7d09SAndy Fiddaman# make sure we use the ksh93 "cat" builtin which supports the "-u" option
921*b4dd7d09SAndy Fiddamanbuiltin basename
922*b4dd7d09SAndy Fiddamanbuiltin cat
923*b4dd7d09SAndy Fiddamanbuiltin wc
924*b4dd7d09SAndy Fiddaman
925*b4dd7d09SAndy Fiddamantypeset progname="${ basename "${0}" ; }"
926*b4dd7d09SAndy Fiddaman
927*b4dd7d09SAndy Fiddaman# terminal size rect
928*b4dd7d09SAndy Fiddamancompound termsize=(
929*b4dd7d09SAndy Fiddaman    integer columns=-1
930*b4dd7d09SAndy Fiddaman    integer lines=-1
931*b4dd7d09SAndy Fiddaman)
932*b4dd7d09SAndy Fiddaman
933*b4dd7d09SAndy Fiddaman# global variables
934*b4dd7d09SAndy Fiddamantypeset quiet=false
935*b4dd7d09SAndy Fiddaman
936*b4dd7d09SAndy Fiddamantypeset -A levelmap
937*b4dd7d09SAndy Fiddamantypeset -A player
938*b4dd7d09SAndy Fiddamantypeset -A monster
939*b4dd7d09SAndy Fiddaman# global rendering options
940*b4dd7d09SAndy Fiddamaninteger game_use_colors=0
941*b4dd7d09SAndy Fiddamaninteger game_use_unicode=0
942*b4dd7d09SAndy Fiddaman
943*b4dd7d09SAndy Fiddamantypeset -r gnaw_usage=$'+
944*b4dd7d09SAndy Fiddaman[-?\n@(#)\$Id: gnaw (Roland Mainz) 2009-05-09 \$\n]
945*b4dd7d09SAndy Fiddaman[-author?Roland Mainz <roland.mainz@nrubsig.org>]
946*b4dd7d09SAndy Fiddaman[+NAME?gnaw - maze game written in ksh93]
947*b4dd7d09SAndy Fiddaman[+DESCRIPTION?\bgnaw\b is a maze game.
948*b4dd7d09SAndy Fiddaman        The player maneuvers a yellow "@" sign to navigate a maze while eating
949*b4dd7d09SAndy Fiddaman        small dots. A level is finished when all the dots are eaten. Five monsters
950*b4dd7d09SAndy Fiddaman        (maw, claw, jitterbug, tentacle and grendel) also wander the maze in an attempt
951*b4dd7d09SAndy Fiddaman        to catch the "@". Each level begins with all ghosts in their home, and "@" near
952*b4dd7d09SAndy Fiddaman        the bottom of the maze. The monsters are released from the home one by one at the
953*b4dd7d09SAndy Fiddaman        start of each level and start their rentless hunt after the player.]
954*b4dd7d09SAndy Fiddaman[q:quiet?Disable use of terminal bell.]
955*b4dd7d09SAndy Fiddaman[+SEE ALSO?\bksh93\b(1)]
956*b4dd7d09SAndy Fiddaman'
957*b4dd7d09SAndy Fiddaman
958*b4dd7d09SAndy Fiddamanwhile getopts -a "${progname}" "${gnaw_usage}" OPT ; do
959*b4dd7d09SAndy Fiddaman#    printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
960*b4dd7d09SAndy Fiddaman    case ${OPT} in
961*b4dd7d09SAndy Fiddaman        q)    quiet=true  ;;
962*b4dd7d09SAndy Fiddaman        +q)   quiet=false ;;
963*b4dd7d09SAndy Fiddaman        *)    usage ;;
964*b4dd7d09SAndy Fiddaman    esac
965*b4dd7d09SAndy Fiddamandone
966*b4dd7d09SAndy Fiddamanshift $((OPTIND-1))
967*b4dd7d09SAndy Fiddaman
968*b4dd7d09SAndy Fiddaman# save stty values and register the exit trap which restores these values on exit
969*b4dd7d09SAndy Fiddamansaved_stty="$(stty -g)"
970*b4dd7d09SAndy Fiddamantrap exit_trap EXIT
971*b4dd7d09SAndy Fiddaman
972*b4dd7d09SAndy Fiddamanprint "Loading..."
973*b4dd7d09SAndy Fiddaman
974*b4dd7d09SAndy Fiddaman# set stty values, "-icanon min 1 time 0 -inpck" should improve input latency,
975*b4dd7d09SAndy Fiddaman# "-echo" turns the terminal echo off
976*b4dd7d09SAndy Fiddamanstty -icanon min 1 time 0 -inpck -echo
977*b4dd7d09SAndy Fiddaman
978*b4dd7d09SAndy Fiddamanget_term_size termsize || fatal_error "Could not get terminal size."
979*b4dd7d09SAndy Fiddaman
980*b4dd7d09SAndy Fiddaman# prechecks
981*b4dd7d09SAndy Fiddaman(( termsize.columns < 60 )) && fatal_error "Terminal width must be larger than 60 columns (currently ${termsize.columns})."
982*b4dd7d09SAndy Fiddaman
983*b4dd7d09SAndy Fiddamantypeset -A vtcode
984*b4dd7d09SAndy Fiddaman# color values taken from http://frexx.de/xterm-256-notes/, other
985*b4dd7d09SAndy Fiddaman# codes from http://vt100.net/docs/vt100-tm/
986*b4dd7d09SAndy Fiddamanvtcode=(
987*b4dd7d09SAndy Fiddaman    ["bg_black"]="$(print -n "\E[40m")"
988*b4dd7d09SAndy Fiddaman    ["fg_black"]="$(print -n "\E[30m")"
989*b4dd7d09SAndy Fiddaman    ["fg_red"]="$(print -n "\E[31m")"
990*b4dd7d09SAndy Fiddaman    ["fg_lightred"]="$(print -n "\E[1;31m")"
991*b4dd7d09SAndy Fiddaman    ["fg_green"]="$(print -n "\E[32m")"
992*b4dd7d09SAndy Fiddaman    ["fg_lightgreen"]="$(print -n "\E[1;32m")"
993*b4dd7d09SAndy Fiddaman    ["fg_yellow"]="$(print -n "\E[33m")"
994*b4dd7d09SAndy Fiddaman    ["fg_lightyellow"]="$(print -n "\E[1;33m")"
995*b4dd7d09SAndy Fiddaman    ["fg_blue"]="$(print -n "\E[34m")"
996*b4dd7d09SAndy Fiddaman    ["fg_lightblue"]="$(print -n "\E[1;34m")"
997*b4dd7d09SAndy Fiddaman    ["fg_grey"]="$(print -n "\E[1;37m")"
998*b4dd7d09SAndy Fiddaman    ["fg_white"]="$(print -n "\E[37m")"
999*b4dd7d09SAndy Fiddaman
1000*b4dd7d09SAndy Fiddaman    # misc other vt stuff
1001*b4dd7d09SAndy Fiddaman    ["vtreset"]="$(tput reset)"
1002*b4dd7d09SAndy Fiddaman    ["clear"]="$(tput clear)"
1003*b4dd7d09SAndy Fiddaman    ["bel"]="$(tput bel)"
1004*b4dd7d09SAndy Fiddaman    ["spaceline"]="$(for (( i=0 ; i < termsize.columns ; i++ )) ; do print -n " " ; done)"
1005*b4dd7d09SAndy Fiddaman)
1006*b4dd7d09SAndy Fiddaman
1007*b4dd7d09SAndy Fiddaman# character used to as marker that a single frame ends at this point - this
1008*b4dd7d09SAndy Fiddaman# is used by the "double buffering" code to make sure the "read" builtin
1009*b4dd7d09SAndy Fiddaman# can read a whole "frame" instead of reading stuff line-by-line
1010*b4dd7d09SAndy Fiddamantypeset -r end_of_frame=$'\t'
1011*b4dd7d09SAndy Fiddaman
1012*b4dd7d09SAndy Fiddaman# get terminal sequence to move cursor to position x,y
1013*b4dd7d09SAndy Fiddaman# (see http://vt100.net/docs/vt100-ug/chapter3.html#CPR)
1014*b4dd7d09SAndy Fiddamancase ${TERM} in
1015*b4dd7d09SAndy Fiddaman    xterm | xterm-color | vt100 | vt220 | dtterm | sun | sun-color)
1016*b4dd7d09SAndy Fiddaman        cup="$(infocmp -1 | \
1017*b4dd7d09SAndy Fiddaman	       egrep '^[[:space:]]*cup=' | \
1018*b4dd7d09SAndy Fiddaman	       sed -e 's/.*cup=//' \
1019*b4dd7d09SAndy Fiddaman	           -e 's/%[%id]*p1[%id]*/%2\\\$d/g' \
1020*b4dd7d09SAndy Fiddaman		   -e 's/%[%id]*p2[%id]*/%1\\\$d/g' \
1021*b4dd7d09SAndy Fiddaman		   -e 's/,$//')"
1022*b4dd7d09SAndy Fiddaman        for (( x=0 ; x < termsize.columns ; x++ )) ; do
1023*b4dd7d09SAndy Fiddaman            for (( y=0 ; y < termsize.lines ; y++ )) ; do
1024*b4dd7d09SAndy Fiddaman                vtcode[cup_${x}_${y}]="$(printf "${cup}" $((x + 1)) $((y + 1)) )"
1025*b4dd7d09SAndy Fiddaman            done
1026*b4dd7d09SAndy Fiddaman        done
1027*b4dd7d09SAndy Fiddaman        ;;
1028*b4dd7d09SAndy Fiddaman    *)
1029*b4dd7d09SAndy Fiddaman        printf "# Unrecognised terminal type '%s', fetching %dx%d items from terminfo database, please wait...\n" "${TERM}" "${termsize.columns}" "${termsize.lines}"
1030*b4dd7d09SAndy Fiddaman        for (( x=0 ; x < termsize.columns ; x++ )) ; do
1031*b4dd7d09SAndy Fiddaman            for (( y=0 ; y < termsize.lines ; y++ )) ; do
1032*b4dd7d09SAndy Fiddaman                vtcode[cup_${x}_${y}]="$(tput cup ${y} ${x})"
1033*b4dd7d09SAndy Fiddaman            done
1034*b4dd7d09SAndy Fiddaman        done
1035*b4dd7d09SAndy Fiddaman        ;;
1036*b4dd7d09SAndy Fiddamanesac
1037*b4dd7d09SAndy Fiddaman
1038*b4dd7d09SAndy Fiddamanprint -- "${vtcode["vtreset"]}"
1039*b4dd7d09SAndy Fiddaman
1040*b4dd7d09SAndy Fiddamanrun_logo
1041*b4dd7d09SAndy Fiddamanrun_menu
1042*b4dd7d09SAndy Fiddaman
1043*b4dd7d09SAndy Fiddamanexit 0
1044*b4dd7d09SAndy Fiddaman# EOF.
1045