The last time we discussed stat weights, I promised to update the Monte-Carlo simulation and test it against the analytical calculations to verify their validity. I’ve finally gotten around to that, and the results are about as I expected. There have been no changes that affect these calculations since the posting of the analytical calculation, so both it and these results can be considered current for build 16048.
As usual, the code is available through the matlabadin project. I’ve changed the file names slightly to be more descriptive than just “montecarlo”:
For information on how the Monte-Carlo works, see the previous posts on this subject. In short, it tracks the boss swing timer, the global cooldown, the cooldowns of CS, J, and SotR, and the buff uptimes for SotR, BoG, Divine Purpose, and Grand Crusader. It runs in 10-millisecond timesteps and tracks whether each boss attack is a hit, miss, or block and records the damage (including SotR mitigation).
The cast logic is such that it will prioritize CS>J>AS(only if GC available). Technically it won’t cast J if there’s <0.2 seconds left on the CS cooldown, but now that everything scales equally with haste this conditional should have no effect.
We run the simulation for a total of 100,000 minutes of combat, divided into 10 “encounters” of 10,000 minutes each. Since the paladin version of the simulation requires small times steps, this is very slow – about 3-5 minutes per encounter (unlike the warrior version(link), which is 5-6 seconds per encounter). To determine stat weights, we calculate total damage intake at the base stat values and then again with 1500 points of each stat added (“Remember that thing I said was very slow? Great, now go do that 6 more times!”), and compare the results to determine TDR stat weights.
Our input values are based on a Mists of Pandaria LFR gear set (ilvl 483), with the following relevant stats:
buffed STR: 9208
parry rating: 4834
dodge rating: 4892
mastery rating: 6758
hit rating: 900
exp rating: 1777
haste rating: 621
The boss swing timer is assumed to be 1.5 seconds. I’ve artificially shifted hit rating into haste rating on the gear set so that adding 1500 points of hit won’t over-cap us.
The table below summarizes the statistical information about the simulation. The first three rows represent the mean mitigation scale factor, the standard deviation of that scale factor over all 10 runs, and standard deviation of the mean (basically a measure of the repeatability of the mean value if we ran the simulation again). The bottom three rows are the same data, but normalized by the mastery value (i.e. 0.0091). This doesn’t change the results any, it just makes comparisons easier.
N=10, tau=10000, stat=1500 | | dodge | parry | hit | exp | haste | mastery | | mean | 0.0067 | 0.0073 | 0.0064 | 0.0043 | 0.0027 | 0.0091 | | std | 0.0005 | 0.0005 | 0.0006 | 0.0004 | 0.0004 | 0.0006 | | std_mean | 0.0002 | 0.0001 | 0.0002 | 0.0001 | 0.0001 | 0.0002 | | | | | | | | | | mean | 0.7415 | 0.8067 | 0.7011 | 0.4776 | 0.3025 | 1.0000 | | std | 0.0585 | 0.0512 | 0.0623 | 0.0483 | 0.0422 | 0.0712 | | std_mean | 0.0185 | 0.0162 | 0.0197 | 0.0153 | 0.0134 | 0.0225 |
Mastery is a bit ahead of dodge and parry, while hit is not far behind dodge. Expertise trails further, as expected, and haste trails by even more. Mastery pulling ahead is partly a function of how the simulation handles SotR. In earlier versions, I was lumping it in with the GCD-based casts. Then it occurred to me that since it’s off-GCD, it would make more sense to attempt to cast it any time an event occurs (either a boss swing or the GCD). So I moved it out of the GCD section and put it at the front of the loop. Basically, any time anything should happen, we first check to see if we should cast SotR, and if we can, we do so.
This introduces a bit of an anomaly. Essentially, we know exactly when every boss attack is coming, and we try to make sure we cast SotR immediately before it happens. That gives us an unnaturally high effective uptime on SotR, because we’re using it preferentially. If I put it at the back of the cast sequence, such that the code handles all of our GCD-based abilities and boss swings before checking if we cast SotR, I get the following results:
N=10, tau=10000, stat=1500 | | dodge | parry | hit | exp | haste | mastery | | mean | 0.0078 | 0.0081 | 0.0043 | 0.0027 | 0.0031 | 0.0071 | | std | 0.0005 | 0.0004 | 0.0002 | 0.0004 | 0.0005 | 0.0002 | | std_mean | 0.0002 | 0.0001 | 0.0001 | 0.0001 | 0.0001 | 0.0001 | | | | | | | | | | mean | 1.0897 | 1.1391 | 0.6100 | 0.3758 | 0.4411 | 1.0000 | | std | 0.0729 | 0.0498 | 0.0333 | 0.0618 | 0.0654 | 0.0265 | | std_mean | 0.0231 | 0.0158 | 0.0105 | 0.0195 | 0.0207 | 0.0084 |
As you can see, dodge and parry fare better here. The first set gives us a better feel for what a careful tank who’s anticipating boss attacks will experience, while the second set is a better representation of sloppy play. The stochastic average (which is what the spreadsheet calculates) should be somewhere closer to the latter. And, if we compare all three on on table, we find that this is pretty much the case:
stat SS MC 1 MC 2 parry: 1.1418 0.8067 1.1391 dodge: 1.0931 0.7415 1.0897 strength: 1.1155 mastery: 1.0000 1.0000 1.0000 hit: 0.6866 0.7011 0.6100 exp: 0.4413 0.4776 0.3758 haste: 0.4810 0.3025 0.4411
Most of the stat weights line up pretty well, at least within a reasonable margin of error. The major outlier is haste, which seems to come out consistently low in these Monte-Carlo simulations. I’m not sure exactly why, either – so far I’ve looked in all of the places I could think of that might cause that sort of depression in value, and couldn’t find a bug in any of them.
My guess at this point is that it’s a discretization error. Because of the way we’re using SotR extra haste is less effective at creating overlap between SotR and boss swings. If we were casting SotR pseudo-randomly within time slots, haste should make more difference, because it would increase the number of times that SotR and the boss swings overlap. It’s still doing that to some extent, of course, but it’s less effective when we limit SotR casts to be only on the GCD or coincident with a boss swing. It’s an open question which model is more accurate.
In any event, we now know that the Monte-Carlo and the Spreadsheet are in pretty good agreement. We’re not getting results that we can’t substantiate, like haste or expertise topping dodge and parry. That gives us a level of confidence in both tools, and leads us to our next line of inquiry: what about spike damage? The entire debate over whether to use avoidance gearing or hit/exp/mastery/haste gearing hinges on whether you value TDR or “damage smoothing.” In the next blog post on this topic, I’ll use the Monte-Carlo to try and answer these questions.