#! /usr/bin/env perl
use strict;
use integer;

warn 'About: Dice Calc, by P.
License: WTFPL v2
Usage: Enter a dice count and size, and modifier, one roll per line.
Example Die: d6[return]
Example Magic Sword: 2d4+1[return]
Example Intelligence Check: d20-6[return]

Multiple rolls: [return] to repeat the previous dice, or use Nx to roll with advantage and return the highest value. -Nx for disadvantage.
Example Save with Advantage: 2xd20[return]
Example Save with Disadvantage: -2xd20[return]
Example Damage with Advantage: 2x4d4+2[return]
Example Longest Plausible Dice Setup String: -2x10d10+10[return]

"quit", Control-D, or Control-C to escape.

Irregular-sided dice are also possible.

You can feed files of rolls all at once:
$ cat rouge_atkdmg.txt rouge_hide.txt | perl dice_calc.pl
You can also pipe apps into it:
$ dmenu [insert dice setup here] | perl dice_calc.pl
' if @ARGV;

srand;

my $last = 'quit';
while (<>) {
	chomp;
	$_ = $last if $_ eq '';
	last if $_ eq 'quit';
	$last = $_;
	my ($disadvantage, $tries, $dcount, $dval, $plus, $pcount) = /(?:(\-?)(\d+)x)?(\d+)?d(\d+)(?:([+\-])(\d+))?/;
	unless ($dval) {
		print "?\n";
		next;
	}
	$dcount = $dcount || 1;
	$tries = $tries || 1;
	my $ret = 0;
	for (my $x = 1; $x <= $tries; $x++) {
		my $acc = 0;
		for (my $d = 1; $d <= $dcount; $d++) {
			$acc += 1+(rand($dval)); # the use integer forces the addition to truncate the rand's float.
		}
		if ($plus eq '+') {
			$acc += $pcount;
		} elsif ($plus eq '-') {
			$acc -= $pcount;
		}
		print "Rolling $x: $acc\n" unless ($tries == 1);
		if ($disadvantage) {
			$ret = $ret == 0 || $acc < $ret ? $acc : $ret;
		} else {
			$ret = $acc > $ret ? $acc : $ret;
		}
	}
	print "$_: $ret\n";
}