Disclosure: I may earn affiliate revenue or commissions if you purchase products from links on my website. The prospect of compensation does not influence what I write about or how my posts are structured. The vast majority of articles on my website do not contain any affiliate links.
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.
Pingback: My Homepage()