File Coverage

blib/lib/Games/Dice.pm
Criterion Covered Total %
statement 9 46 19.5
branch 0 26 0.0
condition 0 9 0.0
subroutine 3 5 60.0
pod 0 2 0.0
total 12 88 13.6


line stmt bran cond sub pod time code
1 1     1   863 use strict;
  1         3  
  1         40  
2 1     1   7 use warnings;
  1         2  
  1         102  
3             package Games::Dice;
4             # ABSTRACT: Perl module to simulate die rolls
5             $Games::Dice::VERSION = '0.044';
6             require Exporter;
7              
8             our @ISA = qw(Exporter);
9             our @EXPORT_OK = qw( roll roll_array);
10              
11             # Preloaded methods go here.
12              
13             # Win32 has crummy built in rand() support
14             # So let's use something that's decent and pure perl
15 1     1   1055 use if $^O eq "MSWin32", 'Math::Random::MT::Perl' => qw(rand);
  1         8  
  1         7  
16              
17             sub roll ($) {
18 0     0 0   my($line, $dice_string, $sign, $offset, $sum, @throws, @result);
19              
20 0           $line = shift;
21              
22 0 0         return $line if $line =~ /\A[0-9]+\z/;
23              
24 0 0         return undef unless $line =~ m{
25             ^ # beginning of line
26             ( # dice string in $1
27             (?:\d+)? # optional count
28             [dD] # 'd' for dice
29             (?: # type of dice:
30             \d+ # either one or more digits
31             | # or
32             % # a percent sign for d% = d100
33             )
34             )
35             (?: # grouping-only parens
36             ([-+xX*/bB]) # a + - * / b(est) in $2
37             (\d+) # an offset in $3
38             )? # both of those last are optional
39             \s* # possibly some trailing space (like \n)
40             $
41             }x; # whitespace allowed
42              
43 0           $dice_string = $1;
44 0   0       $sign = $2 || '';
45 0   0       $offset = $3 || 0;
46              
47 0           $sign = lc $sign;
48              
49 0           @throws = roll_array( $dice_string );
50 0 0         return undef unless @throws;
51              
52 0 0         if( $sign eq 'b' ) {
53 0 0         $offset = 0 if $offset < 0;
54 0 0         $offset = @throws if $offset > @throws;
55              
56 0           @throws = sort { $b <=> $a } @throws; # sort numerically, descending
  0            
57 0           @result = @throws[ 0 .. $offset-1 ]; # pick off the $offset first ones
58             } else {
59 0           @result = @throws;
60             }
61              
62 0           $sum = 0;
63 0           $sum += $_ foreach @result;
64 0 0         $sum += $offset if $sign eq '+';
65 0 0         $sum -= $offset if $sign eq '-';
66 0 0 0       $sum *= $offset if ($sign eq '*' || $sign eq 'x');
67 0 0         do { $sum /= $offset; $sum = int $sum; } if $sign eq '/';
  0            
  0            
68              
69 0           return $sum;
70             }
71              
72             sub roll_array ($) {
73 0     0 0   my($line, $num, $type, @throws);
74              
75 0           $line = shift;
76              
77 0 0         return $line if $line =~ /\A[0-9]+\z/;
78              
79 0 0         return undef unless $line =~ m{
80             ^ # beginning of line
81             (\d+)? # optional count in $1
82             [dD] # 'd' for dice
83             ( # type of dice in $2:
84             \d+ # either one or more digits
85             | # or
86             % # a percent sign for d% = d100
87             )
88             }x; # whitespace allowed
89              
90 0   0       $num = $1 || 1;
91 0           $type = $2;
92              
93 0 0         $type = 100 if $type eq '%';
94              
95 0           @throws = ();
96 0           for( 1 .. $num ) {
97 0           push @throws, int (rand $type) + 1;
98             }
99              
100 0           return @throws;
101             }
102              
103             1;
104              
105             =pod
106              
107             =encoding UTF-8
108              
109             =head1 NAME
110              
111             Games::Dice - Perl module to simulate die rolls
112              
113             =head1 VERSION
114              
115             version 0.044
116              
117             =head1 SYNOPSIS
118              
119             use Games::Dice 'roll';
120             $strength = roll '3d6+1';
121              
122             use Games::Dice 'roll_array';
123             @rolls = roll_array '4d8';
124              
125             =head1 DESCRIPTION
126              
127             Games::Dice simulates die rolls. It uses a function-oriented (not
128             object-oriented) interface. No functions are exported by default. At
129             present, there are two functions which are exportable: C and
130             C. The latter is used internally by C, but can also be
131             exported by itself.
132              
133             The number and type of dice to roll is given in a style which should be
134             familiar to players of popular role-playing games: IdI[+-*/b]I.
135             I is optional and defaults to 1; it gives the number of dice to roll.
136             I indicates the number of sides to each die; the most common,
137             cube-shaped die is thus a d6. % can be used instead of 100 for I;
138             hence, rolling 2d% and 2d100 is equivalent. C simulates I rolls
139             of I-sided dice and adds together the results. The optional end,
140             consisting of one of +-*/b and a number I, can modify the sum of the
141             individual dice. +-*/ are similar in that they take the sum of the rolls
142             and add or subtract I, or multiply or divide the sum by I. (x can
143             also be used instead of *.) Hence, 1d6+2 gives a number in the range
144             3..8, and 2d4*10 gives a number in the range 20..80. (Using / truncates
145             the result to an int after dividing.) Using b in this slot is a little
146             different: it's short for "best" and indicates "roll a number of dice,
147             but add together only the best few". For example, 5d6b3 rolls five six-
148             sided dice and adds together the three best rolls. This is sometimes
149             used, for example, in role-playing to give higher averages.
150              
151             Generally, C probably provides the nicer interface, since it does
152             the adding up itself. However, in some situations one may wish to
153             process the individual rolls (for example, I am told that in the game
154             Feng Shui, the number of dice to be rolled cannot be determined in
155             advance but depends on whether any 6s were rolled); in such a case, one
156             can use C to return an array of values, which can then be
157             examined or processed in an application-dependent manner.
158              
159             This having been said, comments and additions (especially if accompanied
160             by code!) to Games::Dice are welcome. So, using the above example, if
161             anyone wishes to contribute a function along the lines of roll_feng_shui
162             to become part of Games::Dice (or to support any other style of die
163             rolling), you can contribute it to the author's address, listed below.
164              
165             =head1 NAME
166              
167             =head1 AUTHORS
168              
169             =over 4
170              
171             =item *
172              
173             Philip Newton
174              
175             =item *
176              
177             Ricardo Signes
178              
179             =back
180              
181             =head1 COPYRIGHT AND LICENSE
182              
183             This software is Copyright (c) 1999 by Philip Newton.
184              
185             This is free software, licensed under:
186              
187             The MIT (X11) License
188              
189             =cut
190              
191             __END__