Created
March 1, 2018 16:38
-
-
Save scottchiefbaker/e721811255d27d99c288f4a1e1cc9a14 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
################################################### | |
# Scott Baker - 2008-03-06 | |
# Released under the GPLV3 | |
# | |
# A simple script to roll dice, or multiple dice | |
# Example: Roll two d20 and add 10 | |
# ./dice_roll.pl 2d20+10 | |
# | |
# Roll a d6 | |
# ./dice_roll.pl 1d6 | |
# | |
# Roll three d10 subtract three (10 times) | |
# ./dice_roll.pl 3d10-3 10 | |
################################################### | |
use Data::Dumper; | |
use List::Util qw[min max sum]; | |
# Get the dice and times | |
my $dice = valid_dice($ARGV[0]); | |
my $times = int($ARGV[1]) || 1; | |
my $verbose = argv('v'); | |
# Make sure we have something valid to process | |
if (!$dice) { | |
die(usage()); | |
} | |
my ($res,$gt); | |
# Loop through for each roll | |
for (my $i = 0; $i < $times; $i++) { | |
# Roll the actual dice | |
my $roll = roll_me($dice); | |
# Get the total for summary later, and also update the grand total | |
my $tot = $roll->{'total'}; | |
$gt += $tot; | |
# Store the total of the roll for stats later | |
$res->{$tot}++; | |
# Print the roll details | |
printf("Roll #%02d: %s\n", ($i + 1), $roll->{'textual'}); | |
} | |
# If there is more than one roll show some summary stats | |
if ($times > 1) { | |
my $min = min(keys(%$res)); | |
my $max = max(keys(%$res)); | |
my $avg = sprintf("%.2f",$gt / $times); | |
print "\n"; | |
print "Min: $min Max: $max\n"; | |
print "Average roll: " . round($avg) . " ($avg)\n"; | |
} | |
########################################################## | |
sub roll_me { | |
my $dice = shift(); | |
$dice =~ /\s+/g; | |
# Get the appropriate pieces of the dice syntax | |
my ($mult,$sides,$neg,$addit) = $dice =~ /(\d+?)?d(\d+)([+\-])?(\d+)?/i; | |
$mult = int($mult) || 1; # Can't have a mult of zero | |
$addit = int($addit); | |
# If the +/- is negative, flip addit to negative | |
if ($neg eq '-') { | |
$addit = -$addit; | |
} | |
if ($verbose) { | |
print "\n* '$dice' means roll a $sides sided dice $mult times"; | |
if ($addit) { | |
print " and add $addit"; | |
} | |
print "\n"; | |
} | |
my @roll = (); | |
# For each mult roll the dice and add it to the array | |
for (my $i = 0; $i < $mult; $i++) { | |
my $num = int(rand($sides)) + 1; | |
# 10 sided dice are weird and have numbers 0-9 (instead of 1-10) | |
# so subtract 1 to get the right number | |
if ($sides == 10) { | |
$num--; | |
} | |
push(@roll,$num); | |
} | |
# Get the total of all the dice rolls | |
my $total = sum(@roll) + $addit; | |
my $text; | |
# If there is an additional add that section at the end | |
if ($addit) { | |
$text = "(" . join(" + ", @roll) . ") + " . $addit . " = " . $total; | |
} else { | |
$text = "(" . join(" + ", @roll) . ") = " . $total; | |
} | |
# Build the big return hash | |
my $ret; | |
$ret->{'total'} = $total; | |
$ret->{'additional'} = $addit; | |
$ret->{'rolls'} = \@roll; | |
$ret->{'textual'} = $text; | |
return $ret; | |
} | |
# Only works for positive numbers (good enough) | |
sub round { | |
my $number = shift; | |
return int($number + .5); | |
} | |
sub usage { | |
my $ret .= "$0 [Dice] [Times]\n"; | |
$ret .= "Example: $0 2d20+3 10\n"; | |
} | |
sub valid_dice { | |
my $t = shift(); | |
# At the minimum make sure there is a litteral d in the dice string | |
if ($t =~ /\d?d\d/i) { | |
return $t; | |
} else { | |
return 0; | |
} | |
} | |
sub argv { | |
my $ret = {}; | |
for (my $i = 0; $i < scalar(@ARGV); $i++) { | |
# If the item starts with "-" it's a key | |
if ((my ($key) = $ARGV[$i] =~ /^--?([a-zA-Z_-]*\w)$/) && ($ARGV[$i] !~ /^-\w\w/)) { | |
# If the next item does not start with "--" it's the value for this item | |
if (defined($ARGV[$i + 1]) && ($ARGV[$i + 1] !~ /^--?\D/)) { | |
$ret->{$key} = $ARGV[$i + 1]; | |
# Bareword like --verbose with no options | |
} else { | |
$ret->{$key}++; | |
} | |
} | |
} | |
# We're looking for a certain item | |
if ($_[0]) { return $ret->{$_[0]}; } | |
return $ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment