Claim set · data/claims/pokered-capture.yaml

Pokémon Red and Blue's capture formula (pret/pokered)

Game: Pokémon Red and Blue. Concept: Capture.

A wild Pokémon's catch rate is its species' catch-rate byte, copied into wEnemyMonActualCatchRate when the battle loads it (45 for Bulbasaur). In the Safari Zone, bait halves that copy and a rock doubles it, capped at 255. pokered-capture/catch-rate

Codepokered: disassembly of Pokémon Red and Blue · engine/battle/core.asm#L6107-L6118ld hl, wMonHBaseStats ld de, wEnemyMonBaseStats … ld hl, wMonHCatchRate ld a, [hli] ld [de], apokered: disassembly of Pokémon Red and Blue · data/pokemon/base_stats/bulbasaur.asm#L7db 45 ; catch ratepokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L1432-L1455ld hl, wEnemyMonActualCatchRate srl [hl] ; halve catch rate … ld hl, wEnemyMonActualCatchRate ld a, [hl] add a ; double catch rate jr nc, .noCarry ld a, $ffChecked by claude, 2026-10-22 — read LoadEnemyMonData's copy (the five base stats, then wMonHCatchRate into the next byte, which ram/wram.asm L1200-L1201 names wEnemyMonActualCatchRate), Bulbasaur's base stats, and ItemUseBait and ItemUseRock

ItemUseBall first draws a random byte R1: any value for a Poké Ball, redrawn until it is at most 200 for a Great Ball and at most 150 for an Ultra or Safari Ball. A Master Ball catches before the range test. pokered-capture/ball-roll

Value
{
 "kind": "roll-range",
 "poke": [
  0,
  255
 ],
 "great": [
  0,
  200
 ],
 "ultra": [
  0,
  150
 ],
 "safari": [
  0,
  150
 ],
 "master": "caught"
}
Codepokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L177-L214; Get the first random number. Let it be called Rand1. … .loop call Random ld b, a … cp MASTER_BALL jp z, .captured … cp POKE_BALL jr z, .checkForAilments … …Checked by claude, 2026-10-22 — read the loop: Random returns a byte, cp 200 / cp 150 jump back to .loop when the byte is larger, and the Master Ball test comes before both

Cited by: Capture

A status subtracts from R1: 25 for sleep or freeze, 12 for any other (burn, paralysis, poison), 0 for none. If R1 is below that value the Pokémon is caught at once; otherwise the ball fails when R1 less the value is greater than the catch rate, and passes on to the HP check when it is not. pokered-capture/status-and-rate

Value
{
 "kind": "status-subtract",
 "sleepOrFreeze": 25,
 "burnParalysisPoison": 12,
 "none": 0
}
Codepokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L216-L239; no status ailment: Status = 0 ; Burn/Paralysis/Poison: Status = 12 ; Freeze/Sleep: Status = 25 ; If Status is greater than Rand1, the Pokémon will be caught for sure. ld a, [wEnemyMonStatus] and a jr z, .skipAilmentValueSubtraction ; no ailments and (1 << FRZ) | SLP_MASK ld c, 12 jr z, .notFrozenOrAsleep ld c, 25 .notFrozenOrAsleep …pokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L298-L303pop bc ; b = Rand1 - Status ; If Rand1 - Status > CatchRate, the ball fails to capture the Pokémon. ld a, [wEnemyMonActualCatchRate] cp b jr c, .failedToCaptureChecked by claude, 2026-10-22 — read the subtraction (sub c sets carry, and jumps to .captured, when R1 < c) and the comparison against wEnemyMonActualCatchRate (carry, so failure, when the rate is below R1 - S)

Cited by: Capture

For the HP check, ItemUseBall computes W=⌊⌊255M/F⌋/max⁡(⌊H/4⌋,1)⌋ from max HP M and current HP H, where the ball factor F is 8 for a Great Ball and 12 for every other ball. A W over 255 catches; otherwise a second random byte R2 catches when it is at most W. The check runs only after the status and catch-rate test has passed. pokered-capture/hp-check

Value
{
 "kind": "hp-check",
 "numerator": 255,
 "ballFactor": {
  "great": 8,
  "other": 12
 },
 "hpDivisor": 4,
 "minDivisor": 1,
 "cap": 255
}
Codepokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L241-L316; Calculate MaxHP * 255. … ; Determine BallFactor. It's 8 for Great Balls and 12 for the others. ld a, [wCurItem] cp GREAT_BALL ld a, 12 jr nz, .skip1 ld a, 8 … ; Divide the enemy's current HP by 4. HP is not supposed to exceed 999 so ; the result should fit in a. If the division results in a quotient of 0, ; change it to 1. …Checked by claude, 2026-10-22 — read the multiply by 255, the ball factor (12 unless the item is GREAT_BALL), the two-shift quarter of HP with 0 raised to 1, the second divide, the W > 255 branch on the quotient's high byte, and the R2 comparison (carry, so failure, when W < R2)

Cited by: Capture

Computed, counting every value of each roll as equally likely: with no status, Red and Blue catch with chance min⁡(C+1,N)N⋅min⁡(W+1,256)256, where N is 256, 201, or 151 values of R1 for a Poké, Great, or Ultra Ball. For a Bulbasaur (catch rate 45) with max HP 100 in a Poké Ball, that is about 6.0% at full HP and 46 in 256 (18.0%) at 1 HP. pokered-capture/chance

Value
{
 "kind": "example",
 "catchRate": 45,
 "maxHP": 100,
 "ball": "poke",
 "status": "none",
 "fullHP": 0.0604,
 "oneHP": 0.1797
}
Codepokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L185-L214.loop call Random … ld a, 200 cp b jr c, .loop … ld a, 150 cp b jr c, .looppokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L298-L316; If Rand1 - Status > CatchRate, the ball fails to capture the Pokémon. … ; If W > 255, the ball captures the Pokémon. … call Random ; Let this random number be called Rand2. ; If Rand2 > X, the ball fails to capture the Pokémon.pokered: disassembly of Pokémon Red and Blue · data/pokemon/base_stats/bulbasaur.asm#L7db 45 ; catch rateChecked by claude, 2026-10-22 — counted with a script that runs ItemUseBall's integer steps over every R1 and R2: at full HP W = floor(2125 / 25) = 85, so 46/256 × 86/256 ≈ 6.04%; at 1 HP the quarter of HP is 0, raised to 1, so W = 2125 > 255 and only R1 ≤ 45 matters, 46/256

Computed: because the Great Ball's ball factor is 8 and the Ultra Ball's is 12, a Great Ball can beat an Ultra Ball. With a catch rate of 200 or more, both first rolls always pass, so the Great Ball never catches less often. For a Bulbasaur (catch rate 45) with max HP 100 at full HP and no status, the Great Ball catches about 11.4% of the time and the Ultra Ball about 10.2%. pokered-capture/great-over-ultra

Value
{
 "kind": "example",
 "catchRate": 45,
 "maxHP": 100,
 "hp": 100,
 "great": 0.1144,
 "ultra": 0.1023
}
Codepokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L201-L214; If it's a Great/Ultra/Safari Ball and Rand1 is greater than 200, try again. ld a, 200 cp b jr c, .loop … ld a, [hl] cp GREAT_BALL jr z, .checkForAilments ; If it's an Ultra/Safari Ball and Rand1 is greater than 150, try again. ld a, 150 cp b jr c, .looppokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L253-L259; Determine BallFactor. It's 8 for Great Balls and 12 for the others. ld a, [wCurItem] cp GREAT_BALL ld a, 12 jr nz, .skip1 ld a, 8Checked by claude, 2026-10-25 — counted with the same script; Great: 46/201 × 128/256 (W = floor(3187 / 25) = 127) ≈ 11.44%, Ultra: 46/151 × 86/256 ≈ 10.23%; for C ≥ 200 both R1 tests always pass and F = 8 gives a W at least as large as F = 12; read the ball's Rand1 retries at L201-L214 (Great Ball over 200, Ultra over 150)

Cited by: Capture

When the ball fails, Red and Blue choose its shakes without a roll: Y=⌊100C/B⌋, with B 255 for a Poké Ball, 200 for a Great Ball, and 150 otherwise; then Z=⌊min⁡(W,255)⋅Y/255⌋, plus 10 for sleep or freeze or 5 for another status. A Z under 10 is a miss ("You missed the Pokémon!"), under 30 one shake, under 70 two, and 70 or more three ("Shoot! It was so close too!"). pokered-capture/shakes

Value
{
 "kind": "shake-display",
 "ballDivisor": {
  "poke": 255,
  "great": 200,
  "other": 150
 },
 "statusAdd": {
  "sleepOrFreeze": 10,
  "other": 5
 },
 "thresholds": [
  10,
  30,
  70
 ]
}
Codepokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L321-L412.failedToCapture ldh a, [hQuotient + 3] ld [wPokeBallCaptureCalcTemp], a ; Save X. … ; Poké Ball: BallFactor2 = 255 ; Great Ball: BallFactor2 = 200 ; Ultra/Safari Ball: BallFactor2 = 150 … ; Let Y = (CatchRate * 100) / BallFactor2. Calculate Y. … ; no status ailment: Status2 = 0 ; Burn/Paralysis/Poison: Status2 = 5 …pokered: disassembly of Pokémon Red and Blue · data/text/text_6.asm#L9-L27_ItemUseBallText01:: text "You missed the" line "#MON!" … _ItemUseBallText04:: text "Shoot! It was so" line "close too!"Checked by claude, 2026-10-22 — read .failedToCapture through the threshold compares (no Random call between them), and the message table at L439-L455 that maps $20 to ItemUseBallText01 and $63 to ItemUseBallText04

Cited by: Capture

Before any roll, ItemUseBall makes the ball dodge an unidentified ghost and the Restless Soul Marowak on Pokémon Tower 6F, and catches the old man's demonstration Pokémon outright. pokered-capture/uncatchable

Codepokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L149-L175; If the player is fighting an unidentified ghost, set the value that indicates ; the Pokémon can't be caught and skip the capture calculations. … ; Old Man battle … jp .captured … cp POKEMON_TOWER_6F … cp RESTLESS_SOUL ld b, $10 ; can't be caught value jp z, .setAnimDataChecked by claude, 2026-10-22 — read the ghost test, the old man branch, and the Tower 6F Marowak test, all before .loop

Yellow runs the same capture code as Red and Blue from the first roll to the shake count: the ranges, the status values, the ball factors, and the shake thresholds match line for line. Before the rolls it adds a Pikachu battle (BATTLE_TYPE_PIKACHU), which takes the old man's branch and catches outright. pokered-capture/yellow-same

About: Pokémon Yellow Capture

Codepokeyellow: disassembly of Pokémon Yellow · engine/items/item_effects.asm#L197-L428.loop call Random … ld a, 200 cp b jr c, .loop … ld c, 12 jr z, .notFrozenOrAsleep ld c, 25 … ; Determine BallFactor. It's 8 for Great Balls and 12 for the others. …pokered: disassembly of Pokémon Red and Blue · engine/items/item_effects.asm#L185-L414.loop call Random … ld a, 200 cp b jr c, .loop … ld c, 12 jr z, .notFrozenOrAsleep ld c, 25 … ; Determine BallFactor. It's 8 for Great Balls and 12 for the others. …pokeyellow: disassembly of Pokémon Yellow · engine/items/item_effects.asm#L157-L171ld a, [wBattleType] cp BATTLE_TYPE_OLD_MAN jr z, .oldManBattle cp BATTLE_TYPE_PIKACHU jr z, .oldManBattle ; pikachu battle technically old man battle … ld a, [wBattleType] cp BATTLE_TYPE_OLD_MAN jp nz, .capturedChecked by claude, 2026-10-22 — diffed ItemUseBall between the pinned pokered and pokeyellow; from .loop to .setAnimData the only differences are two blank lines, and before .loop Yellow adds the BATTLE_TYPE_PIKACHU branches

Cited by: Capture