Programming Pokémon Showdown Damage Calculator

While entry hazards are toggled, in addition to displaying %KO after hazards, is it feasible for phasing moves to display how many phasings will KO?

Also, can the calculator's output be given a more nuanced tense? If a mon's HP after the next hit isn't greater than a turn of sand chip, it's a KO after 1 Hit & 1 sand chip. Yet the calculator calls this a guaranteed 2HKO even if it's not guaranteed that a 2nd hit will ever happen.

with Leftovers held & Sand toggled (1 chip=full/16), the events headsup will be:
Turn 1: 1st Option
Turn 1: 1st Hit (full-dam1)
100 % GTOneHitKO if full>max, else
100 % OneHitKO unless full>min, thence
100 % = OneHitKO % + GTOneHitKO %.
Turn 1: 1st Sand (full-dam1-chip)
100 % GTOneHitSandKO if full>max+chip, else
100 % OneHitSandKO unless full>min+chip, thence
100 % = OneHitSandKO % + GTOneHitSandKO %.
Turn 1: 1st Leftovers (full-dam1)
Turn 2: 2nd Option
Turn 2: 2nd Hit (full-dam1-dam2)
100 % GTTwoHitKO if full>2*max, else
100 % TwoHitKO unless full>2*min, thence
100 % = TwoHitKO % + GTTwoHitKO %.
Turn 2: 2nd Sand (full-dam1-dam2-chip)
100 % GTTwoHitSandKO if full>2*max+chip, else
100 % TwoHitSandKO unless full>2*min+chip, thence
100 % =TwoHitSandKO % + GTTwoHitSandKO %.
Turn 2: 2ndLeftovers (full-dam1-dam2)
Turn 3: 3rd Option
...

my head hurts after pondering the output's tense, but I think there's an inconsistency about the reference point in each turn period. like i think the calculator sometimes calculates the odds to KO over time in the moment after a move has hit but before the turn has ended which is a point where the player has no options, so that calculation is out of phase with the actual times that players can make decisions.
 
Last edited:
The following Gen 3 sets have the wrong hidden power IVs since they don't need the 31st IV to push beyond 252 EVs:

Bug:
Golem: OU Choice Band; UU Choice Band.
Trapinch: NU Choice Band.
Sandslash: UU Swords Dance, Choice Band.
Graveler: NU Choice Band.
Forretress: OU Standard; Ubers Support.
Donphan: OU Choice Band.
Tyranitar: OU Bulky Dragon Dance.
Armaldo: OU Rapid Spin, Knock Off, Choice Band.
Groudon: Ubers Choice Band.
Rayquaza: Ubers Choice Band.

Flying:
Gyarados: OU Standard, Rest.
Raichu: RU Mixed Sweeper.
Feraligatr: Physical Sweeper.
Jumpluff: OU Offensive; UU Swords Dance.
Sceptile: OU Swords Dance Mixed Sweeper.
Ariados: ZU Agility.
Dragonite: OU Standard Dragon Dance, Choice Band, Offensive Dragon Dance.
Gligar: UU Swords Dance + Salac.
Altaria: UU Dragon Dance.
Tropius: NU Swords Dance (PU Swords Dance does run max speed); ZU Physically Defensive

there may be mistakes in some of the special hidden power types, but those are harder for me to find with control-f since possibly minimizing attack causes so many variations.


I've written a few spreadsheet formulas that may be useful, I'll see if I can track down my most refined versions of them:
OPTIMAL_IVS( [Species], [HidPow_Type], [set_HP], [set_Atk], [set_Def], [set_SpA], [set_SpD], [set_Spe] ) = let(

[array {h, a, d, c, e, s}], { [set_HP], [set_Atk], [set_Def], [set_SpA], [set_SpD], [set_Spe] },
[array { [base stats }] , [lookup base stats],
[array { hv, av, dv, cv, ev, sv }], [formula I wrote somewhere that calculates total IVs & EVs to obtain the target stats that even optimizes nature, distributes remaining EVs, & readjusts the build if the hidden power is changed],
av, index( [^], 2 ), dv, index( [^], 3 ), cv, index( [^], 4 ), ev, index( [^], 5 ), sv, index( [^], 6 ),

phys_types, { "fig", "fly", "poi", "gro", "roc", "bug", "gho", "ste" },
spec_types, { "fir", "wat", "gra", "ele", "psy", "ice", "dra", "dar" },
hpt, iferror( iferror( match( left( [HidPow_Type], 3 ), phys_types, 0 ), - match( left( [HidPow_Type], 3 ), spec_types, 0 ) ), 0 ),

output, makearray( 6, 1, lambda( r, c, ifs(
hpt=1, if( r>2, 30, 31 ),
hpt=2, if( sv=94 , if( r<6, 30, 31 ), if( r>3, 30, 31) ),
hpt=3, if( or( r<3, r=6 ) , 31 , 30 ),
hpt=4, if( or( r<4, r=6 ) , 31 , 30 ),
hpt=5, if( or( r<3, r=4 ) , 31 , 30 ),
hpt=6, ifs( r=4 , 31, sv=94, if( or( r=1, r=6 ), 31, 30 ), 1, if( r>4, 30, 31 ) ),
hpt=7, if( or( r=if( av<dv, 2, 3 ), r=5 ) , 30 , 31 ),
hpt=8, if( ev=94 , if( or( r=1, r=5 ), 31, 30 ) , if( r=5, 30, 31 ) ),
hpt=-1, if( r=if( av=94, 3, 2 ), if( av<31, 2, 30 ), if( isodd( r ), 31, 30 ) ),
hpt=-2, ifs( or( r=1, r=5 ), 31, or( av=94, dv=94 ), if( r<4, 31, 30 ), 1, if( r=6, 31, 30 ) ),
hpt=-3, ifs( r=4, 30, r=if( av=94, 3, 2 ), if( av<31, 2, 30 ), 1, 31 ),
hpt=-4, if( cv=94, ifs( r=2, if( av<31, 2, 30 ), or( r=3, r=6 ), 30, 1, 31 ), ifs( r=2, if( av<31, 3, 31 ), r=4, 30 , 1, 31 ) ),
hpt=-5, ifs( r=6, 30, av>dv, if( r=3, 30, 31 ), 1, if( r=2, if( av<31, 2, 30 ), 31 ) ),
hpt=-6, ifs( and( av<31, dv=94 ), ifs( r=2, 3, r=6, 30, 1, 31 ), sv=94, ifs( r=2, if( av<31, 3, 30 ), r=3, 30, 1, 31 ), 1, if( r=6, 30, 31 ) ),
hpt=-7, if( r=if( av=94, 3, 2 ), if( a<31, 2, 30 ), 31),
hpt=-8, if( r=2, if( av<31, 3, 31 ), 31 ) ,
(av<31)*(r=2), 0,
1, 31 ) ) ), output )
 
Last edited:
The way the Showdown Calc calculates multi-hit moves is wrong, or at least very weird. Im using Nerd of Now here to demonstrate but like you can hand calculate the chances, which I did for the Urshifu ones

2 examples here, the first is Nerd of Now second is Showdown Damage Calc

252+ Atk Urshifu-Rapid Strike Surging Strikes (3 hits) vs. 244 HP / 132 Def Flutter Mane on a critical hit: 138-165 (85.7 - 102.4%) -- 1.98% chance to OHKO
(46, 46, 48, 48, 48, 49, 49, 51, 51, 51, 52, 52, 52, 54, 54, 55)

252+ Atk Urshifu-Rapid-Strike Surging Strikes (3 hits) vs. 244 HP / 132 Def Flutter Mane on a critical hit: 138-165 (85.7 - 102.4%) -- approx. 18.8% chance to OHKO
Possible damage amounts: (138, 138, 144, 144, 144, 147, 147, 153, 153, 153, 156, 156, 156, 162, 162, 165)

and

252 Atk Ogerpon Bullet Seed (5 hits) vs. 244 HP / 132 Def Flutter Mane: 135-165 (83.8 - 102.4%) -- 0.02% chance to OHKO
(27, 27, 28, 28, 28, 28, 30, 30, 30, 30, 30, 31, 31, 31, 31, 33)

252 Atk Ogerpon Bullet Seed (5 hits) vs. 244 HP / 132 Def Flutter Mane: 135-165 (83.8 - 102.4%) -- approx. 6.3% chance to OHKO
Possible damage amounts: (135, 135, 140, 140, 140, 140, 150, 150, 150, 150, 150, 155, 155, 155, 155, 165)

Showdowns calc takes the first damage value and assumes its doing the same damage for the rest of the hits, thus inflating OHKO chances. With Urshifu for example, 3 of the scenarios deal over 161 damage to flutter. Theres a 3/16 chance its 54 or 55, which x3 is 162 and 165 damage, which OHKOes 18% of the time. Damage is calculated per hit, Nerd of Now does it that way and has the true damage chance. If you by hand calculate the first Urshifu calc, its 1.8%.

Screenshot 2025-01-11 at 12.07.18.png
Screenshot 2025-01-11 at 12.07.39.png
 
Boosted Knock Off seems to be calculated with 97 BP, despite the calc saying it's 97.5 BP.
I've modified Throat Chop's base power to 97 in the following screenshots:
1736578918359.png

1736578959776.png

The two have identical damage rolls.
Update: Boosted Knock Off is 97 BP in-game. The text is wrong, but the damage calc is correct.
 
Last edited:
Boosted Knock Off seems to be calculated with 97 BP, despite the calc saying it's 97.5 BP.
I've modified Throat Chop's base power to 97 in the following screenshots:
View attachment 703618
View attachment 703619
The two have identical damage rolls.
Update: Boosted Knock Off is 97 BP in-game. The text is wrong, but the damage calc is correct.

This is not quite accurate.
Screenshot 2025-01-11 235918.png

Screenshot 2025-01-11 235905.png

In all calcs here, Hold Back is modified to be a 97 BP Dark-type move if you want to run it yourself.

Knock Off ingame is not technically 97.5 BP but instead is a 65 BP move with a 6144/4096 modifier if the conditions for bonus damage are met. This is applied alongside other modifiers applied to base power, such as Tough Claws, Toxic Boost, Supreme Overlord, or type-specific items like Blackglasses, prior to rounding.

Screenshot 2025-01-12 001646.png

Screenshot 2025-01-12 001656.png


If the item boost from Knock Off is the only BP modifier, then it will have rolls identical to a 97 BP move due to how the damage formula rounds here, but other modifiers that apply to the base power (NOT something like STAB, type effectiveness, or Choice Band, which apply later on after a rounding step occurs) can result in it behaving differently from a 97 BP move.
 
I was attempting to verify a player in a draft league I am in was using the same team they sent in discord after forgetting to do “!showteam” at the end of their game by running the calcs for every turn of their game and I ran into a couple of issues along the way that I wanted to bring to someones attention.

First issue is minor but it would be nice to have an option to add the charge buff to a pokemon for calculation purposes but grand scheme it isn't the worst because you can always just multiple by 2 but still.

Second issue is way more interesting. Basically there was a situation where a bellibolt hit a clef that had been soaked with acid spray and it did 7% in game but the calc shows the roll should fall between 8.3-9.8 or something like that (i will included my calcs screenshots and the replay at the end of this post)

I reran the calc on a fresh page multiple times to make sure I was setting everything up correctly and it kept giving me the same roll and the only way i was able to get belli to do 7% to water type clef with 20 spdef (clef was on the team that did !showteam so we know the set is correct) was by setting bellis spa evs to 0 (they were 8 previously) and then also dropping the spatk iv to 25 just to make the 7% damage roll that the replay displays possible.

In the game 26/27 total damage rolls and 5/6 of the belli into clef damage rolls lined up with what i was able to recreate in the calculator so I believe its highly improbable the belli was secretly 25 spatk ivs and just got high rolls for every other attack it made in the game.

Teams used:
https://pokepast.es/54c3039740381f30
https://pokepast.es/db416abd62706de0

Replay:
https://replay.pokemonshowdown.com/gen9natdexdraft-2283734641. Discrepancy is on turn 21

Not sure where attached files show up as I do not use the forums often but attached is a screenshot of the calc I made in case I was making an error with the setup and also one of the replay on the specific turn I am talking about showing the 7% damage that does not line up with what I recreated.
 

Attachments

  • IMG_6100.png
    IMG_6100.png
    1.3 MB · Views: 22
  • IMG_6099.png
    IMG_6099.png
    392.4 KB · Views: 24
Second issue is way more interesting. Basically there was a situation where a bellibolt hit a clef that had been soaked with acid spray and it did 7% in game but the calc shows the roll should fall between 8.3-9.8 or something like that (i will included my calcs screenshots and the replay at the end of this post)
The Clefable is at +1 SpD when it is hit by Acid Spray on turn 21. When that is accounted for, the calc shows that it is possible to show 5% damage dealt: 8 SpA Bellibolt Acid Spray vs. +1 252 HP / 20 SpD Tera Water Clefable: 22-26 (5.5 - 6.5%) -- possibly the worst move ever
This is incorrect
 
Last edited:
The Clefable is at +1 SpD when it is hit by Acid Spray on turn 21. When that is accounted for, the calc shows that it is possible to show 5% damage dealt: 8 SpA Bellibolt Acid Spray vs. +1 252 HP / 20 SpD Tera Water Clefable: 22-26 (5.5 - 6.5%) -- possibly the worst move ever

This is incorrect, the Clefable used Cosmic Power to go from -1 to +0 at the start of Turn 21.

I'm fairly sure this is due to how PS displays HP% to give away as little information as possible - the Clefable was likely at a very high 99%, almost 100%, and dropped to just above 91% which PS would display as 92% due to being greater than 91% HP. This means that PS displays a 7% change (99->92) despite the actual damage being somewhere just under 9% (~99.9%->~91.1%).
 
I have question with flooring on damage calculation. [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Damage)'s base damage calculation does not have floor calculation. code for damaage calculation in the source code for SMSSSV use a base damage calculation function as below.

export function getBaseDamage(level: number, basePower: number, attack: number, defense: number) {
return Math.floor(
OF32(
Math.floor(
OF32(OF32(Math.floor((2 * level) / 5 + 2) * basePower) * attack) / defense
) / 50 + 2
)
);
}

This calculation uses multiple floors in the intermediate calculation. According to bulbapedia, this is not the case after gen 5. Can I get a verification on the correct calculation method?
 
I have question with flooring on damage calculation. [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Damage)'s base damage calculation does not have floor calculation. code for damaage calculation in the source code for SMSSSV use a base damage calculation function as below.

export function getBaseDamage(level: number, basePower: number, attack: number, defense: number) {
return Math.floor(
OF32(
Math.floor(
OF32(OF32(Math.floor((2 * level) / 5 + 2) * basePower) * attack) / defense
) / 50 + 2
)
);
}

This calculation uses multiple floors in the intermediate calculation. According to bulbapedia, this is not the case after gen 5. Can I get a verification on the correct calculation method?
Bulbapedia's explication of the damage formula in modern generations has never been correct.
 
it's possible that this is the same bug as in the previous message but using the calculator in gen3 mode move damage is not consistent when clicking the same moves multiple times

252+ Atk Choice Band Deoxys-Attack Superpower vs. 252 HP / 56+ Def Skarmory: 178-210 (53.2 - 62.8%) -- guaranteed 2HKO
252+ Atk Choice Band Deoxys-Attack Superpower over 2 turns vs. 252 HP / 56+ Def Skarmory: 535-630 (160.1 - 188.6%) -- guaranteed KO in 2 turns

one would expect 2 superpowers to do less than twice as much as 1 superpower but it appears to do more
 
it's possible that this is the same bug as in the previous message but using the calculator in gen3 mode move damage is not consistent when clicking the same moves multiple times

252+ Atk Choice Band Deoxys-Attack Superpower vs. 252 HP / 56+ Def Skarmory: 178-210 (53.2 - 62.8%) -- guaranteed 2HKO
252+ Atk Choice Band Deoxys-Attack Superpower over 2 turns vs. 252 HP / 56+ Def Skarmory: 535-630 (160.1 - 188.6%) -- guaranteed KO in 2 turns

one would expect 2 superpowers to do less than twice as much as 1 superpower but it appears to do more
The ability to perform N calculations is not a bug - it is a new feature.

Multi-hit moves in ADV not taking drops into account is a bug though which I just fixed.
 
fix is appreciated, thanks

252+ Atk Choice Band Deoxys-Attack Superpower over 2 turns vs. 252 HP / 56+ Def Skarmory: 297-350 (88.9 - 104.7%) -- 31.3% chance to 2HKO after Leftovers recovery

it does still appear to not be taking lefties into account if they occur between multiple hits of the move; this could not 2hko skarm after lefties (max roll of 350, it needs to do 334 [skarm's hp] + 20 [lefties] = 354 to kill)
 
Bad Dreams doesn't work because the check looks for the ability "isBadDreams" instead of "Bad Dreams"

} else if (
(defender.hasStatus('slp') || defender.hasAbility('Comatose')) &&
attacker.hasAbility('isBadDreams') &&
!defender.hasAbility('Magic Guard') &&
!(defender.hasAbility('Shield Dust') && field.chromaticField === 'Jungle') // Jungle - Shield Dust grants Magic Guard
) {
damage -= Math.floor(defender.maxHP() / 8);
texts.push('Bad Dreams');
}
 
Bad Dreams doesn't work because the check looks for the ability "isBadDreams" instead of "Bad Dreams"

} else if (
(defender.hasStatus('slp') || defender.hasAbility('Comatose')) &&
attacker.hasAbility('isBadDreams') &&
!defender.hasAbility('Magic Guard') &&
!(defender.hasAbility('Shield Dust') && field.chromaticField === 'Jungle') // Jungle - Shield Dust grants Magic Guard
) {
damage -= Math.floor(defender.maxHP() / 8);
texts.push('Bad Dreams');
}
oh lol I just noticed that I posted the code with an addition I made for a custom calc, but the point still stands
 
idk how to frame this so I'll pretend this is a real intro

the damage calc doesn't account for arceus types being visual without multitype or the plates in gens before gen 8, which if you didn't know, in generations 4~7, arceus is always normal type, no matter what your screen says, unless it has the ability multitype AND it is holding a plate.
 
As a new feature, I think it'd be convenient to add a button that applies the Knock Off effect in the calc so you don't need to go and change the item by hand. It'd remove the effect of the item and also show new damage values for the next knock off.
 
Last edited:
https://replay.pokemonshowdown.com/gen9ou-2298525448
0 SpA Mew Psychic Noise vs. 0 HP / 0 SpD Ludicolo: 82-97 (27.2 - 32.2%) -- 58.7% chance to 4HKO after Rain Dish recovery

Psychic Noise does block effects such as Rain Dish, but Psychic noise doesn't block Rain Dish recovery in the damage calc (likely applies to Ice Body and stuff like that too).

PS: the damage from what I calced doesn't match up with what is shown in the replay, that Ludicolo had 252 HP EVs but I had to increase the damage for Rain Dish recovery to be relevant for the calc
 
https://replay.pokemonshowdown.com/gen9ou-2298525448
0 SpA Mew Psychic Noise vs. 0 HP / 0 SpD Ludicolo: 82-97 (27.2 - 32.2%) -- 58.7% chance to 4HKO after Rain Dish recovery

Psychic Noise does block effects such as Rain Dish, but Psychic noise doesn't block Rain Dish recovery in the damage calc (likely applies to Ice Body and stuff like that too).

PS: the damage from what I calced doesn't match up with what is shown in the replay, that Ludicolo had 252 HP EVs but I had to increase the damage for Rain Dish recovery to be relevant for the calc
https://replay.pokemonshowdown.com/gen9ou-2298527882
0 SpA Mew Psychic Noise vs. 252 HP / 252 SpD Payapa Berry Toxicroak: 168-198 (45.4 - 53.5%) -- guaranteed 3HKO after Dry Skin recovery
0 SpA Mew Psychic Noise vs. 4 HP / 0 SpD Glaceon: 84-100 (30.8 - 36.7%) -- guaranteed 4HKO after Ice Body recovery

Ice Body and Dry Skin are also affected, but they still show up in the calc
 
There is an issue with Poltergeist and Protosynthesis/Quark Drive where the calc shows Polter as doing zero damage to any mon with Protosynthesis/Quark Drive active even if they have items (Under Sun/In Electric Terrain).

1740692765593.png


1740692812193.png
 
Bad Dreams doesn't work because the check looks for the ability "isBadDreams" instead of "Bad Dreams"

} else if (
(defender.hasStatus('slp') || defender.hasAbility('Comatose')) &&
attacker.hasAbility('isBadDreams') &&
!defender.hasAbility('Magic Guard') &&
!(defender.hasAbility('Shield Dust') && field.chromaticField === 'Jungle') // Jungle - Shield Dust grants Magic Guard
) {
damage -= Math.floor(defender.maxHP() / 8);
texts.push('Bad Dreams');
}
Fixed
There is an issue with Poltergeist and Protosynthesis/Quark Drive where the calc shows Polter as doing zero damage to any mon with Protosynthesis/Quark Drive active even if they have items (Under Sun/In Electric Terrain).

Fixed
 
Back
Top