RPG   =   Role Playing Game.



You're running a tabletop RPG, and your players are creating characters.

Each character has six core attributes: strength, dexterity, constitution, intelligence, wisdom, and charisma.

One way of generating values for these attributes is to roll four, 6-sided dice (d6) and sum the three highest rolls, discarding the lowest roll.

Some players like to assign values to their attributes in the order they're rolled.

To ensure generated characters don't put players at a disadvantage, the following requirements must be satisfied:

 The total of all character attributes must be at least 75.
 At least two of the attributes must be at least 15.

However, this can require a lot of manual dice rolling. A programatic solution would be much faster.



Task

Write a program that:

 Generates 4 random, whole values between 1 and 6.
 Saves the sum of the 3 largest values.
 Generates a total of 6 values this way.
 Displays the total, and all 6 values once finished.

 The order in which each value was generated must be preserved.
 The total of all 6 values must be at least 75.
 At least 2 of the values must be 15 or more.

 
#!/bin/ksh
 
# RPG attributes generator
 
#	# Variables:
#
typeset -a attribs=( strength dexterity constitution intelligence wisdom charisma )
integer MINTOT=75 MIN15S=2
 
#	# Functions:
#
#   # Function _diceroll(sides, number, reportAs) - roll number of side-sided
#   # dice, report (s)sum or (a)array (pseudo) of results
#
function _diceroll {
  typeset _sides    ; integer _sides=$1         # Number of sides of dice
  typeset _numDice  ; integer _numDice=$2       # Number of dice to roll
  typeset _rep      ; typeset -l -L1 _rep="$3"  # Report type: (sum || array)
 
  typeset _seed    ; (( _seed = SECONDS / $$ )) ; _seed=${_seed#*\.}
  typeset _i _sum  ; integer _i _sum=0
  typeset _arr     ; typeset -a _arr
 
  RANDOM=${_seed}
  for (( _i=0; _i<_numDice; _i++ )); do
      (( _arr[_i] = (RANDOM % _sides) + 1 ))
      [[ ${_rep} == s ]] && (( _sum += _arr[_i] ))
  done
 
    if [[ ${_rep} == s ]]; then
      echo ${_sum}
    else
      echo "${_arr[@]}"
    fi
}
 
#	# Function _sumarr(n arr) - Return the sum of the first n arr elements
#
function _sumarr {
	typeset _n ; integer _n=$1
	typeset _arr ; nameref _arr="$2"
	typeset _i _sum ; integer _i _sum
 
	for ((_i=0; _i<_n; _i++)); do
		(( _sum+=_arr[_i] ))
	done
	echo ${_sum}
}
 
 ######
# main #
 ######
 
until (( total >= MINTOT )) && (( cnt15 >= MIN15S )); do
	integer total=0 cnt15=0
	unset attrval ; typeset -A attrval
	for attr in ${attribs[*]}; do
		unset darr ; typeset -a darr=( $(_diceroll 6 4 a) )
		set -sK:nr -A darr
		attrval[${attr}]=$(_sumarr 3 darr)
		(( total += attrval[${attr}] ))
		(( attrval[${attr}] > 14 )) && (( cnt15++ ))
	done
done
 
for attr in ${attribs[*]}; do
	printf "%12s: %2d\n" ${attr} ${attrval[${attr}]}
done
print "Attribute value total: ${total}"
print "Attribule count >= 15:  ${cnt15}"
 