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