osrs image

September 2018 Update: Staking has changed significantly due to recent game updates. I wrote a follow-up article covering that. I will leave this unedited, though I have come to suspect I made an error in my calculations and also dislike the verbosity.

If you were a teenager using the internet nine years ago, you had the chance to play Runescape in its prime. I really hope you did. For those who didn’t make it past Tutorial Island, Runescape is an MMORPG with a player versus player (PvP) aspect that has been lauded as timeless. Out of the flurry of similar MMO’s I played all those years ago, Runescape was the only one in which the outcome of PvP encounters depended on both a character’s levels as well as a human player’s ability in executing the fight. Fun to watch; fun to execute. Combined with different PvP environments (The Wilderness, The Duel Arena, PvP Worlds, Bounty Hunter) and a combat-level formula that allows for competitive fights at every stage of one’s training, Runescape was a favorite amongst casual and hardcore gamers alike. It should come as no surprise that Jagex, the developers of the game, maintain an entirely separate branch, called Old School Runescape (aka 2007scape or OSRS), that has just as many active players as the most up-to-date version of the game.

PvP in 2007scape is extremely competitive because all of the 12 and 13-year-olds from a decade ago are now much smarter and in their mid-twenties. Not only does skill play a major part in being successful, but an account’s build (its combat levels) has to be carefully planned and achieved. There is no low-hanging fruit. I thought it would be neat to develop an end-to-end combat simulator to determine an optimal character build, taking into account game ticks, combat scenarios, and all possible stat and gear combinations. This would have been an extensive work, and wouldn’t have been of much use. People already know what the best builds are and use them. Further, in the wilderness, skill is the real determining factor. If I wrote a program to evaluate all those factors, at the end of the day I could say, hey, risking item x is marginally more costly than risking item y. I could say with authority that 2 levels in skill b are preferable to 2 levels in skill c at combat level d in scenarios 1, 3, 4 & 5, but not 2 or 6, but there’s really no basis of application as it would be too stratified. I had to find a PvP environment in which my model could ignore skill & human error, operate using simplified game mechanics, and produce results leading to an indisputable, repeatable edge over the competition.

In the Duel Arena, all of that criteria is met. Players are free to choose their own rules and the most popular rule combination turns off all armor, weapons, food, potions, and prayer. Players fight in a predictively simple manner that requires no skill. You just click once and watch. This is known as “boxing”. While most people who box have maximum combat stats, I’ve selected a different, lower leveled build that may be able to compete with maxed-out accounts if I can determine optimal stats and odds I’m willing to take.

The combat stats in Runescape are Attack, Strength, Defense, Ranged, Magic, Prayer and Hitpoints and can be leveled between 1 and 99. We’ll be ignoring Ranged, Magic, and Prayer for the simulation since those styles are almost always turned off in the duel arena. The game’s combat formula, resulting in combat levels 3 and 126, is calculated in a way that allows for some pretty wacky builds. One is the ranged tank. While 1-prayer accounts might be staking with 99 attack, strength, defense, and hp at 113 combat, I can have 99 defense and hp while having 149 “points” to distribute between my attack and strength at only 97 combat. My idea is that if I can find a winning combination of attack/strength levels at 97 combat, I will not only win virtually every fight against players around my level (because 99 hp and defense with 1 prayer is overpowered), but can maintain an edge versus opponents of higher levels if they are willing to stake (wager) a magnified amount. I just need to find out what those odds are and if they would make sense.

For example, If my model shows that I win 26% of fights with (atk/str/def/hp) 80/69/99/99 (80+69 = 149) versus opponents who are 99/99/99/99, I should be willing to make a one million gp (gold pieces, in-game currency) stake versus an opponent’s three million gp wager. In the long run, I will come out ahead. My expected value would be positive: (.26 * 3) – (.74 * 1). Against accounts that aren’t maxed, say, 97/99/95/98, I’ll stand to make even more. Why is this worth pursuing? Above, I stated that the most competitive builds are commonly known- hasn’t somebody already figured out what I am proposing? They have not. The calculations for comparing builds in the constrained combat environment of the duel arena are so particular that it would be impossible for anyone to manually test the optimal combination without programming their own combat simulator.

In my simulation, I will not only be finding the optimal allocation of the 149 atk/str levels, but, for every distribution of those 149 levels, I will produce the maximum odds at which a player should be staking 99/99/99/99 accounts if they aim to make money in the long run. Although trading in-game currency for real-world money is against the rules, to put this into perspective, a hypothetical 10% edge on staking for one-billion gp per hour will net you a profit of $250 USD per hour. (Disclosure: a player will have no problem finding enough opponents to sustain that volume, however, finding a consistent stream of players willing to stake with the odds in your favor may not be easy). Though the arena is wildly popular, those duking it out with maxed stats are gambling on 50-50 odds, only slightly better when an opponent isn’t maxed. There is no possible way to sustain a winning streak, which is why the lion’s share of Runescape PvP footage on YouTube features the wilderness, not the duel arena. By creating a combat simulator, I hope to calculate the optimal skill allocation for an account that will allow me to arbitrate between odds people are willing to give and what the odds actually are.

Let’s start building the simulator. I’ll be using Java. First, the assumptions and constraints. I will assume two players are boxing with no armor on, no weapons equipped, no prayer allowed, no food/potions allowed, and no other stat bonuses. One assumption that will be considered controversial is that I will assume no attack style bonuses. I consider this necessary for obtaining normalized results. Since there are no weapons, both players will be attacking at the same speed, which is speed 6. This is 2.4 seconds or 4 game ticks, but this doesn’t need to be implemented since there is no difference between player attack speeds and no external actions that could depend on game ticks. A turn-by-turn will fit the simulation just fine. Further, I’ll grant each player “first hit” equally. First hit refers to who, despite both players clicking at the exact same time, attacks first in a fight (by one game tick). Jagex randomly gives a player priority over another in a fight. In the duel arena, and especially with restrictive rules, this is important so that both players don’t both deal the final blow at the same time, thus ending the match in a draw. A duel can never end in a draw.

For the simulation, I will generate two characters. One will be maxed. The other will start with 99 hitpoints and defense with 50 attack and 99 strength. I will simulate combat between the two builds 1000 times and then will move on to an account with 51 attack and 98 strength versus a maxed account. And then a 52 atk/97 str, and so on, until I test a 99/50/99/99 vs a 99/99/99/99. From there, I’ll calculate odds for each build. Maybe you only need to get 1.35x, or maybe I’m completely off and you need 40x. We’ll have a clear idea of the best build. My guess is 82/67/99/99.

I coded this up with just a main method and a Player class. The player is constructed with certain stats at which point the defense roll, attack roll, and max hit are calculated.

public Player(String alias, int atk, int str, int def, int hp){
  this.alias = alias;
  this.attack = atk;
  this.strength = str;
  this.defense = def;
  this.hitpoints = hp;
  this.hitpointsRemaining = hp;

  //precalc this stuff
  this.attackRoll = 10 * atk * (1 + atk / 64);
  this.defenseRoll = 10 * def * (1 + def / 64);
  this.maxHit = Math.round((str + 8 + (str + 0) / 64) / 10);
}

Then, in the main, after the two players are constructed, I precalc each player’s accuracy percentage, which is predetermined since we know the attack and defense rolls are constant.

Max.precalculateAccuracyPercentage(Tim);
Tim.precalculateAccuracyPercentage(Max);

The runtime difference would be negligible if I only run a couple thousand tests, but if I want to nail down the statistics, the optimization helps out a lot. Here’s what that looks like in the Player class.

//Assume nothing is changing during the fight, save some time by doing this first.

public void precalculateAccuracyPercentage(Player opponent){
  if (this.attackRoll < opponent.defenseRoll){
    this.accuracyPercentage = (double)(this.attackRoll - 1) / (2 * opponent.defenseRoll); 
    System.out.println("attackroll: " + this.attackRoll + "\nDefense roll: " + opponent.defenseRoll + "\nAP is: " +     this.accuracyPercentage + "\n"); 
  } 
  else{ 
    this.accuracyPercentage = 1 - (double)(opponent.defenseRoll + 1) / (2 * this.attackRoll); 
  }
}

I fired up a simple loop pitting two maxed accounts against each other over 10000 fights, just to confirm there were no (glaring) mistakes in the code. Everything seems fine.

...
Max attacks... and doesn't hit
Tim attacks... and hits a 3 Max's HP is now 8
Max attacks... and doesn't hit
Tim attacks... and doesn't hit
Max attacks... and hits a 4 Tim's HP is now 2
Tim attacks... and doesn't hit
Max attacks... and hits a 9 Tim's HP is now -7
Tim died!

Tim won: 5002, Max won: 4998

Next, I tested every build from 50/99/99/99 to 99/50/99/99 against a 99/99/99/99 a million times. Here are the results:

Attack Strength Wins Win Percentage Against Maxed Account Deviation from Mean
50 99 21 0.0021 0.000336
51 98 28 0.0028 -0.000364
52 97 25 0.0025 -0.000064
53 96 26 0.0026 -0.000164
54 95 25 0.0025 -0.000064
55 94 21 0.0021 0.000336
56 93 18 0.0018 0.000636
57 92 27 0.0027 -0.000264
58 91 23 0.0023 0.000136
59 90 29 0.0029 -0.000464
60 89 32 0.0032 -0.000764
61 88 30 0.003 -0.000564
62 87 16 0.0016 0.000836
63 86 29 0.0029 -0.000464
64 85 28 0.0028 -0.000364
65 84 19 0.0019 0.000536
66 83 20 0.002 0.000436
67 82 21 0.0021 0.000336
68 81 24 0.0024 0.000036
69 80 20 0.002 0.000436
70 79 30 0.003 -0.000564
71 78 24 0.0024 0.000036
72 77 20 0.002 0.000436
73 76 33 0.0033 -0.000864
74 75 18 0.0018 0.000636
75 74 18 0.0018 0.000636
76 73 22 0.0022 0.000236
77 72 33 0.0033 -0.000864
78 71 19 0.0019 0.000536
79 70 18 0.0018 0.000636
80 69 27 0.0027 -0.000264
81 68 24 0.0024 0.000036
82 67 33 0.0033 -0.000864
83 66 19 0.0019 0.000536
84 65 32 0.0032 -0.000764
85 64 30 0.003 -0.000564
86 63 21 0.0021 0.000336
87 62 30 0.003 -0.000564
88 61 22 0.0022 0.000236
89 60 28 0.0028 -0.000364
90 59 25 0.0025 -0.000064
91 58 20 0.002 0.000436
92 57 29 0.0029 -0.000464
93 56 17 0.0017 0.000736
94 55 21 0.0021 0.000336
95 54 28 0.0028 -0.000364
96 53 23 0.0023 0.000136
97 52 31 0.0031 -0.000664
98 51 16 0.0016 0.000836
99 50 25 0.0025 -0.000064
mean: 0.002436

 

As you can see, the odds are stacked against this account fighting maxed players. The best odds, at 73/76, 77/72, or 82/67, have our underdog winning just .0033% of fights. For every 1,000 GP you stake, your maxed opponent would have to put up 30000x your wager for you to break even: 30,000,000 GP. Nobody in their right mind would do this, meaning that our attempt at gaming the odds falls short. However, the combat simulator that I have created opens up a lot of possibilities for cool projects. Stay tuned.

 


Questions & Criticisms:

Do you seriously think you’re the first person to write a program that simulates combat?
– No, but people who have done it have been rather secretive.

Not accounting for attack style is flawed.
– Choosing one attack style, assuming perfect “switching”, or even cycling through attack styles would have produced similar (if not identical) results and wouldn’t have been worth the effort.

Staking does require skill in that you should be switching attack styles.
– I agree, however it doesn’t take much skill to do this and boxing is still the most bare-bones way to run a simulation of combat.

Nobody is going to stake you magnified amounts, they will figure it is a scam.
– After a certain point, this is probably true. However, 2-3x wagers still happen with some frequency.

Your accuracy formula is imprecise.
– I believe all formulas used were extremely accurate and best represented game mechanics

Will you release all of your code?
– Yes. I’m planning on making it more robust first. Ideally, I’ll make a GUI if I find the time.

Your base build point (99 defense and hitpoints) is arbitrary.
– Sure, but finding an optimal distribution of atk/str points is more clean cut than figuring how defense and hitpoints factor in.

Accounts with level 1 prayer are going to be seen as suspicious staking-focused accounts.
– True.

Your best builds here are only “optimal” vs maxed accounts.
– I know. I’d have to run a more thorough simulation to figure out the best build at each combat level or the best build relative to odds you can get.

What about whip/dds, another popular variant of staking rules?
– I would like to simulate this in the future.

An Optimal Runescape Staking Build
  • Ryan

    This is quite an interesting study.
    Is it ironic we see peaks at 60 and 70 attack? (When you obtain a new potential in game item)
    Obvious you arent using d scims in boxing, but it does seem odd that those seem to be sweet spots.

    I would love to see a study incorperating defense, as defense increases combat levels more signifcantly than attack and str.
    I would also want to look at even combat level duels, not trying to beat a maxed account necessarily.

    This is very cool and awesome that you made your code public so we all can try.

    • Thanks for your comment. Several months ago I did develop a more advanced simulation that tested every possible combination of stats at each combat level. This required a lot of computing power and, even while renting Amazon servers, there was some bug in my code that I couldn’t figure out. If I ever get it to work, the results will be very interesting and I look forward to sharing them.

      • Ryan

        feel free to share the code on github and comment back the link.
        Me and a buddy of mine can take a look at it and maybe find the issue.

  • Drew

    Tim, I’m interesting in getting a better understanding of your simulation with Java. I’m not very experienced with coding in Java, but I would like to learn for my own purposes. Could you refer me to a source that would serve as a crash course in understanding this type of Java simulation so that I could try this myself? Additionally, I have an idea about using this type of simulation along with the ‘Kelly criterion’ to possibly maximize profits at osrs staking. I am interested in discussing further. Please get back to me

    • This is an example of a brute force/exhaustive simulation. Fast runtime was sacrificed in the interest of getting all data points rather than finding one optimal build. The good news is that this is just a massive nested ‘for’ loop where I get permutation of player_1’s atk+stk == 149 and run it against the max build 1,000,000 times. It gets really ugly when you remove the artificial constraints and try to test everything, as I mentioned below.

      The Kelly Criterion is something I have thought about as well. Fortune’s Formula is a really great book that gave me a lot of ideas for cool side projects. Once you get the win percentage, it’s easy to use the formula. If I ever generalize this and create a GUI, I will probably add that calculation.

  • Drew

    Any chance you could post the github link?

  • Rieno Dota

    Cool study but the math that is the fundation for your research is wrong. If u stake them 1 mill for 2 mill, u need to win 1 out of 3 times, not 1 out of 4.

    • The ‘30000x stake’ logic is correct as well as the ‘150USD per hour with 10% edge’. But I erroneously figured that 26% win percent had edge when staking double, when in actually it has edge when staking triple. Not only would applying an expected value formula have made my argument more clear, but it would have caught any errors in my mental math. Thanks for the correction, I’ll update the article later today.