#! /usr/bin/perl -w

srand;

# Usage:  roll [specifier] . . .
# [specifier] is MxXdY/Z{+,-}N, where M, X, Y, Z, and N are nonnegative
# integers, and Z <= X.  Computes M random numbers between (X-Z)±N and
# (X-Z)Y±N, inclusive.  Rolls X Y-sided dice, drops the lowest Z, then
# adds N.  Useful for RPGs or other games that involve dice.
#
# Mx, X, /Z, ±N, or any combination thereof may be omitted.

for (@ARGV) {
	if(! /^(?:([0-9]+)x)?([0-9]+)?d([0-9]+)(?:\/([0-9]+))?(?:([+-])([0-9]+))?$/) {
		print <<"EOF";
Bad specifier: $_

Specifiers are of the form XdY, optionally followed by /Z, +N, or -N,
and optionally proceeded by Mx.  X, Y, Z, M, and N are nonnegative
integers; if given, Z must be less than or equal to X.  Only one of
+N or -N may be given; if /Z is given along with +N or -N, /Z most
come first.  Z and N default to zero if not specified.  M and X default
to 1 if not specified

Rolls X Y-sided dice, drops the Z lowest, and finally adds or subtracts
the constant N.  Do this M times, showing the result from each such roll.
EOF
		exit 1;
	}
	$times = defined($1) ? $1 : 1;
	$rolls = defined($2) ? $2 : 1;
	$drop = defined($4) ? $4 : 0;
	$bonus = defined($6) ? $5 eq "-" ? -$6 : $6 : 0;
	$type = $3;
	die "cannot drop $drop dice of $rolls in $_" if($drop > $rolls);

	for (1..$times) {
		@rolled = ();
		$val = 0;
		for (1..$rolls) {
			push @rolled,(int rand($type)) + 1;
		}
		@rolled = sort {$a <=> $b} @rolled;
		for(1..$drop){shift @rolled};
		for(@rolled){$val += $_};
		$val += $bonus;
		print "$_: $val\n";
	}
}
