Hi, writing OO code by hand is a pain the arse and consumes valuable time that should be spent developing your game scenarios :-) Use a Modern Perl OO framework instead. Working "without CPAN" is for masochists.
Here is a small demonstration using Moo based on what I could glean from your OP. I hope it's useful.
use 5.026; use warnings; use Data::Dumper;
{
package Entity;
use Moo;
use Types::Standard qw/ InstanceOf Int /;
has race => ( is => 'ro', isa => InstanceOf['Race'], require
+d => 1 );
has class => ( is => 'ro', isa => InstanceOf['Class'], require
+d => 1 );
has game_rank => ( is => 'rw', isa => Int, default => sub{ 0 } );
sub increase_rank { $_[0]->game_rank( $_[0]->game_rank + $_[1] ) }
sub decrease_rank { $_[0]->game_rank( $_[0]->game_rank - $_[1] ) }
1;
}
{
package Race;
use Moo;
use Types::Standard qw/ Str /;
has name => ( is => 'ro', isa => Str, required => 1 );
has realm => ( is => 'ro', isa => Str, default => sub {'Middle Ear
+th'} );
1;
}
{
package Class;
use Moo;
use Types::Standard qw/ Str /;
has name => ( is => 'ro', isa => Str, required => 1 );
has is_noble => ( is => 'lazy', builder => sub { $_[0]->name eq 'h
+igh' } );
1;
}
{
package Elf;
use Moo::Role;
use Types::Standard qw/ Enum Str /;
has name => ( is => 'ro', isa => Str, required => 1 );
has sex => ( is => 'ro', isa => Enum[qw/ m f /], required => 1 );
1;
}
{
package Ranger;
use Moo::Role;
use Types::Standard qw/ Str /;
has ranger_rank => ( is => 'ro', isa => Str, default => sub { 'Pri
+vate' } );
1;
}
{
package RangerElf;
use Moo;
use Types::Standard qw/ Str /;
extends 'Entity';
with 'Elf', 'Ranger';
around BUILDARGS => sub {
my ( $orig, $class, %args ) = @_;
$args{'class'} = Class->new( name => $args{'class'} );
$args{'race'} = Race->new( name => 'Elf', realm => 'Gondor' )
+;
return $class->$orig( %args );
};
has sword_name => ( is => 'rw', isa => Str );
1;
}
#####################################################
my $ranger = RangerElf->new(
name => 'Fingolfin',
sex => 'm',
class => 'high',
ranger_rank => 'Captain',
);
say sprintf '%s\'s game ranking is now: %s',
$ranger->name,
$ranger->game_rank;
if ( $ranger->race->name eq 'Elf' ) {
say sprintf 'As an Elf, %s gets a special sword.', $ranger->name;
$ranger->sword_name('Ringil');
}
if ( $ranger->class->name eq 'high' and $ranger->sword_name ) {
say sprintf '%s\'s game ranking is now: %s',
$ranger->name,
$ranger->increase_rank(10);
}
say sprintf '%s %s a member of the nobility.',
$ranger->name,
$ranger->class->is_noble ? 'is' : 'is not';
say '-' x 32;
say 'Obj dump: ' . Dumper $ranger;
__END__
Outputs:
$ perl 1203175.pl
Fingolfin's game ranking is now: 0
As an Elf, Fingolfin gets a special sword.
Fingolfin's game ranking is now: 10
Fingolfin is a member of the nobility.
--------------------------------
Obj dump: $VAR1 = bless( {
'class' => bless( {
'is_noble' => 1,
'name' => 'high'
}, 'Class' ),
'game_rank' => 10,
'name' => 'Fingolfin',
'race' => bless( {
'name' => 'Elf',
'realm' => 'Gondor'
}, 'Race' ),
'ranger_rank' => 'Captain',
'sex' => 'm',
'sword_name' => 'Ringil'
}, 'RangerElf' );
The way forward always starts with a minimal test.
|