int ways(int to_hit, int sides, int count)
/*
** Calculates the number of ways to roll to_hit
** on count dice with sides sides.
**
** Recursive subroutine. Recursion is a software
** term for a subroutine which calls itself.
** Recursion is not a moral risk, but is a risk to the
** sanity of a programmer not used to the method.
**
** Entering zero or negative numbers for to_hit,
** sides, or count should not hang the routine,
** but no metaphysical comment is intended on the
** true meaning of rolling negative numbers of dice.
** This routine is intended for dice statistics, not
** as a Zen teaching tool. ;-)
*/
{
int sum ;
int index ;
/*
** The lowest number that can be rolled is count.
** The highest is count times sides.
** If to_hit is outside this range, can't roll it.
*/
if (to_hit < count) return 0 ;
if (to_hit > (count * sides)) return 0 ;
/*
** To_hit can be rolled.
** If there is only one die, it can only
** be rolled one way.
**
** Requests for zero or negative dice count
** return one just to make sure no infinite
** recursive call sequences can hang things up.
** In normal operation, count will always be positive.
*/
if (count <= 1) return 1 ;
/*
** It is possible to roll this number.
** There are two or more dice being rolled.
** No instant answer. We are going recursive.
** Initialize sum counter.
*/
sum = 0 ;
/*
** One of the dice has sides possible ways to fall.
** Loop through each possibility.
*/
for (index = 1 ; index <= sides ; index++)
{
/*
** Index holds how one of the dice has fallen.
** How many ways can the rest of the dice fall
** such that when index is added, the total is to_hit?
**
** As the call requests fewer dice and a smaller total,
** the recursive calls do close. Recursion is not magic.
** It only works by breaking down big problems
** into smaller problems. Ways keeps
** calling ways with smaller and smaller parameters until
** to_hit is out of range or count becomes one.
** A zero or one is then returned, and added into sum.
**
** Recursion only works in languages where every time a
** routine is called, new storage is allocated for that
** invocation's variables. If 12 dice are being rolled,
** up to twelve copies of index and sum might be set up
** in the computer's memory.
*/
sum += ways(to_hit - index, sides, count - 1) ;
}
return sum ;
}