Category: | Fun Stuff |
Author/Contact Info | hakim@earthling.net |
Description: | OK I discovered Dice::Dice and RPG::Dice here on Perlmonks but this wheel was such fun to reinvent... this code is more like RPG::Dice, but written in a different way, so I thought it might be worth posting. update: I quited liked the way I was handling tt clauses, but it was unnecessary. Combined parsing of template into one regex substitution and put the logic into the _roll sub. |
package Dice::Simple; =head1 NAME Dice::Simple - a simple module to throw dice =head1 SYNOPSIS use Dice::Simple qw(roll); my $total=roll '3d6'; # simple die roll print "You threw $total\n"; my @roll=roll '(2d4+d6)/2+20'; # more complicated dice expressio +n my ($total, $template, @dice)=@roll; =head1 DESCRIPTION There are a number of Dice throwing modules (L<Dice::Dice>, L<RPG::Dic +e>). Dice::Dice has an OO interface and allows some interesting possibiliti +es but I didn't feel I needed its complexity. This module, Dice::Simple does +n't really do anything that RPG::Dice does apart from more flexible dice t +emplates. However, if you are going to use the function a lot C<roll> is a lot q +uicker to type than C<computeDice> ;-> This was a surprisingly fun wheel to reinvent. =cut use strict; use warnings; BEGIN { use Exporter; our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); $VERSION = 0.02; @ISA = qw(Exporter); @EXPORT = qw(); %EXPORT_TAGS = (); @EXPORT_OK = qw(roll); } =head1 FUNCTIONS No functions are exported by default. The only function that can be i +mported is C<roll>. To do this insert C<use Dice::Simple qw(roll)> at the beginn +ing of your script. If you don't want to import the function you can still call it using C<Dice::Simple::roll()>. =over 4 =item C<roll> Roll takes a dice template corresponding to the standard Role Playing +Game dice conventions d4 4-sided dice d6 6-sided dice d100 100-sided dice Each dice may be optionally prefaced by a number indicating how many t +imes to roll the dice. 3d6 Roll 3 six-sided dice, (total between 3 and 18) And may have a simple arithmetic modifier 2d4+2 Roll 2 four-sided dice, and add 2 to the total Other arithmetic can be performed using the symbols + - * / ( ) for example: (3d6+2d4)/2 And we can optionally choose only the best dice using the notation C<t +t> tt3 6d6 Roll 6 six-sided dice and keep the best 3 I<NB:> we are not bound by those troublesome laws of reality we can cr +eate C<d5>, C<d7> etc. If called in a scalar context, C<roll> returns the total of the expres +sion requested. my $total=roll '2d4+4'; If called in a list context, C<roll> returns =over 4 =item 1 the sum =item 2 the template (e.g. the first value passed to C<roll>) =item 3 the results of each die, in order they were thrown (e.g. as specified +by the template). =back For example, C<2d4 + d6 + 3> might return (13, "2d4 + d6 + 3", 3, 2, 5) Total: 13 Template: "2d4 + d6 + 3" Dice: 3, 2, 5 Note that the dice rolls do not retain any memory of which dice rolled + them. =for undocumented I<NB:> C<roll> may optionally be passed a list of dice rolls which wil +l be used B<in stead> of a randomly rolled integer. No error checking is curren +tly done to check that the value passed could have rolled by the dice spec +ified. This is not necessarily useful just yet..., however it means that the +result of a C<roll> call in list context can be passed back to C<roll> just by s +hifting off the result. =back =cut use vars qw(@DICE); sub roll { my $template=shift || $_; @DICE=@_; my @scores; (my $dice=$template)=~ s{(?:tt(\d+)\s+)?(\d+)?d(\d+)} # e.g. tt{n}? d4, 3d6, 2d8 {my($tot,@sc) # get total & dice for that role =_roll($2||1,$3,$1); push@scores,@sc; # add to overall dice. $tot # replace #d# expression with tot +al }egx; # eg modifiers: apply this functi +on to # each occurrence of the #d# pa +ttern if ($dice=~/^[0-9+*()\/ -]*$/) { # eval should be safe because onl +y my $eval=eval($dice); # accept specified characters return wantarray ? ($eval, $template, @scores) : $eval } undef; # return undef on failure } sub _roll { my ($count, $die, $topn)=@_; my $total=0; my @scores=map {shift @DICE || int(rand $die)+1} 1..$count; if ($topn) { # restrict to best dice only @scores=(sort {$b<=>$a} @scores)[0..$topn-1] # In v0.01 I made sure that the dice were returned # in the order thrown. Don't think this is needed # so just returning sorted values. } $total+=$_ for @scores; return $total, @scores; } =head1 AUTHOR, BUGS, LICENSE Version: 0.02 7th Dec 2001 Untested. No warranty implied. May be distributed under the same terms as Perl itself. (c) hakim@earthling.net http://www.perlmonks.org /msg osfameron =cut int(rand 6)+1; |
|
---|
Replies are listed 'Best First'. | |
---|---|
Dice::Simpler with Filter::Simple (Re: Reinventing Dice...)
by osfameron (Hermit) on Dec 08, 2001 at 23:58 UTC | |
by TheDamian (Vicar) on Dec 09, 2001 at 04:09 UTC | |
Submit to CPAN? Re: Reinventing Dice...
by osfameron (Hermit) on Dec 08, 2001 at 15:54 UTC | |
by Ovid (Cardinal) on Dec 09, 2001 at 02:19 UTC |
Back to
Code Catacombs