initial commit

This commit is contained in:
2021-08-08 21:11:22 +02:00
commit fe7136d801
130 changed files with 6858 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
# D&D Character
For a game of [Dungeons & Dragons][DND], each player starts by generating a
character they can play with. This character has, among other things, six
abilities; strength, dexterity, constitution, intelligence, wisdom and
charisma. These six abilities have scores that are determined randomly. You
do this by rolling four 6-sided dice and record the sum of the largest three
dice. You do this six times, once for each ability.
Your character's initial hitpoints are 10 + your character's constitution
modifier. You find your character's constitution modifier by subtracting 10
from your character's constitution, divide by 2 and round down.
Write a random character generator that follows the rules above.
For example, the six throws of four dice may look like:
* 5, 3, 1, 6: You discard the 1 and sum 5 + 3 + 6 = 14, which you assign to strength.
* 3, 2, 5, 3: You discard the 2 and sum 3 + 5 + 3 = 11, which you assign to dexterity.
* 1, 1, 1, 1: You discard the 1 and sum 1 + 1 + 1 = 3, which you assign to constitution.
* 2, 1, 6, 6: You discard the 1 and sum 2 + 6 + 6 = 14, which you assign to intelligence.
* 3, 5, 3, 4: You discard the 3 and sum 5 + 3 + 4 = 12, which you assign to wisdom.
* 6, 6, 6, 6: You discard the 6 and sum 6 + 6 + 6 = 18, which you assign to charisma.
Because constitution is 3, the constitution modifier is -4 and the hitpoints are 6.
## Notes
Most programming languages feature (pseudo-)random generators, but few
programming languages are designed to roll dice. One such language is [Troll].
[DND]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons
[Troll]: http://hjemmesider.diku.dk/~torbenm/Troll/
Run the tests with:
```bash
bats dnd_character_test.sh
```
After the first test(s) pass, continue by commenting out or removing the
`[[ $BATS_RUN_SKIPPED == true ]] || skip`
annotations prepending other tests.
To run all tests, including the ones with `skip` annotations, run:
```bash
BATS_RUN_SKIPPED=true bats dnd_character_test.sh
```
## Source
Simon Shine, Erik Schierboom [https://github.com/exercism/problem-specifications/issues/616#issuecomment-437358945](https://github.com/exercism/problem-specifications/issues/616#issuecomment-437358945)
## External utilities
`Bash` is a language to write "scripts" -- programs that can call
external tools, such as
[`sed`](https://www.gnu.org/software/sed/),
[`awk`](https://www.gnu.org/software/gawk/),
[`date`](https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html)
and even programs written in other programming languages,
like [`Python`](https://www.python.org/).
This track does not restrict the usage of these utilities, and as long
as your solution is portable between systems and does not require
installation of third party applications, feel free to use them to solve
the exercise.
For an extra challenge, if you would like to have a better understanding
of the language, try to re-implement the solution in pure `Bash`,
without using any external tools. Note that there are some types of
problems that bash cannot solve, such as performing floating point
arithmetic and manipulating dates: for those, you must call out to an
external tool.
## Submitting Incomplete Solutions
It's possible to submit an incomplete solution so you can see how others
have completed the exercise.

View File

@@ -0,0 +1,115 @@
#!/usr/bin/env bash
#
# v1: initial version
# v2: cleanup, replaced while loops with for loops when possible
# external tools: none
# set to 0 to disable log function output, 1 otherwise
debug=0
declare -a abilities=( strength dexterity intelligence wisdom charisma constitution )
usage() {
echo "dnd_characters.sh generate|modifier <n>" >&2
exit 1
}
# log function takes 1 argument which is echoed if $debug is > 0
# todo: Add another argument (mask ?) to selectively log portions of code
log () {
(( $debug )) && echo "$*"
}
# simple bubble sort for numeric array (descending)
# args: 1: the array
# todo: add a parameter for asc/desc order.
sort_n() {
local -a array=( "$@" )
local -i max=$(( ${#array[@]} - 1 ))
for (( max= $(( ${#array[@]} - 1 )); max > 0; max-- )); do
local -i i
for (( i=0; i<max; i++ )); do
local -i val1=${array[$i]}
local -i val2=${array[$((i + 1))]}
# switch if necessary
if (( $val1 < $val2 )); then
local tmp=$val1
array[$i]=$val2
array[$(($i + 1))]=$tmp
fi
done
done
echo "${array[@]}"
}
# roll $2 times a $1 faces dice
roll() {
local -a rolls
local -i i
for (( i=1; i<=$2; i++ )); do
rolls[$i]=$((RANDOM % $1 + 1))
done
echo ${rolls[@]}
}
modifier() {
local -i res
local -i in=$1
local -i out=$(( $in - 10 ))
log modifier in "$1"
res=$(( $out / 2 )) # will alwaid round down
log modifier div "$res"
# adjust for negative numbers
(( $out < 0 )) && (( $out % 2 )) && (( res-- ))
log modifier adjust negative "$res"
echo $res
}
generate() {
local -i s
local -a dices
for ability in ${abilities[@]}; do
dices=( $(roll 6 4) )
s=( $(sort_n ${dices[@]}) )
sum=$(( ${s[1]} + ${s[2]} + ${s[3]} ))
echo $ability $sum
if [[ $ability == "constitution" ]]; then
echo "hitpoints $(( 10 - $(modifier $sum) ))"
fi
done
}
command="$1"
case "$command" in
"modifier")
(( $# != 2 )) && usage
modifier "$2"
;;
"generate")
(( $# != 1 )) && usage
generate
;;
*)
usage
;;
esac
exit 0
# Indent style for emacs
# Local Variables:
# sh-basic-offset: 4
# sh-indentation: 4
# indent-tabs-mode: nil
# comment-column: 60
# End: