#!/usr/bin/perl -w use strict; sub roll { return int(1+rand($_[0])); } # Interprets expressions like "6x3of4d6+2" sub dice { my $spec = shift; die "bad dice expression" if $spec !~ m/(?:(\d+)x)? # repeat N times (?:(\d+)of)? # select top N dice (?:(\d+))? # count of dice to roll d(\d+) # die type, only field required (?:([\-+]\d+))?/x; # add/subtract offset my ($repeat, $select, $count, $type, $off) = ($1, $2, $3, $4, $5); if(!defined $repeat or $repeat eq "") { $repeat = 1; } if(!defined $count or $count eq "") { $count = 1; } if(!defined $select or $select eq "") { $select = $count; } if(!defined $off or $off eq "") { $off = 0; } my @raw_rolls = (); my @results = (); for(my $rep=0; $rep<$repeat; $rep++) { my @rolls = (); for(my $roll=0; $roll<$count; $roll++) { my $val = roll($type); push @raw_rolls, $val; push @rolls, $val; } @rolls = sort {$b<=>$a} @rolls; for(my $i=$select; $i<$count; $i++) { pop @rolls; } my $total = $off; foreach my $r (@rolls) { $total += $r; } push @results, $total; } print "Results:"; foreach my $r (@results) { print " $r"; } print " (raw rolls:"; foreach my $r (@raw_rolls) { print " $r"; } print ")\n"; } foreach my $s (@ARGV) { dice($s); }