Thoughts on Combat Models

From RogueBasin
Revision as of 03:41, 14 February 2009 by Nate879 (talk | contribs) (fix category)
Jump to navigation Jump to search

As stated on other pages, combat is an integral part of most Roguelikes (and in fact, most RPGs). Here are some thoughts on possible models for combat. (This may need some cleaning up by someone that's better at it than me.)

In general

All combat systems boil down to just two basic questions:

  • What chance do I have to hit the enemy?
  • How much damage do I do?

Many systems will also deal with a third, less basic, question:

  • What else happens to the enemy?

In specific

For the purposes of discussion, let's assume that the entire combat system consists of three numbers: ATK, DEF and HP. Each combatant has different values for each of these. With such simplicity, you might think that there aren't many different ways the above questions (ignoring the third for now) can be answered. Below is a (non-exhaustive) list of possibilities. In all of the examples, rnd() returns a random number between 0 and 1. (For example, rnd()+rnd() would be a number between 0 and 2, which is most likely near 1; while 2*rnd() would re a number evenly distributed between 0 and 2.) I'll use C-style syntax to represent the examples.

Feel free to expand this list and discuss the pros and cons for each (which can be listed below). Some of the ideas came from this discussion.

Possibility #1

Enemy.HP -= min(Player.ATK - Enemy.DEF, 0);

or

Enemy.HP -= min(rnd()*(Player.ATK - Enemy.DEF), 0);

or

Enemy.HP -= min(rnd()*Player.ATK - rnd()*Enemy.DEF, 0);

Possibility #2

Enemy.HP -= rnd()*Player.ATK > Enemy.DEF;

or

Enemy.HP -= rnd()*Player.ATK > rnd()*Enemy.DEF;

Possibility #3

Enemy.HP -= rnd() < Player.ATK / (Player.ATK + Enemy.DEF);

or (equivalently)

Enemy.HP -= rnd() > Enemy.DEF / (Player.ATK + Enemy.DEF);

Possibility #4

while(rnd() < Player.ATK / (Player.ATK + Enemy.DEF))
  Enemy.HP--;

Possibility #5

if(rnd()*Player.ATK - rnd()*Player.DEF > Enemy.HP)
  Enemy.HP = 0;

Possibility #6

Enemy.HP -= (ATK/DEF)*((3 + rnd())/(3 + rnd());

Possibility #7

if(rnd() < Player.ATK / (Player.ATK + Enemy.DEF))
  Enemy.HP -= Player.ATK;

Question 3

The question of secondary effects can be dealt with is several ways as well.

  • Each attack could be limited to one effect or could have the possibility of multiple effects
  • Resistance can be handled in several ways
  • The list of effects itself can be big or small

Other thoughts

By limiting the system to just three variables (plus some random numbers) it makes things very simple, both to design and to balance. Such simplicity doesn't have to be a major limitation though. For example, imagine you used the list of D&D attributes (STR, DEX, CON, INT, WIS, CHA). You can reduce these to ATK, DEF and HP and with more variables, you can mix it up a little more. A fighter-type with a light melee weapon might use something like HP = CON + DEX/2; ATK = STR + DEX/2 + WIS/2; DEF = DEX + CON/2 + WIS/2;. Other classes and types of equipment would use different equations.

Still, three basic variables can be limiting. By adding just one more, say ACC or DEX, you can make the hit chance more meaningful and the equipment more balanced. With only three variables, weapons would simply increase ATK and armor would increase DEF. With something like DEX, heavier weapons and armor could decrease DEX in addition to increasing ATK and DEF, which would make the player decide between hit chance/dodge rate and damage/defence.

Also, by starting simple and adding complexity slowly, it can (sometimes) be easier to balance the system (assuming that adding complexity doesn't break the system).