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. |
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. |
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. |
As all projects, this one get quickly mired in vexing questions that weren’t obvious at first:
- 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.
- 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.
- 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.
- 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. |
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:
![]() |
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.
Civilization VI

I'm a very casual fan of the series, but I gave Civilization VI a look to see what was up with this nuclear war simulator.
The Dumbest Cutscene

This is it. This is the dumbest cutscene ever created for a AAA game. It's so bad it's simultaneously hilarious and painful. This is "The Room" of video game cutscenes.
Why The Christmas Shopping Season is Worse Every Year

Everyone hates Black Friday sales. Even retailers! So why does it exist?
Hardware Review

So what happens when a SOFTWARE engineer tries to review hardware? This. This happens.
Good to be the King?

Which would you rather be: A king in the middle ages, or a lower-income laborer in the 21st century?
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.
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.
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
That last part was intended to be tagged with a fanboy tag, but I botched the formatting.
… After all, that may be the last time any mere human understands the whole of the project… (:
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).
I love Monte Carlo approaches, it’s such a clever work around
Probabilistic and randomized algorithms are the shit. That’s thanks to them that you can have hard problems like Traveling Salesman which are hard but easy to approximate.
In this situation, the deterministic approach is quite easy, too:
Lanchester Equation
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.
You could even use derivatives to calcutate the exact rate at which the line becomes more curved.
“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”Âť.
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.
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.
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.
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.
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 :)
Don’t know if this applies here, but Visual Studios still doesn’t include every feature from C++11
But it has included <random> since VS2010. And VS2013 has nearly everything.
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).
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.
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%)
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.
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.
It first glance, it *looks like* it all filters down to damage per time-unit in the cases that Shamus has worked up.
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.
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.
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.
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.
yeah I was thinking the same thing throughout the post since it is more in keeping with borderlands’ playstyle.
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.
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.
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.
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.
But oh man, once those stacks have been built…
Conference Call was among the most broken weapons with her anarchy build. Loved that gun.
I will agree though, farming anarchy is a major pain.
I used single-shot shotguns to help build Anarchy.
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.
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.
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.
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.
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.
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.
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.
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.
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.
If I’m reading this correctly, and you never played the Tiny Tina DLC, you’ve done yourself a disservice.
Tiny Tina DLC was, hands down, the best DLC in a *long* time and frankly better than the main game. So yeah, disservice indeed.
Yeah. I know. But I lost my original saves and my latest only has half the game finished. Not gonna bother now.
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.
Goes without saying you should probably agree beforehand to specialize in different gun types for BL1. That’s what I did on my group runs and never had problems.
Speaking of get out of dying buttons, have you tried dropping a fireworks grenade at your feet? It’s overpowered AND hilarious.
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.
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.
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.
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.
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.
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.
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.
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.
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.