# ---------------- path/to/lib/MyRPG.pm package MyRPG; our $VERSION = "0.01"; use MyRPG::Die; use MyRPG::NPC; # ---------------- path/to/lib/MyRPG/Die.pm package MyRPG::Die; use Moose; use Moose::Util::TypeConstraints; has "sides" => is => "ro", isa => enum([qw( 4 6 8 12 20 100 )]), required => 1, ; around BUILDARGS => sub { my $orig = shift; my $class = shift; if ( @_ == 1 && ! ref $_[0] ) { return $class->$orig(sides => $_[0]); } else { return $class->$orig(@_); } }; sub roll { int(rand(+shift->sides))+1; } __PACKAGE__->meta->make_immutable; 1; # ---------------- path/to/lib/MyRPG/NPC.pm package MyRPG::NPC; use Moose; has [qw( name type )] => is => "ro", isa => "Str", required => 1, ; has "hitdice" => is => "rw", isa => "ArrayRef[MyRPG::Die]", required => 1, auto_deref => 1, ; has "hitpoints" => is => "ro", isa => "Int", default => sub { my $hitpoints; $hitpoints += $_->roll for +shift->hitdice; return $hitpoints; }, lazy => 1, ; has "current_hitpoints" => is => "rw", isa => "Int", default => sub { +shift->hitpoints; }, lazy => 1, ; sub damage { # This would be trait/role/type/armor/alignment influenced! my $self = shift; my $attack = shift; # Should be an object, we'll just call it raw points. $self->current_hitpoints( $self->current_hitpoints - $attack ); } sub dump { my $self = shift; my $line = "-"x50; sprintf("%s\n%20s -> %s (%dhp)\n current hitpoints: %d (%s)\n%s\n", $line, $self->name, $self->type, $self->hitpoints, $self->current_hitpoints, $self->status, $line); } sub status { my $self = shift; $self->current_hitpoints <= 0 ? "dead" : ( $self->current_hitpoints < $self->hitpoints * .3 ) ? "not so hot..." : ( $self->current_hitpoints < $self->hitpoints * .8 ) ? "s'okay" : $self->current_hitpoints != $self->hitpoints ? "tip top" : "never better"; } __PACKAGE__->meta->make_immutable; 1; # ------------------- some test code in a regular executable use warnings; use strict; use MyRPG; my $six_sided = MyRPG::Die->new(6); print "Warming up the bones... test roll $_: ", $six_sided->roll, $/ for 1 .. 3; my $npc = MyRPG::NPC->new( name => "CmdrTaco", type => "SwampYankee", hitdice => [ ( $six_sided ) x 3 ] ); print $npc->dump; my $dodecahedron = MyRPG::Die->new(12); print "Take that, ", $npc->name, $/; $npc->damage( $dodecahedron->roll ); print $npc->dump;