package Enemy {
use Moo::Role;
has wounds => (is => 'ro');
...;
}
# Look how tiny these classes are.
# Creating lots of classes doesn't have to be painful.
package Rat { use Moo; with 'Enemy' }
package Cat { use Moo; with 'Enemy' }
####
use Moops;
role Enemy {
has wounds => (is => 'ro', isa => Int);
}
class Rat with Enemy;
class Cat with Enemy;
####
use Moops;
class Attack {
has name => (is => 'ro', isa => Str);
has damage => (is => 'ro', isa => Int);
method light ($class: ) {
state $me = $class->new( name => 'light attack', damage => 1 );
return $me;
}
method heavy ($class: ) {
state $me = $class->new( name => 'heavy attack', damage => 3 );
return $me;
}
}
role Enemy {
requires "get_attack";
has wounds => (is => 'ro');
method is_weak () { $self->wounds > 5 }
}
class Rat with Enemy {
method get_attack (Object $target) {
return Attack->light;
}
}
class Cat with Enemy {
has lives => (is => 'rw', isa => Int, default => 9);
method get_attack (Object $target) {
return Attack->heavy;
}
around is_weak () {
return false if $self->lives > 2;
return $self->$next(@_);
}
}
class Monkey with Enemy {
method get_attack (Object $target) {
$target->is_weak || $self->is_weak ? Attack->light : Attack->heavy;
}
}
class Ninja with Enemy {
method get_attack (Object $target) {
return Attack->new(name => 'ninja attack', damage => int rand(5));
}
}
class Priest with Enemy {
method get_attack (Object $target) {
$target->is_sinful ? Attack->heavy : Attack->light;
}
}