Verify random battle and capture routines against the original engine
Checks / web (push) Canceled after 0s
Checks / web (push) Canceled after 0s
This commit is contained in:
1 parent
be7575a4d0
commit
00972bad10
9 files changed
+978
-74
No files matched your search
+38
-28
@@ -296,7 +296,7 @@ export function applyTypeMatchups(
|
||||
* native translation. Unsupported AI, switching, contest and item paths are refused. */
|
||||
/** PokeBallEffect's wFinalCatchRate for Poké, Great and Ultra Balls, in
|
||||
* the original 8- and 16-bit registers. Returns undefined when the
|
||||
* formula would divide by zero (a maximum HP of 342). */
|
||||
* formula would divide by zero (e.g. maximum HP of 342 or 683). */
|
||||
export function catchRate(input: {
|
||||
rate: number;
|
||||
ball: number;
|
||||
@@ -1310,33 +1310,7 @@ export class Battle {
|
||||
this.wildMon = 0;
|
||||
yield* this.say(BATTLE.ItemUsedText);
|
||||
|
||||
let caught = tutorial || item === C.MASTER_BALL;
|
||||
if (!caught) {
|
||||
const held = this.data.heldEffect(this.player.mon?.item ?? 0);
|
||||
const chance = catchRate({
|
||||
rate: this.enemyBase.catchRate,
|
||||
ball: item,
|
||||
hp: this.enemy.mon.hp,
|
||||
maxHp: this.enemy.mon.maxHp,
|
||||
status: this.enemy.mon.status,
|
||||
held,
|
||||
});
|
||||
if (chance === undefined) throw new UnsupportedBattle("The catch rate divides by zero.");
|
||||
this.finalCatchRate = chance;
|
||||
caught = this.random() <= chance;
|
||||
}
|
||||
|
||||
// BattleAnim_ThrowPokeBall's .Shake loop runs GetPokeBallWobble until
|
||||
// the ball clicks or the Pokémon breaks free.
|
||||
let wobbles = 0;
|
||||
for (;;) {
|
||||
wobbles++;
|
||||
if (wobbles === 4) break;
|
||||
if (caught) continue;
|
||||
let entry = BATTLE.WobbleProbabilities;
|
||||
while (this.reader.byte(entry) < this.finalCatchRate) entry += 2;
|
||||
if (this.random() >= this.reader.byte(entry + 1)) break;
|
||||
}
|
||||
const { caught, wobbles } = this.rollCapture(item, tutorial);
|
||||
|
||||
if (!caught) {
|
||||
yield* this.say(
|
||||
@@ -1410,6 +1384,42 @@ export class Battle {
|
||||
this.tossItem("balls", item, slot);
|
||||
return true;
|
||||
}
|
||||
/** PokeBallEffect's decision, before animation and caught-mon loading. */
|
||||
private rollCapture(item: number, tutorial: boolean) {
|
||||
let caught = tutorial || item === C.MASTER_BALL;
|
||||
if (!caught) {
|
||||
const held = this.data.heldEffect(this.player.mon?.item ?? 0);
|
||||
const chance = catchRate({
|
||||
rate: this.enemyBase.catchRate,
|
||||
ball: item,
|
||||
hp: this.enemy.mon.hp,
|
||||
maxHp: this.enemy.mon.maxHp,
|
||||
status: this.enemy.mon.status,
|
||||
held,
|
||||
});
|
||||
if (chance === undefined) throw new UnsupportedBattle("The catch rate divides by zero.");
|
||||
this.finalCatchRate = chance;
|
||||
caught = this.random() <= chance;
|
||||
}
|
||||
|
||||
return { caught, wobbles: this.ballWobbles(caught) };
|
||||
}
|
||||
|
||||
private ballWobbles(caught: boolean): number {
|
||||
// BattleAnim_ThrowPokeBall's .Shake loop runs GetPokeBallWobble until
|
||||
// the ball clicks or the Pokémon breaks free.
|
||||
let wobbles = 0;
|
||||
for (;;) {
|
||||
wobbles++;
|
||||
if (wobbles === 4) break;
|
||||
if (caught) continue;
|
||||
let entry = BATTLE.WobbleProbabilities;
|
||||
while (this.reader.byte(entry) < this.finalCatchRate) entry += 2;
|
||||
if (this.random() >= this.reader.byte(entry + 1)) break;
|
||||
}
|
||||
return wobbles;
|
||||
}
|
||||
|
||||
/** AskGiveNicknameText, then NamingScreen (NAME_MON) if accepted: the
|
||||
* chosen name, or the species name for a declined or blank one. */
|
||||
private *askNickname(name: string): Gen<string> {
|
||||
|
||||
Reference in new issue
Block a user