18462SApril.Chin@Sun.COM#!/usr/bin/ksh93
28462SApril.Chin@Sun.COM
38462SApril.Chin@Sun.COM#
48462SApril.Chin@Sun.COM# CDDL HEADER START
58462SApril.Chin@Sun.COM#
68462SApril.Chin@Sun.COM# The contents of this file are subject to the terms of the
78462SApril.Chin@Sun.COM# Common Development and Distribution License (the "License").
88462SApril.Chin@Sun.COM# You may not use this file except in compliance with the License.
98462SApril.Chin@Sun.COM#
108462SApril.Chin@Sun.COM# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
118462SApril.Chin@Sun.COM# or http://www.opensolaris.org/os/licensing.
128462SApril.Chin@Sun.COM# See the License for the specific language governing permissions
138462SApril.Chin@Sun.COM# and limitations under the License.
148462SApril.Chin@Sun.COM#
158462SApril.Chin@Sun.COM# When distributing Covered Code, include this CDDL HEADER in each
168462SApril.Chin@Sun.COM# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
178462SApril.Chin@Sun.COM# If applicable, add the following below this CDDL HEADER, with the
188462SApril.Chin@Sun.COM# fields enclosed by brackets "[]" replaced with your own identifying
198462SApril.Chin@Sun.COM# information: Portions Copyright [yyyy] [name of copyright owner]
208462SApril.Chin@Sun.COM#
218462SApril.Chin@Sun.COM# CDDL HEADER END
228462SApril.Chin@Sun.COM#
238462SApril.Chin@Sun.COM
248462SApril.Chin@Sun.COM#
25*10898Sroland.mainz@nrubsig.org# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
268462SApril.Chin@Sun.COM# Use is subject to license terms.
278462SApril.Chin@Sun.COM#
288462SApril.Chin@Sun.COM
298462SApril.Chin@Sun.COM#
308462SApril.Chin@Sun.COM# gnaw - a simple ksh93 technology demo
318462SApril.Chin@Sun.COM#
328462SApril.Chin@Sun.COM# Note that this script has been written with the main idea to show
338462SApril.Chin@Sun.COM# many of ksh93's new features (comparing to ksh88/bash) and not
348462SApril.Chin@Sun.COM# as an example of efficient&&clean script code (much of the code
358462SApril.Chin@Sun.COM# could be done more efficient using compound variables, this script
368462SApril.Chin@Sun.COM# focus is the usage of associative arrays).
378462SApril.Chin@Sun.COM#
388462SApril.Chin@Sun.COM
398462SApril.Chin@Sun.COM# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
408462SApril.Chin@Sun.COMexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
418462SApril.Chin@Sun.COM
428462SApril.Chin@Sun.COM# Make sure all math stuff runs in the "C" locale to avoid problems
438462SApril.Chin@Sun.COM# with alternative # radix point representations (e.g. ',' instead of
448462SApril.Chin@Sun.COM# '.' in de_DE.*-locales). This needs to be set _before_ any
458462SApril.Chin@Sun.COM# floating-point constants are defined in this script).
468462SApril.Chin@Sun.COMif [[ "${LC_ALL}" != "" ]] ; then
478462SApril.Chin@Sun.COM    export \
488462SApril.Chin@Sun.COM        LC_MONETARY="${LC_ALL}" \
498462SApril.Chin@Sun.COM        LC_MESSAGES="${LC_ALL}" \
508462SApril.Chin@Sun.COM        LC_COLLATE="${LC_ALL}" \
518462SApril.Chin@Sun.COM        LC_CTYPE="${LC_ALL}"
528462SApril.Chin@Sun.COM        unset LC_ALL
538462SApril.Chin@Sun.COMfi
548462SApril.Chin@Sun.COMexport LC_NUMERIC=C
558462SApril.Chin@Sun.COM
568462SApril.Chin@Sun.COMfunction print_setcursorpos
578462SApril.Chin@Sun.COM{
588462SApril.Chin@Sun.COM    print -n -- "${vtcode[cup_${1}_${2}]}"
598462SApril.Chin@Sun.COM}
608462SApril.Chin@Sun.COM
618462SApril.Chin@Sun.COMfunction beep
628462SApril.Chin@Sun.COM{
638462SApril.Chin@Sun.COM    ${quiet} || print -n -- "${vtcode["bel"]}"
648462SApril.Chin@Sun.COM}
658462SApril.Chin@Sun.COM
668462SApril.Chin@Sun.COMfunction fatal_error
678462SApril.Chin@Sun.COM{
688462SApril.Chin@Sun.COM    print -u2 "${progname}: $*"
698462SApril.Chin@Sun.COM    exit 1
708462SApril.Chin@Sun.COM}
718462SApril.Chin@Sun.COM
728462SApril.Chin@Sun.COM# Get terminal size and put values into a compound variable with the integer
738462SApril.Chin@Sun.COM# members "columns" and "lines"
748462SApril.Chin@Sun.COMfunction get_term_size
758462SApril.Chin@Sun.COM{
768462SApril.Chin@Sun.COM	nameref rect=$1
778462SApril.Chin@Sun.COM
788462SApril.Chin@Sun.COM	rect.columns=${ tput cols ; } || return 1
798462SApril.Chin@Sun.COM	rect.lines=${ tput lines ; }  || return 1
808462SApril.Chin@Sun.COM
818462SApril.Chin@Sun.COM	return 0
828462SApril.Chin@Sun.COM}
838462SApril.Chin@Sun.COM
848462SApril.Chin@Sun.COMfunction print_levelmap
858462SApril.Chin@Sun.COM{
868462SApril.Chin@Sun.COM    integer screen_y_offset=$1
878462SApril.Chin@Sun.COM    integer start_y_pos=$2 # start at this line in the map
888462SApril.Chin@Sun.COM    integer max_numlines=$3 # maximum lines we're allowed to render
898462SApril.Chin@Sun.COM    integer x
908462SApril.Chin@Sun.COM    integer y
918462SApril.Chin@Sun.COM    typeset line=""
928462SApril.Chin@Sun.COM
938462SApril.Chin@Sun.COM    print_setcursorpos 0 ${screen_y_offset}
948462SApril.Chin@Sun.COM
958462SApril.Chin@Sun.COM    for (( y=start_y_pos; (y-start_y_pos) < max_numlines && y < levelmap["max_y"] ; y++ )) ; do
968462SApril.Chin@Sun.COM        line=""
978462SApril.Chin@Sun.COM        for (( x=0 ; x < levelmap["max_x"] ; x++ )) ; do
988462SApril.Chin@Sun.COM            line+="${levelmap["${x}_${y}"]}"
998462SApril.Chin@Sun.COM        done
1008462SApril.Chin@Sun.COM
1018462SApril.Chin@Sun.COM        print -- "${line} "
1028462SApril.Chin@Sun.COM    done
1038462SApril.Chin@Sun.COM
1048462SApril.Chin@Sun.COM    # print lines filled with spaces for each line not filled
1058462SApril.Chin@Sun.COM    # by the level map
1068462SApril.Chin@Sun.COM    line="${vtcode["spaceline"]:0:${levelmap["max_x"]}}"
1078462SApril.Chin@Sun.COM    for (( ; (y-start_y_pos) < max_numlines ; y++ )) ; do
1088462SApril.Chin@Sun.COM        print -- "${line} "
1098462SApril.Chin@Sun.COM    done
1108462SApril.Chin@Sun.COM    return 0
1118462SApril.Chin@Sun.COM}
1128462SApril.Chin@Sun.COM
1138462SApril.Chin@Sun.COMfunction level_completed
1148462SApril.Chin@Sun.COM{
1158462SApril.Chin@Sun.COM    integer i
1168462SApril.Chin@Sun.COM    typeset dummy
1178462SApril.Chin@Sun.COM    typeset render_buffer="$(
1188462SApril.Chin@Sun.COM    print -n -- "${vtcode["clear"]}"
1198462SApril.Chin@Sun.COM    cat <<ENDOFTEXT
1208462SApril.Chin@Sun.COM
1218462SApril.Chin@Sun.COM #       ######  #    #  ######  #
1228462SApril.Chin@Sun.COM #       #       #    #  #       #
1238462SApril.Chin@Sun.COM #       #####   #    #  #####   #
1248462SApril.Chin@Sun.COM #       #       #    #  #       #
1258462SApril.Chin@Sun.COM #       #        #  #   #       #
1268462SApril.Chin@Sun.COM ######  ######    ##    ######  ######
1278462SApril.Chin@Sun.COM
1288462SApril.Chin@Sun.COM             (Good job)
1298462SApril.Chin@Sun.COM
1308462SApril.Chin@Sun.COM     #####    ####   #    #  ######
1318462SApril.Chin@Sun.COM     #    #  #    #  ##   #  #
1328462SApril.Chin@Sun.COM     #    #  #    #  # #  #  #####
1338462SApril.Chin@Sun.COM     #    #  #    #  #  # #  #
1348462SApril.Chin@Sun.COM     #    #  #    #  #   ##  #
1358462SApril.Chin@Sun.COM     #####    ####   #    #  ######
1368462SApril.Chin@Sun.COM
1378462SApril.Chin@Sun.COM
1388462SApril.Chin@Sun.COMENDOFTEXT
1398462SApril.Chin@Sun.COM
1408462SApril.Chin@Sun.COM    printf "    SCORE: --> %s <--\n" "${player["score"]}"
1418462SApril.Chin@Sun.COM    printf "    LIVES: --> %s <--\n" "${player["lives"]}"
1428462SApril.Chin@Sun.COM    )"
1438462SApril.Chin@Sun.COM    print -- "${render_buffer}${end_of_frame}"
1448462SApril.Chin@Sun.COM
1458462SApril.Chin@Sun.COM    # wait five seconds and swallow any user input
1468462SApril.Chin@Sun.COM    for (( i=0 ; i < 50 ; i++ )) ; do
1478462SApril.Chin@Sun.COM        read -r -t 0.1 -n 1 dummy
1488462SApril.Chin@Sun.COM    done
1498462SApril.Chin@Sun.COM
1508462SApril.Chin@Sun.COM    print "Press any key to continue...${end_of_frame}"
1518462SApril.Chin@Sun.COM    # wait five secs or for a key
1528462SApril.Chin@Sun.COM    read -r -t 5 -n 1 dummy
1538462SApril.Chin@Sun.COM    return 0
1548462SApril.Chin@Sun.COM}
1558462SApril.Chin@Sun.COM
1568462SApril.Chin@Sun.COMfunction game_over
1578462SApril.Chin@Sun.COM{
1588462SApril.Chin@Sun.COM    typeset dummy
1598462SApril.Chin@Sun.COM    typeset render_buffer="$(
1608462SApril.Chin@Sun.COM    print -n -- "${vtcode["clear"]}"
1618462SApril.Chin@Sun.COM    cat <<ENDOFTEXT
1628462SApril.Chin@Sun.COM
1638462SApril.Chin@Sun.COM  ####     ##    #    #  ######
1648462SApril.Chin@Sun.COM #    #   #  #   ##  ##  #
1658462SApril.Chin@Sun.COM #       #    #  # ## #  #####
1668462SApril.Chin@Sun.COM #  ###  ######  #    #  #
1678462SApril.Chin@Sun.COM #    #  #    #  #    #  #
1688462SApril.Chin@Sun.COM  ####   #    #  #    #  ######
1698462SApril.Chin@Sun.COM
1708462SApril.Chin@Sun.COM            (LOSER!)
1718462SApril.Chin@Sun.COM
1728462SApril.Chin@Sun.COM  ####   #    #  ######  #####
1738462SApril.Chin@Sun.COM #    #  #    #  #       #    #
1748462SApril.Chin@Sun.COM #    #  #    #  #####   #    #
1758462SApril.Chin@Sun.COM #    #  #    #  #       #####
1768462SApril.Chin@Sun.COM #    #   #  #   #       #   #
1778462SApril.Chin@Sun.COM  ####     ##    ######  #    #
1788462SApril.Chin@Sun.COM
1798462SApril.Chin@Sun.COMENDOFTEXT
1808462SApril.Chin@Sun.COM
1818462SApril.Chin@Sun.COM    printf "\n    SCORE: --> %s <--\n" "${player["score"]}"
1828462SApril.Chin@Sun.COM    )"
1838462SApril.Chin@Sun.COM    print -r -- "${render_buffer}${end_of_frame}"
1848462SApril.Chin@Sun.COM
1858462SApril.Chin@Sun.COM    # wait five seconds and swallow any user input
1868462SApril.Chin@Sun.COM    for (( i=0 ; i < 50 ; i++ )) ; do
1878462SApril.Chin@Sun.COM        read -r -t 0.1 -n 1 dummy
1888462SApril.Chin@Sun.COM    done
1898462SApril.Chin@Sun.COM
1908462SApril.Chin@Sun.COM    print "Press any key to continue...${end_of_frame}"
1918462SApril.Chin@Sun.COM    # wait five secs or for a key
1928462SApril.Chin@Sun.COM    read -r -t 5 -n 1 dummy
1938462SApril.Chin@Sun.COM    return 0
1948462SApril.Chin@Sun.COM}
1958462SApril.Chin@Sun.COM
1968462SApril.Chin@Sun.COMfunction run_logo
1978462SApril.Chin@Sun.COM{
1988462SApril.Chin@Sun.COM    typeset render_buffer="$(
1998462SApril.Chin@Sun.COM    cat <<ENDOFTEXT
2008462SApril.Chin@Sun.COM
2018462SApril.Chin@Sun.COM #####  #     #    #    #     #   ###
2028462SApril.Chin@Sun.COM#     # ##    #   # #   #  #  #   ###
2038462SApril.Chin@Sun.COM#       # #   #  #   #  #  #  #   ###
2048462SApril.Chin@Sun.COM#  #### #  #  # #     # #  #  #    #
2058462SApril.Chin@Sun.COM#     # #   # # ####### #  #  #
2068462SApril.Chin@Sun.COM#     # #    ## #     # #  #  #   ###
2078462SApril.Chin@Sun.COM #####  #     # #     #  ## ##    ###
2088462SApril.Chin@Sun.COMENDOFTEXT
2098462SApril.Chin@Sun.COM    )"
2108462SApril.Chin@Sun.COM    print -- "${vtcode["clear"]}${render_buffer}"
2118462SApril.Chin@Sun.COM
2128462SApril.Chin@Sun.COM    # wait two seconds and swallow any user input
2138462SApril.Chin@Sun.COM    for (( i=0 ; i < 20 ; i++ )) ; do
2148462SApril.Chin@Sun.COM        read -r -t 0.1 -n 1 dummy
2158462SApril.Chin@Sun.COM    done
2168462SApril.Chin@Sun.COM
2178462SApril.Chin@Sun.COM    print "\n   (The KornShell 93 maze game)"
2188462SApril.Chin@Sun.COM
2198462SApril.Chin@Sun.COM    attract_mode
2208462SApril.Chin@Sun.COM    return 0
2218462SApril.Chin@Sun.COM}
2228462SApril.Chin@Sun.COM
2238462SApril.Chin@Sun.COMfunction attract_mode
2248462SApril.Chin@Sun.COM{
2258462SApril.Chin@Sun.COM(
2268462SApril.Chin@Sun.COM    # Now present some info, line-by-line in an endless loop
2278462SApril.Chin@Sun.COM    # until the user presses a key (we turn the "magic" return
2288462SApril.Chin@Sun.COM    # code for that)
2298462SApril.Chin@Sun.COM    integer -r magic_return_code=69
2308462SApril.Chin@Sun.COM    typeset line
2318462SApril.Chin@Sun.COM    IFS='' ; # Make sure we do not swallow whitespaces
2328462SApril.Chin@Sun.COM
2338462SApril.Chin@Sun.COM    while true ; do
2348462SApril.Chin@Sun.COM        (
2358462SApril.Chin@Sun.COM            redirect 5<&0
2368462SApril.Chin@Sun.COM
2378462SApril.Chin@Sun.COM        (cat <<ENDOFTEXT
2388462SApril.Chin@Sun.COM
2398462SApril.Chin@Sun.COM
2408462SApril.Chin@Sun.COM
2418462SApril.Chin@Sun.COM
2428462SApril.Chin@Sun.COM
2438462SApril.Chin@Sun.COM         ################
2448462SApril.Chin@Sun.COM     ########################
2458462SApril.Chin@Sun.COM   ############################
2468462SApril.Chin@Sun.COM  #######     ######     #######
2478462SApril.Chin@Sun.COM  ######     ######     ########
2488462SApril.Chin@Sun.COM  #######     ######     #######
2498462SApril.Chin@Sun.COM  ##############################
2508462SApril.Chin@Sun.COM  ##############################
2518462SApril.Chin@Sun.COM  ##############################
2528462SApril.Chin@Sun.COM  ##############################
2538462SApril.Chin@Sun.COM  ##############################
2548462SApril.Chin@Sun.COM  #########  ########  #########
2558462SApril.Chin@Sun.COM  #  ####      ####      ####  #
2568462SApril.Chin@Sun.COM
2578462SApril.Chin@Sun.COM
2588462SApril.Chin@Sun.COM
2598462SApril.Chin@Sun.COM
2608462SApril.Chin@Sun.COM
2618462SApril.Chin@Sun.COM
2628462SApril.Chin@Sun.COM           Written by
2638462SApril.Chin@Sun.COM
2648462SApril.Chin@Sun.COM          Roland Mainz
2658462SApril.Chin@Sun.COM    (roland.mainz@nrubsig.org)
2668462SApril.Chin@Sun.COM
2678462SApril.Chin@Sun.COM
2688462SApril.Chin@Sun.COM
2698462SApril.Chin@Sun.COM
2708462SApril.Chin@Sun.COM
2718462SApril.Chin@Sun.COM
2728462SApril.Chin@Sun.COM           ##############         
2738462SApril.Chin@Sun.COM      ########################    
2748462SApril.Chin@Sun.COM   #################**############
2758462SApril.Chin@Sun.COM  ################################
2768462SApril.Chin@Sun.COM ############################     
2778462SApril.Chin@Sun.COM ######################           
2788462SApril.Chin@Sun.COM ################                 
2798462SApril.Chin@Sun.COM ######################           
2808462SApril.Chin@Sun.COM ############################     
2818462SApril.Chin@Sun.COM  ################################
2828462SApril.Chin@Sun.COM   ############################## 
2838462SApril.Chin@Sun.COM      ########################    
2848462SApril.Chin@Sun.COM           ##############    
2858462SApril.Chin@Sun.COM
2868462SApril.Chin@Sun.COM
2878462SApril.Chin@Sun.COM
2888462SApril.Chin@Sun.COM
2898462SApril.Chin@Sun.COM
2908462SApril.Chin@Sun.COM
2918462SApril.Chin@Sun.COM
2928462SApril.Chin@Sun.COM             High scores:
2938462SApril.Chin@Sun.COM  
2948462SApril.Chin@Sun.COM        * 'chin'      8200 pt
2958462SApril.Chin@Sun.COM        * 'gisburn'   7900 pt
2968462SApril.Chin@Sun.COM        * 'tpenta'    5520 pt
2978462SApril.Chin@Sun.COM        * 'kupfer'    5510 pt
2988462SApril.Chin@Sun.COM        * 'noname'    5000 pt
2998462SApril.Chin@Sun.COM        * 'noname'    4000 pt
3008462SApril.Chin@Sun.COM        * 'livad'     3120 pt
3018462SApril.Chin@Sun.COM        * 'noname'    3000 pt
3028462SApril.Chin@Sun.COM        * 'noname'    2000 pt
3038462SApril.Chin@Sun.COM        * 'noname'    1000 pt
3048462SApril.Chin@Sun.COM  
3058462SApril.Chin@Sun.COMENDOFTEXT
3068462SApril.Chin@Sun.COM
3078462SApril.Chin@Sun.COM        # clear screen, line-by-line
3088462SApril.Chin@Sun.COM        for (( i=0 ; i < termsize.lines ; i++ )) ; do print "" ; done
3098462SApril.Chin@Sun.COM        ) | (while read -r line ; do
3108462SApril.Chin@Sun.COM                read -r -t 0.3 -n 1 c <&5
3118462SApril.Chin@Sun.COM                [[ "$c" != "" ]] && exit ${magic_return_code}
3128462SApril.Chin@Sun.COM                print -- "${line}"
3138462SApril.Chin@Sun.COM            done)
3148462SApril.Chin@Sun.COM        (( $? == magic_return_code )) && exit ${magic_return_code}
3158462SApril.Chin@Sun.COM        )
3168462SApril.Chin@Sun.COM        (( $? == magic_return_code )) && return 0
3178462SApril.Chin@Sun.COM
3188462SApril.Chin@Sun.COM        sleep 2
3198462SApril.Chin@Sun.COM    done
3208462SApril.Chin@Sun.COM)
3218462SApril.Chin@Sun.COM}
3228462SApril.Chin@Sun.COM
3238462SApril.Chin@Sun.COMfunction run_menu
3248462SApril.Chin@Sun.COM{
3258462SApril.Chin@Sun.COM    integer numlevels=0
3268462SApril.Chin@Sun.COM    integer selected_level=0
3278462SApril.Chin@Sun.COM    typeset l
3288462SApril.Chin@Sun.COM
3298462SApril.Chin@Sun.COM    # built list of available levels based on the "function levelmap_.*"
3308462SApril.Chin@Sun.COM    # built into this script
3318462SApril.Chin@Sun.COM    typeset -f | egrep "^function.*levelmap_.*" | sed 's/^function //' |
3328462SApril.Chin@Sun.COM    while read -r l ; do
3338462SApril.Chin@Sun.COM        levellist[numlevels]="$l"
3348462SApril.Chin@Sun.COM        numlevels+=1
3358462SApril.Chin@Sun.COM    done
3368462SApril.Chin@Sun.COM
3378462SApril.Chin@Sun.COM    # swallow any queued user input (e.g. drain stdin)
3388462SApril.Chin@Sun.COM    read -r -t 0.1 -n 100 dummy
3398462SApril.Chin@Sun.COM
3408462SApril.Chin@Sun.COM    while true ; do
3418462SApril.Chin@Sun.COM        # menu loop with timeout (which switches to "attract mode")
3428462SApril.Chin@Sun.COM        while true ; do
3438462SApril.Chin@Sun.COM            print -n -- "${vtcode["clear"]}"
3448462SApril.Chin@Sun.COM
3458462SApril.Chin@Sun.COM    cat <<ENDOFTEXT
3468462SApril.Chin@Sun.COM>======================================\   
3478462SApril.Chin@Sun.COM>  /-\     .--.                        |
3488462SApril.Chin@Sun.COM> | OO|   / _.-' .-.   .-.  .-.   .-.  |
3498462SApril.Chin@Sun.COM> |   |   \  '-. '-'   '-'  '-'   '-'  |
3508462SApril.Chin@Sun.COM> ^^^^^    '--'                        |
3518462SApril.Chin@Sun.COM>======\       /================\  .-. |
3528462SApril.Chin@Sun.COM>      |       |                |  '-' |
3538462SApril.Chin@Sun.COM ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3548462SApril.Chin@Sun.COMENDOFTEXT
3558462SApril.Chin@Sun.COM            print "    GNAW - the ksh93 maze game"
3568462SApril.Chin@Sun.COM            print "\n\tMenu:"
3578462SApril.Chin@Sun.COM
3588462SApril.Chin@Sun.COM            print "\t - [L]evels:"
3598462SApril.Chin@Sun.COM            for (( i=0 ; i < numlevels ; i++ )) ; do
3608462SApril.Chin@Sun.COM                printf "\t    %s %s \n" "$( (( i == selected_level )) && print -n "*" || print -n " ")" "${levellist[i]##levelmap_}"
3618462SApril.Chin@Sun.COM            done
3628462SApril.Chin@Sun.COM
3638462SApril.Chin@Sun.COM            print  "\t - Rendering options:"
3648462SApril.Chin@Sun.COM            printf "\t    [%s] Use [U]nicode\n" "$( (( game_use_unicode == 1 )) && print -n "x" || print -n "_" )"
3658462SApril.Chin@Sun.COM            printf "\t    [%s] Use [C]olors\n"  "$( (( game_use_colors  == 1 )) && print -n "x" || print -n "_" )"
3668462SApril.Chin@Sun.COM
3678462SApril.Chin@Sun.COM            print "\t - [S]tart - [Q]uit"
3688462SApril.Chin@Sun.COM
3698462SApril.Chin@Sun.COM            # wait 30 secs (before we switch to "attract mode")
3708462SApril.Chin@Sun.COM            c="" ; read -r -t 30 -n 1 c
3718462SApril.Chin@Sun.COM            case "$c" in
3728462SApril.Chin@Sun.COM                'l') (( selected_level=(selected_level+numlevels+1) % numlevels )) ;;
3738462SApril.Chin@Sun.COM                'L') (( selected_level=(selected_level+numlevels-1) % numlevels )) ;;
3748462SApril.Chin@Sun.COM                ~(Fi)s)
3758462SApril.Chin@Sun.COM                    (( game_use_colors == 1 )) && print -- "${vtcode["bg_black"]}"
3768462SApril.Chin@Sun.COM                    case "${game_use_colors}${game_use_unicode}" in
3778462SApril.Chin@Sun.COM                        "00") main_loop "${levellist[selected_level]}" ;;
3788462SApril.Chin@Sun.COM                        "01") main_loop "${levellist[selected_level]}" | map_filter 0 1 ;;
3798462SApril.Chin@Sun.COM                        "10") main_loop "${levellist[selected_level]}" | map_filter 1 0 ;;
3808462SApril.Chin@Sun.COM                        "11") main_loop "${levellist[selected_level]}" | map_filter 1 1 ;;
3818462SApril.Chin@Sun.COM                    esac
3828462SApril.Chin@Sun.COM                    print -- "${vtcode["vtreset"]}"
3838462SApril.Chin@Sun.COM                    ;;
3848462SApril.Chin@Sun.COM                ~(Fi)q | $'\E')
3858462SApril.Chin@Sun.COM                    # make sure we do not exit on a cursor key (e.g. <esc>[A,B,C,D)
3868462SApril.Chin@Sun.COM                    read -r -t 0.01 -n 1 c
3878462SApril.Chin@Sun.COM                    if [[ "$c" == "[" ]] ; then
3888462SApril.Chin@Sun.COM                        # this was a cursor key sequence, just eat the 3rd charcater
3898462SApril.Chin@Sun.COM                        read -r -t 0.01 -n 1 c
3908462SApril.Chin@Sun.COM                    else
3918462SApril.Chin@Sun.COM                        exit 0
3928462SApril.Chin@Sun.COM                    fi
3938462SApril.Chin@Sun.COM                    ;;
3948462SApril.Chin@Sun.COM                ~(Fi)u) (( game_use_unicode=(game_use_unicode+2+1) % 2)) ;;
3958462SApril.Chin@Sun.COM                ~(Fi)c) (( game_use_colors=(game_use_colors+2+1) % 2))   ;;
3968462SApril.Chin@Sun.COM                "") break ;; # timeout, switch to attract mode
3978462SApril.Chin@Sun.COM                *) beep ;;
3988462SApril.Chin@Sun.COM            esac
3998462SApril.Chin@Sun.COM        done
4008462SApril.Chin@Sun.COM
4018462SApril.Chin@Sun.COM        print -n -- "${vtcode["clear"]}"
4028462SApril.Chin@Sun.COM        attract_mode
4038462SApril.Chin@Sun.COM    done
4048462SApril.Chin@Sun.COM    return 0
4058462SApril.Chin@Sun.COM}
4068462SApril.Chin@Sun.COM
4078462SApril.Chin@Sun.COMfunction levelmap_stripes
4088462SApril.Chin@Sun.COM{
4098462SApril.Chin@Sun.COMcat <<ENDOFLEVEL
4108462SApril.Chin@Sun.COM###################################
4118462SApril.Chin@Sun.COM#.......    ...............    P  #
4128462SApril.Chin@Sun.COM#########..#################..### #
4138462SApril.Chin@Sun.COM#########..#################..### #
4148462SApril.Chin@Sun.COM#.......    ..    ..............# #
4158462SApril.Chin@Sun.COM###############  ################ #
4168462SApril.Chin@Sun.COM###############  ################ #
4178462SApril.Chin@Sun.COM#............. M  ..............# #
4188462SApril.Chin@Sun.COM##..#####################  ###### #
4198462SApril.Chin@Sun.COM##..#####################  ###### #
4208462SApril.Chin@Sun.COM#.......  ...........    .......# #
4218462SApril.Chin@Sun.COM########  ############  ######### #
4228462SApril.Chin@Sun.COM#   ####  ############  ######### #
4238462SApril.Chin@Sun.COM# #..................     ......# #
4248462SApril.Chin@Sun.COM# ############################### # 
4258462SApril.Chin@Sun.COM#                                 #
4268462SApril.Chin@Sun.COM###################################
4278462SApril.Chin@Sun.COMENDOFLEVEL
4288462SApril.Chin@Sun.COM    return 0
4298462SApril.Chin@Sun.COM}
4308462SApril.Chin@Sun.COM
4318462SApril.Chin@Sun.COMfunction levelmap_livad
4328462SApril.Chin@Sun.COM{
4338462SApril.Chin@Sun.COMcat <<ENDOFLEVEL
4348462SApril.Chin@Sun.COM#####################################################
4358462SApril.Chin@Sun.COM#                                                   #
4368462SApril.Chin@Sun.COM# ##############  ###############  ################ #
4378462SApril.Chin@Sun.COM# #............       P             ..............# #
4388462SApril.Chin@Sun.COM#  .#############################################.# #
4398462SApril.Chin@Sun.COM# #.#..........                     ............#.  #
4408462SApril.Chin@Sun.COM# #.#.##########  ###############  ############.#.# #
4418462SApril.Chin@Sun.COM# #...#........                     ..........#...# #
4428462SApril.Chin@Sun.COM# #...#.#####################################.#.#.# #
4438462SApril.Chin@Sun.COM# #...#.#......                     ........#...#.# #
4448462SApril.Chin@Sun.COM# #.#.#...######  #########################.#.#.#.# #
4458462SApril.Chin@Sun.COM#  .#.....#....          M          ......#...#.#.# #
4468462SApril.Chin@Sun.COM# #.#.#...#######################  ########.#.#.#.# #
4478462SApril.Chin@Sun.COM# #...#.#......                     ........#...#.# #
4488462SApril.Chin@Sun.COM# #...#.########  ###############  ##########.#.#.# #
4498462SApril.Chin@Sun.COM# #...#........                     ..........#...# #
4508462SApril.Chin@Sun.COM# #.#.#########################################.#.# #
4518462SApril.Chin@Sun.COM# #.#..........                     ............#.  #
4528462SApril.Chin@Sun.COM#  .############  ###############  ##############.# #
4538462SApril.Chin@Sun.COM# #............                     ..............# #
4548462SApril.Chin@Sun.COM# ################################################# #
4558462SApril.Chin@Sun.COM#                                                   #
4568462SApril.Chin@Sun.COM#####################################################
4578462SApril.Chin@Sun.COMENDOFLEVEL
4588462SApril.Chin@Sun.COM    return 0
4598462SApril.Chin@Sun.COM}
4608462SApril.Chin@Sun.COM
4618462SApril.Chin@Sun.COMfunction levelmap_classic1
4628462SApril.Chin@Sun.COM{
4638462SApril.Chin@Sun.COMcat <<ENDOFLEVEL
4648462SApril.Chin@Sun.COM#########################
4658462SApril.Chin@Sun.COM#.P.........#...........#
4668462SApril.Chin@Sun.COM#.####.####.#.####.####.#
4678462SApril.Chin@Sun.COM#.#  #.#  #.#.#  #.#  #.#
4688462SApril.Chin@Sun.COM#.#  #.#  #.#.#  #.#  #.#
4698462SApril.Chin@Sun.COM#.####.####.#.####.####.#
4708462SApril.Chin@Sun.COM#.......................#
4718462SApril.Chin@Sun.COM#.####.#.#######.#.####.#
4728462SApril.Chin@Sun.COM#.#  #.#.#     #.#.#  #.#
4738462SApril.Chin@Sun.COM#.####.#.#######.#.####.#
4748462SApril.Chin@Sun.COM#......#....#....#......#
4758462SApril.Chin@Sun.COM######.####.#.####.######
4768462SApril.Chin@Sun.COM###### #         # ######
4778462SApril.Chin@Sun.COM###### # ##   ## # ######
4788462SApril.Chin@Sun.COM###### # #     # # ######
4798462SApril.Chin@Sun.COM#        #  M  #        #
4808462SApril.Chin@Sun.COM###### # ####### # ######
4818462SApril.Chin@Sun.COM###### #         # ######
4828462SApril.Chin@Sun.COM###### # ####### # ######
4838462SApril.Chin@Sun.COM###### # #     # # ######
4848462SApril.Chin@Sun.COM######.#.#######.#.######
4858462SApril.Chin@Sun.COM#...........#...........#
4868462SApril.Chin@Sun.COM#.###.###...#...###.###.#
4878462SApril.Chin@Sun.COM#...#...............#...#
4888462SApril.Chin@Sun.COM###.#....#######....#.###
4898462SApril.Chin@Sun.COM# #.#..#.#     #.#..#.# #
4908462SApril.Chin@Sun.COM###....#.#######.#....###
4918462SApril.Chin@Sun.COM#......#....#....#......#
4928462SApril.Chin@Sun.COM#.#########.#.#########.#
4938462SApril.Chin@Sun.COM#.......................#
4948462SApril.Chin@Sun.COM#########################
4958462SApril.Chin@Sun.COMENDOFLEVEL
4968462SApril.Chin@Sun.COM    return 0
4978462SApril.Chin@Sun.COM}
4988462SApril.Chin@Sun.COM
4998462SApril.Chin@Sun.COMfunction levelmap_classic2
5008462SApril.Chin@Sun.COM{
5018462SApril.Chin@Sun.COMcat <<ENDOFLEVEL
5028462SApril.Chin@Sun.COM#######################
5038462SApril.Chin@Sun.COM#.P...#.........#.....#
5048462SApril.Chin@Sun.COM#.###.#.#######.#.###.#
5058462SApril.Chin@Sun.COM#.....................#
5068462SApril.Chin@Sun.COM###.#.####.#.####.#.###
5078462SApril.Chin@Sun.COM###.#......#......#.###
5088462SApril.Chin@Sun.COM###.###.#######.###.###
5098462SApril.Chin@Sun.COM###.................###
5108462SApril.Chin@Sun.COM###.###.### ###.###.###
5118462SApril.Chin@Sun.COM###.#...#M    #...#.###
5128462SApril.Chin@Sun.COM###.#.#.#######.#.#.###
5138462SApril.Chin@Sun.COM#.....#.........#.....#
5148462SApril.Chin@Sun.COM###.#####..#..#####.###
5158462SApril.Chin@Sun.COM###........#........###
5168462SApril.Chin@Sun.COM###.###.#######.###.###
5178462SApril.Chin@Sun.COM#.....................#
5188462SApril.Chin@Sun.COM#.###.####.#.####.###.#
5198462SApril.Chin@Sun.COM#.###.#....#....#.###.#
5208462SApril.Chin@Sun.COM#.###.#.#######.#.###.#
5218462SApril.Chin@Sun.COM#.....................#
5228462SApril.Chin@Sun.COM#######################
5238462SApril.Chin@Sun.COMENDOFLEVEL
5248462SApril.Chin@Sun.COM    return 0
5258462SApril.Chin@Sun.COM}
5268462SApril.Chin@Sun.COM
5278462SApril.Chin@Sun.COMfunction levelmap_easy
5288462SApril.Chin@Sun.COM{
5298462SApril.Chin@Sun.COMcat <<ENDOFLEVEL
5308462SApril.Chin@Sun.COM##################
5318462SApril.Chin@Sun.COM# .............. #
5328462SApril.Chin@Sun.COM# . ######       #
5338462SApril.Chin@Sun.COM# . #  M #       #
5348462SApril.Chin@Sun.COM# . #    #       #
5358462SApril.Chin@Sun.COM# . ### ##       #
5368462SApril.Chin@Sun.COM# .   #          #
5378462SApril.Chin@Sun.COM# .   ###        #
5388462SApril.Chin@Sun.COM# .              #
5398462SApril.Chin@Sun.COM# ..........     #
5408462SApril.Chin@Sun.COM# .......... P   #
5418462SApril.Chin@Sun.COM##################
5428462SApril.Chin@Sun.COMENDOFLEVEL
5438462SApril.Chin@Sun.COM    return 0
5448462SApril.Chin@Sun.COM}
5458462SApril.Chin@Sun.COM
5468462SApril.Chin@Sun.COMfunction levelmap_sunsolaristext
5478462SApril.Chin@Sun.COM{
5488462SApril.Chin@Sun.COMcat <<ENDOFLEVEL
5498462SApril.Chin@Sun.COM################################################
5508462SApril.Chin@Sun.COM# .####   .    #  #....#                       #
5518462SApril.Chin@Sun.COM# #       #    #  #....#                       #
5528462SApril.Chin@Sun.COM#  ####   #    #  #.#..#          M            #
5538462SApril.Chin@Sun.COM#      #  #    #  #..#.#                       #
5548462SApril.Chin@Sun.COM# #    #  #    #  #...##                       #
5558462SApril.Chin@Sun.COM#  ####    ####   #....#                       #
5568462SApril.Chin@Sun.COM#                                              #
5578462SApril.Chin@Sun.COM#  ####    ####  #       ##    #####  #  ####  #
5588462SApril.Chin@Sun.COM# #       #.  .# #      #  #   #....# # #      #
5598462SApril.Chin@Sun.COM#  ####   #    # #      # P #  #....# #  ####  #
5608462SApril.Chin@Sun.COM#      #  #    ###      #.#### #.###  #      # #
5618462SApril.Chin@Sun.COM# #   .#  #.  ..        #    # #...#  # #    # #
5628462SApril.Chin@Sun.COM#  ####    ####  ###### .    #  ....# #  ####. #
5638462SApril.Chin@Sun.COM################################################
5648462SApril.Chin@Sun.COMENDOFLEVEL
5658462SApril.Chin@Sun.COM    return 0
5668462SApril.Chin@Sun.COM}
5678462SApril.Chin@Sun.COM
5688462SApril.Chin@Sun.COMfunction read_levelmap
5698462SApril.Chin@Sun.COM{
5708462SApril.Chin@Sun.COM    typeset map="$( $1 )"
5718462SApril.Chin@Sun.COM
5728462SApril.Chin@Sun.COM    integer y=0
5738462SApril.Chin@Sun.COM    integer x=0
5748462SApril.Chin@Sun.COM    integer maxx=0
5758462SApril.Chin@Sun.COM    integer numdots=0
5768462SApril.Chin@Sun.COM    typeset line
5778462SApril.Chin@Sun.COM    typeset c
5788462SApril.Chin@Sun.COM
5798462SApril.Chin@Sun.COM    while read -r line ; do
5808462SApril.Chin@Sun.COM        for (( x=0 ; x < ${#line} ; x++ )) ; do
5818462SApril.Chin@Sun.COM            c="${line:x:1}"
5828462SApril.Chin@Sun.COM
5838462SApril.Chin@Sun.COM            case $c in
5848462SApril.Chin@Sun.COM                ".") numdots+=1 ;;
5858462SApril.Chin@Sun.COM                "M")
5868462SApril.Chin@Sun.COM		    # log start position of monsters
5878462SApril.Chin@Sun.COM                    levelmap["monsterstartpos_x"]="$x"
5888462SApril.Chin@Sun.COM                    levelmap["monsterstartpos_y"]="$y"
5898462SApril.Chin@Sun.COM                    c=" "
5908462SApril.Chin@Sun.COM                    ;;
5918462SApril.Chin@Sun.COM                "P")
5928462SApril.Chin@Sun.COM		    # log start position of player
5938462SApril.Chin@Sun.COM                    levelmap["playerstartpos_x"]="$x"
5948462SApril.Chin@Sun.COM                    levelmap["playerstartpos_y"]="$y"
5958462SApril.Chin@Sun.COM                    c=" "
5968462SApril.Chin@Sun.COM                    ;;
5978462SApril.Chin@Sun.COM            esac
5988462SApril.Chin@Sun.COM
5998462SApril.Chin@Sun.COM            levelmap["${x}_${y}"]="$c"
6008462SApril.Chin@Sun.COM        done
6018462SApril.Chin@Sun.COM        (( maxx=x , y++ ))
6028462SApril.Chin@Sun.COM    done <<<"${map}"
6038462SApril.Chin@Sun.COM
6048462SApril.Chin@Sun.COM    levelmap["max_x"]=${maxx}
6058462SApril.Chin@Sun.COM    levelmap["max_y"]=${y}
6068462SApril.Chin@Sun.COM    levelmap["numdots"]=${numdots}
6078462SApril.Chin@Sun.COM
6088462SApril.Chin@Sun.COM    # consistency checks
6098462SApril.Chin@Sun.COM    if [[ "${levelmap["monsterstartpos_x"]}" == "" ]] ; then
6108462SApril.Chin@Sun.COM        fatal_error "read_levelmap: monsterstartpos_x is empty."
6118462SApril.Chin@Sun.COM    fi
6128462SApril.Chin@Sun.COM    if [[ "${levelmap["playerstartpos_x"]}" == "" ]] ; then
6138462SApril.Chin@Sun.COM        fatal_error "read_levelmap: playerstartpos_x is empty."
6148462SApril.Chin@Sun.COM    fi
6158462SApril.Chin@Sun.COM
6168462SApril.Chin@Sun.COM    return 0
6178462SApril.Chin@Sun.COM}
6188462SApril.Chin@Sun.COM
6198462SApril.Chin@Sun.COMfunction player.set
6208462SApril.Chin@Sun.COM{
6218462SApril.Chin@Sun.COM    case "${.sh.subscript}" in
6228462SApril.Chin@Sun.COM        pos_y)
6238462SApril.Chin@Sun.COM            if [[ "${levelmap["${player["pos_x"]}_${.sh.value}"]}" == "#" ]] ; then
6248462SApril.Chin@Sun.COM                .sh.value=${player["pos_y"]}
6258462SApril.Chin@Sun.COM                beep
6268462SApril.Chin@Sun.COM            fi
6278462SApril.Chin@Sun.COM            ;;
6288462SApril.Chin@Sun.COM
6298462SApril.Chin@Sun.COM        pos_x)
6308462SApril.Chin@Sun.COM            if [[ "${levelmap["${.sh.value}_${player["pos_y"]}"]}" == "#" ]] ; then
6318462SApril.Chin@Sun.COM                .sh.value=${player["pos_x"]}
6328462SApril.Chin@Sun.COM                beep
6338462SApril.Chin@Sun.COM            fi
6348462SApril.Chin@Sun.COM            ;;
6358462SApril.Chin@Sun.COM    esac
6368462SApril.Chin@Sun.COM    return 0
6378462SApril.Chin@Sun.COM}
6388462SApril.Chin@Sun.COM
6398462SApril.Chin@Sun.COMfunction monster.set
6408462SApril.Chin@Sun.COM{
6418462SApril.Chin@Sun.COM    case "${.sh.subscript}" in
6428462SApril.Chin@Sun.COM        *_pos_y)
6438462SApril.Chin@Sun.COM            if [[ "${levelmap["${monster[${currmonster}_"pos_x"]}_${.sh.value}"]}" == "#" ]] ; then
6448462SApril.Chin@Sun.COM                .sh.value=${monster[${currmonster}_"pos_y"]}
6458462SApril.Chin@Sun.COM                # turn homing off when the monster hit a wall
6468462SApril.Chin@Sun.COM                monster[${currmonster}_"homing"]=0
6478462SApril.Chin@Sun.COM            fi
6488462SApril.Chin@Sun.COM            ;;
6498462SApril.Chin@Sun.COM
6508462SApril.Chin@Sun.COM        *_pos_x)
6518462SApril.Chin@Sun.COM            if [[ "${levelmap["${.sh.value}_${monster[${currmonster}_"pos_y"]}"]}" == "#" ]] ; then
6528462SApril.Chin@Sun.COM                .sh.value=${monster[${currmonster}_"pos_x"]}
6538462SApril.Chin@Sun.COM                # turn homing off when the monster hit a wall
6548462SApril.Chin@Sun.COM                monster[${currmonster}_"homing"]=0
6558462SApril.Chin@Sun.COM            fi
6568462SApril.Chin@Sun.COM            ;;
6578462SApril.Chin@Sun.COM    esac
6588462SApril.Chin@Sun.COM    return 0
6598462SApril.Chin@Sun.COM}
6608462SApril.Chin@Sun.COM
6618462SApril.Chin@Sun.COMfunction render_game
6628462SApril.Chin@Sun.COM{
6638462SApril.Chin@Sun.COM    # render_buffer is some kind of "background buffer" to "double buffer"
6648462SApril.Chin@Sun.COM    # all output and combine it in one write to reduce flickering in the
6658462SApril.Chin@Sun.COM    # terminal
6668462SApril.Chin@Sun.COM    typeset render_buffer="$(
6678462SApril.Chin@Sun.COM        integer screen_y_offset=1
6688462SApril.Chin@Sun.COM        integer start_y_pos=0
6698462SApril.Chin@Sun.COM        integer render_num_lines=${levelmap["max_y"]}
6708462SApril.Chin@Sun.COM
6718462SApril.Chin@Sun.COM        if (( (termsize.lines-3) < levelmap["max_y"] )) ; then
6728462SApril.Chin@Sun.COM            (( start_y_pos=player["pos_y"] / 2))
6738462SApril.Chin@Sun.COM            (( render_num_lines=termsize.lines-5))
6748462SApril.Chin@Sun.COM        fi
6758462SApril.Chin@Sun.COM
6768462SApril.Chin@Sun.COM        #print -n -- "${vtcode["clear"]}"
6778462SApril.Chin@Sun.COM        print_setcursorpos 0 0
6788462SApril.Chin@Sun.COM
6798462SApril.Chin@Sun.COM        # print score (note the " " around "%d" are neccesary to clean up cruft
6808462SApril.Chin@Sun.COM        # when we overwrite the level
6818462SApril.Chin@Sun.COM        printf "SCORE: %05d  DOTS: %.3d  LIVES: %2.d " "${player["score"]}" "${levelmap["numdots"]}" "${player["lives"]}"
6828462SApril.Chin@Sun.COM        print_levelmap ${screen_y_offset} ${start_y_pos} ${render_num_lines}
6838462SApril.Chin@Sun.COM
6848462SApril.Chin@Sun.COM        # render player
6858462SApril.Chin@Sun.COM        print_setcursorpos ${player["pos_x"]} $((player["pos_y"]+screen_y_offset-start_y_pos))
6868462SApril.Chin@Sun.COM        print -n "@"
6878462SApril.Chin@Sun.COM
6888462SApril.Chin@Sun.COM        # render monsters
6898462SApril.Chin@Sun.COM        for currmonster in ${monsterlist} ; do
6908462SApril.Chin@Sun.COM            (( m_pos_x=monster[${currmonster}_"pos_x"] ))
6918462SApril.Chin@Sun.COM            (( m_pos_y=monster[${currmonster}_"pos_y"]+screen_y_offset-start_y_pos ))
6928462SApril.Chin@Sun.COM
6938462SApril.Chin@Sun.COM            if (( m_pos_y >= screen_y_offset && m_pos_y < render_num_lines )) ; then
6948462SApril.Chin@Sun.COM                print_setcursorpos ${m_pos_x} ${m_pos_y}
6958462SApril.Chin@Sun.COM                print -n "x"
6968462SApril.Chin@Sun.COM            fi
6978462SApril.Chin@Sun.COM        done
6988462SApril.Chin@Sun.COM
6998462SApril.Chin@Sun.COM        # status block
7008462SApril.Chin@Sun.COM        print_setcursorpos 0 $((render_num_lines+screen_y_offset))
7018462SApril.Chin@Sun.COM        emptyline="                                                            "
7028462SApril.Chin@Sun.COM        print -n " >> ${player["message"]} <<${emptyline:0:${#emptyline}-${#player["message"]}}"
7038462SApril.Chin@Sun.COM    )"
7048462SApril.Chin@Sun.COM    print -r -- "${render_buffer}${end_of_frame}"
7058462SApril.Chin@Sun.COM#    print "renderbuffersize=$(print "${render_buffer}" | wc -c) ${end_of_frame}"
7068462SApril.Chin@Sun.COM    return 0
7078462SApril.Chin@Sun.COM}
7088462SApril.Chin@Sun.COM
7098462SApril.Chin@Sun.COMfunction main_loop
7108462SApril.Chin@Sun.COM{
7118462SApril.Chin@Sun.COM    float   sleep_per_cycle=0.2
7128462SApril.Chin@Sun.COM    float   seconds_before_read
7138462SApril.Chin@Sun.COM    integer num_cycles=0
7148462SApril.Chin@Sun.COM    float   rs
7158462SApril.Chin@Sun.COM
7168462SApril.Chin@Sun.COM    print -n -- "${vtcode["clear"]}"
7178462SApril.Chin@Sun.COM
7188462SApril.Chin@Sun.COM    read_levelmap "$1"
7198462SApril.Chin@Sun.COM
7208462SApril.Chin@Sun.COM    # player init
7218462SApril.Chin@Sun.COM    player["pos_x"]=${levelmap["playerstartpos_x"]}
7228462SApril.Chin@Sun.COM    player["pos_y"]=${levelmap["playerstartpos_y"]}
7238462SApril.Chin@Sun.COM    player["score"]=0         # player score
7248462SApril.Chin@Sun.COM    player["lives"]=5         # number of lives
7258462SApril.Chin@Sun.COM    player["invulnerable"]=10 # cycles how long the player remains invulnerable
7268462SApril.Chin@Sun.COM    player["message"]="Go..."
7278462SApril.Chin@Sun.COM
7288462SApril.Chin@Sun.COM    monsterlist="maw claw jitterbug tentacle grendel"
7298462SApril.Chin@Sun.COM
7308462SApril.Chin@Sun.COM    for currmonster in ${monsterlist} ; do
7318462SApril.Chin@Sun.COM        monster[${currmonster}_"pos_x"]=${levelmap["monsterstartpos_x"]}
7328462SApril.Chin@Sun.COM        monster[${currmonster}_"pos_y"]=${levelmap["monsterstartpos_y"]}
7338462SApril.Chin@Sun.COM        monster[${currmonster}_"xstep"]=0
7348462SApril.Chin@Sun.COM        monster[${currmonster}_"ystep"]=0
7358462SApril.Chin@Sun.COM        monster[${currmonster}_"homing"]=0
7368462SApril.Chin@Sun.COM    done
7378462SApril.Chin@Sun.COM
7388462SApril.Chin@Sun.COM    # main game cycle loop
7398462SApril.Chin@Sun.COM    while true ; do
7408462SApril.Chin@Sun.COM        num_cycles+=1
7418462SApril.Chin@Sun.COM        seconds_before_read=${SECONDS}
7428462SApril.Chin@Sun.COM        c="" ; read -r -t ${sleep_per_cycle} -n 1 c
7438462SApril.Chin@Sun.COM
7448462SApril.Chin@Sun.COM        if [[ "$c" != "" ]] ; then
7458462SApril.Chin@Sun.COM            # special case handling for cursor keys which are usually composed
7468462SApril.Chin@Sun.COM            # of three characters (e.g. "<ESC>[D"). If only <ESC> is hit we
7478462SApril.Chin@Sun.COM            # quicky exit
7488462SApril.Chin@Sun.COM            if [[ "$c" == $'\E' ]] ; then
7498462SApril.Chin@Sun.COM                read -r -t 0.1 -n 1 c
7508462SApril.Chin@Sun.COM                if [[ "$c" != "[" ]] ; then
7518462SApril.Chin@Sun.COM                    return 0
7528462SApril.Chin@Sun.COM                fi
7538462SApril.Chin@Sun.COM
7548462SApril.Chin@Sun.COM                # we assume the user is using the cursor keys, this |read|
7558462SApril.Chin@Sun.COM                # should fetch the 3rd byte of the three-character sequence
7568462SApril.Chin@Sun.COM                # for the cursor keys
7578462SApril.Chin@Sun.COM                read -r -t 0.1 -n 1 c
7588462SApril.Chin@Sun.COM            fi
7598462SApril.Chin@Sun.COM
7608462SApril.Chin@Sun.COM            # if the user hit a key the "read" above was interrupted
7618462SApril.Chin@Sun.COM            # and didn't wait exactly |sleep_per_cycle| seconds.
7628462SApril.Chin@Sun.COM            # We wait here some moments (|rs|="remaining seconds") to
7638462SApril.Chin@Sun.COM            # avoid that the game gets "faster" when more user input
7648462SApril.Chin@Sun.COM            # is given.
7658462SApril.Chin@Sun.COM            (( rs=sleep_per_cycle-(SECONDS-seconds_before_read) ))
7668462SApril.Chin@Sun.COM            (( rs > 0.001 )) && sleep ${rs}
7678462SApril.Chin@Sun.COM
7688462SApril.Chin@Sun.COM            player["message"]=""
7698462SApril.Chin@Sun.COM
7708462SApril.Chin@Sun.COM            case "$c" in
7718462SApril.Chin@Sun.COM                j|D|4) (( player["pos_x"]-=1 )) ;;
7728462SApril.Chin@Sun.COM                k|C|6) (( player["pos_x"]+=1 )) ;;
7738462SApril.Chin@Sun.COM                i|A|8) (( player["pos_y"]-=1 )) ;;
7748462SApril.Chin@Sun.COM                m|B|2) (( player["pos_y"]+=1 )) ;;
7758462SApril.Chin@Sun.COM
7768462SApril.Chin@Sun.COM                q) return 0 ;;
7778462SApril.Chin@Sun.COM            esac
7788462SApril.Chin@Sun.COM
7798462SApril.Chin@Sun.COM            if [[ "${levelmap["${player["pos_x"]}_${player["pos_y"]}"]}" == "." ]] ; then
7808462SApril.Chin@Sun.COM                levelmap["${player["pos_x"]}_${player["pos_y"]}"]=" "
7818462SApril.Chin@Sun.COM                (( levelmap["numdots"]-=1 ))
7828462SApril.Chin@Sun.COM
7838462SApril.Chin@Sun.COM                (( player["score"]+=10 ))
7848462SApril.Chin@Sun.COM                player["message"]='GNAW!!'
7858462SApril.Chin@Sun.COM
7868462SApril.Chin@Sun.COM                if (( levelmap["numdots"] <= 0 )) ; then
7878462SApril.Chin@Sun.COM                    level_completed
7888462SApril.Chin@Sun.COM                    return 0
7898462SApril.Chin@Sun.COM                fi
7908462SApril.Chin@Sun.COM            fi
7918462SApril.Chin@Sun.COM        fi
7928462SApril.Chin@Sun.COM
7938462SApril.Chin@Sun.COM        # generic player status change
7948462SApril.Chin@Sun.COM        if (( player["invulnerable"] > 0 )) ; then
7958462SApril.Chin@Sun.COM            (( player["invulnerable"]-=1 ))
7968462SApril.Chin@Sun.COM        fi
7978462SApril.Chin@Sun.COM        if (( player["lives"] <= 0 )) ; then
7988462SApril.Chin@Sun.COM            game_over
7998462SApril.Chin@Sun.COM            return 0
8008462SApril.Chin@Sun.COM        fi
8018462SApril.Chin@Sun.COM
8028462SApril.Chin@Sun.COM        # move monsters
8038462SApril.Chin@Sun.COM        for currmonster in ${monsterlist} ; do
8048462SApril.Chin@Sun.COM            # make monster as half as slow then the others when it is following the user
8058462SApril.Chin@Sun.COM            if (( monster[${currmonster}_"homing"] > 0 )) ; then
8068462SApril.Chin@Sun.COM                (( (num_cycles%2) > 0 )) && continue
8078462SApril.Chin@Sun.COM            fi
8088462SApril.Chin@Sun.COM
8098462SApril.Chin@Sun.COM            if [[ ${monster[${currmonster}_"pos_x"]} == ${player["pos_x"]} ]] ; then
8108462SApril.Chin@Sun.COM                if (( (monster[${currmonster}_"pos_y"]-player["pos_y"]) > 0 )) ; then
8118462SApril.Chin@Sun.COM                    (( monster[${currmonster}_"xstep"]=+0 , monster[${currmonster}_"ystep"]=-1 ))
8128462SApril.Chin@Sun.COM                else
8138462SApril.Chin@Sun.COM                    (( monster[${currmonster}_"xstep"]=+0 , monster[${currmonster}_"ystep"]=+1 ))
8148462SApril.Chin@Sun.COM                fi
8158462SApril.Chin@Sun.COM                monster[${currmonster}_"homing"]=1
8168462SApril.Chin@Sun.COM                if (( player["invulnerable"] <= 0 )) ; then
8178462SApril.Chin@Sun.COM                    player["message"]="Attention: ${currmonster} is chasing you"
8188462SApril.Chin@Sun.COM                fi
8198462SApril.Chin@Sun.COM            elif (( monster[${currmonster}_"pos_y"] == player["pos_y"] )) ; then
8208462SApril.Chin@Sun.COM                if (( (monster[${currmonster}_"pos_x"]-player["pos_x"]) > 0 )) ; then
8218462SApril.Chin@Sun.COM                    (( monster[${currmonster}_"xstep"]=-1 , monster[${currmonster}_"ystep"]=-0 ))
8228462SApril.Chin@Sun.COM                else
8238462SApril.Chin@Sun.COM                    (( monster[${currmonster}_"xstep"]=+1 , monster[${currmonster}_"ystep"]=+0 ))
8248462SApril.Chin@Sun.COM                fi
8258462SApril.Chin@Sun.COM                monster[${currmonster}_"homing"]=1
8268462SApril.Chin@Sun.COM                if (( player["invulnerable"] <= 0 )) ; then
8278462SApril.Chin@Sun.COM                    player["message"]="Attention: ${currmonster} is chasing you"
8288462SApril.Chin@Sun.COM                fi
8298462SApril.Chin@Sun.COM            else
8308462SApril.Chin@Sun.COM                if (( monster[${currmonster}_"homing"] == 0 )) ; then
8318462SApril.Chin@Sun.COM                    case $((SECONDS % 6 + RANDOM % 4)) in
8328462SApril.Chin@Sun.COM                        0) (( monster[${currmonster}_"xstep"]=+0 , monster[${currmonster}_"ystep"]=+0 )) ;;
8338462SApril.Chin@Sun.COM                        2) (( monster[${currmonster}_"xstep"]=+0 , monster[${currmonster}_"ystep"]=+1 )) ;;
8348462SApril.Chin@Sun.COM                        3) (( monster[${currmonster}_"xstep"]=+1 , monster[${currmonster}_"ystep"]=+0 )) ;;
8358462SApril.Chin@Sun.COM                        5) (( monster[${currmonster}_"xstep"]=+0 , monster[${currmonster}_"ystep"]=-1 )) ;;
8368462SApril.Chin@Sun.COM                        6) (( monster[${currmonster}_"xstep"]=-1 , monster[${currmonster}_"ystep"]=+0 )) ;;
8378462SApril.Chin@Sun.COM                    esac
8388462SApril.Chin@Sun.COM                fi
8398462SApril.Chin@Sun.COM            fi
8408462SApril.Chin@Sun.COM
8418462SApril.Chin@Sun.COM            (( monster[${currmonster}_"pos_x"]=monster[${currmonster}_"pos_x"]+monster[${currmonster}_"xstep"] ))
8428462SApril.Chin@Sun.COM            (( monster[${currmonster}_"pos_y"]=monster[${currmonster}_"pos_y"]+monster[${currmonster}_"ystep"] ))
8438462SApril.Chin@Sun.COM
8448462SApril.Chin@Sun.COM            # check if a monster hit the player
8458462SApril.Chin@Sun.COM            if (( player["invulnerable"] <= 0 )) ; then
8468462SApril.Chin@Sun.COM                if (( monster[${currmonster}_"pos_x"] == player["pos_x"] && \
8478462SApril.Chin@Sun.COM                      monster[${currmonster}_"pos_y"] == player["pos_y"] )) ; then
8488462SApril.Chin@Sun.COM                     # if player was hit by a monster take one life and
8498462SApril.Chin@Sun.COM                     # make him invulnerable for 10 cycles to avoid that
8508462SApril.Chin@Sun.COM                     # the next cycle steals more lives
8518462SApril.Chin@Sun.COM                     player["message"]="Ouuuchhhh"
8528462SApril.Chin@Sun.COM                     player["invulnerable"]=10
8538462SApril.Chin@Sun.COM                     (( player["lives"]-=1 ))
8548462SApril.Chin@Sun.COM
8558462SApril.Chin@Sun.COM                     beep ; beep ; sleep 0.2 ; beep ; beep
8568462SApril.Chin@Sun.COM                fi
8578462SApril.Chin@Sun.COM            fi
8588462SApril.Chin@Sun.COM        done
8598462SApril.Chin@Sun.COM
8608462SApril.Chin@Sun.COM        render_game
8618462SApril.Chin@Sun.COM    done
8628462SApril.Chin@Sun.COM    return 0
8638462SApril.Chin@Sun.COM}
8648462SApril.Chin@Sun.COM
8658462SApril.Chin@Sun.COMfunction map_filter
8668462SApril.Chin@Sun.COM{
8678462SApril.Chin@Sun.COM    typeset ch_player ch_monster ch_wall var
8688462SApril.Chin@Sun.COM
8698462SApril.Chin@Sun.COM    if (( $1 == 1 )) ; then
8708462SApril.Chin@Sun.COM        ch_player="${vtcode["fg_yellow"]}"
8718462SApril.Chin@Sun.COM        ch_monster="${vtcode["fg_red"]}"
8728462SApril.Chin@Sun.COM        ch_wall="${vtcode["fg_blue"]}"
8738462SApril.Chin@Sun.COM    else
8748462SApril.Chin@Sun.COM        ch_player=""
8758462SApril.Chin@Sun.COM        ch_monster=""
8768462SApril.Chin@Sun.COM        ch_wall=""
8778462SApril.Chin@Sun.COM    fi
8788462SApril.Chin@Sun.COM
8798462SApril.Chin@Sun.COM    if (( $2 == 1 )) ; then
8808462SApril.Chin@Sun.COM        # unicode map
8818462SApril.Chin@Sun.COM        ch_player+="$(printf '\u[24d2]')"
8828462SApril.Chin@Sun.COM        ch_monster+="$(printf '\u[2605]')"
8838462SApril.Chin@Sun.COM        ch_wall+="$(printf '\u[25a6]')"
8848462SApril.Chin@Sun.COM    else
8858462SApril.Chin@Sun.COM        # ascii map
8868462SApril.Chin@Sun.COM        ch_player+="@"
8878462SApril.Chin@Sun.COM        ch_monster+="x"
8888462SApril.Chin@Sun.COM        ch_wall+="#"
8898462SApril.Chin@Sun.COM    fi
8908462SApril.Chin@Sun.COM
8918462SApril.Chin@Sun.COM    # note that this filter currently defeats the "double-buffering"
8928462SApril.Chin@Sun.COM    while IFS='' read -r -d "${end_of_frame}" var ; do
8938462SApril.Chin@Sun.COM        var="${var// /${vtcode["fg_grey"]} }"
8948462SApril.Chin@Sun.COM        var="${var//\./${vtcode["fg_lightred"]}.}"
8958462SApril.Chin@Sun.COM        var="${var//@/${ch_player}}"
8968462SApril.Chin@Sun.COM        var="${var//x/${ch_monster}}"
8978462SApril.Chin@Sun.COM        var="${var//#/${ch_wall}}"
8988462SApril.Chin@Sun.COM
8998462SApril.Chin@Sun.COM        print -r -- "${var}"
9008462SApril.Chin@Sun.COM    done
9018462SApril.Chin@Sun.COM    return 0
9028462SApril.Chin@Sun.COM}
9038462SApril.Chin@Sun.COM
9048462SApril.Chin@Sun.COMfunction exit_trap
9058462SApril.Chin@Sun.COM{
9068462SApril.Chin@Sun.COM    # restore stty settings
9078462SApril.Chin@Sun.COM    stty ${saved_stty}
9088462SApril.Chin@Sun.COM
9098462SApril.Chin@Sun.COM    print "bye."
9108462SApril.Chin@Sun.COM    return 0
9118462SApril.Chin@Sun.COM}
9128462SApril.Chin@Sun.COM
9138462SApril.Chin@Sun.COMfunction usage
9148462SApril.Chin@Sun.COM{
9158462SApril.Chin@Sun.COM    OPTIND=0
9168462SApril.Chin@Sun.COM    getopts -a "${progname}" "${gnaw_usage}" OPT '-?'
9178462SApril.Chin@Sun.COM    exit 2
9188462SApril.Chin@Sun.COM}
9198462SApril.Chin@Sun.COM
9208462SApril.Chin@Sun.COM# program start
9218462SApril.Chin@Sun.COM# make sure we use the ksh93 "cat" builtin which supports the "-u" option
9228462SApril.Chin@Sun.COMbuiltin basename
9238462SApril.Chin@Sun.COMbuiltin cat
9248462SApril.Chin@Sun.COMbuiltin wc
9258462SApril.Chin@Sun.COM
9268462SApril.Chin@Sun.COMtypeset progname="${ basename "${0}" ; }"
9278462SApril.Chin@Sun.COM
9288462SApril.Chin@Sun.COM# terminal size rect
929*10898Sroland.mainz@nrubsig.orgcompound termsize=(
9308462SApril.Chin@Sun.COM    integer columns=-1
9318462SApril.Chin@Sun.COM    integer lines=-1
9328462SApril.Chin@Sun.COM)
9338462SApril.Chin@Sun.COM
9348462SApril.Chin@Sun.COM# global variables
9358462SApril.Chin@Sun.COMtypeset quiet=false
9368462SApril.Chin@Sun.COM
9378462SApril.Chin@Sun.COMtypeset -A levelmap
9388462SApril.Chin@Sun.COMtypeset -A player
9398462SApril.Chin@Sun.COMtypeset -A monster
9408462SApril.Chin@Sun.COM# global rendering options
9418462SApril.Chin@Sun.COMinteger game_use_colors=0
9428462SApril.Chin@Sun.COMinteger game_use_unicode=0
9438462SApril.Chin@Sun.COM
9448462SApril.Chin@Sun.COMtypeset -r gnaw_usage=$'+
945*10898Sroland.mainz@nrubsig.org[-?\n@(#)\$Id: gnaw (Roland Mainz) 2009-05-09 \$\n]
9468462SApril.Chin@Sun.COM[-author?Roland Mainz <roland.mainz@nrubsig.org>]
9478462SApril.Chin@Sun.COM[+NAME?gnaw - maze game written in ksh93]
9488462SApril.Chin@Sun.COM[+DESCRIPTION?\bgnaw\b is a maze game.
9498462SApril.Chin@Sun.COM        The player maneuvers a yellow "@" sign to navigate a maze while eating
9508462SApril.Chin@Sun.COM        small dots. A level is finished when all the dots are eaten. Five monsters
9518462SApril.Chin@Sun.COM        (maw, claw, jitterbug, tentacle and grendel) also wander the maze in an attempt
9528462SApril.Chin@Sun.COM        to catch the "@". Each level begins with all ghosts in their home, and "@" near
9538462SApril.Chin@Sun.COM        the bottom of the maze. The monsters are released from the home one by one at the
9548462SApril.Chin@Sun.COM        start of each level and start their rentless hunt after the player.]
9558462SApril.Chin@Sun.COM[q:quiet?Disable use of terminal bell.]
9568462SApril.Chin@Sun.COM[+SEE ALSO?\bksh93\b(1)]
9578462SApril.Chin@Sun.COM'
9588462SApril.Chin@Sun.COM
9598462SApril.Chin@Sun.COMwhile getopts -a "${progname}" "${gnaw_usage}" OPT ; do
9608462SApril.Chin@Sun.COM#    printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
9618462SApril.Chin@Sun.COM    case ${OPT} in
9628462SApril.Chin@Sun.COM        q)    quiet=true  ;;
9638462SApril.Chin@Sun.COM        +q)   quiet=false ;;
9648462SApril.Chin@Sun.COM        *)    usage ;;
9658462SApril.Chin@Sun.COM    esac
9668462SApril.Chin@Sun.COMdone
9678462SApril.Chin@Sun.COMshift $((OPTIND-1))
9688462SApril.Chin@Sun.COM
9698462SApril.Chin@Sun.COM# save stty values and register the exit trap which restores these values on exit
9708462SApril.Chin@Sun.COMsaved_stty="$(stty -g)"
9718462SApril.Chin@Sun.COMtrap exit_trap EXIT
9728462SApril.Chin@Sun.COM
9738462SApril.Chin@Sun.COMprint "Loading..."
9748462SApril.Chin@Sun.COM
9758462SApril.Chin@Sun.COM# set stty values, "-icanon min 1 time 0 -inpck" should improve input latency,
9768462SApril.Chin@Sun.COM# "-echo" turns the terminal echo off
9778462SApril.Chin@Sun.COMstty -icanon min 1 time 0 -inpck -echo
9788462SApril.Chin@Sun.COM
9798462SApril.Chin@Sun.COMget_term_size termsize || fatal_error "Could not get terminal size."
9808462SApril.Chin@Sun.COM
9818462SApril.Chin@Sun.COM# prechecks
9828462SApril.Chin@Sun.COM(( termsize.columns < 60 )) && fatal_error "Terminal width must be larger than 60 columns (currently ${termsize.columns})."
9838462SApril.Chin@Sun.COM
9848462SApril.Chin@Sun.COMtypeset -A vtcode
9858462SApril.Chin@Sun.COM# color values taken from http://frexx.de/xterm-256-notes/, other
9868462SApril.Chin@Sun.COM# codes from http://vt100.net/docs/vt100-tm/
9878462SApril.Chin@Sun.COMvtcode=(
9888462SApril.Chin@Sun.COM    ["bg_black"]="$(print -n "\E[40m")"
9898462SApril.Chin@Sun.COM    ["fg_black"]="$(print -n "\E[30m")"
9908462SApril.Chin@Sun.COM    ["fg_red"]="$(print -n "\E[31m")"
9918462SApril.Chin@Sun.COM    ["fg_lightred"]="$(print -n "\E[1;31m")"
9928462SApril.Chin@Sun.COM    ["fg_green"]="$(print -n "\E[32m")"
9938462SApril.Chin@Sun.COM    ["fg_lightgreen"]="$(print -n "\E[1;32m")"
9948462SApril.Chin@Sun.COM    ["fg_yellow"]="$(print -n "\E[33m")"
9958462SApril.Chin@Sun.COM    ["fg_lightyellow"]="$(print -n "\E[1;33m")"
9968462SApril.Chin@Sun.COM    ["fg_blue"]="$(print -n "\E[34m")"
9978462SApril.Chin@Sun.COM    ["fg_lightblue"]="$(print -n "\E[1;34m")"
9988462SApril.Chin@Sun.COM    ["fg_grey"]="$(print -n "\E[1;37m")"
9998462SApril.Chin@Sun.COM    ["fg_white"]="$(print -n "\E[37m")"
10008462SApril.Chin@Sun.COM
10018462SApril.Chin@Sun.COM    # misc other vt stuff
10028462SApril.Chin@Sun.COM    ["vtreset"]="$(tput reset)"
10038462SApril.Chin@Sun.COM    ["clear"]="$(tput clear)"
10048462SApril.Chin@Sun.COM    ["bel"]="$(tput bel)"
10058462SApril.Chin@Sun.COM    ["spaceline"]="$(for (( i=0 ; i < termsize.columns ; i++ )) ; do print -n " " ; done)"
10068462SApril.Chin@Sun.COM)
10078462SApril.Chin@Sun.COM
10088462SApril.Chin@Sun.COM# character used to as marker that a single frame ends at this point - this
10098462SApril.Chin@Sun.COM# is used by the "double buffering" code to make sure the "read" builtin
10108462SApril.Chin@Sun.COM# can read a whole "frame" instead of reading stuff line-by-line
10118462SApril.Chin@Sun.COMtypeset -r end_of_frame=$'\t'
10128462SApril.Chin@Sun.COM
10138462SApril.Chin@Sun.COM# get terminal sequence to move cursor to position x,y
10148462SApril.Chin@Sun.COM# (see http://vt100.net/docs/vt100-ug/chapter3.html#CPR)
10158462SApril.Chin@Sun.COMcase ${TERM} in
10168462SApril.Chin@Sun.COM    xterm | xterm-color | vt100 | vt220 | dtterm | sun | sun-color)
10178462SApril.Chin@Sun.COM        cup="$(infocmp -1 | \
10188462SApril.Chin@Sun.COM	       egrep '^[[:space:]]*cup=' | \
10198462SApril.Chin@Sun.COM	       sed -e 's/.*cup=//' \
10208462SApril.Chin@Sun.COM	           -e 's/%[%id]*p1[%id]*/%2\\\$d/g' \
10218462SApril.Chin@Sun.COM		   -e 's/%[%id]*p2[%id]*/%1\\\$d/g' \
10228462SApril.Chin@Sun.COM		   -e 's/,$//')"
10238462SApril.Chin@Sun.COM        for (( x=0 ; x < termsize.columns ; x++ )) ; do
10248462SApril.Chin@Sun.COM            for (( y=0 ; y < termsize.lines ; y++ )) ; do
10258462SApril.Chin@Sun.COM                vtcode[cup_${x}_${y}]="$(printf "${cup}" $((x + 1)) $((y + 1)) )"
10268462SApril.Chin@Sun.COM            done
10278462SApril.Chin@Sun.COM        done
10288462SApril.Chin@Sun.COM        ;;
10298462SApril.Chin@Sun.COM    *)
10308462SApril.Chin@Sun.COM        printf "# Unrecognised terminal type '%s', fetching %dx%d items from terminfo database, please wait...\n" "${TERM}" "${termsize.columns}" "${termsize.lines}"
10318462SApril.Chin@Sun.COM        for (( x=0 ; x < termsize.columns ; x++ )) ; do
10328462SApril.Chin@Sun.COM            for (( y=0 ; y < termsize.lines ; y++ )) ; do
10338462SApril.Chin@Sun.COM                vtcode[cup_${x}_${y}]="$(tput cup ${y} ${x})"
10348462SApril.Chin@Sun.COM            done
10358462SApril.Chin@Sun.COM        done
10368462SApril.Chin@Sun.COM        ;;
10378462SApril.Chin@Sun.COMesac
10388462SApril.Chin@Sun.COM
10398462SApril.Chin@Sun.COMprint -- "${vtcode["vtreset"]}"
10408462SApril.Chin@Sun.COM
10418462SApril.Chin@Sun.COMrun_logo
10428462SApril.Chin@Sun.COMrun_menu
10438462SApril.Chin@Sun.COM
10448462SApril.Chin@Sun.COMexit 0
10458462SApril.Chin@Sun.COM# EOF.
1046