==== 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