Latest Diablo 3 News
DiabloWiki Updates
Support the site! Become a Diablo: IncGamers PAL - Remove ads and more!

Calculating experience for Pindleskin

Discussion in 'Theorycrafting and Statistics' started by Crehl, Jul 10, 2010.

  1. Crehl

    Crehl IncGamers Member

    Joined:
    Jul 29, 2007
    Messages:
    171
    Likes Received:
    0
    Trophy Points:
    41
    Calculating experience for Pindleskin

    I have a spreadsheet that calculates the experience gained by running Pindleskin + minions on any difficulty, /players setting and character level. I thought I had it working correctly down to an exact amount of experience, but it turns out it's incorrect in some situations, often just 2 or 3xp (14 or 21xp for the entirety of Pindleskin + his minions on normal) - though I've one case which was off by 27xp (243xp for Pindleskin + minions on hell). In all cases I've tested my calculator thought the xp gained was higher than the real amount.

    I've tested it through with a 47 barb on normal (As well as 45+46, which show the exact same results, to be expected), an 82 paladin on hell and a 90 sorceress, also on hell:

    Barbarian: (Clvl 47, Normal Pindleskin - mlvl 45, base xp 12845)
    -Works correctly for /p1, /p3, /p5 and /p7
    -/p2: Calculates 19,267xp, actual value: 19,265 (-2xp)
    -/p4: Calculates 32,112xp, actual value: 32,110 (-2xp)
    -/p6: Calculates 44,957xp, actual value: 44,955 (-2xp)
    -/p8: Calculates 57,802xp, actual value: 57,800 (-2xp)

    Paladin: (Clvl 82, Hell Pindleskin - mlvl 86, base xp 254500)
    -Works correctly for /p2 - /p7
    -/p1: Calculates 94,790xp, actual value: 94,789 (-1xp)
    -/p8: Calculates 426,555xp, actual value 426,528 (-27xp)

    Sorceress: (Clvl 90, Hell Pindleskin - mlvl 86, base xp 254500)
    -Works correctly for /p1 - /p8

    As an example, this is how I calculate the experience for my Paladin on /p8:
    Code:
    clvl = 82
    mlvl = 86
    baseXP = 254500
    
    mlvl - clvl = 4 [So, we use clvl/mlvl]
    clvl/mlvl = 82/86 = [b]0.9535[/b] [Correct to 4dp here, exact value is used in the calculator]
    
    clvl >= 70 [So, we apply another penalty]
    400/1024 = [b]0.3906[/b] [Again, only correct to 4dp here.]
    
    /players 8, so we get an xp bonus
    (8 + 1)/2 = [b]4.5[/b]
    
    [b]0.9535[/b] * [b]0.3906[/b] * [b]4.5[/b] = [b]1.6761[/b] [Again, only correct to 4dp here]
    
    254500 * [b]1.6761[/b] = [b]426,555.7[/b] [1dp this time. I [i]believe[/i] this is rounded down based upon the results from my Sorc:]
    int([b]426555.7[/b]) = [b]426,555 xp[/b]
    
    As I mentioned before, the correct value is actually 426,528xp. Evidently this isn't a huge issue if I'm off by around 0.01% in the some of the worse cases, but I'm a sucker for perfection and I want to know the exact formulae and values I need, and not something that's "almost there". I'm far more of a mathematician than an engineer ;)

    Can someone help me out here? Show me where I'm going wrong? I'm almost certain it's to do with the /players command as that's the only thing that should affect the XP gained on the barb, who is within 5 levels above Pindleskin, and is far from the level 70+ penalties. The fact that it works perfectly on my Sorceress across the board, falters on /p1 and /p8 with my Paladin and every other /pX with my Barbarian is simply confusing for me.

    Thanks,
    -Crehl

    Update #1:
    After plenty of time spent messing around with the formulae and many more Pindleskin runs (Not to mention late nights at 4/5am) I've made some progress. I'm only updating this now for future reference for me and/or anyone who comes across this thread looking for the answer.

    Based on everything I've done in Normal & Nightmare (I shall get to Hell in a second), it seems that D2 does the following:

    1. Takes the Base XP and multiplies it by the /players factor (e.g., 4.5)
    2. Rounds down to the nearest multiple of 5
    3. Multiplies by the clvl/mlvl factor (Sometimes clvl/mlvl, sometimes 1, sometimes from a lookup table using clvl-mlvl)
    4. Multiplies by the clvl penalty factor (For clvl >= 70)

    This appears to explain everything I've seen in Normal and Nightmare. The Base XP for Pindleskin in both those difficulties is 12845 and 74805 - both multiples of 5 but not 10. Hence, multiplying by 1, 2, 3 or 4 (/p1,3,5,7) will result in a multiple of 5 - so rounding to the neareast 5 makes no difference and my formula still works for those players settings.
    Multiplying by 1.5,2.5,3.5 or 4.5 (/p2,4,6,8) won't result in a multiple of 5, but will result instead in a slightly greater number (2.5 greater than the next-lowest multiple, in fact). Rounding down to the nearest 5 and continuing with everything else results in correct values for everything I've got data for in Normal and Nightmare (Most of the late 40's - mid 60's, in terms of clvl).

    Unfortunately, the results I got from my Paladin in Hell would still be incorrect. The Base XP for Pindleskin in Hell is 254500 - a multiple of 10 so multiplying by any of the players settings will always result in a multiple of 5 anyway.

    This means (As far as I can tell) at least one of three things is hapenning:

    1. The experience formula works differently in Hell for some reason
    2. My formula is still not correct with regards to the clvl penalty
    3. Experience is calculated slightly differently depending on the class

    Firstly, I am highlighy dubious of no. 3. Not likely to happen at all (I have no idea why it would, anyway), but until I've got data to rule it out, it's a possibility.
    No. 1 and 2 then, would have to work in such as way that at clvl90 in hell things are identical to my calculations, but differ at clvl 82.

    A bit of a long edit, but there's a chance - albeit a very small one - that someone running into the same problems as me will benefit from this.

    Update #2:
    It occurred to me shortly after that last update that Uniques get a 5x bonus to their experience.. which would explain the strange rounding if the 5x is applied after rounding down to the nearest integer instead. Essentially the same thing, but makes a little more sense. I have also found that at /p1 and /p5 on Nightmare even my new calculations don't work.

    Damnit Diablo, why do you do this to me.. :/
     
    Last edited: Jul 15, 2010
  2. Victus

    Victus IncGamers Member

    Joined:
    Apr 27, 2008
    Messages:
    278
    Likes Received:
    0
    Trophy Points:
    42
    Re: Calculating experience for Pindleskin

    Hi,there! I looked at the german exp calculator and found that it calculates the exp for your paladin (clvl82, hell Pindleskin) on p1 and p8 correctly. But it shows the wrong values (which you calculate in your post) for your barbarian (clvl47, normal Pindleskin) on p2,p4,p6 and p8.
    I'm not a programmer but was curious to know why this happens. The source code of the page on the calculator shows one really interesting thing: there is different rounding down formula for experience above or equal to 0x100000 (2^20=1 048 576 in decimal) and above or equal to 0x200000 (2^21=2 097 152) compared to the formula for experience below 0x100000.

    First the game defines the case when clvl>=mlvl:
    Code:
    if (clvl >= mlvl) {
    		switch (clvl - mlvl) {
    		case 0:
    		case 1:
    		case 2:
    		case 3:
    		case 4:
    		case 5: penalty = 256; break;
    		case 6: penalty = 207; break;
    		case 7: penalty = 159; break;
    		case 8: penalty = 110; break;
    		case 9: penalty = 61; break;
    		default: penalty = 13;
    		}
    		if (penalty != 256) {
    			if (exp < 0x100000) exp = Math.floor(exp * penalty / 256);
    			else exp = Math.floor(exp / 256) * penalty;
    		}
    	}
    As you can see when exp>=0x100000 you could get slightly less experience because of the rounding down.

    The next part defines the special case when clvl<25 and mlvl>=clvl:
    Code:
    else {
    		if (clvl < 25) {
    			switch (mlvl - clvl) {
    			case 0:
    			case 1:
    			case 2:
    			case 3:
    			case 4:
    			case 5: penalty = 256; break;
    			case 6: penalty = 225; break;
    			case 7: penalty = 174; break;
    			case 8: penalty = 92; break;
    			case 9: penalty = 38; break;
    			default: penalty = 5;
    			}
    			if (penalty != 256) {
    				if (exp < 0x100000) exp = Math.floor(exp * penalty / 256);
    				else exp = Math.floor(exp / 256) * penalty;
    			}
    		}
    And the only case left when clvl>=25 and mlvl>clvl is:
    Code:
    else {
    			if (exp < 0x100000) exp = Math.floor(exp * clvl / mlvl);
    			else exp = Math.floor(exp / mlvl) * clvl;
    		}
    	}
    Then comes the penalty for clvl>=70:
    Code:
    penalty = 1024;
    	switch (clvl) {
    	case 70: penalty = 976; break;
    	case 71: penalty = 928; break;
    	case 72: penalty = 880; break;
    	case 73: penalty = 832; break;
    	case 74: penalty = 784; break;
    	case 75: penalty = 736; break;
    	case 76: penalty = 688; break;
    	case 77: penalty = 640; break;
    	case 78: penalty = 592; break;
    	case 79: penalty = 544; break;
    	case 80: penalty = 496; break;
    	case 81: penalty = 448; break;
    	case 82: penalty = 400; break;
    	case 83: penalty = 352; break;
    	case 84: penalty = 304; break;
    	case 85: penalty = 256; break;
    	case 86: penalty = 192; break;
    	case 87: penalty = 144; break;
    	case **: penalty = 108; break;
    	case 89: penalty = 81; break;
    	case 90: penalty = 61; break;
    	case 91: penalty = 46; break;
    	case 92: penalty = 35; break;
    	case 93: penalty = 26; break;
    	case 94: penalty = 20; break;
    	case 95: penalty = 15; break;
    	case 96: penalty = 11; break;
    	case 97: penalty = 8; break;
    	case 98: penalty = 6; break;
    	case 99: penalty = 0; break;
    	}
     
    	if ((clvl < 70) && (exp < 0x100000)) exp = Math.floor(exp * 1024 / 1024);
    	if ((clvl < 70) && (exp >= 0x100000)) exp = Math.floor(exp / 1024) * 1024;
    	if ((clvl >= 70) && (exp < 0x200000)) exp = Math.floor(exp * penalty / 1024);
    	if ((clvl >= 70) && (exp >= 0x200000)) exp = Math.floor(exp / 1024) * penalty;
    The last part is for experience bonus. That should be (not sure though) experience from experince shrine, anni, ondal staff:
    Code:
    if (expbonus > 0) {
    		if (exp <= 0x100000) exp += Math.floor(exp * expbonus / 100);
    		else exp += Math.floor(exp / 100) * expbonus;
    	}

    This should answer your question about the 27exp difference (due to different round down) and 1exp difference (due to the rounding on each step above).
    About your finding that experience is rounded down to a multiple of 5 after the players count is applied it looks like the most simlpe and logical explanation for the 2exp differences. (look at the edit for other explanation)
    Hope you'll test and confirm that. :thumbup:

    EDIT: I think I've found what causes the 2exp difference. The game first calculates the experience of the normal monster on a given players count, rounds down that value and then multiplies it by 5(for minions and uniques) or by 3(champions).
    Example: Normal Defiled Warrior at p1 gives 2569exp. So at p2 the experience is int(2569*1.5)=3853. Normal Pindleskin at p2 gives 3853*5=19265.
     
    Last edited: Aug 18, 2010

Share This Page