bash/roller: D&D-style dice roller
This commit is contained in:
parent
cd2aaf04f9
commit
791f617acb
|
@ -0,0 +1,116 @@
|
|||
#!/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
|
Loading…
Reference in New Issue