Those look very much like B-splines, which are related to Berstein Polynomials but can be more complicated. They might be nonuniform, rational B-splines or have some sort of other modification to make it fit so the probabilities of each of the different resistance levels adds to 1.
I've done some work with B-splines this year and they have the many of the qualities which would best represent this sort of function. They partition unity (IE the basis functions add up to one) which is good for probabilities, they are always nonnegative if they have nonnegative coeffients, and they can be calculated simply by piecewise polynomials. Marsden's Identity allows you to fit any low enough order polynomial exactly, although locking the resist values to 0%, 25%, 50%, 75%, 100% makes me doubt that they are simple uniform rational B-splines like in sui's picture. Some form of B-spline would also make it easy to extend out one more knot and add in the 100% versus only going up to 75%.
The only other explanation that I could come up with would be some combination of exponential functions, such as in normal or exponential distributions. But that would be a lot more complicated to figure out and calculate, which makes me doubt that is what they are.
Edit: also exponentials wouldn't evaluate exactly to zero for zero resistence, so you would have a miniscule but nonzero chance of resisting with no resistence, whereas with a B-spline you could easily make it exactly zero for zero resistance. And empirically we don't see partial resists with no resistance on players.
Before I go to bed now, i wanted to clarify a bit.
I was not suggesting that the unchanged Bernstein Polynomials formed the basis for the resistance mechanic. A quick check for the Bi4 Basis (as to implement full resists) showed that there is no way that this could be the case, as the mismatch to blizzard posted resists was enormous.
I was merely suggesting that they could have been expanded in one form or two (and to show that a piecewise linear approximation is not needed to achive such characteristics as worded on the blizzard resistance page)
Aesthete pointed out that there could be some B-Splines in play. (for which the bernstein polynomials are used) and which would have some very nice attributes ... such as the observed cutoff of 0% resists at a certain resist level.
I'd suggest to collect more data so we get more points. This would be way more effective than to start reconstructing linear or polynomial base functions at this moment.
Please don't be rude and patronising. Try it yourself - plot the Blizzard data and the gathered data on the same axes - they're not in any way contradictory. So I think the assumptions I've made based on that data are reasonable.
As others have posted, there are plenty of ways to get nice smooth curves that together sum to zero while still remaining >0 in all cases. So it doesn't have to be partial linear. On the other hand, we know Bernstein cubics are wrong, because:
1) We should have 5 curves, not 4. Yes, for this data set, since it's melee data, 100% resists are being converted straight over to 75% resists. You still need to fit 100% and 75% resists separately if you want to derive the underlying algorithm. Any overly neat equation you derive for the 75% values in that data is thus by definition wrong, since it's the sum of two terms.
2) We know that resistance tops out at 75%, while the Bernstein equations are symmetrical and will give a 100% chance of a 100% resist at 100% of total resist.
Quigon: you state (with only this dataset for evidence) that the chance of a 0% resist goes to 0 at ~68% of total resist. Have you tested this statistically? Is the data set large enough to make that call? 1% is not easy to observe - especially if it's actually rounded up from 0.5% (or thereabouts) in Blizzard's published tables. As I said - try it yourself: plot Blizzard's figures and the measured figures on the same axes. The fit is just too good for Blizzard to be lying (which is what you're implicitly claiming).
Suiciuque: in contrast, I think you're a little too critical of the dataset - especially your criticism of the last point. Yes, the average resistance hardly changes between the points - but that's because they're measured at 100.53% and 108.42% of total resistance - we're expecting them to be identical! In fact, we can use the assumption that the 100.53% and 108.42% points should be identical to get a rough idea of the size of the error bars in the data set. Based on that, it looks to me like the error margin is around 1% each way. Certainly way to wide to be making the kind of dogmatic claims Quigon's making about values that go to zero.
Summary of wall of text: these values in no way contradict Blizzard's published values, and you don't have to invoke piecewise linear functions *or* negative probabilities in order to fit them. Error margins on the gathered data are likely to be around 1%.
The larger points are Blizzard's published values. I don't see how you can claim there's a significant difference between the gathered data and Blizzard's data. Not if you have the least understanding of error margins in data sets.
Songster, this thread data is in regards to melee elemental swings. There is a 0% chance to be hit past a "magic number." This is different than blizzard's values afaik.
My "joke" graph was in reply to the silly comment that you cannot have a function go negative and have it function in a program, when obviously you can in coding, and in really most anything, and the function for defense does that very same thing. There are clear limits in place that every major program puts forth, and conditionals with barriers.
Also... I graphed both already, I did "try it myself."
Quigon: you state (with only this dataset for evidence) that the chance of a 0% resist goes to 0 at ~68% of total resist.
Read the Hydross thread - I'm not really making this claim up... I should've been hit many times by now with a zero-resist. You are not able to be hit by a 0% resist at max resist... that is why this entire thread was made in the first place.
Clumping 100% and 75% together is one thing, but that isn't what their data table is showing now is it? I agree that adding them together is a decent approximation, but the connotations are pretty large for that, as indicated by a previous poster (something like 25% mitigation in efficacy terms)... and that is part of the point of this thread, to denote reality, not what blizzard probably changed 1 year ago.
Piecewise linear functions as proposed by Arawethion:
It seems a reasonable assumption then that the cutoff for 25% resists will occur at 200 x attackerLevel / 60.
This would be at 244.33 resist for a L73 attacker, 126.66 resist for a L38 attacker. I assume that the server would use a look up table with limited precision to actually perform the resist check. Depending on the level of precision then you would have to round up past the nearest multiple of some number, perhaps 1 or 5 or more to break the no 0% hit barrier.
Here's my latest curves, fixed the abberation at high resistances:
The key point is that average resist is NOT linearly increasing! As we can see from the data, the 100% resists are getting converted to 75% resists. Therefore average resists will start at 0.75 * x, but will drop down at the end (to about 0.7 * x) due to the higher number of full resists.
Piecewise linear functions as proposed by Arawethion:
It seems a reasonable assumption then that the cutoff for 25% resists will occur at 200 x attackerLevel / 60.
This would be at 244.33 resist for a L73 attacker, 126.66 resist for a L38 attacker. I assume that the server would use a look up table with limited precision to actually perform the resist check. Depending on the level of precision then you would have to round up past the nearest multiple of some number, perhaps 1 or 5 or more to break the no 0% hit barrier.
that looks pretty good, although i still contend that collecting more data will make it easier to make a determination between piecewise-linear and higher order polynomial fits.
It seems like the only issue with Blizzard's info is that whoever made the chart assumed you couldn't hit 0% to take full damage. Which, interestingly enough, means that that was probably intended at some point. I bet whoever designed Hydross is annoyed.
And the findings I got from this thread (up to this point) are:
1) After a certain cutoff point you can be sure to eliminate 0% resists. This is backed up by the Hydross fight which would be at no way tankable in his 250% mark state. Obviously he has been tanked from 100 to 0 in this state.
2) The avg resist you can expect with full resist gear is lower than the stated 75%. This has been backed up by data which show a significant delta to the expected 75%, but I remain skeptical. Are we sure to exclude methological errors in the tests?
If it is verified, this observation makes going for full reisist gear slightly less desirable.
Kenco in fact suggests that stopping early could sport better results.
Both of these findings I find very worthwhile and look forward to further validation. Thanks for the data.
Last edited by suicuique : 04/05/07 at 4:34 AM.
Reason: typos
Piecewise linear functions as proposed by Arawethion:
{picture}
Thanks, that's exactly what I was thinking. Can you post the coefficients you used to draw those lines?
I don't understand the confusion about the fact that average mitigation is tailing off near the cap. It seems clear that it was intended to grow linearly, and will grow linearly against attacks which allow a full resist.
2) The avg resist you can expect with full resist gear is lower than the stated 75%. This has been backed up by data which show a significant delta to the expected 75%, but I remain skeptical. Are we sure to exclude methological errors in the tests?
If it is verified, this observation makes going for full reisist gear slightly less desirable.
Kenco in fact suggests that stopping early could sport better results.
Some old data I gathered back a few months ago show the same thing for average resists in BRD (heh someone was saying resists were tiered and I said they weren't so after a raid ran off to BRD to gather data since couldn't find anything easily). Posted them as well somewhere here on these forums.
Recording of that data was by taking the first Blazing Fireguard in BRD aggroing him taking some fire damage for a while with an addon that recorded damage resisted and damage taken at a certain fire resist level. Do a few things to change fire resist while I'm in combat (addon stores the numbers based on current resist level). Run out of the instance and back in change gear and redo till I figured I had enough data.
Big thing is the data capped at 69.7% though I didn't think of it at the time it concurs with this data on value in that similar range.
For the image I posted previously I snapped some lines over the graph in photoshop. After looking at the numbers closely a bit I picked out some points that seem to work and produced equations for them below.
I've been doing some of my own research about resistances and I've discovered the following:
1) Crit chance is independent of level-based resists. Take a level 25 Warlock with 10% Shadowbolt crit and shoot a few dozen shadowbolts at a level 70 with no shadow resist. You'll get 70-75% resisted, 15-20% hits, and ~10% crits.
2) No matter how much resist someone has, shoot enough spells at them (in PvP) and you'll eventually get a full-damage hit; even if you're a low-level character shooting rank 1 shadowbolts at a level 70 with resistance gear. This is easily confirmed in game, though it might take a few hundred casts to get the hit. Therefore, the "1% chance of full damage hit" in the Blizzard resistance table (http://worldofwarcraft.com/info/basics/resistances.html) appears to be correct.
3) The numbers given in the OP's spreadsheet match the Blizzard table pretty closely with the following modifications:
All 100% resists are replaced by 75% resists (at any point).
At 131 resistance and above (69%+ of max resist), all 0% resists are replaced by 25% resists.
4) Attempting to perfectly match Blizzard's table with the suggested triphasic linear function (0->25% resist, 25-50% resist, 50-75%) is impossible. That said, it's not hard to come damned close.
4A) The following resistance table was drawn by hand and averages out to a perfect 25%, 50%, and 75% resistance. It is a reasonable fit for both Blizzard's table and the datamined data, although it tends to have more error around the 40-50% portion of the table. It also contains the 1.0% "no resist" chance from the Blizzard table.
5) It is entirely possible that the function is linear but with four segments:
0-25%
25-37.5%
37.5-50%
50-75%
I'll try refitting it to that curve when I get more time.
6) All that said, the important part for raiders is the two conclusions that were supported by the very first post:
- Beyond 50% average resist (2/3 of MAX or 244 resist against a 73 boss) elemental melee attacks will never hit for full damage.
- You cannot fully resist an elemental melee attack, therefore resistances above 2/3 MAX are slightly less useful. (though still necessary for Hydross MT)
With the additional caveat that player spells and possibly mob spells always have a 1% chance to be entirely unresisted. Not that it matters, as any "spell" that hits hard enough to matter is either binary to begin with ("Shadow Flame") or should be completely avoided. ("Dark Glare")
No offense, but thats basically the stupidest thing i've read on EJ in a long time. Going below 0 is perfectly legal. Why in the world would it not be?
Probabilities have to add to 1, with none less than 1 in the domain in question (resists at 0 to level*5).
Hrm. Got a fair bit of empirical data here with corresponding observations and exceptions. Nailing down the exact algorithm might be as simple as now considering what is probable (as opposed to possible) with regards to the actual coding blizz might be using. I think it's very safe to say that they aren't doing any high order math, as the results from casts and melee dmg events must be coming from the immediate action/resolution stack. So what type of calculation could they be doing, given that there are literally hundreds/thousands of these results being generated per second?
At a guess it's some type of bit shift/filter, but it's been literally the better part of two decades since I looked at MUD/MUSE code. I can think of a few ways to implement a (really fast/efficient) simple lookup table as well... any ideas? The whole combat system must be heavily optimized, there's simply no time to do anything complicated.
I remember testing in EQ, where there seemed to be several components in their RNG for entire zones that had measurable durations in real time (1 server tick, resulting in strings of crits/resists for an entire raid, monster loot on initial spawns after zone resets, etc.). I haven't seen the same thing in WoW, but that could simply be due to better coding and faster hardware. Anyway, with the data available for resists, and a few (reasonable?) assumptions, we should be able to make a good guess how they coded the resist calculations.
Having said that, the conclusions mentioned in previous posts are all that really matter to anyone who isn't trying to code a private server I guess. Fun topic tho.
Last edited by Remf : 07/11/07 at 7:35 PM.
Reason: removed offending 4 letter sig
Interesting reading there...
The post is dealing mainly with melee elemental damage.
1) Do we have a similar trend for spell damage ? 0% resist never happening beyond an amount of resist ? etc... (I did a search, nothing found easily :/)
2) About the 70% resist convergence ... Does that mean the max mitigation we can have from resist gear seems to be 70% ? Did someone perform tests concerning binary spells / basic spells on that as well ?
Decided to go back and re-read the blizz web page, here's the relevant bits (I bolded a few key parts).
When hit by a spell, you have two chances to resist the spell. The first chance is based on your level. If you are much higher level than the attacking caster, you will have a significant chance to resist the caster's spell, but if you are much lower level, you will have a minimal chance to resist the spell (minimum of 1%). If you make this resistance chance, you are completely unaffected by the spell.
Sounds like this is coded as a separate check, presumably before the "amount resisted" check below... and is likely skipped if the source of the damage is melee instead of a cast spell perhaps? Or converted directly (and transparently) into a miss?
The second chance to resist is based on your resistance score and the level of the caster. The higher your resistance score in relation to the level of the attacking caster, the higher your average resistance percentage, up to a maximum of 75%. Against most spells, this resistance percentage is the straight % chance to completely resist the spell. Against direct-damage spells (spells that deliver their full damage upon impact, such as Fireball, Mind Blast, and Earth Shock), this resistance is the percentage of damage you will resist on average.
So, for direct dmg, you can resist at most, on average, 75pct. Since there are no 100% resists reported for "melee spell damage" hits, either the 100% resists are converted to 75%, as proposed in other posts above... or perhaps they are converted into "misses" instead? Would need to look at hit% as a function of resist to see which was occuring... any chance the OP might take a look at that?
If the 100% resists in melee are really converted into 75% resists, but the average percent resisted remains consistent at the expected value, then I guess I'm pretty impressed with the coding. If they are simply/transparently converted into "misses", then a much simplier (and consistent between "melee" and "ranged" spell damage) coding would work.
I think that makes sense, apologies if I'm missing something basic.
Last edited by Remf : 07/11/07 at 8:09 PM.
Reason: fixed some formatting
Man this thread. Dragons, danger zone, and a lot of proof that some of us have too much free time at work... good times.
Remf, if you look in this thread there is already a graph that compares elemental melee to blizzard's data (was mine or someone else's graph). I would think you'd see an aberrant number of misses if they were just transfered... but we don't see that - some resist checks are straight up different - like Sapphirons aura is almost never resisted. And column stacking doesn't seem to work either so much since you cannot take a 100% hit, and thats a 1% for blizzard's column. I guess it is close though.
I calculated chi^2 for those and the results point at those having near 0 chance of being true according to the chi^2 calculator on Chi-Square Calculator
Here's the file with the calculations: FileFactory.com - free file hosting
I estimated the error for the number of resisted spells as (resisted spells)^0.5 and divided that by the number of total spells casted for estimated error in resist % and used a macro to make a parabolic graph of A0+A1X+A2X^2:
results (non-weighted fit, I'd rater have weighted fit but the macro I used is kinda buggy with my office version):
NON WEIGHTED FIT
A 0
1.004617
2.233255E-02
A 1
-2.809561
.1515186
A 2
2.009645
.2164369
R^2
.9922916
COV(A 0,A 1)= -2.701701E-03
COV(A 0,A 2)= 3.111546E-03
COV(A 1,A 2)= -3.150472E-02
R^2 being 0.99 is not bad at all, as well as very low covariances between A0/A1/A2, when if the fit was perfect we'd have R^2=1 and (i=/=j) COV(Ai,Aj)=0. I'm not too sure though but considering the margin of error in the data (up to 7% relative error) it looks like it's as close as we can get without further testing, although with a really good fit I would expect R^2 to be more around 0.999...
So chance for 0% resist is 1.81t²-2.6t+.99 if this is really how it works, with the errors in coefficients for t listed above under their values, and t being the relative resistance you have compared to max resistance.
For 25% though trying to adjust a second order polynom of A0+A1x+A2x^2 just doesn't work, R^2=.7629074 which is very far from fitting well. Doing the same for 50% yields results almost as bad, and doing the same for 75% yields better results but still probably not close enough (R^2=0.97 and chi^2 norm=13.3 which is just not good).
While my "error" estimation could be inaccurate (although I think with a big sample size it's a reasonable estimation), it looks like the chance to resist 0% is at least something very close to a 2nd order polynom between 0 resist and max resist needed for 0% chance to see it. The rest of the resistance values are something more complicated than a 2nd order polynom.
Here's the file if you're interested (although I didn't make it too easy to read was kinda in a rush to get done with it): FileFactory.com - free file hosting
Feel free to edit those files again if you find any errors or find a better way to do it.
EDIT: Removed the "0" points from the graph for 0% chance and updated the results accordingly (but not the uploaded file)
Also the minimum point of the polynom is at like 70.5% which is higher than what claimed earlier. Of course I didn't go into calculating the error of it (which I really don't have time for right now but it's perfectly doable) and see how much lower resistance you'll need to have and still never see 0% resistances to disprove the polynom formula.