==== Common bash shell functions ==== This is the common function library cf_funcs_common.sh that is sourced for example by [[client_side_scripting:scripts:bash:cf_melt_icecube]] . It contains a many functions and is pretty 1200+ lines long. Most noteworthy may be the _set_global_variables() function, where all the most used global variables are collected, and the user should have a look at it to change settings for his and her needs. Log file names come in mind, that a user may think should be differently named. I have put an interpreter line at the to, so that my file manager displays it as a shell script file, and my editor does use a color highlighting scheme related to shell scripts. The interpreter in this case is `#!/bin/ash' and not bash, because the busybox ash is very similar to bash and usually two or more times faster than bash. Some math code is done in some functions, and to test it for the '.' and ',' differences. I have set LC_NUMERIC=de_DE LC_ALL=de_DE which is something you very likely would change to `en_US' or 'C' or whatever your home LANG is; usually printed by the `locale' command in the xterm terminal. #!/bin/ash [ "$HAVE_FUNCS_COMMON" ] && return 0 export LC_NUMERIC=de_DE export LC_ALL=de_DE # *** Color numbers found in common/shared/newclient.h : *** # #define NDI_BLACK 0 #define NDI_WHITE 1 #define NDI_NAVY 2 #define NDI_RED 3 #define NDI_ORANGE 4 #define NDI_BLUE 5 /**< Actually, it is Dodger Blue */ #define NDI_DK_ORANGE 6 /**< DarkOrange2 */ #define NDI_GREEN 7 /**< SeaGreen */ #define NDI_LT_GREEN 8 /**< DarkSeaGreen, which is actually paler # * than seagreen - also background color. */ #define NDI_GREY 9 #define NDI_BROWN 10 /**< Sienna. */ #define NDI_GOLD 11 #define NDI_TAN 12 /**< Khaki. */ #define NDI_MAX_COLOR 12 /**< Last value in. */ _set_global_variables(){ LOGGING=${LOGGING:-''} #bool, set to ANYTHING ie "1" to enable, empty to disable #DEBUG=${DEBUG:-''} #bool, set to ANYTHING ie "1" to enable, empty to disable MSGLEVEL=${MSGLEVEL:-6} #integer 1 emergency - 7 debug #case $MSGLEVEL in #7) DEBUG=${DEBUG:-1};; 6) INFO=${INFO:-1};; 5) NOTICE=${NOTICE:-1};; 4) WARN=${WARN:-1};; #3) ERROR=${ERROR:-1};; 2) ALERT=${ALERT:-1};; 1) EMERG=${EMERG:-1};; #esac DEBUG=1; INFO=1; NOTICE=1; WARN=1; ERROR=1; ALERT=1; EMERG=1; Q=-q; VERB=-v case $MSGLEVEL in 7) unset Q;; 6) unset DEBUG Q;; 5) unset DEBUG INFO VERB;; 4) unset DEBUG INFO NOTICE VERB;; 3) unset DEBUG INFO NOTICE WARN VERB;; 2) unset DEBUG INFO NOTICE WARN ERROR VERB;; 1) unset DEBUG INFO NOTICE WARN ERROR ALERT VERB;; *) _error "MSGLEVEL variable not set from 1 - 7";; esac TMOUT=${TMOUT:-1} # read -t timeout, integer, seconds SLEEP=${SLEEP:-1} #default sleep value, float, seconds, refined in _get_player_speed() DELAY_DRAWINFO=${DELAY_DRAWINFO:-2} #default pause to sync, float, seconds, refined in _get_player_speed() DRAWINFO=${DRAWINFO:-drawinfo} #older clients <= 1.12.0 use drawextinfo , newer clients drawinfo FUNCTION_CHECK_FOR_SPACE=_check_for_space # request map pos works case $* in *-version" "*) CLIENT_VERSION="$2" case $CLIENT_VERSION in 0.*|1.[0-9].*|1.1[0-2].*) DRAWINFO=drawextinfo #older clients <= 1.12.0 use drawextinfo , newer clients drawinfo # except use_skill alchemy :watch drawinfo 0 The cauldron emits sparks. # and except apply :watch drawinfo 0 You open cauldron. # # and probably more ...? TODO! FUNCTION_CHECK_FOR_SPACE=_check_for_space_old_client # needs request map near ;; esac ;; esac COUNT_CHECK_FOOD=${COUNT_CHECK_FOOD:-10} # number between attempts to check foodlevel. # 1 would mean check every single time, which is too much EAT_FOOD=${EAT_FOOD:-waybread} # set to desired food to eat ie food, mushroom, booze, .. etc. FOOD_DEF=haggis # default MIN_FOOD_LEVEL_DEF=${MIN_FOOD_LEVEL_DEF:-300} # default minimum. 200 starts to beep. # waybread has foodvalue of 500 # 999 is max foodlevel HP_MIN_DEF=${HP_MIN_DEF:-20} # minimum HP to return home. Lowlevel charakters probably need this set. DIRB=${DIRB:-west} # direction back to go case $DIRB in west) DIRF=east;; east) DIRF=west;; north) DIRF=south;; northwest) DIRF=southeast;; northeast) DIRF=southwest;; south) DIRF=north;; southwest) DIRF=northeast;; southeast) DIRF=northwest;; esac SOUND_DIR="$HOME"/.crossfire/sounds # Log file path in /tmp #MY_SELF=`realpath "$0"` ## needs to be in main script #MY_BASE=${MY_SELF##*/} ## needs to be in main script TMP_DIR=/tmp/crossfire mkdir -p "$TMP_DIR" LOGFILE=${LOGFILE:-"$TMP_DIR"/"$MY_BASE".$$.log} REPLY_LOG="$TMP_DIR"/"$MY_BASE".$$.rpl REQUEST_LOG="$TMP_DIR"/"$MY_BASE".$$.req ON_LOG="$TMP_DIR"/"$MY_BASE".$$.ion ERROR_LOG="$TMP_DIR"/"$MY_BASE".$$.err exec 2>>"$ERROR_LOG" } _say_version(){ _draw 6 "$MY_BASE Version:${VERSION:-0.0}" exit ${1:-2} } _watch(){ echo unwatch ${*:-$DRAWINFO} sleep 0.4 echo watch ${*:-$DRAWINFO} } _unwatch(){ echo unwatch ${*:-$DRAWINFO} } _sleep(){ SLEEP=${SLEEP//,/.} sleep ${SLEEP:-1} } _draw(){ local lCOLOUR="${1:-$COLOUR}" lCOLOUR=${lCOLOUR:-1} #set default shift echo draw $lCOLOUR $@ # no double quotes here, # multiple lines are drawn using __draw below } __draw(){ case $1 in [0-9]|1[0-2]) lCOLOUR="$1"; shift;; esac local lCOLOUR=${lCOLOUR:-1} #set default dcnt=0 echo -e "$*" | while read line do dcnt=$((dcnt+1)) echo draw $lCOLOUR "$line" done unset dcnt line } __msg(){ ##+++2018-01-08 local LVL=$1; shift case $LVL in 7|debug) test "$DEBUG" && _debug "$*";; 6|info) test "$INFO" && _info "$*";; 5|note) test "$NOTICE" && _notice "$*";; 4|warn) test "$WARN" && _warn "$*";; 3|err) test "$ERROR" && _error "$*";; 2|alert) test "$ALERT" && _alert "$*";; 1|emerg) test "$EMERG" && _emerg "$*";; *) _debug "$*";; esac } _msg(){ ##+++2018-01-08 local LVL=$1; shift case $LVL in 7|debug) _debug "$*";; 6|info) _info "$*";; 5|note) _notice "$*";; 4|warn) _warn "$*";; 3|err) _error "$*";; 2|alert) _alert "$*";; 1|emerg) _emerg "$*";; *) _debug "$*";; esac } _debug(){ test "$DEBUG" || return 0 echo draw 10 "DEBUG:$@" } __debug(){ ##+++2018-01-06 test "$DEBUG" || return 0 dcnt=0 echo "$*" | while read line do dcnt=$((dcnt+1)) echo draw 3 "__DEBUG:$dcnt:$line" done unset dcnt line } _info(){ test "$INFO" || return 0 echo draw 7 "INFO:$@" } _notice(){ test "$NOTICE" || return 0 echo draw 2 "NOTICE:$@" } _warn(){ test "$WARN" || return 0 echo draw 6 "WARNING:$@" } _error(){ test "$ERROR" || return 0 echo draw 4 "ERROR:$@" } _alert(){ test "$ALERT" || return 0 echo draw 3 "ALERT:$@" } _ermerg(){ test "$EMERG" || return 0 echo draw 3 "EMERGENCY:$@" } _log(){ test "$LOGGING" || return 0 local lFILE test "$2" && { lFILE="$1"; shift; } || lFILE="$LOGFILE" echo "$*" >>"$lFILE" } _sound(){ local lDUR test "$2" && { lDUR="$1"; shift; } lDUR=${lDUR:-0} test -e "$SOUND_DIR"/${1}.raw && \ aplay $Q $VERB -d $lDUR "$SOUND_DIR"/${1}.raw } _success(){ _sound 0 bugle_charge } _failure(){ _sound 0 ouch1 } _disaster(){ _sound 0 Missed } _unknown(){ _sound 0 TowerClock } _beep_std(){ beep -l 1000 -f 700 } _say_start_msg(){ # *** Here begins program *** # _draw 2 "$0 has started.." _draw 2 "PID is $$ - parentPID is $PPID" _check_drawinfo # *** Check for parameters *** # _draw 5 "Checking the parameters ($*)..." } _tell_script_time(){ test "$TIMEA" || return 1 TIMEE=`date +%s` TIME=$((TIMEE-TIMEA)) TIMEM=$((TIME/60)) TIMES=$(( TIME - (TIMEM*60) )) _draw 4 "Loop of script had run a total of $TIMEM minutes and $TIMES seconds." } _say_script_time(){ ##+++2018-01-07 TIME_ELAPSED=`ps -o pid,etime,args | grep -w "$$" | grep -vwE "grep|ps|${TMP_DIR:-/tmp}"` __debug "$TIME_ELAPSED" TIME_ELAPSED=`echo "$TIME_ELAPSED" | awk '{print $2}'` __debug "$TIME_ELAPSED" case $TIME_ELAPSED in *:*:*) _draw 5 "Script had run a time of $TIME_ELAPSED h:m:s .";; *:*) _draw 5 "Script had run a time of $TIME_ELAPSED m:s .";; *) _draw 5 "Script had run a time of $TIME_ELAPSED s .";; esac } _say_end_msg(){ # *** Here ends program *** # _is 1 1 fire_stop test -f "$HOME"/.crossfire/sounds/su-fanf.raw && aplay $Q "$HOME"/.crossfire/sounds/su-fanf.raw & aPID=$! _tell_script_time || _say_script_time test "$DEBUG" || { test -s "$ERROR_LOG" || rm -f "$ERROR_LOG"; } test "$DEBUG" -o "$INFO" || rm -f "$TMP_DIR"/*.$$* test "$aPID" && wait $aPID _draw 2 "$0 $$ has finished." } _loop_counter(){ test "$TIMEA" -a "$TIMEB" -a "$NUMBER" -a "$one" || return 0 TRIES_STILL=$((NUMBER-one)) TIMEE=`date +%s` TIME=$((TIMEE-TIMEB)) TIMEZ=$((TIMEE-TIMEA)) TIMEAV=$((TIMEZ/one)) TIMEEST=$(( (TRIES_STILL*TIMEAV) / 60 )) _draw 4 "Elapsed $TIME s, $success of $one successfull, still $TRIES_STILL ($TIMEEST m) to go..." } #** the messages in the msgpane may pollute **# #** need to catch msg to discard them into an unused variable **# _empty_message_stream(){ local lREPLY while :; do read -t $TMOUT lREPLY _log "$REPLY_LOG" "_empty_message_stream:$lREPLY" test "$lREPLY" || break case $lREPLY in *scripttell*break*) break ${lREPLY##*?break};; *scripttell*exit*) _exit_stdalone 1 $lREPLY;; *'YOU HAVE DIED.'*) _just_exit_stdalone;; esac _msg 7 "_empty_message_stream:$lREPLY" unset lREPLY sleep 0.01 #sleep 0.1 done } _check_drawinfo(){ ##+++2018-01-08 _debug "_check_drawinfo:$*" oDEBUG=$DEBUG; DEBUG=${DEBUG:-''} oLOGGING=$LOGGING; LOGGING=${LOGGING:-1} _draw 2 "Checking drawinfo ..." echo watch while :; do # I use search here to provoke # a response from the server # like You search the area. # It could be something else, # but I have no better idea for the moment. _is 0 0 search _is 0 0 examine unset cnt0 TICKS while : do cnt0=$((cnt0+1)) read -t $TMOUT _log "_check_drawinfo:$cnt0:$REPLY" _msg 7 "$cnt0:$REPLY" #_debug 3 "$cnt0:$REPLY" case $REPLY in *drawinfo*'You search'*|*drawinfo*'You spot'*) DRAWINFO0=drawinfo; break 2;; *drawextinfo*'You search'*|*drawextinfo*'You spot'*) DRAWINFO0=drawextinfo; break 2;; *drawinfo*'That is'*|*drawinfo*'Those are'*) DRAWINFO0=drawinfo; break 2;; *drawextinfo*'That is'*|*drawextinfo*'Those are'*) DRAWINFO0=drawextinfo; break 2;; *drawinfo*'This is'*|*drawinfo*'These are'*) DRAWINFO0=drawinfo; break 2;; *drawextinfo*'This is'*|*drawextinfo*'These are'*) DRAWINFO0=drawextinfo; break 2;; *tick*) TICKS=$((TICKS+1)); test "$TICKS" -gt 19 && break 1;; '') break 1;; *) :;; esac sleep 0.001 done _sleep done echo unwatch _empty_message_stream unset cnt0 test "$DRAWINFO0" = "$DRAWINFO" || { _msg 5 "Changing internally from $DRAWINFO to $DRAWINFO0" DRAWINFO=$DRAWINFO0 } DEBUG=$oDEBUG LOGGING=$oLOGGING _draw 6 "Done." } # *** EXIT FUNCTIONS *** # _exit(){ case $1 in [0-9]|[0-9][0-9]|[0-9][0-9][0-9]) RV=$1; shift;; esac _move_back_and_forth 2 _sleep test "$*" && _draw 3 $@ _draw 3 "Exiting $0. PID was $$" #echo unwatch _unwatch "" _beep_std test ${RV//[0-9]/} && RV=3 exit ${RV:-0} } _just_exit(){ _draw 3 "Exiting $0." _unwatch _beep_std exit ${1:-0} } _emergency_exit(){ RV=${1:-4}; shift local lRETURN_ITEM=${*:-"$RETURN_ITEM"} case $lRETURN_ITEM in ''|*rod*|*staff*|*wand*|*horn*) _is 1 1 apply -u ${lRETURN_ITEM:-'rod of word of recall'} _is 1 1 apply -a ${lRETURN_ITEM:-'rod of word of recall'} _is 1 1 fire center _is 1 1 fire_stop ;; *scroll*) _is 1 1 apply ${lRETURN_ITEM};; *) invoke "$lRETURN_ITEM";; # assuming spell esac _draw 3 "Emergency Exit $0 !" _unwatch # apply bed of reality sleep 6 _is 1 1 apply _beep_std exit ${RV:-0} } _exit_no_space(){ _draw 3 "On position $nr $DIRB there is something ($IS_WALL)!" _draw 3 "Remove that item and try again." _draw 3 "If this is a wall, try on another place." _beep_std exit ${1:-0} } # *** __error(){ # _error 1 "Some error occured" # *** RV=$1;shift eMSG=`echo -e "$*"` __draw 3 "$eMSG" exit ${RV:-1} } __direction_to_number(){ DIRECTION=${1:-$DIRECTION} test "$DIRECTION" || return 254 DIRECTION=`echo "$DIRECTION" | tr '[A-Z]' '[a-z]'` case $DIRECTION in 0|center|centre|c) DIRECTION=0; DIRN=0;; 1|north|n) DIRECTION=1; DIRN=1;; 2|northeast|ne) DIRECTION=2; DIRN=2;; 3|east|e) DIRECTION=3; DIRN=3;; 4|southeast|se) DIRECTION=4; DIRN=4;; 5|south|s) DIRECTION=5; DIRN=5;; 6|southwest|sw) DIRECTION=6; DIRN=6;; 7|west|w) DIRECTION=7; DIRN=7;; 8|northwest|nw) DIRECTION=8; DIRN=8;; #*) ERROR=1 _error "Not recognized: '$DIRECTION'";; # bash *) oERROR="$ERROR"; ERROR=1 _error "Not recognized: '$DIRECTION'" ERROR="$oERROR"; unset oERROR;; esac DIRECTION_NUMBER=$DIRN return ${DIRN:-255} } __number_to_direction(){ DIRECTION=${1:-$DIRECTION} test "$DIRECTION" || return 254 DIRECTION=`echo "$DIRECTION" | tr '[A-Z]' '[a-z]'` case $DIRECTION in 0|center|centre|c) DIRECTION=center; DIRN=0;; 1|north|n) DIRECTION=north; DIRN=1;; 2|northeast|ne) DIRECTION=northeast; DIRN=2;; 3|east|e) DIRECTION=east; DIRN=3;; 4|southeast|se) DIRECTION=southeast; DIRN=4;; 5|south|s) DIRECTION=south; DIRN=5;; 6|southwest|sw) DIRECTION=southwest; DIRN=6;; 7|west|w) DIRECTION=west; DIRN=7;; 8|northwest|nw) DIRECTION=northwest; DIRN=8;; #*) ERROR=1 _error "Not recognized: '$DIRECTION'";; # bash *) oERROR="$ERROR"; ERROR=1 _error "Not recognized: '$DIRECTION'" ERROR="$oERROR"; unset oERROR;; esac DIRECTION_NUMBER=$DIRN return ${DIRN:-255} } _direction_to_number(){ # cf_funcs_move.sh local lDIRECTION=${1:-$DIRECTION} test "$lDIRECTION" || return 254 lDIRECTION=`echo "$lDIRECTION" | tr '[A-Z]' '[a-z]'` case $lDIRECTION in 0|center|centre|c) DIRECTION=center; DIRN=0; DIRB=; DIRF=;; 1|north|n) DIRECTION=north; DIRN=1; DIRB=south; DIRF=north;; 2|northeast|ne) DIRECTION=northeast; DIRN=2; DIRB=southwest; DIRF=northeast;; 3|east|e) DIRECTION=east; DIRN=3; DIRB=west; DIRF=east;; 4|southeast|se) DIRECTION=southeast; DIRN=4; DIRB=northwest; DIRF=southeast;; 5|south|s) DIRECTION=south; DIRN=5; DIRB=north; DIRF=south;; 6|southwest|sw) DIRECTION=southwest; DIRN=6; DIRB=northeast; DIRF=southwest;; 7|west|w) DIRECTION=west; DIRN=7; DIRB=east; DIRF=west;; 8|northwest|nw) DIRECTION=northwest; DIRN=8; DIRB=southeast; DIRF=northwest;; #*) ERROR=1 _error "Not recognized: '$lDIRECTION'";; # bash *) oERROR="$ERROR"; ERROR=1 _error "Not recognized: '$DIRECTION'" ERROR="$oERROR"; unset oERROR;; esac DIRECTION_NUMBER=$DIRN return ${DIRN:-255} } _number_to_direction(){ # cf_funcs_move.sh local lDIRECTION=${1:-$DIRECTION} test "$lDIRECTION" || return 254 lDIRECTION=`echo "$lDIRECTION" | tr '[A-Z]' '[a-z]'` case $lDIRECTION in 0|center|centre|c) DIRECTION=center; DIRN=0; DIRB=; DIRF=;; 1|north|n) DIRECTION=north; DIRN=1; DIRB=south; DIRF=north;; 2|northeast|ne) DIRECTION=northeast; DIRN=2; DIRB=southwest; DIRF=northeast;; 3|east|e) DIRECTION=east; DIRN=3; DIRB=west; DIRF=east;; 4|southeast|se) DIRECTION=southeast; DIRN=4; DIRB=northwest; DIRF=southeast;; 5|south|s) DIRECTION=south; DIRN=5; DIRB=north; DIRF=south;; 6|southwest|sw) DIRECTION=southwest; DIRN=6; DIRB=northeast; DIRF=southwest;; 7|west|w) DIRECTION=west; DIRN=7; DIRB=east; DIRF=west;; 8|northwest|nw) DIRECTION=northwest; DIRN=8; DIRB=southeast; DIRF=northwest;; #*) ERROR=1 _error "Not recognized: '$lDIRECTION'";; # bash *) oERROR="$ERROR"; ERROR=1 _error "Not recognized: '$DIRECTION'" ERROR="$oERROR"; unset oERROR;; esac DIRECTION_NUMBER=$DIRN return ${DIRN:-255} } _round_up_and_down(){ ##+++2018-01-08 echo "_round_up_and_down:$1" >&2 #123 STELLEN=${#1} #3 echo "STELLEN=$STELLEN" >&2 LETZTSTELLE=${1:$((STELLEN-1))} #123:2 echo "LETZTSTELLE=$LETZTSTELLE" >&2 VORLETZTSTELLE=${1:$((STELLEN-2)):1} #123:1:1 echo "VORLETZTSTELLE=$VORLETZTSTELLE" >&2 GERUNDET_BASIS=${1:0:$((STELLEN-1))} #123:0:2 echo "GERUNDET_BASIS=$GERUNDET_BASIS" >&2 case $LETZTSTELLE in 0) GERUNDET="${GERUNDET_BASIS}0";; [5-9]) GERUNDET="$((GERUNDET_BASIS+1))0";; [1-4]) GERUNDET="${GERUNDET_BASIS}0";; *) :;; esac echo $GERUNDET } _set_sync_sleep(){ _debug "_set_sync_sleep:$*" local lPL_SPEED=${1:-$PL_SPEED} lPL_SPEED=${lPL_SPEED:-50000} if test "$lPL_SPEED" -gt 60000; then SLEEP=0.4; DELAY_DRAWINFO=1.0; TMOUT=1 elif test "$lPL_SPEED" -gt 55000; then SLEEP=0.5; DELAY_DRAWINFO=1.1; TMOUT=1 elif test "$lPL_SPEED" -gt 50000; then SLEEP=0.6; DELAY_DRAWINFO=1.2; TMOUT=1 elif test "$lPL_SPEED" -gt 45000; then SLEEP=0.7; DELAY_DRAWINFO=1.4; TMOUT=1 elif test "$lPL_SPEED" -gt 40000; then SLEEP=0.8; DELAY_DRAWINFO=1.6; TMOUT=1 elif test "$lPL_SPEED" -gt 35000; then SLEEP=1.0; DELAY_DRAWINFO=2.0; TMOUT=2 elif test "$lPL_SPEED" -gt 30000; then SLEEP=1.5; DELAY_DRAWINFO=3.0; TMOUT=2 elif test "$lPL_SPEED" -gt 25000; then SlEEP=2.0; DELAY_DRAWINFO=4.0; TMOUT=2 elif test "$lPL_SPEED" -gt 20000; then SlEEP=2.5; DELAY_DRAWINFO=5.0; TMOUT=2 elif test "$lPL_SPEED" -gt 15000; then SLEEP=3.0; DELAY_DRAWINFO=6.0; TMOUT=2 elif test "$lPL_SPEED" -gt 10000; then SLEEP=4.0; DELAY_DRAWINFO=8.0; TMOUT=2 elif test "$lPL_SPEED" -ge 0; then SLEEP=5.0; DELAY_DRAWINFO=10.0; TMOUT=2 elif test "$lPL_SPEED" = ""; then _draw 3 "WARNING: Could not set player speed. Using defaults." else _exit 1 "ERROR while processing player speed." fi _info "Setting SLEEP=$SLEEP ,TMOUT=$TMOUT ,DELAY_DRAWINFO=$DELAY_DRAWINFO" } __set_sync_sleep(){ _debug "__set_sync_sleep:$*" local lPL_SPEED=${1:-$PL_SPEED1} lPL_SPEED=${lPL_SPEED:-50} if test "$lPL_SPEED" -gt 60; then SLEEP=0.4; DELAY_DRAWINFO=1.0; TMOUT=1 elif test "$lPL_SPEED" -gt 55; then SLEEP=0.5; DELAY_DRAWINFO=1.1; TMOUT=1 elif test "$lPL_SPEED" -gt 50; then SLEEP=0.6; DELAY_DRAWINFO=1.2; TMOUT=1 elif test "$lPL_SPEED" -gt 45; then SLEEP=0.7; DELAY_DRAWINFO=1.4; TMOUT=1 elif test "$lPL_SPEED" -gt 40; then SLEEP=0.8; DELAY_DRAWINFO=1.6; TMOUT=1 elif test "$lPL_SPEED" -gt 35; then SLEEP=1.0; DELAY_DRAWINFO=2.0; TMOUT=2 elif test "$lPL_SPEED" -gt 30; then SLEEP=1.5; DELAY_DRAWINFO=3.0; TMOUT=2 elif test "$lPL_SPEED" -gt 25; then SlEEP=2.0; DELAY_DRAWINFO=4.0; TMOUT=2 elif test "$lPL_SPEED" -gt 20; then SlEEP=2.5; DELAY_DRAWINFO=5.0; TMOUT=2 elif test "$lPL_SPEED" -gt 15; then SLEEP=3.0; DELAY_DRAWINFO=6.0; TMOUT=2 elif test "$lPL_SPEED" -gt 10; then SLEEP=4.0; DELAY_DRAWINFO=8.0; TMOUT=2 elif test "$lPL_SPEED" -ge 0; then SLEEP=5.0; DELAY_DRAWINFO=10.0; TMOUT=2 elif test "$lPL_SPEED" = ""; then _draw 3 "WARNING: Could not set player speed. Using defaults." else _exit 1 "ERROR while processing player speed." fi _info "Setting SLEEP=$SLEEP ,TMOUT=$TMOUT ,DELAY_DRAWINFO=$DELAY_DRAWINFO" } _player_speed_to_human_readable(){ _debug "_player_speed_to_human_readable:$*" local lPL_SPEED=${1:-$PL_SPEED} test "$lPL_SPEED" || return 254 local PL_SPEED_PRE PL_SPEED_POST oLC_NUMERIC=$oLC_NUMERIC LC_NUMERIC=C case ${#lPL_SPEED} in 7) PL_SPEED1="${lPL_SPEED:0:5}"; PL_SPEED1=`dc $PL_SPEED1 1000 \/ p`;; 6) PL_SPEED1="${lPL_SPEED:0:4}"; PL_SPEED1=`dc $PL_SPEED1 1000 \/ p`;; 5) PL_SPEED1="0.${lPL_SPEED:0:3}";; 4) PL_SPEED1="0.0.${lPL_SPEED:0:2}";; *) :;; esac _msg 7 "Player speed is '$PL_SPEED1'" case $PL_SPEED1 in *.*) PL_SPEED_PRE="${PL_SPEED1%.*}." PL_SPEED_POST="${PL_SPEED1##*.}" ;; *,*) PL_SPEED_PRE="${PL_SPEED1%,*}," PL_SPEED_POST="${PL_SPEED1##*,}" ;; [0-9]*) PL_SPEED_PRE="${PL_SPEED1}." PL_SPEED_POST=00 ;; esac case ${#PL_SPEED_POST} in 1) PL_SPEED_POST="${PL_SPEED_POST}0";; esac PL_SPEED_POST=`_round_up_and_down $PL_SPEED_POST` _msg 7 "Rounded Player speed is '${PL_SPEED_PRE}$PL_SPEED_POST'" PL_SPEED_POST=${PL_SPEED_POST:0:2} _msg 7 "Rounded Player speed is '${PL_SPEED_PRE}$PL_SPEED_POST'" PL_SPEED1="${PL_SPEED_PRE}${PL_SPEED_POST}" _msg 7 "Rounded Player speed is '$PL_SPEED1'" PL_SPEED1=`echo "$PL_SPEED1" | sed 's!\.!!g;s!\,!!g;s!^0*!!'` LC_NUMERIC=$oLC_NUMERIC } __player_speed_to_human_readable(){ _debug "__player_speed_to_human_readable:$*" local lPL_SPEED=${1:-$PL_SPEED} test "$lPL_SPEED" || return 254 : #TODO } __request(){ # for multi-line replies test "$*" || return 254 local lANSWER lOLD_ANSWER lANSWER= lOLD_ANSWER= ANSWER= _empty_message_stream echo request $* while :; do read -t $TMOUT lANSWER _log "$REQUEST_LOG" "__request $*:$lANSWER" _msg 7 "$lANSWER" #test "$lANSWER" || break #test "$lANSWER" = "$lOLD_ANSWER" && break case $lANSWER in ''|$lOLD_ANSWER|*request*end) break 1;; esac ANSWER="$ANSWER $lANSWER" lOLD_ANSWER="$lANSWER" sleep 0.01 done #ANSWER="$lANSWER" ANSWER=`echo "$ANSWER" | sed 'sI^$II'` test "$ANSWER" } _request(){ # for one line replies test "$*" || return 254 local lANSWER='' _empty_message_stream echo request $* read -t $TMOUT lANSWER _log "$REQUEST_LOG" "_request $*:$lANSWER" _msg 7 "$lANSWER" ANSWER="$lANSWER" test "$ANSWER" } _check_counter(){ ckc=$((ckc+1)) test "$ckc" -lt $COUNT_CHECK_FOOD && return 1 ckc=0 return 0 } _get_player_speed(){ _debug "_get_player_speed:$*" if test "$1" = '-l'; then # loop counter #spdcnt=$((spdcnt+1)) #test "$spdcnt" -ge ${COUNT_CHECK_FOOD:-10} || return 1 #spdcnt=0 _check_counter || return 1 shift fi __old_req(){ local reqANSWER OLD_ANSWER PL_SPEED reqANSWER= OLD_ANSWER= while :; do read -t $TMOUT reqANSWER #read -t $TMOUT r s c WC AC DAM PL_SPEED WP_SPEED #reqANSWER="$r $s $c $WC $AC $DAM $PL_SPEED $WP_SPEED" _log "$REQUEST_LOG" "_get_player_speed:__old_req:$reqANSWER" _msg 7 "$reqANSWER" test "$reqANSWER" || break test "$reqANSWER" = "$OLD_ANSWER" && break OLD_ANSWER="$reqANSWER" sleep 0.1 done #PL_SPEED=`awk '{print $7}' <<<"$reqANSWER"` # *** bash test "$reqANSWER" && PL_SPEED0=`echo "$reqANSWER" | awk '{print $7}'` # *** ash + bash PL_SPEED=${PL_SPEED0:-$PL_SPEED} } __new_req(){ read -t $TMOUT r s c WC AC DAM PL_SPEED WP_SPEED _log "$REQUEST_LOG" "_get_player_speed:__new_req:$r $s $c $WC $AC $DAM PL_SPPED=$PL_SPEED $WP_SPEED" _msg 7 "$r $s $c $WC $AC $DAM PL_SPPED=$PL_SPEED $WP_SPEED" } _use_old_funcs(){ _empty_message_stream echo request stat cmbt # only one line #__old_req __new_req } _use_new_funcs(){ #__request stat cmbt _empty_message_stream _request stat cmbt test "$ANSWER" && PL_SPEED0=`echo "$ANSWER" | awk '{print $7}'` PL_SPEED=${PL_SPEED0:-$PL_SPEED} } _draw 5 "Processing Player's speed..." #_use_old_funcs _use_new_funcs PL_SPEED=${PL_SPEED:-50000} # 0.50 _player_speed_to_human_readable $PL_SPEED _msg 6 "Using player speed '$PL_SPEED1'" _draw 6 "Done." return 0 } _unapply_rod_of_recall(){ # *** Unreadying rod of word of recall - just in case *** # _debug "_unapply_rod_of_recall:$*" local RECALL OLD_REPLY REPLY _draw 5 "Preparing for recall if monsters come forth..." RECALL=0 OLD_REPLY=""; REPLY=""; _empty_message_stream echo request items actv while :; do read -t $TMOUT _log "$REPLY_LOG" "_unapply_rod_of_recall:request items actv:$REPLY" case $REPLY in *rod*of*word*of*recall*) RECALL=1;; '') break;; esac unset REPLY sleep 0.1s done if test "$RECALL" = 1; then # unapply it now , _emergency_exit applies again _is 1 1 apply -u rod of word of recall fi _draw 6 "Done." } #** we may get attacked and die **# _check_hp_and_return_home(){ _debug "_check_hp_and_return_home:$*" local currHP currHPMin currHP=${1:-$HP} currHPMin=${2:-$HP_MIN_DEF} currHPMin=${currHPMin:-$((MHP/10))} _msg 7 "currHP=$currHP currHPMin=$currHPMin" if test "$currHP" -le ${currHPMin:-20}; then __old_recall(){ _empty_message_stream _is 1 1 apply -u ${RETURN_ITEM:-'rod of word of recall'} _is 1 1 apply -a ${RETURN_ITEM:-'rod of word of recall'} _empty_message_stream _is 1 1 fire center ## TODO: check if already applied and in inventory _is 1 1 fire_stop _empty_message_stream _unwatch $DRAWINFO exit 5 } _emergency_exit fi unset HP } _check_if_on_item_examine(){ # Using 'examine' directly after dropping # the item examines the bottommost tile # as 'That is marble' _debug "_check_if_on_item_examine:$*" local DO_LOOP TOPMOST LIST unset DO_LOOP TOPMOST LIST while [ "$1" ]; do case $1 in -l) DO_LOOP=1;; -t) TOPMOST=1;; -lt|-tl) DO_LOOP=1; TOPMOST=1;; *) break;; esac shift done local lITEM=${*:-"$ITEM"} test "$lITEM" || return 254 _draw 5 "Checking if standing on $lITEM ..." _watch $DRAWINFO #_is 0 0 examine while :; do unset REPLY _is 0 0 examine _sleep read -t $TMOUT _log "_check_if_on_item_examine:$REPLY" _msg 7 "$REPLY" case $REPLY in *"That is"*"$lITEM"*|*"Those are"*"$lITEM"*|*"Those are"*"${lITEM// /?*}"*) break 1;; *"That is"*|*"Those are"*) break 1;; *scripttell*break*) break ${REPLY##*?break};; *scripttell*exit*) _exit 1 $REPLY;; *'YOU HAVE DIED.'*) _just_exit;; '') break 1;; *) continue;; #:;; esac LIST="$LIST $REPLY" # sleep 0.01 #sleep 0.1 done _unwatch _empty_message_stream LIST=`echo "$LIST" | sed 'sI^$II'` if test "$TOPMOST"; then echo "${LIST:-$REPLY}" | tail -n1 | grep -q -i -E " $lITEM| ${lITEM}s| ${lITEM}es| ${lITEM// /[s ]+}" else echo "$REPLY" | grep -q -i -E " $lITEM| ${lITEM}s| ${lITEM}es| ${lITEM// /[s ]+}" fi local lRV=$? test "$lRV" = 0 && return $lRV if test "$DO_LOOP"; then return ${lRV:-3} else _exit ${lRV:-3} "$lITEM not here or not on top of stack." fi } _check_if_on_item(){ _debug "_check_if_on_item:$*" local DO_LOOP TOPMOST lMSG lRV unset DO_LOOP TOPMOST lMSG lRV while [ "$1" ]; do case $1 in -l) DO_LOOP=1;; -t) TOPMOST=1;; -lt|-tl) DO_LOOP=1; TOPMOST=1;; *) break;; esac shift done local lITEM=${*:-"$ITEM"} test "$lITEM" || return 254 _draw 5 "Checking if standing on $lITEM ..." UNDER_ME=''; UNDER_ME_LIST=''; _empty_message_stream echo request items on while :; do read -t $TMOUT UNDER_ME _log "$ON_LOG" "_check_if_on_item:$UNDER_ME" _msg 7 "$UNDER_ME" case $UNDER_ME in '') continue;; *request*items*on*end*) break 1;; *scripttell*break*) break ${REPLY##*?break};; *scripttell*exit*) _exit 1 $REPLY;; *'YOU HAVE DIED.'*) _just_exit;; esac UNDER_ME_LIST="$UNDER_ME $UNDER_ME_LIST" unset UNDER_ME sleep 0.1s done UNDER_ME_LIST=`echo "$UNDER_ME_LIST" | sed 's%^$%%'` __debug "UNDER_ME_LIST='$UNDER_ME_LIST'" NUMBER_ITEM=`echo "$UNDER_ME_LIST" | grep -iE " $lITEM| ${lITEM}s| ${lITEM}es| ${lITEM// /[s ]+}" | wc -l` unset TOPMOST_MSG case "$UNDER_ME_LIST" in *"$lITEM"|*"${lITEM}s"|*"${lITEM}es"|*"${lITEM// /?*}") TOPMOST_MSG='some' ;; esac test "$TOPMOST" && { UNDER_ME_LIST=`echo "$UNDER_ME_LIST" | tail -n1`; TOPMOST_MSG=${TOPMOST_MSG:-topmost}; } case "$UNDER_ME_LIST" in *"$lITEM"|*"${lITEM}s"|*"${lITEM}es"|*"${lITEM// /?*}") lRV=0;; *) lMSG="You appear not to stand on $TOPMOST_MSG $lITEM!" lRV=1;; esac if test $lRV = 0; then case "$UNDER_ME_LIST" in *cursed*) lMSG="You appear to stand upon $TOPMOST_MSG cursed $lITEM!" lRV=1;; *damned*) lMSG="You appear to stand upon $TOPMOST_MSG damned $lITEM!" lRV=1;; esac fi test "$lRV" = 0 && return 0 _beep_std _draw 3 $lMSG test "$DO_LOOP" && return 1 || _exit 1 } __check_if_on_item(){ _debug "__check_if_on_item:$*" local DO_LOOP TOPMOST lMSG lRV unset DO_LOOP TOPMOST lMSG lRV while [ "$1" ]; do case $1 in -l) DO_LOOP=1;; -t) TOPMOST=1;; -lt|-tl) DO_LOOP=1; TOPMOST=1;; *) break;; esac shift done local lITEM=${*:-"$ITEM"} test "$lITEM" || return 254 _draw 5 "Checking if standing on $lITEM ..." UNDER_ME=''; UNDER_ME_LIST=''; _empty_message_stream echo request items on while :; do read -t $TMOUT UNDER_ME _log "$ON_LOG" "__check_if_on_item:$UNDER_ME" _msg 7 "$UNDER_ME" case $UNDER_ME in '') continue;; *request*items*on*end*) break 1;; *scripttell*break*) break ${REPLY##*?break};; *scripttell*exit*) _exit 1 $REPLY;; *'YOU HAVE DIED.'*) _just_exit;; esac UNDER_ME_LIST="$UNDER_ME $UNDER_ME_LIST" unset UNDER_ME sleep 0.1s done UNDER_ME_LIST=`echo "$UNDER_ME_LIST" | sed 's%^$%%'` __debug "UNDER_ME_LIST='$UNDER_ME_LIST'" NUMBER_ITEM=`echo "$UNDER_ME_LIST" | grep -iE " $lITEM| ${lITEM}s| ${lITEM}es| ${lITEM// /[s ]+}" | wc -l` if test "$TOPMOST"; then TOP_UNDER_ME_LIST=`echo "$UNDER_ME_LIST" | tail -n1` if test "`echo "$TOP_UNDER_ME_LIST" | grep -iE " $lITEM| ${lITEM}s| ${lITEM}es| ${lITEM// /[s ]+}" | grep -E 'cursed|damned'`"; then lMSG="Topmost $lITEM appears to be cursed!" false elif test "`echo "$TOP_UNDER_ME_LIST" | grep -iE " $lITEM| ${lITEM}s| ${lITEM}es| ${lITEM// /[s ]+}"`"; then true elif test "`echo "$UNDER_ME_LIST" | grep -iE " $lITEM| ${lITEM}s| ${lITEM}es| ${lITEM// /[s ]+}"`"; then lMSG="$lITEM appears not to be topmost!" false else lMSG="You appear not to stand on some $lITEM!" false fi lRV=$? else case "$UNDER_ME_LIST" in *"$lITEM"*cursed*|*"${lITEM}s"*cursed*|*"${lITEM}es"*cursed*|*"${lITEM// /?*}"*cursed*) lMSG="${lMSG:-You appear to stand upon some cursed $lITEM!}" lRV=1;; *"$lITEM"*damned*|*"${lITEM}s"*damned*|*"${lITEM}es"*damned*|*"${lITEM// /?*}"*damned*) lMSG="${lMSG:-You appear to stand upon some damned $lITEM!}" lRV=1;; *"$lITEM"|*"${lITEM}s"|*"${lITEM}es"|*"${lITEM// /?*}") lRV=${lRV:-0};; *) lMSG="You appear not to stand on some $lITEM!" lRV=1;; esac fi test "$lRV" = 0 && return 0 _beep_std _draw 3 $lMSG test "$DO_LOOP" && return 1 || _exit 1 } _check_have_item_in_inventory(){ _debug "_check_have_item_in_inventory:$*" local oneITEM oldITEM ITEMS ITEMSA lITEM lITEM=${*:-"$ITEM"} test "$lITEM" || return 254 TIMEB=`date +%s` unset oneITEM oldITEM ITEMS ITEMSA _empty_message_stream echo request items inv while :; do read -t ${TMOUT:-1} oneITEM _log "_check_have_item_in_inventory:$oneITEM" _debug "$oneITEM" case $oneITEM in $oldITEM|'') break 1;; *"$lITEM"*) _draw 7 "Got that item $lITEM in inventory.";; *scripttell*break*) break ${oneITEM##*?break};; *scripttell*exit*) _exit 1 $oneITEM;; *'YOU HAVE DIED.'*) _just_exit;; esac ITEMS="${ITEMS}${oneITEM}\n" #$oneITEM" oldITEM="$oneITEM" sleep 0.01 done unset oldITEM oneITEM TIMEE=`date +%s` TIME=$((TIMEE-TIMEB)) _debug 4 "Fetching Inventory List: Elapsed $TIME sec." #_debug "lITEM=$lITEM" #_debug "head:`echo -e "$ITEMS" | head -n1`" #_debug "tail:`echo -e "$ITEMS" | tail -n2 | head -n1`" #HAVEIT=`echo "$ITEMS" | grep -E " $lITEM| ${lITEM}s| ${lITEM}es"` #__debug "HAVEIT=$HAVEIT" echo -e "$ITEMS" | grep -q -i -E " $lITEM| ${lITEM}s| ${lITEM}es" } _is(){ # issue - send # to server on behalf of client. # is the number of times to execute command # tells whether or not the command must sent at all cost (1 or 0). # and are optional parameters. _debug "issue $*" echo issue "$@" sleep 0.2 } _drop(){ _sound 0 drip & #_is 1 1 drop "$@" #01:58 There are only 1 chests. _is 0 0 drop "$@" } _set_pickup(){ # Usage: pickup <0-7> or . # pickup 0:Don't pick up. # pickup 1:Pick up one item. # pickup 2:Pick up one item and stop. # pickup 3:Stop before picking up. # pickup 4:Pick up all items. # pickup 5:Pick up all items and stop. # pickup 6:Pick up all magic items. # pickup 7:Pick up all coins and gems # #TODO: In pickup 4 and 5 mode # seems to pick up only # one piece of the topmost item, if more than one # piece of the item, as 4 coins or 23 arrows # but all items below the topmost item get # picked up wholly # in _open_chests() ..? #_is 0 0 pickup ${*:-0} #_is 1 0 pickup ${*:-0} #_is 0 1 pickup ${*:-0} _is 1 1 pickup ${*:-0} } ###END### HAVE_FUNCS_COMMON=1