Dependency Injection

So, is anyone here familiar with dependency injection? I have a technical issue I’m trying to solve in my game of which DI seems to be the only clean way to deal with it. Basically I’m trying to make the attacker/victim logic completely self-contained so that I don’t have to duplicate logic to each and every attackable thing in the game. The problem is there’s three branches I’m current working with class-wise:

IActor -> Player
IActor -> NPC -> OldMan
IEnemy -> Crab
IEnemy -> EvilGirl

Player is going to have ‘attacking’ abilities, but oldman is not. But i also want to share the same logic with IEnemy as well… So the ONLY thing I can think is to create an IAttackableActor interface which defines what I need to do my processing (getters/setters for certain things like health and defense, death, etc), then implement that interface on Player, Crab, and EvilGirl. That allow me to do this:

public class AttackLogic {
    public static void Attack(final IAttackableActor attacker, final IAttackableActor victim) {

        // Do not process attacks on a victim that is currently being staggered
        if (victim.getStaggered()) {
            return;
        }

        // Determine the damage that will be dealt
        final int damageToDeal =
                Math.min(
                    // This is a bit anal, but make sure damage is never greater than total health.
                    victim.getHealth(),
                    // At least 1 damage must take place
                    Math.max(1, attacker.getAttackStrength() - victim.getAttackDefense())
                );

        // Apply damage to the victim
        victim.setHealth(victim.getHealth() - damageToDeal);

        if (victim.getHealth() > 0) {
            victim.setStaggered(true);
            return;
        }

        victim.onKilledBy(attacker);
        attacker.onVictimKilled(victim);
    }
}

Any thoughts on this, or if someone has a better idea on how to cleanly implement this?

DI is all about runtime selection of implementations, but the type system has to be set up beforehand so you could do it all without DI if you need to (and when unit testing that’s usually what you do). Statically trying to enforce a particular character’s behavior (OldMan’s pacifism) through the type system is really just not feasible. The typical answer for most RPGs would be that you just allow OldMan to inherit an attack capability through IActor that does no damage, and then just never use it.

PS: Not a fan of that “I” prefix for interfaces BTW, but hey it’s your thing

[quote=“sproingie,post:2,topic:40600”]
I did it here just to imply that I’m passing in an interface - I don’t use them either. I hate decorations on types.

I’ve spent the last hour removing all attack logic from player and enemy (VERY different types of entities) and trying to stuff it into an interface/processor type setup (i guess that’s the right word). There’s a little bit of overhead of course, but the main goal is separation of intent. Most of the game is already logically separated into interlocking and stackable parts. I initially thought about making Actor and Enemy subclass from something else, but the problem is that down the road, there will be more ‘services’ applied to the characters in the game (smart movement, npc to npc interaction, etc). It’s a mixed bag which actors/enemies implement which services, so the fixed hierarchy didn’t seem to fit. The only annoying thing is that since it seems I need to do attacking this way, I’m going to have to roll back some of my other logic to use the same methodology – I don’t want to have two design patterns in the same class, that’d be very annoying. sighs

I suppose you could take the capabilities approach and delegate actions to Action objects, with each entity maintaining a set of actions it can take. A NPC that will never attack could simply lack an AttackAction altogether then.

If you’re still keen on using DI, and combat is central to your game, you could have an attackAction field rather than one big collection of actions, and use DI to inject appropriate instances of AttackAction. But much as I like DI myself, I don’t think it would be very satisfying for defining available actions in general.