in reply to Game related OO design question

Yeah, I concur with McA. Create a new class for each type of enemy.

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' }

Also, please don't use Moos for anything serious. I'm an officially listed as a co-author of it, so I'm entitled to say that. ;-)

Use Moo, or Moose, or Moops. Here's my above example using Moops, showing how it eliminates a lot of boiler-plate code.

use Moops; role Enemy { has wounds => (is => 'ro', isa => Int); } class Rat with Enemy; class Cat with Enemy;

Let's extend that a little with some attack types:

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; } }

That kind of thing.

Replies are listed 'Best First'.
Re^2: Game related OO design question
by blindluke (Hermit) on Nov 28, 2014 at 10:38 UTC

    This is excellent advice. And exactly what I was looking for - especially the design of the Attack class (and the idea to make it its own class, which eluded me completely). Thank you.

    Moops looks excellent indeed, and you are right that when syntactic sugar makes subclassing so cheap, it's no point not to use it. Still, if I could ask you one more question, I'm very curious about those words:

    Also, please don't use Moos for anything serious. I'm an officially listed as a co-author of it, so I'm entitled to say that. ;-)

    Could you elaborate on that a bit? What's wrong with Moos?

    Thanks again. And good luck with your book, I'm sure I'm not alone in waiting eagerly for its completion.

    - Luke

      I don't know of anything specifically wrong with Moos, but Moose and Moo are hundreds of times better tested. Moos is slightly lighter weight than Moo, but it barely seems worth worrying about Moo's fairly small dependency chain.

      If you do feel the need for something smaller than Moo, then Class::Tiny is probably the best solution.