@pkmn/engine 0.1.0-dev.d97c6e03 → 0.1.0-dev.f3aaee39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -56
- package/build/pkg/addon.d.ts +1 -1
- package/build/pkg/addon.js +7 -6
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/layout.json +25 -3
- package/build/pkg/gen1.d.ts +5 -4
- package/build/pkg/gen1.js +46 -30
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +15 -12
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +4 -2
- package/build/pkg/protocol.js +4 -2
- package/build/pkg/protocol.js.map +1 -1
- package/build/test/display.js +29 -12
- package/build/test/display.js.map +1 -1
- package/build.zig +89 -65
- package/package.json +26 -16
- package/src/bin/install-pkmn-engine +11 -6
- package/src/lib/binding/node.zig +45 -140
- package/src/lib/binding/wasm.zig +5 -3
- package/src/lib/common/battle.zig +17 -0
- package/src/lib/common/data.zig +11 -11
- package/src/lib/common/debug.zig +21 -11
- package/src/lib/common/js.zig +118 -0
- package/src/lib/common/optional.zig +60 -0
- package/src/lib/common/options.zig +12 -3
- package/src/lib/common/protocol.zig +242 -178
- package/src/lib/common/rational.zig +353 -0
- package/src/lib/common/rng.zig +10 -10
- package/src/lib/common/util.zig +12 -0
- package/src/lib/gen1/README.md +255 -154
- package/src/lib/gen1/calc.zig +427 -0
- package/src/lib/gen1/chance.zig +1044 -0
- package/src/lib/gen1/data/moves.zig +10 -10
- package/src/lib/gen1/data/species.zig +2 -2
- package/src/lib/gen1/data/types.zig +3 -3
- package/src/lib/gen1/data.zig +64 -38
- package/src/lib/gen1/helpers.zig +592 -32
- package/src/lib/gen1/mechanics.zig +892 -531
- package/src/lib/gen2/README.md +12 -13
- package/src/lib/gen2/data/items.zig +3 -3
- package/src/lib/gen2/data/moves.zig +1 -1
- package/src/lib/gen2/data/species.zig +1 -1
- package/src/lib/gen2/data/types.zig +3 -3
- package/src/lib/gen2/data.zig +33 -22
- package/src/lib/gen2/helpers.zig +9 -11
- package/src/lib/gen2/mechanics.zig +5 -4
- package/src/lib/pkmn.zig +65 -6
package/README.md
CHANGED
|
@@ -12,13 +12,21 @@
|
|
|
12
12
|
<img alt="License" src="https://img.shields.io/badge/License-MIT-blue.svg" />
|
|
13
13
|
</a>
|
|
14
14
|
</p>
|
|
15
|
+
|
|
16
|
+
> [!WARNING]
|
|
17
|
+
> **This project is under heavy development** and currently the `main` branch contains numerous breaking
|
|
18
|
+
> changes which may not work and which are not fully documented. Please **wait for the forthcoming
|
|
19
|
+
> initial v0.1 release** before depending on this project (code from the
|
|
20
|
+
> [`old`](https://github.com/pkmn/engine/releases/tag/old) tag can also be used to experiment with a
|
|
21
|
+
> more stable version of the codebase).
|
|
22
|
+
|
|
15
23
|
<hr />
|
|
16
24
|
|
|
17
25
|
A minimal, complete, Pokémon battle simulation engine optimized for performance and
|
|
18
26
|
[designed](docs/DESIGN.md) for tooling, embedded systems, and [artificial
|
|
19
27
|
intelligence](https://github.com/pkmn/0-ERROR) use cases. This engine aims to be a frame-accurate and
|
|
20
28
|
[bug-for-bug compatible](http://www.catb.org/jargon/html/B/bug-for-bug-compatible.html)
|
|
21
|
-
implementation of both Pokémon battles as defined by the original game code
|
|
29
|
+
implementation of both Pokémon battles as defined by the original game code and the [Pokémon
|
|
22
30
|
Showdown](https://pokemonshowdown.com/)[^1] simulator which represents Pokémon battling as practically
|
|
23
31
|
interpreted online.
|
|
24
32
|
|
|
@@ -49,14 +57,14 @@ $ zig build --prefix /usr/local -Doptimize=ReleaseFast
|
|
|
49
57
|
```
|
|
50
58
|
|
|
51
59
|
The Zig website has [installation instructions](https://ziglang.org/learn/getting-started/) which
|
|
52
|
-
walk through how to install Zig on each platform - the engine code should work on Zig v0.11.0
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
walk through how to install Zig on each platform - the engine code should work on Zig v0.11.0 or
|
|
61
|
+
greater, though tracks Zig's master branch so this may change in the future if breaking language
|
|
62
|
+
changes are introduced.
|
|
55
63
|
|
|
56
64
|
`libpkmn` can be built with `-Dshowdown` to instead produce the Pokémon Showdown compatible
|
|
57
|
-
`libpkmn-showdown` library. Furthermore,
|
|
58
|
-
`libpkmn` and `libpkmn-showdown` objects available in the binary release are compiled with
|
|
59
|
-
|
|
65
|
+
`libpkmn-showdown` library. Furthermore, protocol message logging can be enabled through `-Dlog`.
|
|
66
|
+
The `libpkmn` and `libpkmn-showdown` objects available in the binary release are both compiled with
|
|
67
|
+
the `-Dlog` flag by default.
|
|
60
68
|
|
|
61
69
|
### `@pkmn/engine`
|
|
62
70
|
|
|
@@ -67,12 +75,12 @@ $ npm install @pkmn/engine
|
|
|
67
75
|
```
|
|
68
76
|
|
|
69
77
|
The driver depends on being able to find compiled Node/WASM addons in
|
|
70
|
-
`node_modules/@pkmn/engine/build/lib`
|
|
71
|
-
|
|
72
|
-
[`install-pkmn-engine`](src/bin/install-pkmn-engine) which
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
`node_modules/@pkmn/engine/build/lib` to be useful. When you install the package a [`postinstall`
|
|
79
|
+
lifecycle script](https://docs.npmjs.com/cli/v8/using-npm/scripts) runs
|
|
80
|
+
[`install-pkmn-engine`](src/bin/install-pkmn-engine) which checks for a compatible `zig` compiler
|
|
81
|
+
(see earlier regarding minimum version) and download one to `node_module/@pkmn/engine/build/bin` if
|
|
82
|
+
it can't find one, as well as looking for (and downloading, if necessary) the required Node headers
|
|
83
|
+
needed to successfully build the addons natively.
|
|
76
84
|
|
|
77
85
|
**If you have configured `npm` to `--ignore-scripts` you must either run `npx install-pkmn-engine`
|
|
78
86
|
directly or build the addons manually and place the artifacts in the expected paths.**
|
|
@@ -88,23 +96,23 @@ adding the following to your `build.zig`:
|
|
|
88
96
|
const std = @import("std");
|
|
89
97
|
const pkmn = @import("lib/pkmn/build.zig");
|
|
90
98
|
|
|
91
|
-
pub fn build(b: *std.
|
|
99
|
+
pub fn build(b: *std.Build) void {
|
|
92
100
|
...
|
|
93
|
-
exe.addModule("pkmn", pkmn.module(b, .{ .showdown = true, .
|
|
101
|
+
exe.addModule("pkmn", pkmn.module(b, .{ .showdown = true, .log = true }));
|
|
94
102
|
...
|
|
95
103
|
}
|
|
96
104
|
```
|
|
97
105
|
|
|
98
106
|
The engine's `build.zig` exposes a `module` function that takes an options structure to allow for
|
|
99
|
-
configuring whether or not Pokémon Showdown compatibility mode or
|
|
100
|
-
Alternatively, you may set options via a `pkmn_options` [root source file
|
|
107
|
+
configuring whether or not Pokémon Showdown compatibility mode or protocol message logging should be
|
|
108
|
+
enabled. Alternatively, you may set options via a `pkmn_options` [root source file
|
|
101
109
|
declaration](https://ziglang.org/documentation/master/#Root-Source-File). There are several
|
|
102
110
|
undocumented internal options that can be tweaked as well via build or root options, though these
|
|
103
|
-
options
|
|
111
|
+
options aren't officially supported, affect correctness, and may change meaning or behavior without
|
|
104
112
|
warning. Use at your own risk.
|
|
105
113
|
|
|
106
114
|
```zig
|
|
107
|
-
pub const pkmn_options = .{ .showdown = true, .
|
|
115
|
+
pub const pkmn_options = .{ .showdown = true, .log = true };
|
|
108
116
|
```
|
|
109
117
|
|
|
110
118
|
## Usage
|
|
@@ -112,11 +120,11 @@ pub const pkmn_options = .{ .showdown = true, .trace = true };
|
|
|
112
120
|
For each Pokémon generation, the engine provides a battle structure with two functions - a function
|
|
113
121
|
to `update` the battle's state based on both players' choices and a function that defines which
|
|
114
122
|
`choices` are valid at that decision point (at the beginning of a battle both player's must "pass"
|
|
115
|
-
as their first choice
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
as their first choice to switch in the first member of their party). If `-Dlog` protocol logging is
|
|
124
|
+
enabled each update produces logs which can be decoded into a buffer (`LOGS_SIZE` constants are
|
|
125
|
+
provided to make it easy to allocate a buffer of the correct size). Each `update` returns a result
|
|
126
|
+
to indicate either that the battle has terminated or which types of choices are available for each
|
|
127
|
+
player.
|
|
120
128
|
|
|
121
129
|
Unlike [Pokémon Showdown's
|
|
122
130
|
SIM-PROTOCOL](https://github.com/smogon/pokemon-showdown/blob/master/sim/SIM-PROTOCOL.md#choice-requests)
|
|
@@ -128,7 +136,7 @@ state or cause the engine to crash.**
|
|
|
128
136
|
|
|
129
137
|
Battles may be played out from any point but to freshly initialize a battle which is yet to start
|
|
130
138
|
the turn count and active Pokémon should be zeroed out (driver code should handle this for you).
|
|
131
|
-
Most driver code should also provide helpers to make
|
|
139
|
+
Most driver code should also provide helpers to make initializing battle convenient - check the
|
|
132
140
|
respective documentation and examples for the bindings being used. The engine's [protocol
|
|
133
141
|
documentation](docs/PROTOCOL.md) goes into greater detail on the specifics of updates and the
|
|
134
142
|
potential logs that may result.
|
|
@@ -139,36 +147,39 @@ potential logs that may result.
|
|
|
139
147
|
### C
|
|
140
148
|
|
|
141
149
|
[`pkmn.h`](src/include/pkmn.h) exports the C API for `libpkmn`. Symbols are all prefixed with
|
|
142
|
-
`pkmn_` to avoid name collisions. If `-
|
|
143
|
-
|
|
150
|
+
`pkmn_` to avoid name collisions. If `-Dlog` is enabled and logging throws an error then the error
|
|
151
|
+
is encoded in the `pkmn_result` and can be checked with `pkmn_error`.
|
|
144
152
|
|
|
145
153
|
```c
|
|
146
154
|
#include <pkmn.h>
|
|
147
155
|
|
|
156
|
+
pkmn_battle_options options;
|
|
157
|
+
pkmn_gen1_battle_options_set(&options, ...);
|
|
148
158
|
pkmn_battle battle = ...;
|
|
149
|
-
|
|
159
|
+
|
|
150
160
|
pkmn_result result;
|
|
151
161
|
pkmn_choice c1 = 0, c2 = 0;
|
|
152
|
-
while (!pkmn_result_type(result = pkmn_battle_update(&battle, c1, c2,
|
|
162
|
+
while (!pkmn_result_type(result = pkmn_battle_update(&battle, c1, c2, &options))) {
|
|
153
163
|
c1 = choose(PKMN_PLAYER_P1, pkmn_result_p1(result));
|
|
154
164
|
c2 = choose(PKMN_PLAYER_P2, pkmn_result_p2(result));
|
|
165
|
+
pkmn_gen1_battle_options_set(&options, ...);
|
|
155
166
|
}
|
|
156
167
|
if (pkmn_error(result)) exit(1);
|
|
157
168
|
```
|
|
158
169
|
|
|
159
170
|
[(full code)](src/examples/c/example.c)
|
|
160
171
|
|
|
161
|
-
The C API
|
|
172
|
+
The C API doesn't export any helpers for creating or accessing the opaque battle objects - it's
|
|
162
173
|
instead intended to be used as the foundation for more ergonomic bindings in [other
|
|
163
174
|
languages](#other) (the lack of namespaces and bit fields having an implementation-defined layout in
|
|
164
175
|
C are the main contributing factors to the sparseness of what `libpkmn` chooses to expose).
|
|
165
176
|
|
|
166
177
|
### JavaScript / TypeScript
|
|
167
178
|
|
|
168
|
-
`@pkmn/engine` depends on the [`@pkmn/data`](https://www.npmjs.com/package/@pkmn/data) which
|
|
179
|
+
`@pkmn/engine` depends on the [`@pkmn/data`](https://www.npmjs.com/package/@pkmn/data) package which
|
|
169
180
|
requires a `Dex` implementation to be provided as well. The `Battle.create` function can be used to
|
|
170
181
|
initialize a `Battle` from the beginning, or `Battle.restore` can be used to re-instantiate a battle
|
|
171
|
-
which is in
|
|
182
|
+
which is already in progress. If logging is enabled the output can be turned into Pokémon Showdown
|
|
172
183
|
protocol via `Log.parse`.
|
|
173
184
|
|
|
174
185
|
```ts
|
|
@@ -193,18 +204,18 @@ console.log(result);
|
|
|
193
204
|
|
|
194
205
|
[(full code)](src/examples/js/example.ts)
|
|
195
206
|
|
|
196
|
-
By default, the `@pkmn/engine` package
|
|
207
|
+
By default, the `@pkmn/engine` package compiles the engine with `-Dshowdown`, though by running
|
|
197
208
|
`install-pkmn-engine` directly and passing in `--options` you can override this default and build
|
|
198
209
|
different configurations of the extension for the driver to use. The driver can support
|
|
199
210
|
configurations both with and without Pokémon Showdown compatibility simultaneously if present. On
|
|
200
|
-
update, the post-install script
|
|
211
|
+
update, the post-install script attempts to rebuild whichever extensions it finds with the same
|
|
201
212
|
configuration parameters that were originally used meaning updating to the newest version of the
|
|
202
213
|
library should be seamless.
|
|
203
214
|
|
|
204
215
|
Despite relying on the native engine code, the `@pkmn/engine` code is designed to also work in
|
|
205
216
|
browsers which support [WebAssembly](https://webassembly.org/). Running `npm run start:web` from the
|
|
206
|
-
[`examples`](src/examples/js) directory
|
|
207
|
-
|
|
217
|
+
[`examples`](src/examples/js) directory starts a server that can be used to demonstrate the engine
|
|
218
|
+
running in the browser.
|
|
208
219
|
|
|
209
220
|
### Zig
|
|
210
221
|
|
|
@@ -219,13 +230,13 @@ var random = std.rand.DefaultPrng.init(seed).random();
|
|
|
219
230
|
var choices: [pkmn.CHOICES_SIZE]pkmn.Choice = undefined;
|
|
220
231
|
|
|
221
232
|
var battle = ...
|
|
222
|
-
var
|
|
233
|
+
var options = pkmn.battle.options(...);
|
|
223
234
|
|
|
224
235
|
var c1 = pkmn.Choice{};
|
|
225
236
|
var c2 = pkmn.Choice{};
|
|
226
237
|
|
|
227
|
-
var result = try battle.update(c1, c2,
|
|
228
|
-
while (result.type == .None) : (result = try battle.update(c1, c2,
|
|
238
|
+
var result = try battle.update(c1, c2, &options);
|
|
239
|
+
while (result.type == .None) : (result = try battle.update(c1, c2, &options)) {
|
|
229
240
|
c1 = choices[random.uintLessThan(u8, battle.choices(.P1, result.p1, &choices))];
|
|
230
241
|
c2 = choices[random.uintLessThan(u8, battle.choices(.P2, result.p2, &choices))];
|
|
231
242
|
}
|
|
@@ -237,7 +248,7 @@ std.debug.print("{}\n", .{result.type});
|
|
|
237
248
|
|
|
238
249
|
The Zig package also supports some APIs which are difficult to expose elsewhere such as the
|
|
239
250
|
`FixedRNG` which allows you to fully specify the exact RNG frames (which can be useful for ensuring
|
|
240
|
-
certain outcomes/effects always occur) for a battle, though doing so
|
|
251
|
+
certain outcomes/effects always occur) for a battle, though doing so changes the size of the
|
|
241
252
|
`Battle` object.
|
|
242
253
|
|
|
243
254
|
### Other
|
|
@@ -248,12 +259,12 @@ simplify the process even further [`src/data`](src/data) contains JSON dumps of
|
|
|
248
259
|
data, structure sizes and offsets, and protocol information used by the reference driver code. The
|
|
249
260
|
following is a list of known `libpkmn` bindings written by developers outside of the [pkmn
|
|
250
261
|
organization](https://github.com/pkmn) that may be helpful (though note that these projects may not
|
|
251
|
-
necessarily be up-to-date/complete/correct - inclusion in this list
|
|
262
|
+
necessarily be up-to-date/complete/correct - inclusion in this list doesn't imply endorsement):
|
|
252
263
|
|
|
253
|
-
| Language | License | URL
|
|
254
|
-
| ---------- | --------- |
|
|
255
|
-
| **C++** | `BSL-1.0` | https://github.com/pasyg/
|
|
256
|
-
| **Python** | `MIT` | https://github.com/AnnikaCodes/PyKMN
|
|
264
|
+
| Language | License | URL |
|
|
265
|
+
| ---------- | --------- | ------------------------------------ |
|
|
266
|
+
| **C++** | `BSL-1.0` | https://github.com/pasyg/wrapsire |
|
|
267
|
+
| **Python** | `MIT` | https://github.com/AnnikaCodes/PyKMN |
|
|
257
268
|
|
|
258
269
|
|
|
259
270
|
#### `pkmn-debug`
|
|
@@ -276,7 +287,7 @@ By default, `pkmn-debug` expects to read [binary debug protocol](docs/PROTOCOL.m
|
|
|
276
287
|
$ <cmd> | pkmn-debug > index.html
|
|
277
288
|
```
|
|
278
289
|
|
|
279
|
-
Alternatively, if a single filename argument is passed to the `pkmn-debug` it
|
|
290
|
+
Alternatively, if a single filename argument is passed to the `pkmn-debug` it reads from that
|
|
280
291
|
instead:
|
|
281
292
|
|
|
282
293
|
```sh
|
|
@@ -298,14 +309,14 @@ Currently, most of the foundational work from stage 0 is done:
|
|
|
298
309
|
|
|
299
310
|
- [benchmark and integration testing](src/test) infrastructure
|
|
300
311
|
- [documentation](docs) about design, research, methodology, etc
|
|
301
|
-
- definition and implementation of the [protocol](docs/PROTOCOL.md) that
|
|
312
|
+
- definition and implementation of the [protocol](docs/PROTOCOL.md) that's used by the engine
|
|
302
313
|
|
|
303
|
-
**Stage 1 is currently in progress** and
|
|
314
|
+
**Stage 1 is currently in progress** and involves the implementation of the actual Generation I & II
|
|
304
315
|
battle engines, followed by Generation III & IV in stage 2. The implementation of further Pokémon
|
|
305
|
-
generations is in scope for the project but
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
316
|
+
generations is in scope for the project but shouldn't be considered part of the immediate roadmap
|
|
317
|
+
(i.e. exploring the options for broadening support for old generation APIs is given higher priority
|
|
318
|
+
than implementing more modern generations). Furthermore, implementation of modern generations is
|
|
319
|
+
soft-blocked on the [availability of high quality
|
|
309
320
|
decompilations](https://github.com/orgs/pret/repositories) of the original games in question.
|
|
310
321
|
|
|
311
322
|
Certain features will always be deemed **out of scope**:
|
|
@@ -323,10 +334,10 @@ The pkmn engine is distributed under the terms of the [MIT License](LICENSE).
|
|
|
323
334
|
[^1]: In the case of Pokémon Showdown, only bugs which stem from a misimplementation of specific
|
|
324
335
|
effects are reproduced in the engine, bugs which are the result of a misunderstanding of the
|
|
325
336
|
fundamental mechanics of Pokémon or which simply arise due to specific Pokémon Showdown
|
|
326
|
-
implementation details that
|
|
327
|
-
choices
|
|
337
|
+
implementation details that aren't replicable without making the same (incorrect) architectural
|
|
338
|
+
choices aren't. Furthermore, the "Pokémon Showdown" code referenced by this project includes
|
|
328
339
|
several [patches](docs/TESTING.md#patches) to improve accuracy and smooth over some of the more
|
|
329
340
|
egregious implementation issues. In practical terms, the vast majority of games played out in the
|
|
330
|
-
pkmn engine's compatibility mode and on this patched Pokémon Showdown simulator
|
|
331
|
-
it
|
|
341
|
+
pkmn engine's compatibility mode and on this patched Pokémon Showdown simulator are the same,
|
|
342
|
+
it's only in a well defined and documented set of circumstances where the two implementations
|
|
332
343
|
diverge.
|
package/build/pkg/addon.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Choice, Player, Result } from '.';
|
|
2
2
|
export declare function check(showdown: boolean): void;
|
|
3
|
-
export declare function supports(showdown: boolean,
|
|
3
|
+
export declare function supports(showdown: boolean, log?: boolean): boolean;
|
|
4
4
|
export declare function update(index: number, showdown: boolean, battle: ArrayBuffer, c1?: Choice, c2?: Choice, log?: ArrayBuffer): Result;
|
|
5
5
|
export declare function choices(index: number, showdown: boolean, battle: ArrayBuffer, player: Player, choice: Choice['type'], buf: ArrayBuffer): Choice[];
|
|
6
6
|
export declare function choose(index: number, showdown: boolean, battle: ArrayBuffer, player: Player, choice: Choice['type'], buf: ArrayBuffer, fn: (n: number) => number): Choice;
|
package/build/pkg/addon.js
CHANGED
|
@@ -34,11 +34,12 @@ function load() {
|
|
|
34
34
|
let pkmn = undefined;
|
|
35
35
|
let showdown = undefined;
|
|
36
36
|
try {
|
|
37
|
-
pkmn = require(path.join(ROOT, 'build', 'lib', 'pkmn.node'));
|
|
37
|
+
pkmn = require(path.join(ROOT, 'build', 'lib', 'pkmn.node')).engine;
|
|
38
38
|
}
|
|
39
39
|
catch { }
|
|
40
40
|
try {
|
|
41
|
-
showdown =
|
|
41
|
+
showdown =
|
|
42
|
+
require(path.join(ROOT, 'build', 'lib', 'pkmn-showdown.node')).engine;
|
|
42
43
|
}
|
|
43
44
|
catch { }
|
|
44
45
|
if (!pkmn && !showdown) {
|
|
@@ -48,7 +49,7 @@ function load() {
|
|
|
48
49
|
}
|
|
49
50
|
function check(showdown) {
|
|
50
51
|
if (!load()[+showdown]) {
|
|
51
|
-
const opts = ADDON[+!showdown].options.
|
|
52
|
+
const opts = ADDON[+!showdown].options.log ? ['-log'] : [];
|
|
52
53
|
if (showdown)
|
|
53
54
|
opts.push('-Dshowdown');
|
|
54
55
|
throw new Error(`@pkmn/engine has ${showdown ? 'not' : 'only'} been configured to support Pokémon Showdown.` +
|
|
@@ -56,12 +57,12 @@ function check(showdown) {
|
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
exports.check = check;
|
|
59
|
-
function supports(showdown,
|
|
60
|
+
function supports(showdown, log) {
|
|
60
61
|
if (!load()[+showdown])
|
|
61
62
|
return false;
|
|
62
|
-
if (
|
|
63
|
+
if (log === undefined)
|
|
63
64
|
return true;
|
|
64
|
-
return ADDON[+showdown].options.
|
|
65
|
+
return ADDON[+showdown].options.log === log;
|
|
65
66
|
}
|
|
66
67
|
exports.supports = supports;
|
|
67
68
|
function update(index, showdown, battle, c1, c2, log) {
|
package/build/pkg/addon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addon.js","sourceRoot":"","sources":["../../src/pkg/addon.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAE7B,wBAAyC;AAEzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAE9C,IAAI,KAAK,GAAoD,SAAS,CAAC;AAcvE,SAAS,IAAI;IACX,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,IAAI,IAAI,GAAgC,SAAS,CAAC;IAClD,IAAI,QAAQ,GAA+B,SAAS,CAAC;IACrD,IAAI;QACF,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"addon.js","sourceRoot":"","sources":["../../src/pkg/addon.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,15 +4,17 @@
|
|
|
4
4
|
"Battle": 384,
|
|
5
5
|
"Side": 184,
|
|
6
6
|
"Pokemon": 24,
|
|
7
|
-
"ActivePokemon": 32
|
|
7
|
+
"ActivePokemon": 32,
|
|
8
|
+
"Actions": 16,
|
|
9
|
+
"Summaries": 12
|
|
8
10
|
},
|
|
9
11
|
"offsets": {
|
|
10
12
|
"Battle": {
|
|
11
13
|
"sides": 0,
|
|
12
14
|
"turn": 368,
|
|
13
15
|
"last_damage": 370,
|
|
14
|
-
"
|
|
15
|
-
"rng":
|
|
16
|
+
"last_moves": 372,
|
|
17
|
+
"rng": 374
|
|
16
18
|
},
|
|
17
19
|
"Side": {
|
|
18
20
|
"pokemon": 0,
|
|
@@ -80,6 +82,26 @@
|
|
|
80
82
|
"disabled_duration": 52,
|
|
81
83
|
"disabled_move": 56,
|
|
82
84
|
"toxic": 59
|
|
85
|
+
},
|
|
86
|
+
"Action": {
|
|
87
|
+
"damage": 0,
|
|
88
|
+
"hit": 8,
|
|
89
|
+
"critical_hit": 10,
|
|
90
|
+
"secondary_chance": 12,
|
|
91
|
+
"speed_tie": 14,
|
|
92
|
+
"confused": 16,
|
|
93
|
+
"paralyzed": 18,
|
|
94
|
+
"duration": 20,
|
|
95
|
+
"durations": 24,
|
|
96
|
+
"move_slot": 40,
|
|
97
|
+
"multi_hit": 44,
|
|
98
|
+
"psywave": 48,
|
|
99
|
+
"metronome": 56
|
|
100
|
+
},
|
|
101
|
+
"Damage": {
|
|
102
|
+
"base": 0,
|
|
103
|
+
"final": 2,
|
|
104
|
+
"capped": 4
|
|
83
105
|
}
|
|
84
106
|
}
|
|
85
107
|
}
|
package/build/pkg/gen1.d.ts
CHANGED
|
@@ -39,10 +39,11 @@ export declare class Side implements Gen1.Side {
|
|
|
39
39
|
get(slot: Slot): Pokemon | undefined;
|
|
40
40
|
get lastUsedMove(): ID | undefined;
|
|
41
41
|
get lastSelectedMove(): ID | undefined;
|
|
42
|
-
get
|
|
42
|
+
get lastMoveIndex(): 1 | 2 | 3 | 4 | undefined;
|
|
43
|
+
get lastMoveCounterable(): boolean;
|
|
43
44
|
toJSON(): Gen1.Side;
|
|
44
45
|
static init(gen: Generation, lookup: Lookup, team: Partial<PokemonSet>[], data: DataView, offset: number): void;
|
|
45
|
-
static encode(gen: Generation, lookup: Lookup, battle: Data<Gen1.Battle>, side: Gen1.Side, data: DataView, offset: number): void;
|
|
46
|
+
static encode(gen: Generation, showdown: boolean, lookup: Lookup, battle: Data<Gen1.Battle>, side: Gen1.Side, data: DataView, offset: number): void;
|
|
46
47
|
}
|
|
47
48
|
export declare class Pokemon implements Gen1.Pokemon {
|
|
48
49
|
static Volatiles: {
|
|
@@ -77,11 +78,11 @@ export declare class Pokemon implements Gen1.Pokemon {
|
|
|
77
78
|
toxic: number;
|
|
78
79
|
};
|
|
79
80
|
private get sleep();
|
|
80
|
-
private get
|
|
81
|
+
private get ext();
|
|
81
82
|
private get toxic();
|
|
82
83
|
toJSON(): Gen1.Pokemon;
|
|
83
84
|
static init(gen: Generation, lookup: Lookup, set: Partial<PokemonSet>, data: DataView, offset: number, index: number): void;
|
|
84
|
-
static encodeStored(gen: Generation, lookup: Lookup, pokemon: Gen1.Pokemon, data: DataView, offset: number): void;
|
|
85
|
+
static encodeStored(gen: Generation, showdown: boolean, lookup: Lookup, pokemon: Gen1.Pokemon, data: DataView, offset: number): void;
|
|
85
86
|
static encodeActive(gen: Generation, lookup: Lookup, battle: Data<Gen1.Battle>, pokemon: Gen1.Pokemon | undefined, data: DataView, offset: number): void;
|
|
86
87
|
}
|
|
87
88
|
export declare class StoredPokemon {
|
package/build/pkg/gen1.js
CHANGED
|
@@ -86,7 +86,7 @@ class Battle {
|
|
|
86
86
|
return this.data.getUint16(OFFSETS.Battle.last_damage, data_2.LE);
|
|
87
87
|
}
|
|
88
88
|
get prng() {
|
|
89
|
-
const offset = OFFSETS.Battle.
|
|
89
|
+
const offset = OFFSETS.Battle.last_moves + (this.config.showdown ? 4 : 2);
|
|
90
90
|
// Pokémon Showdown's PRNGSeed is always big-endian
|
|
91
91
|
const seed = [0, 0, 0, 0];
|
|
92
92
|
if (this.config.showdown) {
|
|
@@ -99,10 +99,10 @@ class Battle {
|
|
|
99
99
|
// Gen12RNG seed requires an index, but if we always rotate the seed based on the index when
|
|
100
100
|
// reading we can avoid tracking the index as it will always be zero. NB: the exact bits of
|
|
101
101
|
// the Battle will not roundtrip, but the *logical* Battle state will.
|
|
102
|
-
const index = this.data.getUint8(offset +
|
|
103
|
-
for (let i = 0; i <
|
|
102
|
+
const index = this.data.getUint8(offset + 9);
|
|
103
|
+
for (let i = 0; i < 9; i++) {
|
|
104
104
|
const j = i - index;
|
|
105
|
-
seed[j < 0 ? j +
|
|
105
|
+
seed[j < 0 ? j + 9 : j] = this.data.getUint8(offset + i);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
return seed;
|
|
@@ -127,20 +127,25 @@ class Battle {
|
|
|
127
127
|
const buf = new ArrayBuffer(SIZES.Battle);
|
|
128
128
|
const data = new DataView(buf);
|
|
129
129
|
let offset = OFFSETS.Battle.p1;
|
|
130
|
-
const
|
|
130
|
+
const lastMoves = [];
|
|
131
131
|
for (const side of battle.sides) {
|
|
132
|
-
Side.encode(gen, lookup, battle, side, data, offset);
|
|
132
|
+
Side.encode(gen, !!options.showdown, lookup, battle, side, data, offset);
|
|
133
133
|
offset += SIZES.Side;
|
|
134
|
-
|
|
134
|
+
if (options.showdown) {
|
|
135
|
+
lastMoves.push(+!!side.lastMoveCounterable);
|
|
136
|
+
lastMoves.push((side.lastMoveIndex ?? 0));
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
lastMoves.push((+!!side.lastMoveCounterable << 4) | (side.lastMoveIndex ?? 0));
|
|
140
|
+
}
|
|
135
141
|
}
|
|
136
142
|
data.setUint16(OFFSETS.Battle.turn, battle.turn, data_2.LE);
|
|
137
143
|
data.setUint16(OFFSETS.Battle.last_damage, battle.lastDamage, data_2.LE);
|
|
144
|
+
data.setUint8(OFFSETS.Battle.last_moves, lastMoves[0]);
|
|
145
|
+
data.setUint8(OFFSETS.Battle.last_moves + 1, lastMoves[1]);
|
|
138
146
|
if (options.showdown) {
|
|
139
|
-
data.
|
|
140
|
-
data.
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
data.setUint8(OFFSETS.Battle.last_selected_indexes, (indexes[1] << 4) | indexes[0]);
|
|
147
|
+
data.setUint8(OFFSETS.Battle.last_moves + 2, lastMoves[2]);
|
|
148
|
+
data.setUint8(OFFSETS.Battle.last_moves + 3, lastMoves[3]);
|
|
144
149
|
}
|
|
145
150
|
encodePRNG(data, battle.prng);
|
|
146
151
|
return new Battle(lookup, data, options);
|
|
@@ -201,25 +206,38 @@ class Side {
|
|
|
201
206
|
const m = this.data.getUint8(this.offset + OFFSETS.Side.last_selected_move);
|
|
202
207
|
return m === 0 ? undefined : this.lookup.moveByNum(m);
|
|
203
208
|
}
|
|
204
|
-
get
|
|
209
|
+
get lastMoveIndex() {
|
|
205
210
|
let m;
|
|
206
211
|
if (this.battle.config.showdown) {
|
|
207
212
|
const off = this.id === 'p1' ? 0 : 2;
|
|
208
|
-
m = this.data.
|
|
213
|
+
m = this.data.getUint8(OFFSETS.Battle.last_moves + off);
|
|
209
214
|
}
|
|
210
215
|
else {
|
|
211
|
-
|
|
212
|
-
m = this.
|
|
216
|
+
const off = this.id === 'p1' ? 0 : 1;
|
|
217
|
+
m = this.data.getUint8(OFFSETS.Battle.last_moves + off) & 0x0F;
|
|
213
218
|
}
|
|
214
219
|
return m === 0 ? undefined : m;
|
|
215
220
|
}
|
|
221
|
+
get lastMoveCounterable() {
|
|
222
|
+
let m;
|
|
223
|
+
if (this.battle.config.showdown) {
|
|
224
|
+
const off = this.id === 'p1' ? 1 : 3;
|
|
225
|
+
m = this.data.getUint8(OFFSETS.Battle.last_moves + off);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
const off = this.id === 'p1' ? 0 : 1;
|
|
229
|
+
m = this.data.getUint8(OFFSETS.Battle.last_moves + off) & 0xF0;
|
|
230
|
+
}
|
|
231
|
+
return m !== 0;
|
|
232
|
+
}
|
|
216
233
|
toJSON() {
|
|
217
234
|
return {
|
|
218
235
|
active: this.active?.toJSON(),
|
|
219
236
|
pokemon: Array.from(this.pokemon).map(p => p.toJSON()),
|
|
220
237
|
lastSelectedMove: this.lastSelectedMove,
|
|
221
238
|
lastUsedMove: this.lastUsedMove,
|
|
222
|
-
|
|
239
|
+
lastMoveIndex: this.lastMoveIndex,
|
|
240
|
+
lastMoveCounterable: this.lastMoveCounterable,
|
|
223
241
|
};
|
|
224
242
|
}
|
|
225
243
|
static init(gen, lookup, team, data, offset) {
|
|
@@ -230,11 +248,11 @@ class Side {
|
|
|
230
248
|
data.setUint8(offset + OFFSETS.Side.order + i, i + 1);
|
|
231
249
|
}
|
|
232
250
|
}
|
|
233
|
-
static encode(gen, lookup, battle, side, data, offset) {
|
|
251
|
+
static encode(gen, showdown, lookup, battle, side, data, offset) {
|
|
234
252
|
let i = 0;
|
|
235
253
|
for (const pokemon of side.pokemon) {
|
|
236
254
|
const off = offset + OFFSETS.Side.pokemon + SIZES.Pokemon * (pokemon.position - 1);
|
|
237
|
-
Pokemon.encodeStored(gen, lookup, pokemon, data, off);
|
|
255
|
+
Pokemon.encodeStored(gen, showdown, lookup, pokemon, data, off);
|
|
238
256
|
data.setUint8(offset + OFFSETS.Side.order + (pokemon.position - 1), i + 1);
|
|
239
257
|
i++;
|
|
240
258
|
}
|
|
@@ -424,13 +442,14 @@ class Pokemon {
|
|
|
424
442
|
return status === 'psn' && this.toxic ? 'tox' : status;
|
|
425
443
|
}
|
|
426
444
|
get statusData() {
|
|
427
|
-
|
|
445
|
+
const sleep = this.sleep;
|
|
446
|
+
return { sleep, self: !!sleep && this.ext, toxic: this.toxic };
|
|
428
447
|
}
|
|
429
448
|
get sleep() {
|
|
430
449
|
const val = this.data.getUint8(this.offset.stored + OFFSETS.Pokemon.status);
|
|
431
450
|
return val & 0b111;
|
|
432
451
|
}
|
|
433
|
-
get
|
|
452
|
+
get ext() {
|
|
434
453
|
return (this.data.getUint8(this.offset.stored + OFFSETS.Pokemon.status) >> 7) === 1;
|
|
435
454
|
}
|
|
436
455
|
get toxic() {
|
|
@@ -480,7 +499,7 @@ class Pokemon {
|
|
|
480
499
|
data.setUint8(stored + OFFSETS.Pokemon.types, encodeTypes(lookup, species.types));
|
|
481
500
|
data.setUint8(stored + OFFSETS.Pokemon.level, set.level ?? 100);
|
|
482
501
|
}
|
|
483
|
-
static encodeStored(gen, lookup, pokemon, data, offset) {
|
|
502
|
+
static encodeStored(gen, showdown, lookup, pokemon, data, offset) {
|
|
484
503
|
let off = 0;
|
|
485
504
|
const stats = pokemon.stored.stats;
|
|
486
505
|
for (const stat of gen.stats) {
|
|
@@ -499,7 +518,7 @@ class Pokemon {
|
|
|
499
518
|
data.setUint8(offset + OFFSETS.Pokemon.species, species.num);
|
|
500
519
|
data.setUint8(offset + OFFSETS.Pokemon.types, encodeTypes(lookup, species.types));
|
|
501
520
|
data.setUint8(offset + OFFSETS.Pokemon.level, pokemon.level);
|
|
502
|
-
data.setUint8(offset + OFFSETS.Pokemon.status, encodeStatus(pokemon));
|
|
521
|
+
data.setUint8(offset + OFFSETS.Pokemon.status, encodeStatus(pokemon, showdown));
|
|
503
522
|
}
|
|
504
523
|
static encodeActive(gen, lookup, battle, pokemon, data, offset) {
|
|
505
524
|
if (!pokemon)
|
|
@@ -620,7 +639,7 @@ class StoredPokemon {
|
|
|
620
639
|
}
|
|
621
640
|
exports.StoredPokemon = StoredPokemon;
|
|
622
641
|
function encodePRNG(data, seed) {
|
|
623
|
-
const offset = OFFSETS.Battle.last_damage + 2 + (seed.length === 4 ? 4 :
|
|
642
|
+
const offset = OFFSETS.Battle.last_damage + 2 + (seed.length === 4 ? 4 : 2);
|
|
624
643
|
if (seed.length === 4) {
|
|
625
644
|
data.setUint16(offset, seed[data_2.LE ? 3 : 0], data_2.LE);
|
|
626
645
|
data.setUint16(offset + 2, seed[data_2.LE ? 2 : 1], data_2.LE);
|
|
@@ -628,7 +647,7 @@ function encodePRNG(data, seed) {
|
|
|
628
647
|
data.setUint16(offset + 6, seed[data_2.LE ? 0 : 3], data_2.LE);
|
|
629
648
|
}
|
|
630
649
|
else {
|
|
631
|
-
for (let i = 0; i <
|
|
650
|
+
for (let i = 0; i < 9; i++) {
|
|
632
651
|
data.setUint8(offset + i, seed[i]);
|
|
633
652
|
}
|
|
634
653
|
// NB: ArrayBuffer is zero initialized already so we don't need to set the index to zero
|
|
@@ -646,18 +665,15 @@ function decodeSigned(n) {
|
|
|
646
665
|
function encodeSigned(n) {
|
|
647
666
|
return (n < 0) ? 0b10000 + n : n;
|
|
648
667
|
}
|
|
649
|
-
function encodeStatus(pokemon) {
|
|
668
|
+
function encodeStatus(pokemon, showdown) {
|
|
650
669
|
if (pokemon.statusData.sleep) {
|
|
651
670
|
if (pokemon.status !== 'slp') {
|
|
652
671
|
throw new Error('Pokemon is not asleep but has non-zero sleep turns');
|
|
653
672
|
}
|
|
654
673
|
return (pokemon.statusData.self ? 0x80 : 0) | pokemon.statusData.sleep;
|
|
655
674
|
}
|
|
656
|
-
else if (pokemon.statusData.self) {
|
|
657
|
-
throw new Error('Pokemon is not asleep but has self-inflicted sleep bit set');
|
|
658
|
-
}
|
|
659
675
|
switch (pokemon.status) {
|
|
660
|
-
case 'tox':
|
|
676
|
+
case 'tox': return showdown ? 0b10001000 : 1 << 3;
|
|
661
677
|
case 'psn': return 1 << 3;
|
|
662
678
|
case 'brn': return 1 << 4;
|
|
663
679
|
case 'frz': return 1 << 5;
|