6.2 Tiger Strikes uptime

Update: Geodew has correctly pointed out that because of the low amount of proc events within the duration of the buff, and because you can’t have partial attacks, the Poisson process is not valid. Check back for a corrected post later today. (view the bottom of this post, and the comments, for the conclusion I came to with Hamlet)

As we covered earlier in the 6.2 first look, the structure of Tiger Strikes is changing. It’s losing the ability to proc from multistrikes, but increasing the amount of multistrike it gives when it does proc. So currently, you have a 10% proc chance on all melee attacks and melee multistrikes, and after the patch, it’s merely a 10% proc chance on all melee attacks, but not their multistrikes.

The primary difficulties in theorycrafting the uptime for Tiger Strikes are the fact that it can overlap itself, refreshing the buff instead of stacking or adding time, and the fact that when Tiger Strikes is up, you have a higher chance of further Tiger Strikes chances because of the higher multistrike chance it gives. The 6.2 change removes this second aspect, so all you have to worry about is the overlapping procs.

I was first looking at the effects of weapon speed, haste, and multistrike on Tiger Strikes about two months ago, and ran into all of these same issues. I asked noted WoW theorycrafter Hamlet if he had any tips and he pointed me in the direction of this post, which didn’t quite work out for me because it had the same issues with the multistrike buff. I kept it in the back of my mind, though, and in 6.2, it’ll be perfectly applicable.

If you scroll down to “More Elaborate PPM: Overlaps and Poisson”, this is exactly what we need. Tiger Strikes has a proc chance rather than being PPM, but the PPM isn’t the essential part of the formula anyway. The uptime formula is 1 - e^{-\lambda}, where \lambda is the average procs in the duration of the buff. Then we just have to figure out how many times we attack every 8 seconds (the duration of Tiger Strikes), multiply by .1, and there you have it. The result for \lambda is .1*(8/(Base Weapon Speed/(1+raid buffed haste))), with (1+ raid buffed haste) multiplied by 1.55 if you have a two-hander to account for Way of the Monk. The final formula you have for Tiger Strikes is then

1-e^{-{.1*(8/(BAT/(1+RBH)))}}

We’ll then check this against our sim , which gave us an estimated 46.08% uptime with base attack speed of 1.6 and 1007 haste. That turns into 19.08% raid buffed haste with haste food. Plugging these values in gives us a result of 44.86%, which is close enough for me to breathe a sigh of relief over my sim being mostly accurate.

The section I chose from that post was wrong for these purposes. I missed the most important part: “This is a good model for WoW procs as long as the attack rate is very high compared to the time intervals being examined.” With 3-6 attacks in that 8 second period, that requirement is not met. Instead, we can use the first formula from the appendix, as follows.

{1-(1-P)^N}

In our case, P is the proc chance, 0.1, and N is the number of attacks in the buff period, or how many attacks you can fit into 8 seconds. This is simply 8/(BAT/(1+RBH%/100)). Geodew points out that since attacks are discrete events, you should round down. In our case, with 1007 haste and 250 haste from food, raid buffed haste is 19.665, and base attack speed is 1.9. 8/(1.6/(1+19.665/100))=5.98325, which we truncate to 5. Then you do 1-(1-.1)^5 = .4095, or 40.95%. This is a fair amount lower than the other approximation, which invites further investigation.

If we treat partial attacks as valid, we don’t truncate at all. 1-(1-.1)^5.98325 = .467620, which is 46.76%. This is strikingly close to the simulated result of 46.08%. I’m not saying the sim is perfect, but it does seem curious that the result is so much closer to the non-truncated result. Perhaps treating attacks as discrete is the wrong way to approach it, over long periods of time? Perhaps the sim is way off? I’ll run it again in a few hours when I get home to check the numbers.

Final edit: I got home and ran a longer sim, covering 999,999,999 milliseconds, the equivalent of 277.78 hours. I also made sure to use 250 haste food rather than 200 multistrike food, which I had in an earlier version of the sim. The estimated uptime was 46.76%. I now feel fairly confident in saying treating attacks as discrete events is an incorrect approach.

21 thoughts on “6.2 Tiger Strikes uptime

  1. That’s a very odd result. There’s no reason you wouldn’t expect an integer number of attacks, so it’s worth poking at this more.

    One thing that might be confounding it is that you picked a setup where the # of attacks just is just under an integer (5.98). In theory that shouldn’t matter, because it’s 5 attacks and not 6, and should be the same TS uptime as with 5.01 attacks in the window, but maybe the fact that it’s so close to 6 affects the simulation.

    Does the simulation include any temporary haste effects of any kind?
    Is there any way to check the sim output it detail to see whether, whenever you get a single TS proc, it in fact buffs only 5 swings?

    Basically, now that the MS complication is removed, the discrete model should be a very good one. And while something unexpected can always come up in the real world that makes a model incorrect, it’s different for something unexpected to come up in the simulation (since the simulation only reflects our knowledge, not any unexpected/unknown behaviors). The simulation must be making some assumption that causes the calculation to not be right. It’s worth figuring out what that is so they can be reconciled.

    Like

  2. Also, is the sim measuring “uptime” of the buff, or % of attacks affected? The latter is what matters and what my formula computes.

    Like

    1. I suspect this may be the key here. The sim measures the uptime of the buff. Although Tiger Strikes only procs off of autoattacks, the increase in multistrike% affects all damage events, no matter their source. Because we want to look at the % of all attacks affected, not the % of of autoattacks affected, that’s why I believe we should use the continuous formula rather than the discrete.

      Like

      1. Actually now that I think about it further, to account for DPS gain from added Tiger Strikes, perhaps I should use a weighted average of the discrete formula and the continuous formula, based on how many attacks in each 8 second period are autoattacks and how many are otherwise.

        Like

      2. Yeah, it seems that in a full DPS model, you should use the un-truncated one for the TS uptime (i.e. % of attacks affected) for special attacks, and the truncated one for white attacks. I hadn’t thought about that before–it should be a very accurate model.

        Getting such a good confirmation of the basic formula in a simulation (once we sorted out the tricky part) is really neat too.

        Like

  3. My method on MMOC with n=6 (since I use a different definition of n) and swing speed of (1.6/1.19665) yields 47.4021%.
    0.1*(0.9)^6 = 46.856% (but this may be a coincidence since 5.98325 is so close to 6. Maybe choose a different swing speed for testing?)

    I’ll try to figure out the discrepancies tomorrow.

    Like

    1. Uh, I typed up an entire reply, but I’m not sure it went through… Fucking a… I’ll have to type it up again tomorrow unless it’s just pending and I can’t see it or something, as I’ve got to go. In short, my formula is correct, but I must have punched it in the calculator wrong. The answer is 0.46756992925.

      Like

      1. (as you can see, the fractional exponent thing you did is close, but not correct, and would become more incorrect the farther you go from an integer)

        Like

      2. Did you see the conclusion Hamlet and I came to above regarding discrete vs continuous and white hits vs special attacks?

        Also, I don’t see any pending posts, so I think it went into the void.

        Like

      3. I think I see the problem because it just happened again. The comment is too long to be accepted, and it just deletes it instead of doing anything intelligent. Sorry, but I’ll have to post it in chunks. Wisely, I saved it in a document before trying to post again.
        ——————————————————————————————————–
        Yes, I did see what you guys said, and I was trying to reply :P. It seemed like Hamlet was not sure whether or not the expression
        1-(1-p)^(8/(swing speed)) = 1-(1-.1)^5.98325
        was correctly giving the %time uptime, though. I’m claiming that it is not correct, nor is 1-(1-.1)^5, nor is the continuous-time poisson process model you did.

        Hamlet was correct in realizing that 1-(1-p)^n gives uptime only in the sense of “percentage of autoattacks for which Tiger Strikes is up.” That’s not the formula we want, though, as you two realized; we want “percentage of time for which Tiger Strikes is up.” To help you understand, let me re-derive the formula for the former:

        Tiger Strikes average “uptime,” for autoattacks ONLY
        = P[Tiger Strikes is up at the time of any given autoattack]
        = P[Tiger Strikes has procced in the last 8 seconds, given the current time is that of an autoattack]
        = P[Tiger Strikes has procced in the last n autoattack swings]
        >> where n = floor(8 / T), i.e. Hamlet’s definition; T = time between autoattack swings, including haste effects
        = 1 – P[Tiger Strikes has NOT procced in the last n autoattack swings]
        >> Assume 6.2 proc behavior for now
        = 1 – (1-p)^n
        Q.E.D.

        Like

      4. However, what we actually wanted was this:

        Tiger Strikes average uptime for all steady-state time
        = P[Tiger Strikes is up at time t]
        >> where t is a uniformly random variable in [8.0, infinity] (8.0 to allow steady-state)
        = SUM(P[i autoattacks occurred in the last 8 seconds, given the current time is t] * P[Tiger Strikes would proc after i subsequent attacks]) for i = 0 to +infinity
        = P[n autoattacks occured in the last 8 seconds, given the current time is t] * P[Tiger Strikes would proc after n subsequent attacks] + P[n+1 autoattacks occured in the last 8 seconds, given the current time is t] * P[Tiger Strikes would proc after n+1 subsequent attacks]
        >> See http://imgur.com/OCJYrvM to convince yourself of the above step and the next step
        >> Still assuming 6.2 proc behavior
        = (((n+1)*T – 8.0) / T) * (1 – (1-p)^n) + (((8.0+T) – (n+1)*T) / T) * (1 – (1-p)^(n+1))
        >> for n=5, T=1.6/1.19665, and p=0.1, yields 0.46756992925, which is more than reasonably close to the simulation to give credibility
        Q.E.D.

        However, this makes assumptions about the proc behavior. The reason I derived the formula the way I did on MMOC is because the MMOC formula is easily extensible to the 6.1 case.

        Like

      5. In fact, we can prove the equivalence of the two expressions (i.e. the one above and the first one I derived on MMOC) with some mathemagical algebra.

        Tiger Strikes average uptime for all steady-state time
        = (((n+1)*T – 8.0) / T) * (1 – (1-p)^n) + (((8.0+T) – (n+1)*T) / T) * (1 – (1-p)^(n+1))
        = (1-(1-p)^n) * ((n+1)*T – 8.0) / T + (1-(1-p)^(n+1)) * ((8.0+T) – (n+1)*T) / T
        = (1-(1-p)^n) * ((n+1)*T – 8.0) / T + (1-(1-p)^(n+1)) * (8.0 – n*T) / T
        = (1-(1-p)^n) * ((n+1)*T – 8.0) / T + (1-(1-p)*(1-p)^n) * (8.0 – n*T) / T
        = (1-(1-p)^n) * ((n+1)*T – 8.0) / T + (1-(1-p)^n + p*(1-p)^n) * (8.0 – n*T) / T
        = (1-(1-p)^n) * ((n+1)*T – 8.0) / T + (1-(1-p)^n) * (8.0 – n*T) / T + (p*(1-p)^n) * (8.0 – n*T) / T

        Like

      6. = (1-(1-p)^n) * (((n+1)*T – 8.0) + (8.0 – n*T)) / T + (p*(1-p)^n) * (8.0 – n*T) / T
        = (1-(1-p)^n) + (p*(1-p)^n) * (8.0 – n*T) / T
        = 1 – (1-p)^n + (p*(1-p)^n) * (8.0/T) – n*p*(1-p)^n)
        = 1 – (1-p)^n * (1+n*p) + (p*(1-p)^n)*(8.0/T)
        >> Let N = n + 1 = my MMOC definition of n; => n = N-1
        = 1 – (1-p)^(N-1) * (1+(N-1)*p) + (p*(1-p)^(N-1))*(8.0/T)

        Like

      7. (wtf? my character limit is going down with each post)
        >> Now begins a pattern
        = 1 – (1-p)*(1-p)^(N-2) * (1+(N-1)*p) + (p*(1-p)^(N-1))*(8.0/T)
        = 1 – (1-p)^(N-2) * (1+(N-1)*p) + p*(1-p)^(N-2) * (1+(N-1)*p) + (p*(1-p)^(N-1))*(8.0/T)
        = 1 – (1-p)^(N-2) * (1+(N-1)*p) + p*(1-p)^(N-2) + p*(1-p)^(N-2) * ((N-1)*p) + (p*(1-p)^(N-1))*(8.0/T)

        Like

      8. = 1 – (1-p)^(N-2) * (1+(N-1)*p-p) + (N-1)*p*p*(1-p)^(N-2) + (p*(1-p)^(N-1))*(8.0/T)
        = 1 – (1-p)^(N-2) * (1+(N-2)*p) + (N-1)*p*p*(1-p)^(N-2) + (p*(1-p)^(N-1))*(8.0/T)

        Like

      9. >> Now begins 2nd iteration of pattern
        = 1 – (1-p)*(1-p)^(N-3) * (1+(N-2)*p) + (N-1)*p*p*(1-p)^(N-2) + (p*(1-p)^(N-1))*(8.0/T)
        = 1 – (1-p)^(N-3) * (1+(N-2)*p) + p*(1-p)^(N-3) * (1+(N-2)*p) + (N-1)*p*p*(1-p)^(N-2) + (p*(1-p)^(N-1))*(8.0/T)

        Like

Leave a comment