* Make "All Pokemon" rules more convenient
Previously, "+All Pokemon" did nothing except override "-All Pokemon",
which switched from a default-allow to default-deny system.
They still do that, but they now also override all previous pokemon
bans/unbans. This makes it easier to replace a banlist/whitelist
from an inherited ruleset without needing to reverse every previous
ban/unban.
This also adds an error if you use `+All Pokemon` in a ruleset where
it doesn't do anything.
Fixes#10772
ESLint has a whole new config format, so I figure it's a good time to
make the config system saner.
- First, we no longer have separate eslint-no-types configs. Lint
performance shouldn't be enough of a problem to justify the
relevant maintenance complexity.
- Second, our base config should work out-of-the-box now. `npx eslint`
will work as expected, without any CLI flags. You should still use
`npm run lint` which adds the `--cached` flag for performance.
- Third, whatever updates I did fixed style linting, which apparently
has been bugged for quite some time, considering all the obvious
mixed-tabs-and-spaces issues I found in the upgrade.
Also here are some changes to our style rules. In particular:
- Curly brackets (for objects etc) now have spaces inside them. Sorry
for the huge change. ESLint doesn't support our old style, and most
projects use Prettier style, so we might as well match them in this way.
See https://github.com/eslint-stylistic/eslint-stylistic/issues/415
- String + number concatenation is no longer allowed. We now
consistently use template strings for this.
This makes it so we no longer need to ad-hoc convert seeds from strings
to arrays when we get them from text protocols like the command line or
BattleStream's `reseed` command.
It also has the side benefit of making inputlogs very slightly smaller.
This is the change that renames:
- `Dex.getMove` -> `Dex.moves.get`
- `Dex.getAbility` -> `Dex.abilities.get`
- `Dex.getItem` -> `Dex.items.get`
- `Dex.getSpecies` -> `Dex.species.get`
- `Dex.getEffect` -> `Dex.conditions.get`
- `Dex.getNature` -> `Dex.natures.get`
- `Dex.getType` -> `Dex.types.get`
- `Dex.getFormat` -> `Dex.formats.get`
In addition, some other APIs have been updated:
- `getByID` methods have also been added to every other table.
- `Dex.moves.all()` now gets an array of all moves
- Plus equivalent methods for `abilities`, `items`, `species`, `formats`, `natures`, `types`
- Note: there's no `Dex.conditions.all()`
- new API: `Dex.stats` for naming/iterating stats
- `Dex.getEffectByID` -> `Dex.conditions.getByID`
- `Dex.getType` -> `Dex.types.get`
- `Dex.data.Formats` -> `Dex.data.Rulesets`
- `Dex.formats` -> now an array `Dex.formats.all()`
- `Dex.getRuleTable` -> `Dex.formats.getRuleTable`
- `Dex.validateFormat` -> `Dex.formats.validate`
Team functions have been split off into a new `sim/teams` package:
- `Dex.packTeam` -> `Teams.pack`
- `Dex.fastUnpackTeam` -> `Teams.unpack`
- `Dex.generateTeam` -> `Teams.generate`
- `Dex.stringifyTeam` -> `Teams.export`
`Teams.export` has also been rewritten to better match how it works in client.
This implements #8178
This is required to add support for Stadium in unit tests. A lot of the
codebase assumes that all mods start with "gen" followed by a number,
but I don't want to touch the others at the moment.
It turns out that when I switched us from `assert` to `assert.strict`,
I didn't actually update any existing tests or tell anyone:
0df0d234f2
So apparently everyone else just kept on using `strictEqual`.
This will be a PR and also throw an error if people continue trying to
use it, which should make it much clearer what PS policy is on this.
A lot of the problem may be that TypeScript marks assert.strict.equal
as deprecated when it's not. This was fixed 4 days ago:
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/48452
But this probably hasn't made it to a thing yet. Until then, you'll
have to deal with TS marking your tests as deprecated, but it shouldn't
be too long.
Accidentally using `assert` instead of `assert.strict` should now show
an error. This protects against the probably much worse mistake of
accidentally using `assert.equal` rather than `assert.strict.equal`.
`assert.ok` is also deprecated now.
Not having prefer-const on the JS side makes JS -> TS refactors really
unreadable. This commit just auto-fixes it so we're using
`prefer-const` everywhere.
It turns out not creating a format on-the-fly breaks deserialization.
We now just use the same custom-rule system that tournaments use.
Some hacks are currently necessary (many tests assume that we're
playing in Anything Goes rather than Custom Game) but we'll work them
out in time.
`Dex.installFormat` has been deprecated and removed. Formats are now
directly created and cached by our unit test framework. This should
lead to fewer weird bugs.
- Centiskorch was misspelled in formats-data, causing a crash in the
egg validator
- A few validation errors were due to Gen 6 not inheriting from Gen 7,
Gen 7 not having a scripts file, and Gen 8 having a gen of 7
- Intimidate (Gen 7) wasn't inheriting from Intimidate (Gen 8), giving
it no name, causing a few validation errors
(Technically not a build error, but I also added Keen Eye to the list
of Intimidate immunities, as reported by SadisticMystic.)
- A lot of tests relied on Teleport always failing; these have been
switched to Gen 7 or swapped Teleport for Celebrate
- Inverse Mod suddenly stopped working; its implementation was a huge
hack and I can't figure out what went wrong, so I've switched it to
using the same system the other mod tests use. It's still a huge
hack, but I don't have the free time to fix it right now.
* Refactor validator
This is a major refactor intended to make the default rules easier to
understand, and also easier for OMs to bypass.
Removed rules:
- `Pokemon`: This is now `-Nonexistent`. Its previous name was intended
to be interpreted as "simulate the Pokémon games exactly, and only
allow what they allow". The new name should make it clearer that it
mainly bans CAPs and other nonexistent Pokémon and functionality.
- `-Illegal`: This is now `Obtainable` (see below).
- `Allow CAP`: This is now `+CAP`. Instead of having a hardcoded rule,
OMs can now be manually whitelist any pokemon/item/etc or group of
them, overriding `-Nonexistent`.
- `Ignore Illegal Abilities`: This is now `!Obtainable Abilities` (see
below).
`Obtainable` was previously `-Illegal`, and does the same thing: Makes
sure you have a regular Pokémon game with only Pokémon that can be
obtained without hacking.
But instead of being a ban, it's now a rule that does nothing by
itself, except contain more rules:
- `Obtainable Moves`
- `Obtainable Abilities`
- `Obtainable Formes`
- `Obtainable Misc`
- `-Nonexistent`
- `-Unreleased`
This allows OMs to piecemeal repeal and unban any of these individual
rules, instead of the previous approach of unbanning them all and
manually reimplementing every single validation you wanted to keep.
* Refactor PokemonSources into a class
This mostly just makes a lot of the weirder checks in the validator
substantially more readable.
This also renames `lsetData` to `setSources`, which should also help
readability.
* Validate Bottle Cap HP types
Fixes an issue reported here:
https://github.com/Zarel/Pokemon-Showdown/issues/5742#issuecomment-533850288
* Fix several move validation issues
Fixes#5742
We have a new MoveSource type: R for Restricted. R moves work like
level-up/tutor/TM moves, except you're limited to one R move.
- Shedinja move stolen from Ninjask in Gen 3-4 are now R moves instead
of event moves. This allows them to coexist with Nincada egg moves.
- Necrozma-DW/DM now inherit moves/events from Necrozma (like Rotom,
but with event validation). This allows them to be shiny.
- Pokemon can now get egg moves from their own evolutions. This fixes
some Tyrogue, Charmander, and Treecko sets mentioned in #5742
- Some more C moves were added, fixing some Hitmontop and Chatot sets
mentioned in #5742
* Improve ability/move compatibility validator
`import =` and `export =` are really only intended for backwards
compatibility with CommonJS. While I really don't like the new module
system TC39 has designed for us, it's what we should be using, and
consistency is important.
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 contains a lot of minor refactors, but the main thing that's going
on here is that battle stream writes have been streamlined to be a lot
easier for others to use.
We even support:
./pokemon-showdown simulate-battle
which provides a stdio interface for anyone using any programming
language to simulate a battle.
`Sim.construct` no longer exists. Battles are now constructed directly
with `new Battle()`. Parameters other than formatid are now passed as
`options`.
Now, seeds are passed as arrays, rather than needing to pass an entire
PRNG object. In addition, they're now passed in the options object,
instead of as a separate argument.
This is done mostly so the Miracle Eye can be rewritten with a custom
seed, which requires fewer turns and should overall be faster. Which
was in turn done because a Miracle Eye timed out on Travis CI earlier.
Overall, the speed increase is pretty negligible, so this is mostly
just about improving the test API.
This is a surprisingly minor refactor considering how many files it
touches, but most of this is only renames.
In terms of file renames:
- `tools.js` is now `sim/dex.js`
- `battle-engine.js` is now `sim/index.js` and its three classes are
in `sim/battle.js`, `sim/side.js`, and `sim/pokemon.js`
- `prng.js` is now `sim/prng.js`
In terms of variable renames:
- `Tools` is now `Dex`
- `BattleEngine` is now `Sim`
- `BattleEngine.Battle` is now `Sim.Battle`
- `BattleEngine.BattleSide` is now `Sim.Side`
- `BattleEngine.BattlePokemon` is now `Sim.Pokemon`
PS's choice system has now been majorly rewritten!
Battle#parseChoice has been eliminated, and Battle#choose is now a
very lightweight wrapper around the BattleSide#choose* functions, which
now handle validation.
Partial decisions have been mostly removed. You can manually construct
decisions partially with the side.choose* functions, but there's no
other support for them. Partial undo has been removed completely.
Choice tracking has been renamed from side.choiceData to side.choice.
side.choices has been removed and is now autogenerated from side.choice
when needed.
side.choiceData.decisions has been renamed side.choice.actions. In the
future, "decision" is a deprecated term and should be called "action"
wherever it shows up.
side.choiceData.waiting and side.getDecisionsFinished() have been
merged into side.isChoiceDone().
Other values in side.choiceData have either been rendered unnecessary
or renamed to something clearer.
The "skip" and "pass" choices have been merged together. Passes can
still be filled in automatically (so you can just use `/move 1` in
doubles when you have only one Pokémon left).
This enables battles in tests to reset their RNG to what it originally
was when they were created. A number of tests do this already by
breaking encapsulating and modifying the prng variable directly. This
should fix that.
We also remove createBattleWithPRNG and min/maxSeed properties.
Firstly, the tests that were still using the maxSeed property were
setting it to Battle.seed which has no effect since the PRNG class does
not look at this property any more - so these were no-ops.
After removing this property from tests, maxRollSeed was never used, so
I removed it and renamed minRollSeed to DEFAULT_ROLL_SEED (since it's
constant).
The places that were still using minRollSeed also were no-ops or were
using createBattleWithPRNG. Since every single instance was actually
just using the same code, I removed createBattleWithPRNG and made
createBattle default to giving you a seed with DEFAULT_ROLL_SEED and
removed the minRollSeed property too.
This makes tests much simpler and reduces the usage surface of
TestTools; now, you must define your *own* seed if you're making a PRNG
for a test, or you use one that TestTools gives you; you may not use a
public property that TestTools gives you.
We also remove the code that removes a listener in the Battle Engine.
This was rendered obsolete by f6a7c4b (see more info [in the discussion
on github][disc]
[disc]:
https://github.com/Zarel/Pokemon-Showdown/pull/3272#discussion_r102414795
This removes the 'deterministic test' tools by preventing action at a
distance (namely, preventing the modification of the `init` method in
`Battle` during tests). This action at a distance is incredibly
confusing.
All this action at a distance did was discard any parameters that were
passed to `Battle` that weren't the first three (which was probably a
mistake by the original author) and also hard code `this.seed` and
`this.startingSeed` in `Battle`.
This functionality has now been moved to the `PRNG` class, so instead
users should pass a `PRNG` to `Battle` as the 5th constructor argument.
Users can also pass one as the third argument to `common.createBattle`
or use `common.createBattleWithPRNG` with the PRNG as the first
argument.
The PRNG is just an encapsulation of the pseudo-random algorithm in a
class. It is stateful, so make sure to take a `clone()` of the PRNG if
you want to re-use it.