I'm trying to figure out a good formula for determining a hit when the player attacks an enemy in a Roguelike. I'd like to come up with something simplistic but, still true to the way it's done in D&D or popular Roguelikes like AngBand or NetHack.

What I have so far is adding the differences between player and enemy attributes, along with a random integer:

if ((player.dex - enemy.dex) + (player.speed - enemy.speed) +
    (player.luck - enemy.luck) + random_integer_below_6()) >= 10) {

This makes for unnatural gameplay: the player never misses weak enemies and vice versa for strong ones. Does anyone know of a guide to attribute based combat used in turn based games etc? Should I (and can I) copy the D&D rules verbatim?


4 Answers 4


I'd figure out what you want the "guaranteed hit" and "guaranteed miss" chances to be (i.e. the chances for a kitten to hit a dragon and a dragon to miss a kitten). Store your random result, and before applying power differences, mark a hit if it's within those bounds. That will prevent the 100% hit/miss chance problem... although there's another option for always providing a chance of a hit, detailed below.

D&D is a "flat" system, where probability is evenly distributed across the possible roll results. Other systems use a more curved distribution, usually achieved by rolling multiple dice and adding them. It's easy enough to create a curve like this (rand() + rand())/2 comes to mind).

Another possibility is "exploding dice." In systems like Shadowrun and Savage Worlds, rolling the maximum possible die result lets you reroll that die and add the new result. In your game, you'd test to see if your random result was above a certain threshold, and if so, roll again. If you let dice explode indefinitely, then even the lowliest goblin has a chance to hit a god, and you don't need an explicit "guaranteed hit" mechanic.

So one possible approach with a curved roll, guaranteed chance of missing, and exploding dice would be something like:

function getRoll():Number
  var result:Number = (rand() + rand()) * 3; //Curved result from 0 to 6
  if(result > 5.75) result += getRoll(); //Explode over a certain threshold, recursively
  return result;

function attackHits():Boolean
  var roll:Number = getRoll();
  if(roll < 0.25) return false; //Guaranteed chance of miss
  else return ((player.dex - enemy.dex) + (player.speed - enemy.speed) +
    (player.luck - enemy.luck) + roll) >= 10; //Your original test.

Of course, that's untested and unbalanced; you'd want to adjust all those magic numbers until they felt right.

As for copying rules verbatim, there are legal and ethical issues with that. You're fine pulling inspiration from D&D and other tabletop games, though; that's how they all got designed in the first place. You don't need to show the player exactly how the rules work, either, and you may find that using a smooth floating point dice curve leads to a better feel than restricting yourself to the integer constraints of physical dice.

  • 3
    \$\begingroup\$ what language is that, with the funny type decls? Or is it just pseudocode? \$\endgroup\$
    – tenpn
    Commented Aug 11, 2010 at 7:41
  • 2
    \$\begingroup\$ I think it may be Actionscript or Javascript, but don't hold me to that. \$\endgroup\$ Commented Aug 11, 2010 at 9:44
  • \$\begingroup\$ It's Actionscript 3. I'm a Flash developer. \$\endgroup\$ Commented Aug 12, 2010 at 13:29

I'm assuming this is a game balance question and not a coding question, and there are a lot of ways to handle this. From your existing algorithm, I suspect you are making it more complicated than it has to be (three attributes AND a random number make for an extremely muddy system from the player's perspective). My first instinct is to simplify!

Favor attributes that do multiple things, rather than results that are determined by multiple attributes. DEX works just fine as the primary determiner of to-hit chance; the addition of everything else just serves to make it harder to balance. Think of it this way: a player's expected damage on each hit is their to-hit % multiplied by their average damage when they do hit. How do you plan to calculate an "expected" or "typical" to-hit % with so many variables?

I see another issue, which is that your formula doesn't scale, and this is probably what you're experiencing. Assuming DEX, LUCK and SPEED tend to increase over the course of the game, differences between player and monster in those stats will also tend to increase. Just as an example, if a player's early-game DEX is in the 4 to 6 range and so are monsters, that's a 10-20% to-hit modifier. If the range is more like 10 to 20 in later stages of the game, that's up to a 100% modifier.

One way to fix that is to keep the stats fixed. Player and monster ranges are the same throughout the game, and getting something like +1 DEX is a huge deal, extremely rare, and treated as such (if it exists at all). Then your formula will work fine for the entire game, and you'll see a player with about the same to-hit chance throughout.

Another way is to change that hardcoded "10" to scale with level, so maybe it's "10 + monster level" or "10 + dungeon level" or something, which causes a slight increase in difficulty as the game progresses unless the player levels up their stats accordingly.

A third way, as others have said, is to set hard caps on the highest and lowest acceptable to-hit %, and simply say "if the calculated value is less than X, use X instead".

For the sake of completeness, I'll point out that there's no absolute law that you MUST include a to-hit roll in the first place. Taking an action in a game that's ineffective is not particularly fun, and doesn't really add to the experience except in rare cases. An alternative is to let players ALWAYS hit, and just mess with the damage range so that sometimes they'll do a lot less damage than others. Remember that complex systems are more fun for the designer than the player.

  • \$\begingroup\$ This is a great answer. \$\endgroup\$
    – seanicus
    Commented Apr 19, 2013 at 1:33

You might want to add critical hits (usually can't miss, bonus damage) and critical misses (flat chance to miss no matter what, possibly dazes the player).


A lot of games use a five percent change of a hit regardless of all factors in addition to the normal hit formula.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .