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