v0.1 ⌊ALPHA⌉
On this page
  1. How it works
  2. Implementations
  3. What changed, Gen 1 → Gen 3
  4. Variants and combinations
  5. History
  6. Related
  7. References
  8. Sources

Every Pokémon move has a type, and every Pokémon has one or two. The type chart rates each attacking type against each defending type: ×2, ×½, ×0, or ×1 if unlisted1,2. A dual-type defender takes both matchups, multiplied3. The pret disassemblies and decompilation make the code of Pokémon Red and Blue, Pokémon Crystal, and Pokémon Emerald readable.

#How it works

The chart lists only non-neutral pairs, as (attacking type, defending type, multiplier) rows2. Red/Blue’s has 15 types, 82 rows2; Crystal’s and Emerald’s have 17 types, 108 + 2 rows4. Multipliers are integers scaled by 10: 20 · 10 · 05 · 00 (÷10)1.

In Generations 1–3, the chart runs after the base damage formula and before the random factor5,6,7. The same-type attack bonus (STAB) comes first: d+⌊d/2⌋8 in Red/Blue and Crystal9, ⌊d×15/10⌋10 in Emerald. The two forms agree for every non-negative integer10. Each matching row then costs one multiply and one integer divide, ⌊d×m/10⌋ per row3,11,12.

damage = base_damage(level, power, attack, defense)        # see damage-formula
if move.type in attacker.types:                            # STAB, before the chart
    damage = damage + floor(damage / 2)                     # Gen 3 writes floor(damage * 15 / 10)
for (atk, def, m) in TYPE_CHART, in table order:
    if atk == move.type and def in defender.types:
        damage = floor(damage * m / 10)                     # truncates after every row
        Gen 1:      if damage == 0: the move misses
        Gen 2 / 3:  if damage == 0 and m != 0: damage = 1
damage = random_factor(damage)

Interactive: type-matrix (needs JavaScript)

Type charts of Red/Blue, Crystal and Emerald, from pret. Switch generation to see changes; click a cell or use the picker to replay a hit’s integer math. Numbers link to their claims.

#Truncation makes row order matter

A net-neutral hit whose ½ row precedes its 2× row loses 1 point on odd damage13. Ice against Water/Flying goes 3 → 1 → 213,14,15. The probe lists every such attacker and type pair, per game.

#Implementations

#Red and Blue (Generation 1)

Red and Blue16 do it all in AdjustDamageForMoveType: STAB, then a walk of the full TypeEffects table3. Single-type Pokémon store their type twice, but each row applies once3.

  • Zero means miss. A row that leaves 0 damage flags a miss, which is also how ×0 works3. Under two ½ rows (×¼), damage goes 2 or 3 → 0 (miss)17.
  • The message follows the last row. Each matching row overwrites one effectiveness byte18. Ice against Water/Flying, net ×1, prints “It’s super effective!”19. Ground against Rock/Flying does no damage but prints the plain miss text, not “It doesn’t affect…”20.
  • Fixed-damage moves skip the chart. Sonic Boom, Seismic Toss, Dragon Rage, Night Shade, Psywave, and Super Fang bypass the formula and the type routine21.
  • The trainer AI reads one row, the first matching either defender type, so it ignores 4× weaknesses and canceling pairs22.
  • Type picks the stats. Fire, Water, Grass, Electric, Psychic, Ice, and Dragon moves use Special on both sides; the rest use Attack against Defense23.
  • An unused type. The constants define a BIRD type that no row mentions24.

#Crystal (Generation 2)

Crystal25 adds Steel and Dark26. The work moves into BattleCommand_Stab, which applies weather and badge boosts before STAB9. Struggle skips the routine27.

  • Immunity is explicit. A ×0 row marks a miss28. Any other step that truncates to 0 gives 1, so ×¼ no longer misses: 2 → 1 → 129.
  • The message uses the whole product30, so Ice against Water/Flying prints nothing31.
  • Foresight. The Normal→Ghost and Fighting→Ghost immunities follow a marker row, where the loop stops once the target is identified32.
  • Steel and Dark keep the type-based split: Steel is physical, and Dark is special33.

#Emerald (Generation 3)

Emerald34 keeps Crystal’s chart row for row35, as a flat byte array with the Foresight marker as its own row36,37. The arithmetic is unchanged12.

  • Messages come from flags. A ½ row and a 2× row cancel, and a ×0 row sets “doesn’t affect”38.
  • Abilities act as extra immunities. Levitate makes Ground moves miss, so the loop reads no row39. Wonder Guard lets only super-effective hits through40.
  • Carried over. Struggle skips STAB and the chart41. Type decides physical or special42. The unused slot becomes TYPE_MYSTERY, “???”43.

#What changed, Gen 1 → Gen 3

Red/BlueCrystalEmerald
Types15217, adds Steel and Dark261736
Matchups changed—4, listed below44none35
Step that reaches 0move misses3raised to 1; ×0 is a miss11raised to 1 unless ×012
Effectiveness textlast matching row18combined value30flags, ½ and 2× cancel38
Immunity removersnoneForesight32Foresight37
Random factor×217–255 / 25545×217–255 / 25546×85–100 / 10047

A cell-by-cell diff of the Red/Blue and Crystal tables gives +Steel, +Dark, 4 changed44. The four changes are Poison→Bug ×2 → ×1, Bug→Poison ×2 → ×½, Ghost→Psychic ×0 → ×2, and Ice→Fire ×1 → ×½44. Bulbapedia lists the same four44.

#Ghost and Psychic in Generation 1

Red and Blue’s table gives Ghost moves ×048 against Psychic types, but a Saffron Gym trainer says “Psychic #MON fear only ghosts and bugs!”49. Crystal’s table gives ×250. Bulbapedia reports that “an abundance of evidence suggests that this may have been an error”51.

#Variants and combinations

  • STAB runs in the same routine, directly before the chart, in all three games8,9,10.
  • Damage formula: in Gen 1–3, type also makes a move physical or special23,33,42.

#History

The games read here run from Red and Green (Japan, 1996) to Emerald (2004)16,34.

References

  1. ^ abMultipliers are integers scaled by 10 (SUPER_EFFECTIVE 20, NOT_VERY_EFFECTIVE 05, and NO_EFFECT 00); the table never uses EFFECTIVE (10) or MORE_EFFECTIVE (15). T3pret/pokered · constants/battle_constants.asm L60–65
  2. ^ abcdRed and Blue's type chart (TypeEffects) has 82 non-neutral (attacker, defender, multiplier) rows over 15 types, ended by -1; unlisted pairs are neutral. T3pret/pokered · data/types/type_matchups.asm L1–85, constants/type_constants.asm L1–28
  3. ^ abcdefIn table order, each TypeEffects row matching the move's type and either defender type sets damage to ⌊damage×value/10⌋; 0 marks a miss. T3pret/pokered · engine/battle/core.asm L5127–5185
  4. ^Crystal's type chart (TypeMatchups) has 108 non-neutral rows over 17 types, then a -2 marker, Normal→Ghost and Fighting→Ghost ×0, and a -1 end. T3pret/pokecrystal · data/types/type_matchups.asm L1–118, constants/type_constants.asm L7–37
  5. ^In Red and Blue, a damaging move runs CriticalHitTest, CalculateDamage (base formula), AdjustDamageForMoveType (STAB, then type rows), RandomizeDamage, and then MoveHitTest (accuracy). T3pret/pokered · engine/battle/core.asm L3140–3150, L5531–5543
  6. ^A plain damaging move runs critical, damagestats, damagecalc (base formula, item boosts, and critical ×2), stab (weather, badges, STAB, and type rows), damagevariation, and then checkhit (accuracy). T3pret/pokecrystal · data/moves/effects.asm L5–14, engine/battle/effect_commands.asm L2983–3023
  7. ^A plain damaging move runs critcalc, damagecalc (base damage), typecalc (STAB, then type rows), and then adjustnormaldamage (random factor). T3pret/pokeemerald · data/battle_scripts_1.s L249–252
  8. ^ abAdjustDamageForMoveType applies STAB before any type row: damage+⌊damage/2⌋ when the move's type matches either attacker type. T3pret/pokered · engine/battle/core.asm L5101–5125
  9. ^ abcBattleCommand_Stab applies weather and badge type boosts, then STAB (damage+⌊damage/2⌋ if either attacker type matches), then the type chart. T3pret/pokecrystal · engine/battle/effect_commands.asm L1251–1288
  10. ^ abcBefore the type chart, Cmd_typecalc applies STAB as damage×15/10 when either attacker type equals the move's type. T3pret/pokeemerald · src/battle_script_commands.c L1368–1373, include/battle.h L471
  11. ^ abEach matching row computes damage×value; a nonzero product becomes ⌊product/10⌋, raised to 1 if that truncates to 0. T3pret/pokecrystal · engine/battle/effect_commands.asm L1312–1386
  12. ^ abcFor each row of the move's type, ModulateDmgByType runs once per distinct target type it matches: damage×multiplier/10, raised from 0 to 1 unless the multiplier is 0. T3pret/pokeemerald · src/battle_script_commands.c L1321–1325, L1386–1406
  13. ^ abTruncating after each row costs a net-neutral hit damage when its ½ row comes first: Ice against Water/Flying takes 3 to ⌊3 × 5 / 10⌋ = 1, then ⌊1 × 20 / 10⌋ = 2. T4pret/pokered · data/types/type_matchups.asm L33–36probe probes/pokemon-types/type-charts.mjs
  14. ^Row order still matters: an Ice move against Water/Flying takes 3 damage to 1, then 2 (½ row at L35, 2× at L39). T4pret/pokecrystal · data/types/type_matchups.asm L35–39probe probes/pokemon-types/type-charts.mjs
  15. ^Row order still matters: an Ice move against Water/Flying takes 3 damage to 1, then 2 (½ row at L369, 2× at L373). T4pret/pokeemerald · src/battle_main.c L369–373probe probes/pokemon-types/type-charts.mjs
  16. ^ abPokémon Red and Green came out in Japan on 27 February 1996; the English Red and Blue (developer Game Freak, publisher Nintendo, Game Boy, and Generation I core series) followed in North America on 28 September 1998. T1Bulbapedia, “Pokémon Red and Green Versions” · infobox, Release datesBulbapedia, “Pokémon Red and Blue Versions” · infobox, Basic info and Release dates
  17. ^Under two ½ rows (×¼), 2 or 3 damage truncates to 0 and the move misses; 4 damage gives 1. T4pret/pokered · engine/battle/core.asm L5171–5176, data/types/type_matchups.asm L14probe probes/pokemon-types/type-charts.mjs
  18. ^ abEach matching row overwrites the byte wDamageMultipliers, so the text follows the last row: above 10 is “super effective”, below 10 “not very effective”, and a miss reads “doesn't affect” only at 0. T3pret/pokered · engine/battle/core.asm L5147–5153, engine/battle/display_effectiveness.asm L1–10, engine/battle/core.asm L3718–3733, L3218–3229
  19. ^Since the text follows the last row, an Ice move against Water/Flying, net ×1 (½ row at L33, then 2× at L36), prints “It's super effective!”. T4pret/pokered · data/types/type_matchups.asm L33–36probe probes/pokemon-types/type-charts.mjs
  20. ^A Ground move against Rock/Flying (×0 row at L9, then ×2 at L55) does 0 damage and prints the plain miss text, not “doesn't affect”: the byte holds the last row's 20. T4pret/pokered · data/types/type_matchups.asm L9, L55probe probes/pokemon-types/type-charts.mjs
  21. ^SetDamageEffects moves (Sonic Boom, Seismic Toss, Dragon Rage, Night Shade, Psywave, and Super Fang) jump to the hit test, skipping CalculateDamage and AdjustDamageForMoveType, the only damage routine that reads TypeEffects. T3pret/pokered · engine/battle/core.asm L3134–3139, data/battle/set_damage_effects.asm L1–6, data/moves/moves.asm L62
  22. ^The trainer AI's AIGetTypeEffectiveness stops at the first row matching either defender type, ignoring dual-type products. T3pret/pokered · engine/battle/core.asm L5187–5223, engine/battle/trainer_ai.asm L207–216
  23. ^ abType picks the stats: Fire, Water, Grass, Electric, Psychic, Ice, and Dragon (SPECIAL upward) use Special on both sides; the rest use Attack against Defense. T3pret/pokered · engine/battle/core.asm L4040–4042, constants/type_constants.asm L19–26
  24. ^The type constants still define BIRD ($06), with a name string, but no TypeEffects row names it. T3pret/pokered · constants/type_constants.asm L11, data/types/names.asm L40probe probes/pokemon-types/type-charts.mjs
  25. ^Pokémon Crystal (developer Game Freak, publisher Nintendo, Game Boy Color, and Generation II core series) came out in Japan on 14 December 2000 and North America on 30 July 2001. T1Bulbapedia, “Pokémon Crystal Version” · infobox, Basic info and Release dates
  26. ^ abCrystal's type constants add STEEL (physical), DARK (special), and an unused CURSE_TYPE named “???”; BIRD remains, still with no rows. T3pret/pokecrystal · constants/type_constants.asm L9–37, data/types/names.asm L37probe probes/pokemon-types/type-charts.mjs
  27. ^Struggle returns from BattleCommand_Stab at once, so it skips weather, badge boosts, STAB, and the type chart. T3pret/pokecrystal · engine/battle/effect_commands.asm L1216–1219
  28. ^A ×0 row now marks the attack as missed outright, instead of relying on the damage reaching 0. T3pret/pokecrystal · engine/battle/effect_commands.asm L1329–1336
  29. ^A ×¼ hit no longer truncates to a miss: 2 damage through two ½ rows gives ⌊2 × 5 / 10⌋ = 1, then ⌊1 × 5 / 10⌋ = 0, raised to 1. T4pret/pokecrystal · engine/battle/effect_commands.asm L1361–1373probe probes/pokemon-types/type-charts.mjs
  30. ^ abAfter the loop, CheckTypeMatchup's combined value (m=⌊m×row/10⌋ from 10) replaces the effectiveness byte, so the text reflects every row: ×4 is 40, ×¼ is 2, and ½ with 2× is 10. T3pret/pokecrystal · engine/battle/effect_commands.asm L1388–1396, L1405–1471, L2324–2333, L2197–2202
  31. ^An Ice move against Water/Flying (½ at L35, 2× at L39) prints no effectiveness text: the combined value goes 10 → 5 → 10. T4pret/pokecrystal · data/types/type_matchups.asm L35–39probe probes/pokemon-types/type-charts.mjs
  32. ^ abAgainst an identified (Foresight) target, the loop stops at the -2 marker, skipping the Normal→Ghost and Fighting→Ghost immunities after it. T3pret/pokecrystal · engine/battle/effect_commands.asm L1302–1310, data/types/type_matchups.asm L112–116
  33. ^ abType still picks the stats: Steel is physical (below SPECIAL); Dark is special, using Special Attack against Special Defense. T3pret/pokecrystal · engine/battle/effect_commands.asm L2543–2545, constants/type_constants.asm L9–35
  34. ^ abPokémon Emerald (developer Game Freak, publisher Nintendo, Game Boy Advance, and Generation III core series) came out in Japan on 16 September 2004 and North America on 1 May 2005. T1Bulbapedia, “Pokémon Emerald Version” · infobox, Basic info and Release dates
  35. ^ abEmerald's table holds the same 110 rows as Crystal's, in the same order: no new type and no changed matchup. T4pret/pokecrystal · data/types/type_matchups.asm L1–118pret/pokeemerald · src/battle_main.c L335–449Bulbapedia, “Type/Type chart” · Type charts: Generations II-Vprobe probes/pokemon-types/type-charts.mjs
  36. ^ abEmerald's type chart, gTypeEffectiveness, is a flat u8 array of 108 non-neutral (attacker, defender, multiplier) rows over 17 types, then a TYPE_FORESIGHT marker, two Ghost immunities, and TYPE_ENDTABLE. T3pret/pokeemerald · src/battle_main.c L329–449, include/constants/pokemon.h L5–23
  37. ^ abAgainst a Foresight target, the loop breaks at the TYPE_FORESIGHT row, skipping the Normal→Ghost and Fighting→Ghost immunities after it. T3pret/pokeemerald · src/battle_script_commands.c L1388–1394, src/battle_main.c L445–447
  38. ^ abThe text comes from flags ModulateDmgByType sets per row: a 2× row cancels an earlier not-very-effective flag, a ½ row an earlier super-effective one, and ×0 sets "doesn't affect", clearing both. T3pret/pokeemerald · src/battle_script_commands.c L1327–1352
  39. ^Cmd_typecalc flags a Ground move against a Levitate target as missed and “doesn't affect”, and walks no type row. T3pret/pokeemerald · src/battle_script_commands.c L1375–1384
  40. ^After the rows, a Wonder Guard target makes a damaging move miss on the turn it attacks, unless the move carries the super-effective flag without the not-very-effective one. T3pret/pokeemerald · src/battle_script_commands.c L1409–1419
  41. ^Struggle skips Cmd_typecalc entirely, so neither STAB nor the type chart touches it. T3pret/pokeemerald · src/battle_script_commands.c L1360–1364
  42. ^ abType still decides physical or special in Emerald, by its position relative to TYPE_MYSTERY. T3pret/pokeemerald · include/battle.h L466–467
  43. ^TYPE_MYSTERY (9), named "???", sits between the physical and special types and has no rows. T3pret/pokeemerald · include/constants/pokemon.h L15, src/battle_main.c L462probe probes/pokemon-types/type-charts.mjs
  44. ^ abcdCrystal's table adds Steel and Dark and changes four Red/Blue matchups: Poison→Bug ×2 → ×1, Bug→Poison ×2 → ×½, Ghost→Psychic ×0 → ×2, and Ice→Fire ×1 → ×½. T4pret/pokered · data/types/type_matchups.asm L1–85pret/pokecrystal · data/types/type_matchups.asm L1–118Bulbapedia, “Type/Type chart” · Changes: Between Generations I and IIprobe probes/pokemon-types/type-charts.mjs
  45. ^RandomizeDamage multiplies damage by a random byte, 217–255, and integer-divides by 255, leaving 0 or 1 damage untouched. T3pret/pokered · engine/battle/core.asm L5420–5454, macros/data.asm L3
  46. ^The random factor is unchanged from Red/Blue, a random byte from 217 to 255 over 255. T3pret/pokecrystal · engine/battle/effect_commands.asm L1496–1544
  47. ^The random factor changes form: damage × (100 − rand % 16) / 100, i.e. 85–100 %, raised to 1 if that gives 0. T3pret/pokeemerald · src/battle_script_commands.c L1639–1651
  48. ^The Red/Blue type chart gives Ghost-type moves no effect on Psychic types. T3pret/pokered · data/types/type_matchups.asm L78Bulbapedia, “Type/Type chart” · Changes: Between Generations I and II
  49. ^In Red and Blue, a Saffron Gym trainer's after-battle line contradicts the table: “Psychic #MON fear only ghosts and bugs!” T3pret/pokered · text/SaffronGym.asm L135–139
  50. ^Crystal's type chart makes Ghost-type moves super effective on Psychic types. T3pret/pokecrystal · data/types/type_matchups.asm L94
  51. ^Bulbapedia reports that the Gen 1 Ghost → Psychic ×0 “may have been an error”, citing Nintendo strategy guides, two anime episodes, and the Saffron Gym line. T1Bulbapedia, “Ghost (type)” · Trivia

Sources

Code

Secondary