About the Author
Mass Effect
Final Fantasy X
Batman:Arkham City
Borderlands Series
Weekly Column
Champions Online
World of Warcraft
DM of the Rings
Good Robot
Project Frontier
Forums
"Music"



Borderlands Badass Ranks

By Shamus
on Tuesday Oct 28, 2014
Filed under:
Programming

 
 

The Borderlands games have this thing called “Badass ranks”. It’s this sort of meta-leveling system that’s not tied to any specific character, but is instead based on some global stateActually, in the first one it works a little different, but whatever. For now let’s focus on the Borderlands 2 and Pre-Sequel.. You complete goals, the goals give you badass points, the points fill a leveling bar, and when it fills up you get a single badass token. These tokens can be spent on really, really small upgrades like “Plus a tenth of a percent more damage with guns”. But these upgrades apply to all your characters, now and in the future.

The goals are typical achievement-bait type stuff: Kill X people with fire damage. Open X loot chests. Loot X items of a given rarity. Sell X items. Kill X of creature Y with melee attacks. Get X headshots. Do X sidequests. Deal X points of damage with weapon Y. And so on.

This is Athena from Pre-Sequel. (Best character.) The bonus stats you see on the left apply to all the characters I create. The game lets you disable these if you want, presumably to allow serious players to set up “fair” duels.
This is Athena from Pre-Sequel. (Best character.) The bonus stats you see on the left apply to all the characters I create. The game lets you disable these if you want, presumably to allow serious players to set up “fair” duels.

There are numerous goals, to the point where you’ll be hitting new ones every couple of minutes. If you’re looking to maximize the number of badass tokens you earn, then it’s best to avoid getting stuck in a rut with one favorite character, weapon, and playstyle. Use all the weapons, fight all the foes, use vehicles, use melee, and generally mix things up.

There’s no limit on how many badass tokens you can earn, although they do become harder (slower) to earn over time. This means that your first character will always be your weakest. If you go through the game with multiple characters and earn tons of tokens, then later on your characters will have all these bonuses that weren’t available to you the first time you fired up the game.

The bonuses are small, but they stack and they impact nearly every aspect of your character. An extra one percent gun damage is nothing. But what if you’re shooting one percent faster, hitting one percent more accurately, getting one percent more criticals, have one percent more health, AND doing one percent more damage? That’s probably still a minor advantage, but I’m betting that by the time you’ve got a 5% to all your stats you’re a lot more than just “5% stronger”.

Maya from Borderlands 2. Here you can see I get to choose from five possible bonuses: Elemental Effect CHANCE, Melee Damage, Critical Hit Damage, Elemental Effect Damage, and Gun Accuracy. (These probably yield a tenth of a percent bonus.) Below that you can see the sum of all the bonuses I’ve unlocked so far.
Maya from Borderlands 2. Here you can see I get to choose from five possible bonuses: Elemental Effect CHANCE, Melee Damage, Critical Hit Damage, Elemental Effect Damage, and Gun Accuracy. (These probably yield a tenth of a percent bonus.) Below that you can see the sum of all the bonuses I’ve unlocked so far.

It’s also worth noting that you can’t directly control what stats get boosted. When you go to spend a token on upgrades, you have to choose ONE of five options out of the dozens of possible stats. So if you start pouring everything into (say) shields, the game will stop offering shields as one of the possible upgrades until you put some points in elsewhere. It’s basically a system designed to blunt attempts at min-maxing.

In any case, the upgrades make you stronger. But… how much stronger? That’s a really complex question. Short of looking at the Borderlands game code there’s no way to be sure. But I decided to write a little program to simulate combat to see how much of a benefit “5% to everything” might be.

This all happens in a terminal window, no graphics. (Sorry.) We’re simulating two evenly-matched combatants. The two characters shoot at each other. The moment one drops dead, the victim instantly respawns with full health and a reloaded weapon. We keep track of kills and the simulation ends after 1,000 deaths.

(Upon reflection, it might have been better to have two theoretical players gun down NPC mooks over a fixed period of time, and score them based on who slaughtered the most mooks.)

Axton kinda ruined the game for me. His special power was a turret with massive hitpoints and good damage output that instantly grabbed all aggro. It was basically a “get out of dying, free” button. It felt far more powerful than the other special abilities, but was also kinda boring to use.
Axton kinda ruined the game for me. His special power was a turret with massive hitpoints and good damage output that instantly grabbed all aggro. It was basically a “get out of dying, free” button. It felt far more powerful than the other special abilities, but was also kinda boring to use.

As all projects, this one get quickly mired in vexing questions that weren’t obvious at first:

  1. What kind of weapons are we simulating? In a Borderlands shotgun fight, the guns do MASSIVE (possibly insta-kill) damage but take ages to reload. If we’re using an SMG, then the bullets do tiny damage. With one weapon the bonus damage is meaningless (since every hit is a kill) while the other weapon magnifies the importance of bonus damage.
  2. In Borderlands, weapons have this accuracy stat that controls how wide their cone of possible bullet trajectories is. This is supremely important in a sniper rifle battle at long distances, and completely worthless if we’re using rockets at point-blank range.
  3. If fights are high damage then bonuses to reload speeds and magazine sizes are useless, since combatants will drop dead long before they empty their weapon.
  4. How does a bonus to “refire rate” work? If a weapon had 100% bonus to fire rate, would that make it shoot twice as fast, or would that reduce the cooldown to zero, effectively making a weapon that should fire “infinitely” fast? I’ll assume the former, since the latter just makes no sense. However, there’s no telling what’s going on under the hood in Borderlands. The tooltips were designed for brevity and simplicity, not precision. They exist so you can eyeball the difference between two items at a glance.

Basically, this test is meaningless because I can coerce any result I want. I can set up a fight where 5% bonus can change the entire outcome or I can set up a fight where the 5% bonus does almost nothing.

I try to split the difference and make sure all stats are useful. We’ll assume a fight at medium distance with a low damage weapon with a moderate rate of fire.

Gaige from Borderlands 2. You can see I’ll earn a Badass rank for killing ten midgets. The next tier will probably unlock at something like 100 midgets, then 1000, etc.
Gaige from Borderlands 2. You can see I’ll earn a Badass rank for killing ten midgets. The next tier will probably unlock at something like 100 midgets, then 1000, etc.

I’ve got two combatants, which for the purposes of this exercise I’ve named “Player” and “Mook”. With no bonus, they each have 100 hitpoints, have a 25% chance to hit, their guns fire every 100 time-unitsGeneric time units. Not mapped to real-world time in any meaningful way. I don’t want to actually sit here and wait ten minutes for the contest to play out. and deal 15 damage. Their default guns hold 20 bullets and take 500 time units to reloadEffectively making you miss out on five shots every time you reload..

This isn’t simulating a player duel, because those things happen one at a time and not back-to-back. And we’re not simulating a fight between players and foes, because those aren’t evenly matched. Instead we’re trying to measure the strength of a boosted player against the strength of an un-boosted player. We’re not going to mess around with stuff like shields, melee attacks, grenades, and elemental damage. So don’t think of this as “simulated Borderlands”. It’s more an abstract test to see how powerful it is to have a small percent boost across all stats in a game like Borderlands.

The result? Really unsatisfying.

With no bonus, the match comes out perfectly evenly, with each combatant getting 500 kills.

If I give Player a 1% bonus, then Player scores 522 kills versus the 478 kills of Mook.

With a 3% bonus, then the match comes out 553 to 447.

With a 5% bonus, then the match comes out 584 to 416.

Actually, let’s just put it on a chart:

Bo-ring. :(

I was expecting some kind of curve. Like, maybe early upgrades were useless but then scores would ramp up? Or maybe you’d get a lot of benefit from early bonuses, but their benefit would taper off? But no. We get a linear, shallow progression. At 0% bonus the two are evenly matched, and at a 10% bonus Player gets two-thirds of the kills.

It should be noted that an across-the-board ten percent bonus is pretty hard to achieve. I’ve put about 300 hours into Borderlands 2, and I have 10% bonus in just a couple of stats.

So that’s the experiment. This isn’t remotely definitive, but my guess is that a better test would still result in a similar outcome and a similar chart. My gut tells me that the slope might change slightly, but we wouldn’t see any sort of curve emerge.

But in case you want to have a go at it yourself, here’s the source. It’s only 200 lines of C++ code, and a quarter of that is the silly random number generator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#include <memory.h>
#include <stdio.h>
 
/*-----------------------------------------------------------------------------
The Mersenne Twister by Matsumoto and Nishimura. Our random number generator.
-----------------------------------------------------------------------------*/
 
#define LOWER_MASK            0x7fffffff 
#define M                     397
#define MATRIX_A              0x9908b0df 
#define N                     624
#define TEMPERING_MASK_B      0x9d2c5680
#define TEMPERING_MASK_C      0xefc60000
#define TEMPERING_SHIFT_L(y)  (y >> 18)
#define TEMPERING_SHIFT_S(y)  (y << 7)
#define TEMPERING_SHIFT_T(y)  (y << 15)
#define TEMPERING_SHIFT_U(y)  (y >> 11)
#define UPPER_MASK            0x80000000 
 
static int              k = 1;
static unsigned long    mag01[2] = {0x0, MATRIX_A};
static unsigned long    ptgfsr[N];
 
void RandomInit (unsigned long seed)
{
  mag01[0] = 0;
  mag01[1] = MATRIX_A;
  ptgfsr[0] = seed;
  for (k = 1; k < N; k++)
    ptgfsr[k] = 69069 * ptgfsr[k - 1];
  k = 1;
}
 
unsigned long RandomVal (void)
{
 
  int		            kk;
  unsigned long	    y; 
 
  if (k == N) {
    for (kk = 0; kk < N - M; kk++) {
      y = (ptgfsr[kk] & UPPER_MASK) | (ptgfsr[kk + 1] & LOWER_MASK);
      ptgfsr[kk] = ptgfsr[kk + M] ^ (y >> 1) ^ mag01[y & 0x1];
      }
    for (; kk < N - 1; kk++) {
      y = (ptgfsr[kk] & UPPER_MASK) | (ptgfsr[kk + 1] & LOWER_MASK);
      ptgfsr[kk] = ptgfsr[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1];
      }
    y = (ptgfsr[N - 1] & UPPER_MASK) | (ptgfsr[0] & LOWER_MASK);
    ptgfsr[N - 1] = ptgfsr[M - 1] ^ (y >> 1) ^ mag01[y & 0x1];
    k = 0;
  }
  y = ptgfsr[k++];
  y ^= TEMPERING_SHIFT_U (y);
  y ^= TEMPERING_SHIFT_S (y) & TEMPERING_MASK_B;
  y ^= TEMPERING_SHIFT_T (y) & TEMPERING_MASK_C;
  return y ^= TEMPERING_SHIFT_L (y);
}
 
/*-----------------------------------------------------------------------------
We can really change the outcome of the sim by altering these values.
-----------------------------------------------------------------------------*/
 
#define BASE_HITPOINTS    1000
#define BASE_HIT_CHANCE   25
#define BASE_CRIT_CHANCE  10
#define BASE_DAMAGE       15
#define CRITICAL_DAMAGE   1.0f
#define REFIRE_TIME       100
#define RELOAD_TIME       500
#define MAG_SIZE          20
 
/*-----------------------------------------------------------------------------
Our class for enacting the fight.
-----------------------------------------------------------------------------*/
 
class Fighter
{
private:
  float     _hitpoints;
  int       _cooldown;
  int       _bullets;
  int       _full_mag;
  int       _reload;
  float     _bonus;
  int       _next_shot;
  char      _bar[21];
 
public:
  float     Health () { return _hitpoints; }
  float     BonusPercent () { return _bonus * 0.01f; }
  void      Hit (float damage)  {    _hitpoints -= damage;   }
  bool      Dead () { return _hitpoints <= 0.0f; }
 
  //A status bar showing what this Fighter is doing. Fixed length for easy console viewing.
  char*     Bar () {
    if (_reload) 
      sprintf (_bar, "%3d [reloading] %c", (int)_hitpoints, _cooldown <= 0 ? 'x' : ' ');
    else 
      sprintf (_bar, "%3d [%3d / %3d] %c", (int)_hitpoints, _bullets, _full_mag, _cooldown <= 0 ? 'x' : ' ');
    return _bar;
  }
 
  void      Respawn ()
  {
    _hitpoints = BASE_HITPOINTS + (BASE_HITPOINTS * BonusPercent ());
    _bullets = _full_mag;
    _reload = 0;
    _next_shot = 0;
    _cooldown = 0;
  }
 
  void      Spawn (float bonus=0)
  {
    _bonus = bonus;
    _full_mag = MAG_SIZE + (int)(MAG_SIZE * BonusPercent ());
    Respawn ();
  }
 
  float   Shoot ()
  {
    int   roll;
    float damage;
 
    //Do we need to reload?
    if (!_reload && _bullets < 1) {
      _reload = RELOAD_TIME - (int)(RELOAD_TIME * BonusPercent ());
    }
    //Are we reloading?
    if (_reload) {
      _reload--;
      if (_reload == 0) {
        _bullets = _full_mag;
        _cooldown = 0;
      }
      return 0.0f;
    }
    //Are we ready to fire?
    if (_cooldown>0) {
      _cooldown--;
      return 0.0f;
    }
    //So we pulled the trigger. Put the weapon on cooldown.
    _cooldown = 100 - (int)(50.0f * BonusPercent ());
    _bullets--;
    //Roll to hit...
    roll = RandomVal () % 100 + BASE_HIT_CHANCE;
    roll += (int)_bonus;
    if (roll < 100) // We missed.
      return 0.0f;
    //Calculate damage.
    damage = BASE_DAMAGE;
    damage += (float)BASE_DAMAGE * BonusPercent ();
    //Roll for crit...
    roll = RandomVal () % 100 + BASE_CRIT_CHANCE;
    roll += (int)_bonus;
    if (roll > 100) //Yup, a crit.
      damage += damage * (CRITICAL_DAMAGE + BonusPercent ());
    return damage;    
  }
};
 
/*-----------------------------------------------------------------------------
And now the program itself.
-----------------------------------------------------------------------------*/
 
static bool over;
static int  turn;
static int  deaths_total;
static int  deaths_player;
static int  deaths_mook;
static int  msg_count;
 
int main (int argc, char* argv[])
{
  Fighter   player, mook;
 
  player.Spawn (5.0f);
  mook.Spawn ();
  RandomInit (2);
  while (!over) {
    //Have these two idiots shoot each other at exactly the same time, so we 
    //don't have to worry about who shot first. (It wasn't Greedo.)
    mook.Hit (player.Shoot ());
    player.Hit (mook.Shoot ());
    //Only print info occasionally, or the program takes forever.
    if ((msg_count % 500) == 0)
      printf ("%5d %3d Player: %s | %3d Mook: %s\n", turn, deaths_mook, player.Bar (), deaths_player, mook.Bar ());
    msg_count++;
    //See if either one died in the exchange.
    if (player.Dead ()) {
      player.Respawn ();
      deaths_player++;
      deaths_total++;
    }
    if (mook.Dead ()) {
      mook.Respawn ();
      deaths_mook++;
      deaths_total++;
    }
    if (deaths_total >= 1000) 
      over = true;
    turn++;
  }
  printf ("Player kills: %d\n", deaths_mook);
  printf ("Mook kills: %d\n", deaths_player);
  return 0;
}

Footnotes:

[1] Actually, in the first one it works a little different, but whatever. For now let’s focus on the Borderlands 2 and Pre-Sequel.

[2] Generic time units. Not mapped to real-world time in any meaningful way. I don’t want to actually sit here and wait ten minutes for the contest to play out.

[3] Effectively making you miss out on five shots every time you reload.


 
 
Comments (60)

  1. Abnaxis says:

    These posts always drive me nuts, because I know you could get exactly the result you want without a simulation, just with equations. You’re simplifying it so much you could figure out your answer on a piece of scratch paper–no wonder the results are boring.

    • Gilfareth says:

      On the other hand, there’s something incredibly satisfying about setting up the logic and having the computer do the work for you, even on something simple like this. I don’t know if Shamus gets that same feeling of ‘I am master of all I survey’ that I do when I do this sort of thing, but if he does then I totally get why these posts happen.

      • mhoff12358 says:

        Especially when you’ve been working on larger projects a lot it is incredibly satisfying to work on a simpler script and have some cleaner code that just works and does something neat. The only way this code could be more straightforward was if it was written in python and thus inherently more readable and easier to debug

      • Mephane says:

        I remember one specific puzzle in a game – I think it was SWTOR – that drove me nuts, I knew there was a systematic solution but I could not find it, and did not want to look at a guide. So half a day long I tried coding up some sort of brute force algorithm that would systematically try out each and every option. It would get exponentially complicated and I never really got the code right, until I decided to scrap the code and do something I had never done before:

        A Monte Carlo simulation. I just let the computer perform random steps until it either reaches the goal, or a a maximum number of steps had been done. Print the result of 100 computations in a file and pick the shortest one and repeat it in the game.

        Not only solved it the puzzle, it also started my fascination with probabilistic algorithms, like Path Tracing (See also at Wikipedia).

      • Mmm, yeah, but I’d get a certain satisfaction from laying something like this out on a spreadsheet, say. You could get the whole range of results laid out if you did it right, and I suppose even make the thing make a graph out of the result set, and both the results and the graph would then change if you plugged in different duel parameters. Same “master of all I survey” thing, and arguably a better understanding of what’s going on because, like, you’ve figured out the math that drives it rather than just creating a black-ish box that models it.

        But I guess this is yet another example of a very old Dilbert point: The correct solution to any given problem is always, by an amazing co-incidence, the only one you know. Financier wants to use cash flow analysis, engineers want to build a computer model, union dude says we just need to kick a few hineys, porcupine says “Listen to me, people! We must prick them with quills! It is the only way!”
        And I don’t know how to program worth beans, so I wouldn’t do it that way.

        • Felblood says:

          You could even use derivatives to calcutate the exact rate at which the line becomes more curved.

        • Steve C says:

          “If all you have is a hammer, everything looks like a nail.” — The concept known as the Law of the Instrument, or Maslow’s hammer.

          Ironically it has nothing to do with hammers and everything to do with computers. It’s from a 1963 book titled “Computer Simulation of Personality: Frontier of Psychological Theory”.

      • Abnaxis says:

        I don’t think I made my point clearly.

        I’m not necessarily saying that the simulation route is categorically BAD, per se, but that the input in this case is so simplified that simulation is unnecessary. In my experience in working with simulations, if you can find a formula that gives you what you want in absolute terms, it means whatever you are simulating won’t be all that interesting.

        For example, I once set up a full blown FEA analysis for what was essentially just a 3D cantilever beam problem because, well, my boss (who was an electrical engineer who didn’t know better) told me to run an FEA analysis on it. After spending way too much time drawing out the model and refining it (this is back when FEA was new and the modelling computer, while the fastest in the office, still took on the order of hours to finish), one of my more experienced colleagues said, appropriately, “why don’t you just use the formula?” Five minutes later I was finished, with identical results to the complicated simulation.

        Running simulations might be fun and intuitive, but usually only when the problem is complicated enough that a relatively simple formula can’t get you there.

        • Max says:

          The funny thing though is that you can always find the error level in the simulation by comparing a cantilever beam results from the simulation to the analytical solution. I really like this method to compare the differences between FEA programs (Abaqus to Ansys f.e.). It also gives you a better understanding of supports and load applications in comparison to an analytical solution.

          Other than that you only need FEA programs, when you can’t reduce your problem to beams, rings, cylinders or some such where the surface area is easily computable or you also have contact elasticity problems. At least, that was always my opinion.

    • Loonyyy says:

      Sometimes it’s easier to simulate if you haven’t worked with the Binomial theorem in a while, and a bit messier if the dependant variable is complicatedly linked to the outcome (The bonus is, it’s just close to linear).

      Oddly enough, my stats lecturer always goes straight for simulation, she always refers to breaking it down on a whiteboard as time wasting.

    • Blake says:

      For a programmer it’s much quicker to just write the program than trying to use math you haven’t touched in a long time, it also makes you more confident you haven’t made a mistake somewhere.
      Then it’s also trivial to just change any of the numbers and see the new result within seconds.

      Also: fun.

  2. Csirke says:

    Yes, and I think you’re using a relatively recent Visual Studio Freeloader Edition now, right? So you could avoid coding the Random number generator and use C++11’s built in features :)

    The 3 lines of code that would be needed to get a uniform int from a mersenne twister can be seen, for example, on the uniform_int_distribution page on cppreference.com.

    C++11 has lots of useful, productivity boosting features, I think it can be worth your time to look into it. Stuff I found useful even for small hack projects are range based for loops, initializer lists, and some of the new standard libraries, like regex, random numbers, and smart pointers.

    As for the Borderlands experiment, I think the bonuses gained from 1 badass rank are also smaller for certain attributes than for others. I have a feeling they probably balanced it painstakingly with their own simulations :)

  3. Xapi says:

    A more interesting experiment might be “what should I spend my points into”.

    Intuitively, you’d think it’s best to diversify your BAT investments in several, if not all, of the stats, but it would be nice to see if this is actually true, or under what situation you’d want to max reload instead of fire rate (or something).

    • Merlin says:

      At least in BL2, it prioritizes stats that you haven’t been putting points into. So if, for example, you’ve been heavily hitting Elemental boosts and avoiding Grenade Damage, eventually you’ll stop “drawing” Elemental Chance/Damage and will start getting Grenade Damage as an option on every single badass token. It forces you into fairly even development.

      • Evilmrhenry says:

        In addition, your first point into a skill will give you a much higher boost than your tenth point. (I think it starts at like 1%, and drops down to 0.5%)

      • Ivan says:

        I was going to mention this but basically the point is moot. You can’t choose to specialize, even though I always try to, and so your choices don’t ultimately matter much. Everyone will come out of it looking like a generalist and if you look at Shamus’s scores, it looks like you can only have a few dump stats. He has two but you should be able to have up to 4 stats (the game always gives you 5 to pick from) that you never put points into. It’s also worth noting that a stat will not show up on the list of stats getting a bonus until you put a point into it, so shamus might very well have 4 dump stats with 2 of them never getting a point at all.

  4. mhoff12358 says:

    So, since the simulation is straightforward enough I think a lot of the complexity filters out to just basic math. The two people fire at the same time, so dying never causes you to miss out on the ability to take a shot. Damage is a small enough percentage of overall health that you don’t have to worry overmuch about wasting overkill damage…

    Basically what this means is that each of the improvements sort of stack nicely in this case. If you’ve go 1.05 times as much health, you’ll live that much longer and do proportionally that much damage pretty much exactly. Same goes for fire rate and damage modifiers.

    What’s important then is how these compound. If each stat is multiplied by 1.05, then you’ve got compounding improvements. So its 1.05^n, based on the number of stats. (This doesn’t work for all stats, bonus crit damage is scaled in effectiveness based on the overall proportion of crits to non-crits, and reload speed is only roughly a directly proportional improvement).

    Health, damage ups, and accuracy are pretty straightforward improvements, directly scaling damage. Refire rate, clip size, and reload speed less so, as improving one too much is capped in effectiveness without improving the other. Lets assume that together they’re two more percent improvements. This means that is we scale our stats by 1.05, we’re actually raising our total by 1.05^5. (Hooray, an excuse to say quintic function!)

    Throwing some numbers into the system, a 1% bonus to all stats winds up being about a 5.1% total bonus, and a 5% bonus to all stats winds up being a 27.6% bonus to all stats. Whiiiich is about linear, which matches your simple test data.

    What this means is that there is definitely a turning point where bonuses will compound enough to make a huge difference, but its polynomial not exponential so it won’t happen for a while.

    • Peter H. Coffin says:

      It first glance, it *looks like* it all filters down to damage per time-unit in the cases that Shamus has worked up.

    • Abnaxis says:

      True, but I wonder if 27.6% more stats means 27.6% more victory. I don’t know if they all scale multiplicatively like that.

      To that end, I’ve been trying to come up with different ways to use statistics to determine “probability of player winning.” Because one thing that’s fun about stats (that I find fun at least, as an armchair statistician) is that there’s a lot of avenues to get an answer, half of which are correct, and the other half of which aren’t but give you an answer anyway so they fool you.

      I’ll post a couple of my ideas in reply to this.

      • Abnaxis says:

        Idea A: come up with a rough distribution for player DPS – Mook DPS, and calculate P(Difference in DPS > Player Bonus Health). Use a lot of ugly assumptions to make math less hairy.

        I’m lazy, so let’s just use normal approximation for DPS. This is my first go-to, lazy, dirty way to proceed because then I can look my answer up in a table, and Shamus has already run the simulations for me so I can check my answer.

        So, for my DPS formula, I would say it’s (fire rate * damage * accuracy). Where:

        fire rate = base fire rate * Bonus
        damage = base damage * bonus
        accuracy = P(hit) = Bernoulli(0.25 * bonus)
        bonus = 1.01 if player has 1% bonus, 1.02 if player has 2%, etc

        Note ugly-ish assumption here, just lumping in the reload time into the overall base fire rate, though it makes less of a difference with the way the combatants are set up here because they’re both going to be reloading at about the same time, so it cancels out

        A Bernoulli distribution is a binomial distribution with a single trial. That gives it a mean of 0.25*bonus and variance of (0.25 * bonus)*(1-0.25 * bonus)

        So, with algebra the mean difference in DPS is 0.25*(bonus^3 – 1)*constant, with variance 0.25*0.75*(bonus^6 + 1)*constant^2. I’m gonna throw out the constant and only look at the %difference in DPS rather than the absolute difference. If that %difference is greater than %difference in health (bonus-1), the mook wins.

        So now I can calculate a Z-score, 4*(bonus^3-bonus)/sqrt(3*bonus^6+3), and look it up in a handy normal distribution table. Notice that if bonus = 1 (no advantage for player), Z = 0 and Prob(Player wins) = 50%. Also note that we basically have a cubic on the top and the bottom, so eventually we stop seeing any benefit of giving the player a higher bonus at less than 100% victory (it approaches 98.9% victory asymptotically), so it’s a bit suspect.

        With this formula, I get a z-score of .16 for player bonus of 5%, corresponding to expected 564/1000 victories. This seems pretty close to what Shamus got from his simulation, but it’s really hard to read that thick line on his graph with much precision. Maybe it’s underestimating a bit?

        At player advantage 10%, I get a Z-score of .46, corresponding to 677/1000 player victories. Again, hard to see but it’s preeeeetty close.

        For a first pass, normal approx seems like it gives a good order of magnitude, but it’s far from exact.

      • Abnaxis says:

        So, approach #2: time how long it takes the player to win, and if the mook doesn’t kill them in that time it’s a victory.

        For this approach, I use a negative binomial distribution–the distribution that give “probability you will screw up X times before you succeed Y times.” If I multiply this by “probability the mook didn’t kill player in the time it took him to shoot X+Y times,” that give me “probability player will win in X+Y moves.” Add this together for all possible X, and it gives the total probability of player victory.

        In equation form, this is Sum( NegBin( Screwups, HitNeedForPlayer, PlayerAccuracy) * Sum(Bin(MookSuccesses,0.25)). The nested sum goes from zero to infinity for the outer sum, and from zero to the number of hits the player can take – 1 (depends on bonus) on the inner sum.

        Now, I vaguely remember that NegBin*Bin simplifies into something, but I don’t remember what that was and can’t be arsed to look it up. But we could find the kernel and all that crap, and then we could find a straight up formula to plug in. I cheated and wrote a program to do it for me–it runs a while loop adding more screw-up possibilities until the change in probability is so minuscule I don’t care any more.

        The program wound up being sixteen lines, and revealed some interesting behavior. First, it doesn’t give a 50% chance to the player if they have no bonus. With this analysis, there are no “turns,” both the player and the mook act in continuous time. At 0% bonus, that means the player and the mook fire at exactly the same time, leading to an odd singularity where it’s possible for both to fire a kill shot at the same time, which my system counts as a loss for the player, giving the mook a slight edge (48.3% chance of player victory). I could adjusy my code to count it as a tie instead of a loss, but A) it only happens at 0%, because the combatants never fire at EXACTLY the same time other than that, B) it should count as a player loss anyway–if the suicide psycho kills the player, that’s a win for the psycho, and C) then my program wouldn’t be 16 lines anymore.

        Second, there are cutoffs where the probability of player victory jump sharply. Going from 0% bonus to 0.1% bonus ups victory chance from 48.3% to 51.7%, because the mook looses it’s tie advantage and the player always gets off one extra shot. There’s also a jump from 58.4% to 70.3% victory at 5% bonus, because that is the cutoff where it takes 8 shots to kill the player instead of 7, and another jump from 78.6% to 86.9% chance at 11.1% bonus, because that is the cutoff where the player needs to hit 6 times instead of 7 for a kill.

        Here’s a picture with my graph. It looks a lot like what you got from your simulations. I wonder if the difference between us is if you went in step sizes too big to see the jumps, or because of our differences in methodology. It’s clear the jumps are an artifact from using exact times and damage numbers, and if you’re adding some sort of unmentioned randomness to your simulation that might be smoothing it out.

        EDIT: Also, in your text, it says combatants get 100 HP, but in the code it’s 1000. That makes a pretty sizable difference, because things like “player gets off 1 extra shot” have less of an impact.

  5. Wide And Nerdy says:

    I think you might get more interesting results if you wrote a program that simulates how many mooks your character can kill before he dies. When you factor in more damage, and hitting more often together with taking more punishment and recovering faster, I think it starts to add up.

    Especially so if you can simulate the impact it has on the player’s net earnings (money earned from kills vs money lost to dying/respawning.)

    I didn’t know the badass ranks were global (still new to this). I was more or less ignoring them because the percents are so tiny (a pet peeve of mine with leveling systems). But I really like how that rewards replay by making it faster. I also like the stash idea where you can leave items for your other characters allowing them to gain their optimal equipment more quickly.

  6. Crystalgate says:

    How does the program handle decimals in damage? If it allows decimals, you should have seen a sudden raise at 12% bonus since that decreases the number of shots needed to kill. If you round down, you should instead need a bonus of 14% for that to happen.

  7. Phantos says:

    Axton kinda ruined the game for me. His special power was a turret with massive hitpoints and good damage output that instantly grabbed all aggro. It was basically a “get out of dying, free” button. It felt far more powerful than the other special abilities, but was also kinda boring to use.

    Gaige is like what you described here, but somehow even more game-breakey.

    Not a criticism, just an observation, because after playing as Gaige, I find Axton isn’t game-breakey enough.

    • Shamus says:

      It’s true. I tried Gaige for a bit, but it was like having Axton’s turret fly around. I felt like I was superfluous.

      • Alex says:

        Deathtrap’s a useful distraction, but Gaige is capable of putting out a ton of damage herself. Her biggest problem is that one of her major skills requires a run up. You can’t keep Anarchy stacks between sessions, between hosts or after a wipe, which does not work with the way Borderlands handles co-op. Join a new party? The entire party needs to go farm stacks. Get wiped by a raid boss? The entire party needs to go farm stacks.

    • Darren says:

      I played BL2 mostly single-player for reasons related to truly terrible internet, and I found Maya to be the most powerful. Her ability has a short cooldown, temporarily incapacitates most enemies, and can be upgraded to inflict AoE and DoT elemental damage.

    • Trix2000 says:

      Maybe in first playthrough they have a lot of health, but I can’t count the number of times on later playthrough(s) that I dropped a pair of turrets (with lots of upgrades) and 5-10 seconds later saw the green laser swinging through the air as turret parts rolled on the ground. Lategame enemies’ damage scales a lot better than the turret health does.

      I’d guess the same for Gaige’s thing, but I haven’t used t.

  8. Hal says:

    I think I’d want to see a breakdown between weapon choice and stat weight. That is, “If you prefer shotguns, then your highest benefit comes from reload speed.” Something like that.

  9. syal says:

    So, looks like 1% gives you a 2% advantage, 3% gives you a 5% advantage, and 5% gives you an 8% advantage. Are all the increases Fibonacci increases?

    Also if you wanted a more impressive chart you should have allowed for health regeneration between respawns.

  10. Awetugiw says:

    I think the graph might be kind of misleading. Sure, you get an (approximately) linear effect with these scales. But as a player you are much more likely to care about your kills/deaths ratio, and that grows non-linearly.

  11. WILL says:

    What a worthless post. Simplified to the point where it’s useless and could simply be done with an equation.

    Could’ve worked on Good Robot. Could’ve written your opinions on Borderlands 2 instead.

    • Cinebeast says:

      Oof. You’re clearly disappointed in Shamus’s approach, but did you need to write with hostility? This seems like a poor way to further the discussion.

    • Retsam says:

      What a worthless comment. Needlessly hostile and combined with the assertion that Shamus needs to spend his time in a way that maximally pleases you.

      You could have spent the time you wrote this comment doing *literally* anything else.

  12. poiumty says:

    This is some nice programming you’ve got here. So let’s talk about game design instead.

    Personally I think Badass Ranks were a piss-poor replacement for one of the more surprisingly important systems of Borderlands 1, weapon experience. Yes, I know, it sounds crazy: what am I thinking defending a system where you need to grind for your entire playthrough with the SAME WEAPON TYPE in order to ensure you’re getting full benefit out of it? But hear me out.

    There’s 2 aspects I want to touch in regards to this: the feeling of specialization, and the importance of limitations.
    In RPGs, you usually start off about as bad as everyone else. Meaning, your level 1 Mage can go melee an enemy and not produce insanely different results from a level 1 warrior. As you go up in levels however, you distance yourself from the median as your character becomes more and more powerful in your chosen profession. This is also true if you’re a jack-of-all-trades, because you still have some contrast with all the other classes. There is a significant feel that needs to be achieved here, the feel that you’re de-homogenizing yourself, that you’re standing apart from other characters the more you grow in levels and becoming something unique. As crazy as it was, by incentivizing your character to wield specific weapon types you felt more and more detached from the rest of the game’s customization. The skill trees took full advantage of that.
    Furthermore, weapon XP was a limitation, a rather fundamental concept of game design. Not only did it provide you with a thought-provoking challenge, it also de-incentivized you from looking at loot you didn’t want to use, reducing the amount of loot parsing and mental mathematics you had to do – which in Borderlands 2 felt wholly overwhelming in comparison, to the point where it detracted from the actual game. Did I mention there’s no reason to have 2 of any same class in Borderlands 2?

    Replacing this system with badass ranks in Borderlands 2 had two major effects: one – it removed a limitation from you which butchered the feeling of specialization on a fundamental level, and two – it made it easier for the devs to be veeeery stingy with the amount of good loot that came your way. You can see that in the game in general – the amount of crap-ass drops you get compared to the first Borderlands, and the amount of crap-ass loot you find in shops. The Pre-Sequel tries to alleviate the shop problem which hints that they’ve wised up to it a bit, but it still doesn’t bring it back to the Borderlands 1 level of quitting the game and reloading just to see what awesome items I can possibly get from the shop.
    Speaking about number one, the idea of getting a reward for basically spending time on a game is in my opinion incredibly ass-backwards. If you want to incentivize the player to keep playing, you do that a priori – make sure the player has fun now in order to keep playing later, not the other way around. And since you get gradually better at pretty much everything and the system is rigged for you to not be able to min-max, not only do you benefit from zero contrast in power then vs now (unless you deliberately turn the ranks off just to see how bad you are without them), you can’t even make meaningful decisions over what you’re better at!

    This might all seem like I’m splitting hairs or nitpicking, but I do believe it’s the difference between having 4-5 characters at level 50+ in Borderlands 1 (of which 2 were Sirens) with having played all of the DLCs, and NO characters at max level in Borderlands 2 with no DLCs played and the game only finished once on normal mode.

    Other factors such as the dull skill trees and drawn-out campaign were probably a factor, too, I won’t deny that.

    • Drew says:

      If I’m reading this correctly, and you never played the Tiny Tina DLC, you’ve done yourself a disservice.

    • John Lopez says:

      I understood the idea of the “weapon focus” in BL 1, but as someone who played heavily but only completed a few runs of the game, the specialization system meant that our group was constantly at odds. First, if a sniper dropped, it was about who got the sniper (it was pretty much a “required weapon” for everyone). Then at close range whoever was specialized in the “good drop” was the star of the show for the play session, which was fine except when it wasn’t our hard core players who took not being the kill monster personally.

      Our group played BL 2 and we stuck with it quite a bit more, in part because nobody felt like an idiot for specializing in a gun that never dropped or turned out to be a bad idea in the long run.

      I can’t speak to single player as I find it uninteresting.

  13. shiroax says:

    Speaking of get out of dying buttons, have you tried dropping a fireworks grenade at your feet? It’s overpowered AND hilarious.

  14. Jay says:

    You’d probably get more of a curve if you included recoil. After each bullet past the first subtract .5% from the chance to hit, cumulatively. Reduce the recoil penalty appropriately if the character has a recoil reduction bonus, and eliminate the penalty completely with every reload.

  15. nm says:

    Shamus, if you ever want to learn another language (like Python) this is exactly the kind of little project that would be easy to do. It’s always frustrating to learn a new way of doing something you can already do, but in the long run it’s very rewarding.

  16. Thank you, Shamus, for writing about this!

    For someone like me who is not mathematically inclined (I have a bad case of dyscalculia), games that insist upon forcing me to make these kinds of quantitative decisions DRIVE ME NUTS!

    How can I possibly decide if I want a 2% increase in my critical hit chance if I have no way of quantifying how that will affect my overall enjoyment of the game?

    It all becomes meaningless numbers to me and many times I resort to the “eenie meenie miney mo” approach out of sheer frustration.

  17. Mechaninja says:

    How many people play Borderlands? Because we have math professors and hard core IT guys and high end programmers and etc etc playing WoW, and building spreadsheets, simulators, and optimizers for WoW.

    I have a really frustrating time trying to find optimization information for any other game, compared to WoW. There are a lot of questions I have about Wasteland 2 that I wish I could get Theck or someone to answer for me :/

    The thing about WoW of course, is that the community ends up being similar to the scientific community, in that Theck takes the work of Meloree and combines it with his expertise, which is then combined with the work of the folks behind Simcraft (though I think Theck is actually running the Protection Paladin Simcraft module these days but the point stands) and etc etc. There’s no time for most other games to build that kind of community resource pool.

    • steves says:

      Many people play, but nowhere near as many as WoW (which is a law unto itself these days), but most are of the ‘don’t give a shit about numbers, just want to kill stuff’ persuasion.

      Myself included with Borderlands. You won’t find a more geeky min-maxer than me when it comes to ‘serious’ RPGs, but this is the one game with numbers where I don’t get too obsessive about it.

      Borderlands is mostly about finding which character’s play-style & skills match what you have fun with, and then getting the best loot to support that.

      For me, that’s a glass-cannon style build focused on sniping, with high-powered pistols at close range. Limited ammo, a few shots, high accuracy, high risk, mad damage. Until it all goes to shit and I start needing the backup shotgun/rocket launcher plan of course!

      For others, it’s lots of health regen + elemental AOE all over the place and general chaos. Or an endless stream of bullets bouncing everywhere, or some combo of melee attacks building up shields & crazy gun damage…Borderlands gives you a LOT of options for murdery fun, all of which work well enough until you start worrying about ‘end game grinding’, but if that’s your thing, then WOW/Diablo are probably the better choice.

  18. Retsam says:

    Small critique; this post could really have used an intro paragraph or something. It was odd to read 6 paragraphs of explanation of a game’s mechanic without knowing why I was reading about it and what this post was about.

  19. Mailbox says:

    I want to hear your argument for why Athena is best character. I’m fascinated. Nisha has been the most fun for me. So my bias is with her. Convince me.

    • Shamus says:

      Nisha is really winning me over. I’ve completed the game as Athena, and I’m about halfway through with Nisha. Both characters are better than anything in BL2. I tried Willhelm. Didn’t like it. Felt like an ineffectual Gaige.

  20. Patrick the Pumpkin Spiced Vandal says:

    I know what you’re trying to say with the tone of the article, that is pointing out that the Badass ranks are, for the most part, Un-Badass.

    But that really isn’t the point. You mentioned it early on. It’s simply a subtle way of trying to influence a user to play the game with a different character, or with a different style, and giving them a cookie for trying. It’s a modest addition that adds HOURS of gameplay without adding anything significant to the actual game. I thought it was a great idea, from a design standpoint. It’s influencing, but not railroading. It’s encouraging without being heavy-handed.

Leave a Reply

Comments are moderated and may not be posted immediately. Required fields are marked *

*
*

Thanks for joining the discussion. Be nice, don't post angry, and enjoy yourself. This is supposed to be fun.

You can enclose spoilers in <strike> tags like so:
<strike>Darth Vader is Luke's father!</strike>

You can make things italics like this:
Can you imagine having Darth Vader as your <i>father</i>?

You can make things bold like this:
I'm <b>very</b> glad Darth Vader isn't my father.

You can make links like this:
I'm reading about <a href="http://en.wikipedia.org/wiki/Darth_Vader">Darth Vader</a> on Wikipedia!

You can quote someone like this:
Darth Vader said <blockquote>Luke, I am your father.</blockquote>