I came to the realization this morning that we have a bijillion pieces of code that look like:
int mondex = mon_at(tx, ty);
// If we shot us a monster...
if (mondex != -1 && ((!missed && i == trajectory.size() - 1) ||
one_in((5 - int(zombie(mondex).type->size))))) {
monster &z = zombie(mondex);
// Blablabla details
shoot_monster(this, p, z, dam, goodhit, weapon, effects);
} else if ((!missed || one_in(3)) &&
(npc_at(tx, ty) != -1 || (u.posx == tx && u.posy == ty))) {
// Blabla details
player *h;
if (u.posx == tx && u.posy == ty)
h = &u;
else
h = active_npc[npc_at(tx, ty)];
}
shoot_player(this, p, h, dam, goodhit);
}
}
That should look like:
creature *target = creature_at(tx, ty);
if( creature != NULL && /* Other generic tests for hit-ability */ ) {
// Blabla details
creature->shoot(/* args denoting severity and effects */);
}
So I’m definitely on the side of unifying a base class (My suggestion is creature, I don’t like using CS-ish terms, they tend to be very generic and easy to misinterpret) under pc, monster, and NPC.
The open question is what the player-monster-NPC heirarchy looks like, are they all siblings? are NPCs a subclass of monster that knows how to talk and use tools? Are player and NPC siblings under some other subclass that encapsulates tool use, hit location, etc?
Personally I’m for creature -> monster, creature -> person -> NPC, and creature -> person -> player.