2012-02-29 12:05:49 -08:00
|
|
|
package DDG::Goodie::Dice;
|
2014-08-20 11:45:33 -07:00
|
|
|
# ABSTRACT: roll a number of (abstract) dice.
|
2015-01-15 19:45:40 -08:00
|
|
|
# https://en.wikipedia.org/wiki/Dice_notation
|
2012-02-29 12:05:49 -08:00
|
|
|
|
2015-02-22 12:09:29 -08:00
|
|
|
use strict;
|
2012-02-29 12:05:49 -08:00
|
|
|
use DDG::Goodie;
|
2016-02-29 20:39:29 -08:00
|
|
|
use Lingua::EN::Numericalize;
|
2012-02-29 12:05:49 -08:00
|
|
|
|
|
|
|
triggers start => "roll", "throw";
|
2012-05-23 19:05:08 -07:00
|
|
|
|
2012-03-20 21:08:12 -07:00
|
|
|
zci answer_type => "dice_roll";
|
2014-07-04 16:20:48 -07:00
|
|
|
zci is_cached => 0;
|
2012-05-23 19:05:08 -07:00
|
|
|
|
2013-03-05 09:41:49 -08:00
|
|
|
my %utf8_dice = (
|
|
|
|
1 => "\x{2680}",
|
|
|
|
2 => "\x{2681}",
|
|
|
|
3 => "\x{2682}",
|
|
|
|
4 => "\x{2683}",
|
|
|
|
5 => "\x{2684}",
|
|
|
|
6 => "\x{2685}",
|
|
|
|
);
|
|
|
|
|
2014-10-28 11:36:15 -07:00
|
|
|
# roll_dice generate pseudo random roll
|
2014-01-16 19:20:08 -08:00
|
|
|
# param $_[0] number of faces
|
|
|
|
# return roll
|
|
|
|
sub roll_die {
|
|
|
|
return int(rand($_[0])) + 1 if $_;
|
|
|
|
}
|
|
|
|
|
|
|
|
# set_num_dice set the number of dice to be rolled
|
|
|
|
# param user input x, ex. 'xd4' or 'x dice'
|
|
|
|
# param default for no label, ex. 'd20' or 'dice'
|
|
|
|
# return the number of dice to be rolled
|
|
|
|
sub set_num_dice {
|
|
|
|
my $num_dice = $_[0];
|
|
|
|
my $num_dice_default = $_[1];
|
|
|
|
if(defined($num_dice)){
|
2016-03-01 11:56:27 -08:00
|
|
|
if ($num_dice =~ /^[a-zA-Z\s\-]+$/) {
|
2016-02-29 20:39:29 -08:00
|
|
|
return str2nbr($num_dice);
|
|
|
|
}
|
2014-01-16 19:20:08 -08:00
|
|
|
if ($num_dice ne ''){
|
|
|
|
return $num_dice;
|
|
|
|
}else{
|
|
|
|
return $num_dice_default;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# shorthand_roll_output generate shorthand roll output
|
|
|
|
# param array of rolls
|
|
|
|
# param sum of rolls
|
|
|
|
# return roll output
|
|
|
|
sub shorthand_roll_output {
|
|
|
|
my @rolls = @{$_[0]};
|
|
|
|
my $sum = $_[1];
|
|
|
|
my $out;
|
|
|
|
if (@rolls > 1) { # if( sizeOf(rolls) > 1)
|
2016-02-24 08:57:15 -08:00
|
|
|
$out = join(' + ', @rolls); # append current roll to output
|
|
|
|
$out =~ s/\+\s\-/\- /g; # rewrite + -1 as - 1
|
|
|
|
if ($_[2] > 1) {
|
|
|
|
$out .= " = $sum"; # append sum of rolls to output
|
|
|
|
}
|
2014-01-16 19:20:08 -08:00
|
|
|
} else {
|
|
|
|
$out = $sum; # output is roll value if we have just one roll
|
|
|
|
}
|
2015-12-28 11:34:35 -08:00
|
|
|
return $out;
|
2014-01-16 19:20:08 -08:00
|
|
|
}
|
|
|
|
|
2013-06-19 17:57:27 -07:00
|
|
|
handle remainder_lc => sub {
|
2014-07-04 15:30:29 -07:00
|
|
|
# Ensure rand is seeded for each process
|
|
|
|
srand();
|
2014-07-04 16:06:43 -07:00
|
|
|
|
2014-01-02 12:35:56 -08:00
|
|
|
my @values = split(' and ', $_);
|
2014-01-07 15:47:47 -08:00
|
|
|
my $values = @values; # size of @values;
|
2014-01-16 19:20:08 -08:00
|
|
|
my $out = '';
|
2015-12-28 11:02:05 -08:00
|
|
|
my $diceroll;
|
2015-12-28 10:11:27 -08:00
|
|
|
my @result;
|
2014-01-08 21:00:11 -08:00
|
|
|
my $heading = "Random Dice Roll";
|
2014-01-15 21:58:59 -08:00
|
|
|
my $total; # total of all dice rolls
|
2014-01-30 07:43:31 -08:00
|
|
|
foreach (@values) {
|
2016-03-01 11:56:27 -08:00
|
|
|
if ($_ =~ /^(?:a? ?die|(\d{0,2}|[a-zA-Z\s\-]+)\s*dic?es?)$/) {
|
2016-02-29 20:39:29 -08:00
|
|
|
# ex. 'a die', '2 dice', '5dice', 'five dice'
|
2014-01-02 12:35:56 -08:00
|
|
|
my @output;
|
2014-01-12 11:38:41 -08:00
|
|
|
my $sum = 0;
|
2014-01-16 19:20:08 -08:00
|
|
|
my $number_of_dice = set_num_dice($1, 2); # set number of dice, default 2
|
|
|
|
my $number_of_faces = 6; # number of utf8_dice
|
2016-02-29 20:39:29 -08:00
|
|
|
|
|
|
|
if ($number_of_dice !~ /^\d+$/) {
|
|
|
|
return;
|
|
|
|
}
|
2014-01-16 19:20:08 -08:00
|
|
|
for (1 .. $number_of_dice) { # for all rolls
|
|
|
|
my $roll = roll_die( $number_of_faces ); # roll the die
|
2014-01-15 21:58:59 -08:00
|
|
|
$sum += $roll; # track sum
|
|
|
|
push @output, $utf8_dice{$roll}; # add our roll to array output
|
2012-02-29 12:05:49 -08:00
|
|
|
}
|
2014-01-15 21:58:59 -08:00
|
|
|
$total += $sum; # track total of all rolls
|
2015-12-28 11:34:35 -08:00
|
|
|
$out .= join(', ', @output);
|
2015-12-28 11:02:05 -08:00
|
|
|
$diceroll = join(' ', @output);
|
2016-02-24 08:00:37 -08:00
|
|
|
push @result, {
|
|
|
|
'sum' => $sum,
|
|
|
|
'rolls' => $diceroll,
|
|
|
|
'isdice' => 1
|
|
|
|
};
|
2012-02-29 12:05:49 -08:00
|
|
|
}
|
2014-10-28 11:36:15 -07:00
|
|
|
elsif ($_ =~ /^(\d*)[d|w](\d+)\s?([+-])?\s?(\d+|[lh])?$/) {
|
2014-01-15 21:58:59 -08:00
|
|
|
# ex. '2d8', '2w6 - l', '3d4 + 4', '3d4-l'
|
|
|
|
# 'w' is the German form of 'd'
|
2014-01-02 12:35:56 -08:00
|
|
|
my (@rolls, $output);
|
2014-01-16 19:20:08 -08:00
|
|
|
my $number_of_dice = set_num_dice($1, 1); # set number of dice, default 1
|
|
|
|
# check that input is not greater than or equal to 99
|
|
|
|
# check that input is not 0. ex. 'roll 0d3' should not return a value
|
|
|
|
if( $number_of_dice >= 100 or $1 eq '0'){
|
|
|
|
return; # do not continue if conditions not met
|
2014-01-07 15:47:47 -08:00
|
|
|
}
|
2014-01-16 19:20:08 -08:00
|
|
|
my $min = my $number_of_faces = $2; # set min and number_of_faces to max possible roll
|
|
|
|
my $max = my $sum = 0; # set max roll and sum to -
|
2014-01-15 21:58:59 -08:00
|
|
|
for (1 .. $number_of_dice) { # for each die
|
2014-01-16 19:20:08 -08:00
|
|
|
my $roll = roll_die( $number_of_faces ); # roll the die
|
|
|
|
$min = $roll if $roll < $min; # record min roll
|
|
|
|
$max = $roll if $roll > $max; # record max roll
|
2014-01-15 21:58:59 -08:00
|
|
|
push @rolls, $roll; # add roll to array rolls
|
2014-01-02 12:35:56 -08:00
|
|
|
}
|
|
|
|
if (defined($3) && defined($4)) {
|
|
|
|
# handle special case of " - L" or " - H"
|
|
|
|
if ($3 eq '-' && ($4 eq 'l' || $4 eq 'h')) {
|
|
|
|
if ($4 eq 'l') {
|
2014-01-16 19:20:08 -08:00
|
|
|
push(@rolls, -$min); # add -min roll to array rolls
|
2014-01-02 12:35:56 -08:00
|
|
|
} else {
|
2014-01-16 19:20:08 -08:00
|
|
|
push(@rolls, -$max); # add -max roll to array rolls
|
2014-01-02 12:35:56 -08:00
|
|
|
}
|
2014-01-15 21:58:59 -08:00
|
|
|
} elsif ($3 eq '+' && ($4 eq 'l' || $4 eq 'h')) { # do nothing with '3d5+h'
|
2014-01-02 12:35:56 -08:00
|
|
|
return;
|
2012-02-29 12:05:49 -08:00
|
|
|
} else {
|
2014-01-15 21:58:59 -08:00
|
|
|
push(@rolls, int("$3$4")); # ex. '-4', '+3'
|
2012-02-29 12:05:49 -08:00
|
|
|
}
|
2014-01-02 12:35:56 -08:00
|
|
|
}
|
|
|
|
for (@rolls) {
|
2014-01-15 21:58:59 -08:00
|
|
|
$sum += $_; # track sum
|
2014-01-02 12:35:56 -08:00
|
|
|
}
|
2015-12-29 11:28:09 -08:00
|
|
|
my $roll_output = shorthand_roll_output( \@rolls, $sum, $values ); # initialize roll_output
|
2014-01-16 19:20:08 -08:00
|
|
|
$out .= $roll_output; # add roll_output to our result
|
2016-02-24 08:00:37 -08:00
|
|
|
push @result, {
|
|
|
|
'sum' => $sum,
|
|
|
|
'rolls' => [@rolls],
|
|
|
|
'isdice' => 0
|
|
|
|
};
|
2014-01-07 15:47:47 -08:00
|
|
|
$total += $sum; # add the local sum to the total
|
2014-01-08 21:00:11 -08:00
|
|
|
}else{
|
|
|
|
# an element of @value was not valid
|
|
|
|
return;
|
2012-02-29 12:05:49 -08:00
|
|
|
}
|
|
|
|
}
|
2016-02-24 08:00:37 -08:00
|
|
|
my $group = 'text';
|
|
|
|
|
|
|
|
my $data = {
|
|
|
|
title => $total,
|
|
|
|
list => \@result
|
|
|
|
};
|
|
|
|
|
|
|
|
my $options = {
|
|
|
|
subtitle_content => 'DDH.dice.subtitle_content'
|
|
|
|
};
|
|
|
|
|
|
|
|
if ($values > 1) {
|
2014-01-07 15:47:47 -08:00
|
|
|
# display total sum if more than one value was specified
|
2014-01-16 19:20:08 -08:00
|
|
|
$out .= 'Total: ' . $total;
|
2016-02-24 08:00:37 -08:00
|
|
|
$group = 'list';
|
|
|
|
$options = {
|
|
|
|
list_content => 'DDH.dice.content'
|
|
|
|
};
|
2014-01-07 15:47:47 -08:00
|
|
|
}
|
2014-10-28 11:36:15 -07:00
|
|
|
$out =~ s/<br\/>$//g; # remove trailing newline
|
2016-02-24 08:00:37 -08:00
|
|
|
|
|
|
|
if ($out eq '') {
|
2014-01-07 15:47:47 -08:00
|
|
|
return; # nothing to return
|
|
|
|
}
|
2016-02-24 08:00:37 -08:00
|
|
|
|
|
|
|
return $out,
|
|
|
|
structured_answer => {
|
|
|
|
data => $data,
|
|
|
|
templates => {
|
|
|
|
group => $group,
|
|
|
|
options => $options
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-02-29 12:05:49 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
1;
|