116 lines
2.1 KiB
Bash
Executable file
116 lines
2.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
die() {
|
|
printf "invalid roll: $1\n" "${@:2}" >&2
|
|
exit 1
|
|
}
|
|
|
|
debug() {
|
|
if [[ -v opts[debug] ]]; then
|
|
printf "DEBUG: $1\n" "${@:2}"
|
|
fi
|
|
}
|
|
|
|
verbose() {
|
|
if [[ -v opts[verbose] ]]; then
|
|
printf "$1\n" "${@:2}"
|
|
fi
|
|
}
|
|
|
|
is_integer() {
|
|
if (( $# )); then
|
|
[[ $1 =~ ^[0-9]+$ ]]
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
roll_die() {
|
|
if (( $# )); then
|
|
printf %d "$(( (RANDOM % $1) + 1 ))"
|
|
else
|
|
printf 0
|
|
fi
|
|
}
|
|
|
|
declare -A opts
|
|
|
|
while (( $# )); do
|
|
case $1 in
|
|
-v)
|
|
opts[verbose]=1
|
|
;;
|
|
-d)
|
|
opts[debug]=1
|
|
;;
|
|
-x)
|
|
set -x
|
|
;;
|
|
-*)
|
|
die "unknown option '%s'" "$1"
|
|
;;
|
|
*)
|
|
break
|
|
esac
|
|
|
|
shift
|
|
done
|
|
|
|
if (( $# )); then
|
|
IFS=d read -r quantity rest <<< "$1"
|
|
|
|
if [[ -z $quantity ]]; then
|
|
quantity=1
|
|
elif ! is_integer "$quantity"; then
|
|
die "dice quantity is not a number"
|
|
fi
|
|
|
|
debug "quantity of dice is %d" "$quantity"
|
|
|
|
while (( ${#rest} )) && [[ ${rest:0:1} != @(+|-) ]]; do
|
|
sides+=${rest:0:1} rest=${rest:1}
|
|
done
|
|
|
|
if ! is_integer "$sides"; then
|
|
die "not a good number of die sides"
|
|
fi
|
|
|
|
debug "die has %d side(s)" "$sides"
|
|
total_mod=0
|
|
|
|
while (( ${#rest} )); do
|
|
mod_type=${rest:0:1} rest=${rest:1} next_mod=
|
|
|
|
while [[ -n $rest && ${rest:0:1} != @(+|-) ]]; do
|
|
next_mod+=${rest:0:1} rest=${rest:1}
|
|
done
|
|
|
|
if ! is_integer "$next_mod"; then
|
|
die "'%s' is not a proper modifier" "$next_mod"
|
|
elif [[ $mod_type = + ]]; then
|
|
(( total_mod += next_mod ))
|
|
debug "adding %d to modifier for a total of %d" "$next_mod" "$total_mod"
|
|
else
|
|
(( total_mod -= next_mod ))
|
|
debug "subtracting %d from modifier for a total of %d" "$next_mod" "$total_mod"
|
|
fi
|
|
done
|
|
|
|
score=0 count=0
|
|
|
|
while (( quantity-- )); do
|
|
roll=$(roll_die "$sides")
|
|
(( score += roll ))
|
|
debug "rolled a %d. score is now %d" "$roll" "$score"
|
|
verbose "roll %d: %d" "$(( count++ ))" "$roll"
|
|
done
|
|
|
|
verbose "score before modifier: %d" "$score"
|
|
(( score += total_mod ))
|
|
verbose "score after modifier: %d" "$score"
|
|
debug "score total after modifier is %d" "$score"
|
|
|
|
if [[ ! -v opts[verbose] ]]; then
|
|
printf '%d\n' "$score"
|
|
fi
|
|
fi
|