5
$\begingroup$

Consider a weapon firing shots every $f^{-1}$ seconds (i.e. $f$ is the weapon's fire rate). Each shot deals $n$ damage to is target. Consider another weapon firing every $3f^{-1}$ second, but dealing $5n$ in damage. You want to determine which weapon has the greatest damage potential, assuming those weapons are equally easy to hit with.

Perhaps the most obvious approach is to divide the damage dealt by the time needed to deal it. Ignoring bullet travel speeds, that'll be $fn$ for the former gun and $\frac53fn$ for the latter. This suggests that the second gun, while perhaps harder to use or less forgiving for mistakes, should be preferred thanks to its superior damage output potential.

Things however become less clear when you throw a few variables in the mix:

  • You usually can only arm so many shots in your weapon at any one time (magazine size)
  • You can only reload a weapon so fast (reload time)
  • Some weapons take more time to reload the first piece of ammunition than the subsequent ones
  • You can only carry so many shots for one weapon before running out (ammo capacity)
  • Some weapons can do fancy things such as having a chance to set the target on fire
  • Some weapons have a (non-fixed) chance of dealing random critical hits that deal more damage than usual, some weapons have guaranteed ways to achieve that (headshots), some weapons or combinations thereof ("builds") have a mixture of both
  • Some weapons are more accurate than others (accuracy and recoil)
  • Some weapons may be more effective against certain enemies than others (damage type and resistances in Borderlands 2)

...et ceatera. I find that, rather than attempting to come up with an explicit DPS formula, it's both more simple and more flexible to simply simulate the gun's firing for a while and then divide the damage dealt by the simulation time. In pseudo code:

def dps(gun):
  gun.load()
  time = 0
  damage = 0
  while simulation is not over: #???
    damage += gun.fire()
    time += 1/gun.fire_rate
    if gun.magazine_empty():
      gun.reload()
      time += gun.reload_time
  return damage/time

My conundrum however is determining an appropriate condition to stop the simulation in order to avoid introducing distortions around the cutoff point.

Consider for example a simulation end condition such as "stop after 15 seconds because you probably aren't going to keep firing a gun to a target for longer than that." If a gun does a full empty-magazine-reload-magazine cycle in 3 or 5 seconds, that's probably okay. If a gun empties its magazine in 14 seconds and reloads in 2, the current pseudo code will also do the right thing and divide the damage output by 16 seconds. If, however, the cutoff point happens while the gun is unloading, that might introduce distortions that make the DPS number less useful in its ultimate purpose as a (partial) ordering criterion over the set of weapons.

What should then be my frame of reference?

  • One full fire-reload cycle? (Might save on computations.)
  • Firing the weapon until I run out of ammo? (Handles the situation where your ammo carried isn't a multiple of your magazine size, which is a problem against sufficiently healthy foes)
  • Firing the weapon until I hit a given amount of damage? (Think a situation where all your opponents can take the same amount of damage before they are disabled.)
  • Firing the weapon for a fixed amount of seconds anyway?
$\endgroup$
6
  • 5
    $\begingroup$ Just to make it completely clear, the context of this question is videogame weapons used against fictional opponents, player-controlled or not. $\endgroup$
    – badp
    Commented Feb 2, 2013 at 1:40
  • $\begingroup$ You can get a lot of different numbers; the question is which number is the most useful, and that depends on context. For example, your gun can do $100$ damage before needing to reload for an hour. Should you count the reload time? Depends on whether it takes $90$ damage or $110$ damage to defeat your opponent. $\endgroup$
    – user856
    Commented Feb 2, 2013 at 2:01
  • $\begingroup$ That however only really makes a difference if that 90 hitpoints opponent is the only person you face for the next hour. If he's not, which is exceedingly likely, then it's appropriate to count the reload time regardless. $\endgroup$
    – badp
    Commented Feb 2, 2013 at 2:13
  • $\begingroup$ Then replace "defeat your opponent" with "defeat all the opponents and clear the level". $\endgroup$
    – user856
    Commented Feb 2, 2013 at 2:17
  • $\begingroup$ Still no difference, given that a gun (normally) can only hit one opponent at a time. $\endgroup$
    – badp
    Commented Feb 2, 2013 at 2:29

3 Answers 3

3
$\begingroup$

One commonly useful method is to measure one cycle -- find two points in time where the conditions at the beginning time and the end time are the same. Then compute DPS as being the amount of damage done between those two points in time divided by the duration between those points in time.

e.g. if there is only "open fire" and "time to reload", you could take one cycle to consist of firing until the magazine is empty then reloading. So the starting point is when you start firing, and the ending point is when you begin firing again after reloading.

For probabilistic things (e.g. a weapon has a 10% chance to do a 'critical hit' of double damage), you can replace the actual damage done with the average damage done. If you have a weapon that does 10 damage 90% of the time and 20 damage 10% of the time, just assume it does 11 (i.e. $10 \cdot 0.9 + 20 \cdot 0.1$) damage all of the time.


Do keep in mind downtime needs to be accounted for. If you need to do 100 damage to kill an enemy then have a lull before you move on to the next enemy, then of the two weapons:

  • One clip does 100 damage in 1 second, but has a 3 second reload time (50 DPS)
  • One clip does 200 damage over 3 seconds, but has a 1 second reload time (100 DPS)

then the first weapon may easily turn out to be superior, because it does 100 DPS in the time frame that actually matters, whereas the second weapon only does 66 DPS.

Accounting for this can be trickier, but unfortunately it is usually very relevant in the problems where DPS is an important statistic.


Another important factor is overkill. If you are attacking units with 35 HP, then a weapon that fires one shot every second that does 6 damage is better than a weapon that fires one shot every 8 seconds that does 75 damage.

$\endgroup$
1
$\begingroup$

In the end, any single number will be somewhat misrepresentative, but we can use some basic principles of theorycraft to identify good quantities.

Damage per execution time is one such concept, corresponding to, in this case, damage per shot over time per shot. You can then use this number to estimate real DPS with some guess about how often one must reload.

As far as simulations go, you should try to account for variations in the targets' health--do all targets have the same amount? Do they follow some distribution that you can use instead? Is it realistic for all bullets to do the same damage or to follow some more complicated distribution instead?

Distributions make averaging over many trials make sense, without the artifacts of picking one arbitrary value.

$\endgroup$
1
$\begingroup$

For a very long battle, you should count one time through the magazine and one unload time. This will be the average damage per second for many trips through the magazine. If you have some sort of critical hit, that scales up the damage. Say your gun does 10 per shot, but one time in 5 does 50. Then your average is $10*0.8+50*0.2=18$ per shot. Again, this is a long term average.

This gets perturbed by many factors. If you kill the opponent (and there aren't more until you have reloaded) in the first magazine, you should just count firing time and ignore reload-the reload is free. In fact, maybe the first shot takes zero time. If that one shot is enough to kill, you are safe. Maybe you have a second gun, already loaded, that you can switch to. If it has slightly lower damage per second, but avoids the reload, that can be a winner.

When whole number granularity enters these problems, the tradeoffs can be difficult. The damage per second calculations avoids that, but gets the wrong answer when the granularity matters.

It can probably be proved that this problem is NP-hard, as it looks like a variant on bin packing. In that case, you won't find an easy, optimal solution. But heuristics come pretty close.

$\endgroup$

You must log in to answer this question.

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