Skip to content

Commit

Permalink
Actually pre-sort by speed for better PRNG usage
Browse files Browse the repository at this point in the history
  • Loading branch information
pyuk-bot committed Dec 27, 2024
1 parent e0bdb41 commit a0ed1dd
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 29 deletions.
39 changes: 22 additions & 17 deletions sim/battle-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,38 +169,43 @@ export class BattleActions {
return true;
}
runSwitch(pokemon: Pokemon) {
if (this.battle.gen >= 5) {
const battle = this.battle;
if (battle.gen >= 5) {
const switchersIn = [pokemon];
for (let a = this.battle.queue.peek(); a?.choice === 'runSwitch'; a = this.battle.queue.peek()) {
const nextSwitch = this.battle.queue.shift();
for (let a = battle.queue.peek(); a?.choice === 'runSwitch'; a = battle.queue.peek()) {
const nextSwitch = battle.queue.shift();
switchersIn.push(nextSwitch!.pokemon!);
}
this.battle.prng.shuffle(this.battle.speedTieResolution);
this.battle.fieldEvent('SwitchIn', switchersIn);
const allActive = battle.getAllActive(true);
battle.speedSort(allActive);
battle.speedOrder = allActive.map((a) => a.side.n * battle.sides.length + a.position);
battle.fieldEvent('SwitchIn', switchersIn);

if (!pokemon.hp) return false;
pokemon.isStarted = true;
pokemon.draggedIn = null;
for (const poke of allActive) {
if (!poke.hp) continue;
poke.isStarted = true;
poke.draggedIn = null;
}
return true;
}
this.battle.runEvent('EntryHazard', pokemon);
battle.runEvent('EntryHazard', pokemon);

this.battle.runEvent('SwitchIn', pokemon);
battle.runEvent('SwitchIn', pokemon);

if (this.battle.gen <= 2) {
if (battle.gen <= 2) {
// pokemon.lastMove is reset for all Pokemon on the field after a switch. This affects Mirror Move.
for (const poke of this.battle.getAllActive()) poke.lastMove = null;
if (!pokemon.side.faintedThisTurn && pokemon.draggedIn !== this.battle.turn) {
this.battle.runEvent('AfterSwitchInSelf', pokemon);
for (const poke of battle.getAllActive()) poke.lastMove = null;
if (!pokemon.side.faintedThisTurn && pokemon.draggedIn !== battle.turn) {
battle.runEvent('AfterSwitchInSelf', pokemon);
}
}
if (!pokemon.hp) return false;
pokemon.isStarted = true;
if (!pokemon.fainted) {
this.battle.singleEvent('Start', pokemon.getAbility(), pokemon.abilityState, pokemon);
this.battle.singleEvent('Start', pokemon.getItem(), pokemon.itemState, pokemon);
battle.singleEvent('Start', pokemon.getAbility(), pokemon.abilityState, pokemon);
battle.singleEvent('Start', pokemon.getItem(), pokemon.itemState, pokemon);
}
if (this.battle.gen === 4) {
if (battle.gen === 4) {
for (const foeActive of pokemon.foes()) {
foeActive.removeVolatile('substitutebroken');
}
Expand Down
22 changes: 11 additions & 11 deletions sim/battle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export class Battle {
lastDamage: number;
effectOrder: number;
quickClawRoll: boolean;
speedTieResolution: number[];
speedOrder: number[];

teamGenerator: ReturnType<typeof Teams.getGenerator> | null;

Expand Down Expand Up @@ -262,9 +262,9 @@ export class Battle {
this.lastDamage = 0;
this.effectOrder = 0;
this.quickClawRoll = false;
this.speedTieResolution = [];
this.speedOrder = [];
for (let i = 0; i < this.activePerHalf * 2; i++) {
this.speedTieResolution.push(i / (this.activePerHalf * 2));
this.speedOrder.push(i);
}

this.teamGenerator = null;
Expand Down Expand Up @@ -954,14 +954,14 @@ export class Battle {
}
}
if (handler.effectHolder && (handler.effectHolder as Pokemon).getStat) {
handler.speed = (handler.effectHolder as Pokemon).speed;
const pokemon = (handler.effectHolder as Pokemon);
handler.speed = pokemon.speed;
if (callbackName.endsWith('SwitchIn')) {
// Pokemon speeds including ties are resolved before all onSwitchIn handlers and aren't re-sorted in-between
// so we add a fractional speed to each Pokemon's respective event handlers by using their unique field position
// to index a randomly shuffled array of sequential numbers
const allSlots = 'abcdef';
const speedTieIndex = allSlots.indexOf((handler.effectHolder as Pokemon).getSlot().charAt(2));
handler.speed += this.speedTieResolution[speedTieIndex];
// so we subtract a fractional speed to each Pokemon's respective event handlers by using the index of their
// unique field position in a pre-sorted-by-speed array
const fieldPositionValue = pokemon.side.n * this.sides.length + pokemon.position;
handler.speed -= this.speedOrder.indexOf(fieldPositionValue) / (this.activePerHalf * 2);
}
}
return handler;
Expand Down Expand Up @@ -1248,11 +1248,11 @@ export class Battle {
return pokemonList;
}

getAllActive() {
getAllActive(includeFainted?: boolean) {
const pokemonList: Pokemon[] = [];
for (const side of this.sides) {
for (const pokemon of side.active) {
if (pokemon && !pokemon.fainted) {
if (pokemon && (includeFainted || !pokemon.fainted)) {
pokemonList.push(pokemon);
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/sim/abilities/pastelveil.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('Pastel Veil', function () {
{species: 'wynaut', moves: ['sleeptalk']},
{species: 'wynaut', moves: ['sleeptalk']},
], [
{species: 'croagunk', moves: ['skillswap', 'sleeptalk']},
{species: 'croagunk', moves: ['sleeptalk', 'skillswap']},
{species: 'wynaut', ability: 'compoundeyes', moves: ['poisongas']},
]]);
battle.makeChoices('auto', 'move skillswap 1, move poisongas');
Expand Down

0 comments on commit a0ed1dd

Please sign in to comment.