Previously, using Leppa Berry by itself caused Endless Battle Clause
to consider Pokemon to be stale. However, it is reasonable to use
Leppa Berry without an intent to cause an endless battle - for
instance to increase the PP of a move with a low PP.
This is still wrong because spamming a Fire attack in Primordial Sea
should not boost damage, but then you run into the problem of boosting
multiple times against multiple targets.
TODO: fix this
Often, you just need a random item in an array. Throughout Pokemon
Showdown's code, there are many instances of the following pattern:
let randomThing = things[this.random(things.length)];
Make this code easier to read by factoring the indexing into the
PRNG#sample function:
let randomThing = this.sample(things);
Run the following sed script to refactor lots of code to use sample:
s/\([a-zA-Z0-9.]\{1,\}\)\[this\.random(\1\.length)\]/this.sample(\1)/
This commit should not change behaviour. In particular, PRNG#next is
called the same number of times with the same number of parameter as
before this commit, and PRNG#next's results are interpreted in the same
way as before this commit.
Often, you just need a random boolean. Throughout Pokemon Showdown's
code, there are many creative ways of requesting random booleans. For
example:
if (this.random(10) < 3) {
if (this.isWeather(['sunnyday', 'desolateland']) || this.random(2) === 0) {
let shiny = !this.random(1024);
if (uberCount > 1 && this.random(5) >= 1) continue;
if (!this.random(3)) ability = ability1.name;
} else if ((ability === 'Iron Barbs' || ability === 'Rough Skin') && this.random(2)) {
if (typeof secondary.chance === 'undefined' || this.random(256) <= effectChance) {
if (accuracy !== true && this.random(256) > accuracy) {
Enable these methods to converge by introducing the PRNG#randomChance
function. It accepts a probability and returns true with that
probability.
Run the following sed script to refactor many common patterns to use
randomChance:
s/this\.random(\([0-9]\{1,\}\)) >= \([0-9]\{1,\}\)/!this.randomChance(\2, \1)/g
s/this\.random(\([0-9]\{1,\}\)) < \([0-9]\{1,\}\)/this.randomChance(\2, \1)/g
s/this\.random(\([0-9]\{1,\}\)) === 0/this.randomChance(1, \1)/g
s/!this\.random(\([0-9]\{1,\}\))/this.randomChance(1, \1)/g
The sed script takes advantage of the following properties:
random(x) < y is equivalent to randomChance(y, x)
random(x) >= y is equivalent to !(random(x) < y), i.e. !randomChance(y, x)
random(x) === 0 is equivalent to random(x) < 1, i.e. randomChance(1, x)
!random(x) is equivalent to random(x) === 0, i.e. randomChance(1, x)
This commit should not change behaviour. In particular, PRNG#next is
called the same number of times with the same number of parameter as
before this commit, and PRNG#next's results are interpreted in the same
way as before this commit.
pokemon.moveset is now pokemon.moveSlots, which is at least slightly
clearer about what it's doing (tracking move state, mainly PP).
Mostly, this gives a consistent naming scheme for `move` (a Move
object) vs `moveSlot` (a MoveSlot object).
This also refactors a lot of existing `moveSlot` accesses to be modern,
including using `for...of`.
Previously, if we wanted to test if A was either 'B' or 'C', we would use
the pattern:
A in {B:1, C:1}
I actually don't know how common this pattern is; I just started using
it because I was tired of typing `A === 'B' || A === 'C'` all the time.
I never really liked it, though; the `:1` part made it kind of
blatantly a hack.
I did some testing and `['B', 'C'].includes(A)` is overall faster.
(A switch statement is around 20x faster still, but who wants to type
that much code?)
Anyway, the new standard is
['B', 'C'].includes(A)
Something something progress!