@pkmn/engine 0.1.0-dev.8b83af6b → 0.1.0-dev.90d6c14c

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.
@@ -9,8 +9,8 @@ following files:
9
9
  by the engine, described in detail [below](#data-structures)
10
10
  - [`helpers.zig`](helpers.zig): helpers used to construct complex data types with
11
11
  sensible defaults (internally used by tests and tools)
12
- - [`mechanics.zig`](mechanics.zig): code which manipulates the data structures in order to implement
13
- the mechanics of the game
12
+ - [`mechanics.zig`](mechanics.zig): code which manipulates the data structures to implement the
13
+ mechanics of the game
14
14
  - [`test.zig`](test.zig): unit tests for `mechanics.zig` (the code is also tested by [integration
15
15
  tests](../../../docs/TESTING.md) at a higher level)
16
16
 
@@ -59,39 +59,37 @@ The following information is required to simulate a Generation I Pokémon battle
59
59
  | `volatiles.substitute` | `PlayerSubstituteHP` | `volatiles.substitute.hp` |
60
60
  | `volatiles.disabled_{move,duration}` | `PlayerDisabledMove{,Number}` | `volatiles.disable.{move,time}` |
61
61
 
62
- - Pokémon Showdown [does not implement the correct Generation I RNG](#rng) and as such its `seed` is
62
+ - Pokémon Showdown [doesn't implement the correct Generation I RNG](#rng) and as such its `seed` is
63
63
  different
64
- - `battle.turn` only needs to be tracked in order to be compatible with the Pokémon Showdown
65
- protocol
64
+ - `battle.turn` only needs to be tracked to be compatible with the Pokémon Showdown protocol
66
65
  - Pokémon Showdown tracks several last used move variables (`Battle.lastMove`, `Side.lastMove`, and
67
66
  `Pokemon.lastMove`), none of which accurately match the `PlayerUsedMove` variable from the
68
- cartridge (`Side.lastMove` should be what is used, but is used by Pokémon Showdown only for
69
- Counter and is not set and cleared in the correct locations. `Pokemon.lastMove` matches
70
- `PlayerUsedMove` more often so is what the engine attempts to model, despite the implications for
71
- Counter)
72
- - `battle.last_moves` doesn't map precisely to cartridge concepts because it is used to track desyncs
73
- which instead are represented on the cartridge as discrepancies between the two separate battle states
74
- that exist in the link battle.
75
- - Pokémon Showdown does not implement the [partial-trapping move Mirror Move
67
+ cartridge (`Side.lastMove` should be what's used, but is used by Pokémon Showdown only for Counter
68
+ and isn't set and cleared in the correct locations. `Pokemon.lastMove` matches `PlayerUsedMove`
69
+ more often so is what the engine attempts to model, despite the implications for Counter)
70
+ - `battle.last_moves` doesn't map precisely to cartridge concepts because it's used to track desyncs
71
+ which instead are represented on the cartridge as discrepancies between the two separate battle
72
+ states that exist in the link battle.
73
+ - Pokémon Showdown doesn't implement the [partial-trapping move Mirror Move
76
74
  glitch](https://glitchcity.wiki/Partial_trapping_move_Mirror_Move_link_battle_glitch) and as such
77
- does not need to keep track of a player's last selected move index (`PlayerMoveListIndex`)
75
+ doesn't need to keep track of a player's last selected move index (`PlayerMoveListIndex`)
78
76
  - Battle results (win, lose, draw) and request states are communicated via the return value of
79
77
  `Battle.update`
80
- - Nicknames (`BattleMonNick`/`pokemon.name`) are not handled by the pkmn engine as they are expected
78
+ - Nicknames (`BattleMonNick`/`pokemon.name`) aren't handled by the pkmn engine as they're expected
81
79
  to be handled by driver code if required
82
80
  - Pokémon Red's `LastSwitchInEnemyMonHP`, `InHandlePlayerMonFainted`, `PlayerNumHits`,
83
81
  `PlayerMonMinimized`, and `Move{DidntMiss,Missed}` are relevant for messaging/UI only
84
82
  - Pokémon Red's `TransformedEnemyMonOriginalDVs` is only relevant for the [Transform DV manipulation
85
83
  glitch](https://pkmn.cc/bulba/Transform_glitches#Transform_DV_manipulation_glitch)
86
- - Pokémon Red's `PlayerMove*` tracks information that is stored in the `Move` class
84
+ - Pokémon Red's `PlayerMove*` tracks information that's stored in the `Move` class
87
85
  - Pokémon Red's `PlayerStatsToDouble`/`PlayerStatsToHalve` are constants which are always 0
88
- - pkmn does not store the DVs/stat experience of Pokémon as they are expected to already be
89
- accounted for in the `Pokemon` `stats` and never need to be referenced in-battle (though a `DVs`
90
- struct exists to simplify generating legal test data)
86
+ - pkmn doesn't store the DVs/stat experience of Pokémon as they're expected to already be accounted
87
+ for in the `Pokemon` `stats` and never need to be referenced in-battle (though a `DVs` struct
88
+ exists to simplify generating legal test data)
91
89
  - Instead of storing unmodified stats like Pokémon Red or Pokémon Showdown, pkmn simply tracks the
92
90
  identity of the Pokémon that has been transformed into in the `active.volatiles.transform` field
93
91
  - pkmn uses `volatiles.state` for total accumulated damage for Bide but also for implementing
94
- accuracy overwrite mechanics for certain moves (this glitch is present on the device but is not
92
+ accuracy overwrite mechanics for certain moves (this glitch is present on the device but isn't
95
93
  correctly implemented by Pokémon Showdown currently)
96
94
 
97
95
  ### `Battle` / `Side`
@@ -107,9 +105,9 @@ otherwise be the padding bytes of`Battle` (the `last_moves` field) instead of in
107
105
 
108
106
  ### `Pokemon` / `ActivePokemon`
109
107
 
110
- Similar to the cartridge, in order to save space different information is stored depending on
111
- whether a [Pokémon](https://pkmn.cc/bulba/Pok%c3%a9mon_data_structure_%28Generation_I%29) is
112
- actively participating in battle vs. is switched out (pret's [`battle_struct` vs.
108
+ Similar to the cartridge, to save space different information is stored depending on whether a
109
+ [Pokémon](https://pkmn.cc/bulba/Pok%c3%a9mon_data_structure_%28Generation_I%29) is actively
110
+ participating in battle vs. is switched out (pret's [`battle_struct` vs.
113
111
  `party_struct`](https://pkmn.cc/pokered/macros/ram.asm)). In Pokémon Showdown, all the Pokémon in a
114
112
  battle are represented by the same
115
113
  [`Pokemon`](https://github.com/smogon/pokemon-showdown/blob/master/sim/pokemon.ts) class, and static
@@ -121,14 +119,14 @@ A `MoveSlot` is a data-type for a `(move, current pp)` pair. A pared down versio
121
119
  Showdown's `Pokemon.moveSlot`, it also stores data from the cartridge's `battle_struct::Move` macro
122
120
  and can be used to replace the `PlayerMove*` data. Move PP is stored as a full byte instead of how
123
121
  the cartridge (`battle_struct::PP`) stores it (6 bits for current PP and the remaining 2 bits used
124
- to store the number of applied PP Ups). PP Up bits do not actually need to be stored on move slot
122
+ to store the number of applied PP Ups). PP Up bits don't actually need to be stored on move slot
125
123
  as max PP is never relevant in Generation I.
126
124
 
127
125
  #### `Status`
128
126
 
129
127
  Bitfield representation of a Pokémon's major [status
130
- condition](https://pkmn.cc/bulba/Status_condition), mirroring how it is stored on the cartridge. A
131
- value of `0x00` means that the Pokémon is not affected by any major status, otherwise the lower 3
128
+ condition](https://pkmn.cc/bulba/Status_condition), mirroring how it's stored on the cartridge. A
129
+ value of `0x00` means that the Pokémon isn't affected by any major status, otherwise the lower 3
132
130
  bits represent the remaining duration for Sleep. Other status are denoted by the presence of
133
131
  individual bits - at most one status should be set at any given time.
134
132
 
@@ -137,10 +135,10 @@ below), so the upper most bit of `Status` is instead used to track state require
137
135
  quirks:
138
136
 
139
137
  - when combined with a valid sleep duration (or 0), it indicates that the `SLP` status was
140
- self-inflicted (required in order to implement Pokémon Showdown's "Sleep Clause Mod")
138
+ self-inflicted (required to implement Pokémon Showdown's "Sleep Clause Mod")
141
139
  - when combined with `PSN` it indicates that the Pokémon is actually badly poisoned (required in
142
140
  order to send the same incorrect protocol messages as Pokémon Showdown - the Toxic volatile
143
- alone is not sufficient in compatibility mode because it gets lost on switch)
141
+ alone isn't sufficient in compatibility mode because it gets lost on switch)
144
142
 
145
143
  #### `Volatiles`
146
144
 
@@ -176,17 +174,16 @@ boolean flags that are cleared when the Pokémon faints or switches out:
176
174
  [Toxic](https://pkmn.cc/bulba/Toxic_(move)) (counter),
177
175
  [Transform](https://pkmn.cc/bulba/Transform_(move)) (identity), and
178
176
  [Disable](https://pkmn.cc/bulba/Disable_(move)) (move and duration), and multi-hit attacks all
179
- require additional information that is also stored in the `Volatiles` structure. `MultiHit` is not
180
- strictly required to be stored as it should always be 0 after updates barring errors, however it is
177
+ require additional information that's also stored in the `Volatiles` structure. `MultiHit` isn't
178
+ strictly required to be stored as it should always be 0 after updates barring errors, however it's
181
179
  convenient to maintain as it maps neatly to the cartridge and is effectively "free" space-wise due
182
180
  to padding.
183
181
 
184
182
  The `state` field of `Volatiles` is effectively treated as a union:
185
183
 
186
184
  - if `volatiles.Bide` is set, `volatiles.data.state` reflects the total accumulated Bide damage
187
- - otherwise, `volatiles.data.state` reflects the last computed move accuracy (required in order to
188
- implement the [Rage and Thrash / Petal Dance accuracy
189
- bug](https://www.youtube.com/watch?v=NC5gbJeExbs))
185
+ - otherwise, `volatiles.data.state` reflects the last computed move accuracy (required to implement
186
+ the [Rage and Thrash / Petal Dance accuracy bug](https://www.youtube.com/watch?v=NC5gbJeExbs))
190
187
 
191
188
  #### `Stats` / `Boosts`
192
189
 
@@ -198,8 +195,8 @@ boosts should always range from `-6`...`6` instead of `1`...`13` as on the cartr
198
195
 
199
196
  `Move` serves as an identifier for a unique [Pokémon move](https://pkmn.cc/bulba/Move) that can be
200
197
  used to retrieve `Move.Data` with information regarding base power, accuracy, and type. As covered
201
- above, PP information isn't strictly necessary in Generation I so is dropped. `Move.None` exists as
202
- a special sentinel value to indicate `null`. Move PP data is only included for testing and is not
198
+ earlier, PP information isn't strictly necessary in Generation I so is dropped. `Move.None` exists
199
+ as a special sentinel value to indicate `null`. Move PP data is only included for testing and isn't
203
200
  necessary for the actual engine implementation.
204
201
 
205
202
  In order to workaround various [Pokémon Showdown bugs](#bugs) and to support its protocol in logs,
@@ -221,11 +218,11 @@ places to determine which protocol messages to print.
221
218
  ### `Species` / `Species.Data`
222
219
 
223
220
  `Species` just serves as an identifier for a unique [Pokémon
224
- species](https://pkmn.cc/bulba/Pokémon_species_data_structure_(Generation_I)) as the base stats
225
- of a species are already accounted for in the computed stats in the `Pokemon` structure and nothing
226
- in battle requires these to be recomputed. Similarly, Type is unnecessary to include as it is also
221
+ species](https://pkmn.cc/bulba/Pokémon_species_data_structure_(Generation_I)) as the base stats of a
222
+ species are already accounted for in the computed stats in the `Pokemon` structure and nothing in
223
+ battle requires these to be recomputed. Similarly, Type is unnecessary to include as it's also
227
224
  already present in the `Pokemon` struct. `Species.None` exists as a special sentinel value to
228
- indicate `null`. `Species.Data` is only included for testing and is not necessary for the actual
225
+ indicate `null`. `Species.Data` is only included for testing and isn't necessary for the actual
229
226
  engine implementation, outside of `Species.CHANCES` which is required as the base speed / 2 of the
230
227
  species is necessary for computing critical hit probability.
231
228
 
@@ -238,15 +235,15 @@ effectiveness - like the cartridge, effectiveness is stored as `0`, `5`, `10`, a
238
235
  (technically only a 2-bit value is required, but as with `Types` Zig only allows a minimum of a byte
239
236
  to be stored at each address of an array).
240
237
 
241
- The 'precedence' of the various type matchups matters beyond just the [dual-type damage
238
+ The 'precedence' of the various type match-ups matters beyond just the [dual-type damage
242
239
  misinformation
243
240
  glitch](https://pkmn.cc/bulba/List_of_glitches_(Generation_I)#Dual-type_damage_misinformation) -
244
241
  type effectiveness modifiers are applied based on the (haphazard) ordering of the effectiveness
245
242
  table as opposed to first applying modifiers for a species's first type and then second type. The
246
- engine maintains a `Type.PRECEDENCE` table with just the matchups that are relevant in game (certain
247
- type combinations cannot crop up with the limited Generation I species pool and as such are pruned
248
- for efficiency) and only looks up precedence when necessary to minimize expensive searches. Pokémon
249
- Showdown does not implement type precedence.
243
+ engine maintains a `Type.PRECEDENCE` table with just the match-ups that are relevant in game
244
+ (certain type combinations can't crop up with the limited Generation I species pool and as such are
245
+ pruned for efficiency) and only looks up precedence when necessary to minimize expensive searches.
246
+ Pokémon Showdown doesn't implement type precedence.
250
247
 
251
248
  ## Information
252
249
 
@@ -272,8 +269,8 @@ entropy](https://en.wikipedia.org/wiki/Entropy_(information_theory))) is as foll
272
269
  | **crit chance** | 7..65 | 6 | | **transform** | 0..15 | 4 |
273
270
  | **target** | 0..4 | 3 | | | | |
274
271
 
275
- From this we can determine the minimum bits[^1] required to store each data structure to determine
276
- how much overhead the representations above have after taking into consideration [alignment &
272
+ From this one can determine the minimum bits[^1] required to store each data structure to determine
273
+ how much overhead the preceding representations have after taking into consideration [alignment &
277
274
  padding](https://en.wikipedia.org/wiki/Data_structure_alignment) and
278
275
  [denormalization](https://en.wikipedia.org/wiki/Denormalization):
279
276
 
@@ -286,9 +283,9 @@ padding](https://en.wikipedia.org/wiki/Data_structure_alignment) and
286
283
  - the active Pokémon's level and current and max HP can always be referred to the `Pokemon`
287
284
  struct
288
285
  - **`Side`**: `ActivePokemon` + 6× `Pokemon` + active (`3`) + last used (`8`) + last selected
289
- (`8`)
290
- - `order` does not need to be stored as the party can always be rearranged as switches occur
291
- - **`Battle`**: 6× `Side` + seed (10× `8` + `4`) + turn (`10`) + last damage (`10`)
286
+ (`8`) + counterable (`1`) + last move index (`3`)
287
+ - `order` doesn't need to be stored as the party can always be rearranged as switches occur
288
+ - **`Battle`**: 6× `Side` + seed (9× `8` + `4`) + turn (`10`) + last damage (`10`)
292
289
  - **`Type.CHART`**: attacking types (`15`) × defending types (`15`) × effectiveness (`2`)[^2]
293
290
  - **`Type.PRECEDENCE`**: 29× attacking type (`4`) + defending type (`4`) pairs
294
291
  - **`Moves.DATA`**: 165× base power (`6`) + effect (`7`) + accuracy (`4`) + type (`4`) + target
@@ -299,8 +296,8 @@ padding](https://en.wikipedia.org/wiki/Data_structure_alignment) and
299
296
  | ----------------- | ----------- | ------------ | -------- |
300
297
  | `Pokemon` | 192 | 147 | 30.6% |
301
298
  | `ActivePokemon` | 256 | 202 | 26.7% |
302
- | `Side` | 1472 | 1056 | 33.5% |
303
- | `Battle` | 3088 | 2216 | 33.7% |
299
+ | `Side` | 1472 | 1107 | 33.0% |
300
+ | `Battle` | 3088 | 2310 | 33.7% |
304
301
  | `Type.CHART` | 1800 | 450 | 300.0% |
305
302
  | `Type.PRECEDENCE` | 232 | 232 | 0.0% |
306
303
  | `Moves.DATA` | 5280 | 3960 | 33.3% |
@@ -313,25 +310,25 @@ consideration the worst case all Pokémon types are required and 48 moves. The `
313
310
  could be eliminated and instead the `Move` data actually required by each `Pokemon` could be placed
314
311
  beside the `MoveSlot`, though this is both less general and adds unnecessary complexity.
315
312
 
316
- [^1]: For data with lower cardinality it is possible to save memory by ordinalizing the values and
313
+ [^1]: For data with lower cardinality it's possible to save memory by ordinalizing the values and
317
314
  turning them into indices into a lookup table (e.g. encode all possible move base powers in a lookup
318
315
  table and store the index into that table instead of the actual base power). While this approach may
319
316
  minimize the absolute memory used, performance is more likely to suffer as the goal is to minimize
320
- uncached memory lookups, not total memory usage.
317
+ un-cached memory lookups, not total memory usage.
321
318
 
322
319
  [^2]: Instead of storing as a sparse multi-dimensional array the type chart could instead only
323
320
  [store values which are not normal
324
321
  effectiveness](https://github.com/pret/pokered/blob/master/data/types/type_matchups.asm) in 820 bits
325
322
  as 82× attacking type (`4`) + defending type (`4`) + non-Normal effectiveness (`2`). This would
326
323
  avoid having to do two memory lookups at the cost of a longer time scanning, but the second lookup
327
- should already be fast due to locality of reference meaning it will likely already be in the cache.
324
+ should already be fast due to locality of reference meaning it's likely to already be in the cache.
328
325
  This approach would also render `Type.PRECEDENCE` unnecessary.
329
326
 
330
327
  ## Layout
331
328
 
332
329
  The precise layout of the engine's data structures is important to those implementing driver code,
333
330
  as clients must directly probe the engine's state through these structures (i.e. the pkmn engine
334
- does not produce an equivalent to Pokémon Showdown's `|request|` protocol message, this information
331
+ doesn't produce an equivalent to Pokémon Showdown's `|request|` protocol message, this information
335
332
  must be gleaned through the `Battle` state). Useful size and offset information can be found in
336
333
  the [`layout.json`](../../data/layout.json) which exists to simplify writing driver code.
337
334
 
@@ -348,8 +345,8 @@ data in the browser for ease of debugging.
348
345
  | 184 | 368 | [`sides[1]`](#side) | Player 2's side |
349
346
  | 368 | 370 | `turn` | The current turn number |
350
347
  | 370 | 372 | `last_damage` | The last damage dealt by either side |
351
- | 372 | 373-376 | `last_moves` | The slot index of the last selected moves for each side |
352
- | 373-376 | 384 | `rng` | The RNG state |
348
+ | 372 | 374-376 | `last_moves` | The slot index of the last selected moves for each side |
349
+ | 374-376 | 384 | `rng` | The RNG state |
353
350
 
354
351
  - the current `turn` is 2 bytes, written in native-endianness
355
352
  - `last_moves` layout depends on whether or not Pokémon Showdown compatibility mode is enabled
@@ -359,13 +356,13 @@ data in the browser for ease of debugging.
359
356
  - if `showdown` is enabled byte 372 is used to store the last selected move index of `side[0]` and
360
357
  byte 373 is used to store whether or not the side's last executed move would have been considered
361
358
  "counterable"; and bytes 374 and 375 store the same information for `side[1]`
362
- - otherwise the first 3 bits of byte 372 stores the last selected move index of `side[0]` and the
363
- next bit stores whether that side's last executed move would have been considered "counterable",
364
- with the same information for `side[1]`'s being stored in the second 4 bits
359
+ - otherwise the first 4 bits of byte 372 stores the last selected move index of `side[0]` and the
360
+ next 4 bits store whether that side's last executed move would have been considered
361
+ "counterable", with the same information for `side[1]`'s being stored in the second byte
365
362
  - the `rng` depends on whether or not Pokémon Showdown compatibility mode is enabled (`-Dshowdown`):
366
363
  - if `showdown` is enabled, the RNG state begins on byte 376 and consists of a 64-bit seed,
367
364
  written in native-endianness
368
- - otherwise the RNG state begins on byte 373 and consists of the 10 bytes of the seed followed by
365
+ - otherwise the RNG state begins on byte 374 and consists of the 9 bytes of the seed followed by
369
366
  the index pointing to which byte of the seed is currently being used
370
367
 
371
368
  ### `Side`
@@ -384,7 +381,7 @@ data in the browser for ease of debugging.
384
381
  | 183 | 184 | `last_used_move` | The last move the player used |
385
382
 
386
383
  - `order` is a 6 byte array where `order[i]` represents the "slot" of `pokemon[i]`, where the slot
387
- is usually a unique value from 1-6 but can be 0 in situations where a player brings less than six
384
+ is usually a unique value from 1 to 6 but can be 0 in situations where a player brings less than six
388
385
  Pokémon to battle (note however that if `order[i]` is 0 than for all j > 0 `order[i+j]` **must**
389
386
  equal 0).
390
387
 
@@ -411,7 +408,7 @@ data in the browser for ease of debugging.
411
408
  | 28 | 29 | `moves[2].id` | The active Pokémon's third move |
412
409
  | 29 | 30 | `moves[2].pp` | The PP of the active Pokémon's third move |
413
410
  | 30 | 31 | `moves[3].id` | The active Pokémon's fourth move |
414
- | 31 | 32 | `moves[3].pp` | The PP of the active Pokémon's fourth moe |
411
+ | 31 | 32 | `moves[3].pp` | The PP of the active Pokémon's fourth move |
415
412
 
416
413
  - the active Pokémon's `stats.hp` is always identical to the corresponding stored Pokémon's `stats.hp`
417
414
  - `boosts` and `types` includes bytes which store two 4-bit fields each
@@ -446,7 +443,7 @@ data in the browser for ease of debugging.
446
443
  | 40 | 48 | `substitute` | The remaining HP of the Substitute |
447
444
  | 48 | 52 | `transform` | The identity of whom the active Pokémon is transformed into |
448
445
  | 52 | 56 | `disabled_duration` | The remaining turns the move is disabled |
449
- | 56 | 59 | `disabled_move` | The move slot (1-4) that is disabled |
446
+ | 56 | 59 | `disabled_move` | The move slot (1-4) that's disabled |
450
447
  | 59 | 64 | `toxic` | The number of turns toxic damage has been accumulating |
451
448
 
452
449
  ### `Pokemon`
@@ -480,31 +477,31 @@ Smogon](https://www.smogon.com/forums/posts/5933177/show):
480
477
 
481
478
  - moves on Pokémon Showdown can do 0 damage instead of failing or causing a [division-by-zero
482
479
  freeze](https://pkmn.cc/bulba-glitch-1#Division_by_0).
483
- - Pokémon Showdown does not implement type effectiveness precedence correctly.
480
+ - Pokémon Showdown doesn't implement type effectiveness precedence correctly.
484
481
  - Pokémon Showdown checks for type and OHKO immunity before accuracy.
485
482
  - Confusion self-hits use the wrong damage formula resulting in off-by-one errors (and also fail to
486
- account for an opponent's Reflect). Furthermore, the confusion self-hit damage will erroneously be
487
- inflicted to the confused user's substitute if the confused user had been attempting to use a
483
+ account for an opponent's Reflect). Furthermore, the confusion self-hit damage erroneously gets
484
+ inflicted on the confused user's substitute if the confused user had been attempting to use a
488
485
  self-targeting move. Finally, Pokémon Showdown erroneously considers the *uncapped* self-hit
489
486
  damage for the purposes of tracking the battle's last damage.
490
487
 
491
- Beyond the general bugs listed above, several move effects are implemented incorrectly by Pokémon
492
- Showdown. Some of these moves are [too fundamentally broken to be implemented](#unimplementable) by
493
- the pkmn engine, but the following moves have their broken behavior preserved in `-Dshowdown` mode:
488
+ Beyond these general bugs, several move effects are implemented incorrectly by Pokémon Showdown.
489
+ Some of these moves are [too fundamentally broken to be implemented](#unimplementable) by the pkmn
490
+ engine, but the following moves have their broken behavior preserved in `-Dshowdown` mode:
494
491
 
495
492
  - **Bide**: Bide's damage can overflow if OHKO moves are involved because OHKO moves work by setting
496
493
  the damage to 65535 - Pokémon Showdown doesn't implement this overflow and instead lets Bide's
497
494
  damage grow unbounded. Additionally, if the opponent faints after Bide inflicts damage on Pokémon
498
495
  Showdown residual damage incorrectly still gets applied to Bide's user.
499
- - **Counter**: On Pokémon Showdown choices made while sleeping (which should not have been
496
+ - **Counter**: On Pokémon Showdown choices made while sleeping (which shouldn't have been
500
497
  registered) can erroneously cause Counter to trigger Desync Clause Mod behavior. Additionally,
501
498
  because Pokémon Showdown neglects to zero the last battle damage if a move misses due to immunity
502
- or invulnerability Counter will occasionally work on Pokémon Showdown when it should fail.
499
+ or invulnerability Counter occasionally works on Pokémon Showdown when it should fail.
503
500
  - **Leech Seed**: Leech Seed fails to heal its source side if a seeded target faints due to
504
501
  recoil/crash damage on Pokémon Showdown.
505
502
  - **Pay Day**: Pay Day should still scatter coins if it hits (but doesn't break) and opponent's
506
503
  Substitute but doesn't on Pokémon Showdown.
507
- - **Flinch**: Flinching does not get cleared during move selection on Pokémon Showdown and is
504
+ - **Flinch**: Flinching doesn't get cleared during move selection on Pokémon Showdown and is
508
505
  instead cleared in Pokémon Showdown's "residual" phase, meaning the flinch status gets erroneously
509
506
  preserved across fainting (as fainting triggers Pokémon Showdown's "instaswitch" behavior which
510
507
  skips end-of-turn residuals).
@@ -515,45 +512,45 @@ the pkmn engine, but the following moves have their broken behavior preserved in
515
512
  Petal Dance accuracy bug]( https://www.youtube.com/watch?v=NC5gbJeExbs) incorrectly, as the
516
513
  accuracy only gets written when the volatile is present which can lead to incorrect accuracy
517
514
  values on turns where Rage is used on the same turn as a move which modifies accuracy or evasion.
518
- - **Thrash** / **Petal Dance**: once a Pokémon is locked into a thrashing move they will lose all
519
- speed ties on Pokémon Showdown (due to the fact that if they win the speed tie their action will
520
- then get "changed" and inserted back into the queue after their opponent's action). Pokémon
521
- Showdown also implements accuracy incorrectly, as covered above.
515
+ - **Thrash** / **Petal Dance**: once a Pokémon is locked into a thrashing move they lose all speed
516
+ ties on Pokémon Showdown (due to the fact that if they win the speed tie their action then gets
517
+ "changed" and inserted back into the queue after their opponent's action). Pokémon Showdown also
518
+ implements accuracy incorrectly, as covered earlier.
522
519
  - **Freeze** / **Sleep**: Pokémon Showdown requires a move to be selected when a Pokémon is frozen
523
520
  or sleeping and uses that in the event that the status is removed while on the cartridge no
524
521
  selection is possible and no turn exists for the thawed/woken Pokémon to act except in the case of
525
522
  a Fire-type move thawing a slower Pokémon (which should result in the [Freeze top move selection
526
- glitch](https://glitchcity.wiki/Freeze_top_move_selection_glitch), which is not implemented and
523
+ glitch](https://glitchcity.wiki/Freeze_top_move_selection_glitch), which isn't implemented and
527
524
  would also likely be incorrect if it were to be implemented due to how Pokémon Showdown
528
525
  incorrectly saves arbitrary moves with its choice selection semantics). Furthermore, thrashing
529
- volatiles should not be cleared if the user misses a turn due to freeze / sleep.
526
+ volatiles shouldn't be cleared if the user misses a turn due to freeze / sleep.
530
527
  - **Hyper Beam**: due to improperly implemented selection mechanics, the [Hyper Beam
531
528
  automatic-selection glitch](https://glitchcity.wiki/Hyper_Beam_automatic_selection_glitch) does
532
529
  not exist on Pokémon Showdown. Additionally, Hyper Beam being able to cause [Freeze permanent
533
- helplessness](https://pkmn.cc/bulba-glitch-1#Hyper_Beam_.2B_Freeze_permanent_helplessness) is not
530
+ helplessness](https://pkmn.cc/bulba-glitch-1#Hyper_Beam_.2B_Freeze_permanent_helplessness) isn't
534
531
  implement by Pokémon Showdown.
535
532
  - **Roar** / **Whirlwind**: these moves can miss on Pokémon Showdown (and advance the RNG when
536
- checking) which is incorrect (these moves should always fail, but do not check accuracy or advance
533
+ checking) which is incorrect (these moves should always fail, but don't check accuracy or advance
537
534
  the RNG). More importantly, these moves should *not* cause the tracked last battle damage to be
538
535
  zeroed, but on Pokémon Showdown they do.
539
536
  - **Substitute**: in addition to the [Substitute + Confusion
540
537
  glitch](https://pkmn.cc/bulba-glitch-1#Substitute_.2B_Confusion_glitch) not being implemented
541
- correctly (covered above), the [Substitute 1/4
538
+ correctly (covered earlier), the [Substitute 1/4
542
539
  glitch](https://glitchcity.wiki/Substitute_%C2%BC_HP_glitch) also fails in many cases due to
543
540
  Pokémon Showdown implementing the health check based on floating point division instead of integer
544
- divison like on the cartridge (meaning the Substitute 1/4 glitch will only occur if the Pokémon's
541
+ division like on the cartridge (meaning the Substitute 1/4 glitch only occurs if the Pokémon's
545
542
  maximum HP is evenly divisible by 4). Substitute also incorrectly blocks Dream Eater on
546
- Pokémon Showdown and will incorrectly still heal 1 HP for any draining moves if the attack does 0
543
+ Pokémon Showdown and incorrectly still heals 1 HP for any draining moves if the attack does 0
547
544
  damage. Finally, Pokémon Showdown uses a `subFainted` field to track whether a Substitute was
548
- broken in order to know when to nullify a move's effect, only it doesn't get cleared at the end of
545
+ broken to know when to nullify a move's effect, only it doesn't get cleared at the end of
549
546
  the turn and can result in incorrect behavior on subsequent turns with the moves Mirror Move and
550
547
  Metronome that invoke `runMove` (which is where `subFainted` gets cleared) on the user but skips
551
548
  calling it for the eventual true target.
552
549
 
553
550
  In addition to numerous cases where Pokémon Showdown uses the wrong type of message (e.g. `|-fail`
554
- vs. `|-miss|` vs. `|-immune|`, e.g. in the case of Leech Seed) which are not documented here, Pokémon
555
- Showdown sometimes gets message ordering incorrect (which does not effect the outcome
556
- of the battle, only pedantic UI correctness):
551
+ vs. `|-miss|` vs. `|-immune|`, e.g. in the case of Leech Seed) which aren't documented here, Pokémon
552
+ Showdown sometimes gets message ordering incorrect (which doesn't effect the outcome of the battle,
553
+ only pedantic UI correctness):
557
554
 
558
555
  - **Rage**: Rage should report the `|-boost|` before the Disable `|-miss|`, not after.
559
556
  - **Haze**: Haze clears the status/volatiles in an incorrect order.
@@ -566,21 +563,21 @@ Pokémon Showdown also implements a number of modifications to the cartridge (us
566
563
  called out in the `|rule|` section at the beginning of a battle's log):
567
564
 
568
565
  - **Sleep Clause Mod**: players are prevented from putting more than one of their opponent's Pokémon
569
- to sleep at a time (usage of the move will fail).
566
+ to sleep at a time (usage of the move fails).
570
567
  - **Freeze Clause Mod**: players are prevented from freezing more than one of their opponent's
571
- Pokémon at a time (usage of the move will fail).
572
- - **Desync Clause Mod**: If the usage of a move would cause a desync it instead causes a
573
- failure. However, this mod does not trigger for [**division by
568
+ Pokémon at a time (usage of the move fails).
569
+ - **Desync Clause Mod**: If the usage of a move would cause a desync it instead causes a failure.
570
+ However, this mod doesn't trigger for [**division by
574
571
  zero**](https://pkmn.cc/bulba/List_of_glitches_(Generation_I)#Division_by_0) - instead of failing,
575
572
  Pokémon Showdown silently patches the damage calculation to divide by 1 instead of 0. The
576
573
  definition of the Desync Clause Mod should be extended or the code should be changed to fail
577
574
  instead of succeeding in these cases.
578
575
  - **Endless Battle Clause**: Prematurely ends the battle in a tie after 1000 turns or in certain
579
- situations where it is trivially detectable that no progress can be made.
576
+ situations where it's trivially detectable that no progress can be made.
580
577
  - **Switch Priority Clause Mod**: When both player switch out their Pokémon at the same time the
581
578
  faster Pokémon switches first. This mod is **not broadcast at the start of the battle in the
582
- `|rule|` section** in Generation I (or II) as the actual order of switches here does not have
583
- competitive implications like it does in Generation III, but it is still contrary to how the games
579
+ `|rule|` section** in Generation I (or II) as the actual order of switches here doesn't have
580
+ competitive implications like it does in Generation III, but it's still contrary to how the games
584
581
  work where the [host (Player 1)'s Pokemon would switch
585
582
  first](https://www.smogon.com/forums/posts/5989318/show).
586
583
 
@@ -622,35 +619,35 @@ the correct control flow):
622
619
  Pokémon using Rage/Bide or Thrashing/Charging moves being incorrectly forced to skip a turn when
623
620
  the Pokémon using the Binding move switches.
624
621
  - **Mimic**: Pokémon Showdown checks that the user of Mimic has Mimic in one of their move slots,
625
- which means Mimic legally called via Metronome or Mirror Move will only work if the user also has
626
- Mimic (and the moved mimicked by Mimic called via Metronome / Mirror Move will erroneously
627
- override the Mimic move slot instead of the Metronome / Mirror Move move slot). Furthermore,
628
- because Pokémon Showdown deducts PP based on a move's name instead of slot, if Mimic copies a move
629
- the Pokémon already knows, PP deduction for using either the original move of the mimicked move
630
- will instead deduct PP for whichever appears at the lower move slot index and the PP will be
631
- allowed to go negative (effectively allowing for infinite PP use). Pokémon Showdown also doesn't
632
- deduct PP from using Transform if it was copied by Mimic.
633
- - **Mirror Move**: As covered above, both Substitute and Binding moves misbehave when used via
634
- Mirror Move (though Pokémon Showdown has its own weird behavior and does not implement the
635
- [partial trapping move Mirror Move
622
+ which means Mimic legally called via Metronome or Mirror Move only works if the user also has
623
+ Mimic (and the moved mimicked by Mimic called via Metronome / Mirror Move erroneously overrides
624
+ the Mimic move slot instead of the Metronome / Mirror Move move slot). Furthermore, because
625
+ Pokémon Showdown deducts PP based on a move's name instead of slot, if Mimic copies a move the
626
+ Pokémon already knows, PP deduction for using either the original move of the mimicked move
627
+ instead deducts PP for whichever appears at the lower move slot index and the PP is allowed to go
628
+ negative (effectively allowing for infinite PP use). Pokémon Showdown also doesn't deduct PP from
629
+ using Transform if it was copied by Mimic.
630
+ - **Mirror Move**: As covered earlier, both Substitute and Binding moves misbehave when used via
631
+ Mirror Move (though Pokémon Showdown has its own weird behavior and doesn't implement the [partial
632
+ trapping move Mirror Move
636
633
  glitch](https://glitchcity.wiki/Partial_trapping_move_Mirror_Move_link_battle_glitch) that exists
637
634
  on the cartridge). Additionally, Pokémon Showdown sets the last used move every turn a Pokémon is
638
- Thrashing instead of just on the turn it is actually selected meaning Mirror Move will sometimes
639
- successfully mirror a Thrashing move when it should fail. Finally, if Mirror Move copies
640
- Struggle it should not deduct PP but on Pokémon Showdown it does.
635
+ Thrashing instead of just on the turn it's actually selected meaning Mirror Move sometimes
636
+ successfully mirrors a Thrashing move when it should fail. Finally, if Mirror Move copies Struggle
637
+ it shouldn't deduct PP but on Pokémon Showdown it does.
641
638
  - **Metronome**: In addition to the issues with binding moves and Substitute, Metronome and Mirror
642
- Move cannot mutually call each other more than 3 times in a row without causing the Pokémon
643
- Showdown simulator to crash due to defensive safety checks that do not exist on the cartridge.
639
+ Move can't mutually call each other more than 3 times in a row without causing the Pokémon
640
+ Showdown simulator to crash due to defensive safety checks that don't exist on the cartridge.
644
641
  - **Transform**: Transform screws up the effect of Disable, because on Pokémon Showdown, Disable
645
642
  prevents moves of a given *name* from being used (e.g. "Water Gun") as opposed to moves in a
646
- specific *slot* (e.g. the 2nd move slot), and a Pokémon's moves can change after Transform (this
647
- is not an issue with Disable + Mimic because Mimic happens to replace the same slot). Transform
648
- also has a bad interaction with Pokémon Showdown's buggy Haze implementation, as Haze on Pokémon
649
- Showdown does not copy unmodified stats, leaving the Transformed Pokémon with incorrect stats.
650
- Furthermore, transforming and then using Mirror Move / Metronome can result in [glitchy behavior
651
- and
643
+ specific *slot* (e.g. the second move slot), and a Pokémon's moves can change after Transform
644
+ (this isn't an issue with Disable + Mimic because Mimic happens to replace the same slot).
645
+ Transform also has a bad interaction with Pokémon Showdown's buggy Haze implementation, as Haze on
646
+ Pokémon Showdown doesn't copy unmodified stats, leaving the Transformed Pokémon with incorrect
647
+ stats. Furthermore, transforming and then using Mirror Move / Metronome can result in [glitchy
648
+ behavior and
652
649
  softlocks](https://pkmn.cc/bulba/Transform_glitches#Transform_.2B_Mirror_Move.2FMetronome_PP_error)
653
- which Pokémon Showdown does not implement.
650
+ which Pokémon Showdown doesn't implement.
654
651
 
655
652
  Importantly, Pokémon Showdown's **speed tie RNG mechanics are unimplementable** in the pkmn engine
656
653
  as they rely on internal implementation decisions made by Pokémon Showdown that are impossible to
@@ -661,13 +658,13 @@ below).
661
658
 
662
659
  **The pkmn engine aims to match the cartridge's RNG frame-accurately**, in that provided with the
663
660
  same initial seed and inputs it should produce the same battle playout as the Pokémon Red cartridge.
664
- **Pokémon Showdown does not correctly implement frame-accurate RNG in any generation**, and along
665
- with the [bugs](#bugs) discussed above this results in large differences in the codebase. Because
661
+ **Pokémon Showdown doesn't correctly implement frame-accurate RNG in any generation**, and along
662
+ with the [bugs](#bugs) discussed earlier this results in large differences in the codebase. Because
666
663
  the pkmn engine aims to be as compatible with Pokémon Showdown as possible when in `-Dshowdown`
667
664
  compatibility mode, the implications of these differences are outlined below:
668
665
 
669
666
  - **RNG**: Pokémon Showdown uses the RNG from Generation V & VI in every generation, despite
670
- the seeds and algorithm being different. Pokémon Red uses a simple 8-bit RNG with 10 distinct
667
+ the seeds and algorithm being different. Pokémon Red uses a simple 8-bit RNG with 9 distinct
671
668
  seeds generated when the link connection is established, whereas Pokémon Showdown uses a 64-bit
672
669
  RNG with a 32-bit output.
673
670
  - **Algorithm**: As detailed in the table below, the algorithm used by Pokémon Showdown in the
@@ -680,15 +677,15 @@ compatibility mode, the implications of these differences are outlined below:
680
677
  sampling to ensure uniformity as is done on the cartridge. This means that certain values are
681
678
  fractionally more likely to be chosen than others, though this bias is usually quite small (e.g.
682
679
  in the case of Metronome instead of selecting moves with an equal $1\over163$ chance, Pokémon
683
- Showdown will select some with a $1\over2^{32}$ greater chance than others).
680
+ Showdown selects some with a $1\over2^{32}$ greater chance than others).
684
681
  - **Order of operations**: RNG calls effectively introduce something similar to a ["memory
685
682
  barrier"](https://en.wikipedia.org/wiki/Memory_barrier) in that they must be sequenced correctly
686
683
  (though operations which occur between them may happen in any order). Pokémon Showdown violates
687
684
  this by introducing additional operations (see below) and changing up the order of existing
688
685
  operations (e.g. choosing to check for hit/miss, determine the number of hits for moves with
689
686
  multiple hits, determine if a move hit critically and then the damage instead of checking for
690
- hit/miss and determining number of hits *after* the other two). While it is often desirable to
691
- rearrange code for performance or to improve readability this can only be done if it does not
687
+ hit/miss and determining number of hits *after* the other two). While it's often desirable to
688
+ rearrange code for performance or to improve readability this can only be done if it doesn't
692
689
  affect accuracy.
693
690
  - **Speed-ties**: In addition to [breaking switch-in speed ties with an RNG
694
691
  call](https://www.smogon.com/forums/threads/adv-switch-priority.3622189/), speed ties in Pokémon
@@ -699,16 +696,16 @@ compatibility mode, the implications of these differences are outlined below:
699
696
  ties proves impossible, and thus the reference Pokémon Showdown implementation pkmn engine aims to
700
697
  match has been [patched](../../../docs/TESTING.md#patches) to change this behavior.
701
698
  - **Effects**: Pokémon Showdown occasionally incorrectly inserts RNG calls in move effect handlers
702
- when they are not relevant:
699
+ when they're not relevant:
703
700
  - Roar / Whirlwind roll to hit and can "miss" as opposed to simply failing
704
701
 
705
- Finally, the **initial 10-byte seed for link battles on Pokémon Red cannot include bytes larger than
702
+ Finally, the **initial 9-byte seed for link battles on Pokémon Red can't include bytes larger than
706
703
  the `SERIAL_PREAMBLE_BYTE`**, so must be in the range $\left[0, 252\right]$. This has implications
707
- on the first 10 random numbers generated during the battle and has [**non-trivial competitive
704
+ on the first 9 random numbers generated during the battle and has [**non-trivial competitive
708
705
  implications**](https://www.smogon.com/forums/posts/9068411/show) (at the start of the battle move
709
706
  effects become more likely, the ["1/256-miss" glitch](https://glitchcity.wiki/1/256_miss_glitch)
710
- cannot happen, Player 1 is more likely to win speed ties, etc) that Pokémon Showdown cannot
711
- replicate due to everything described above.
707
+ can't happen, Player 1 is more likely to win speed ties, etc) that Pokémon Showdown can't replicate
708
+ due to everything described earlier.
712
709
 
713
710
  All of places in the link battle code where randomness is required are outlined below:
714
711
 
@@ -728,19 +725,19 @@ All of places in the link battle code where randomness is required are outlined
728
725
  | **Paralysis** (full) | `beforeMove` | Trigger if $X < 63$ |
729
726
  | **Poison** (chance) | `Effects.poison` | Trigger if $X < 52$ ($103$ for Smog / Sludge) |
730
727
  | **Sleep** (duration) | `Effects.sleep` | <dl><dt>Pokémon Red</dt><dd>Continue generating until $X \land 7 \neq 0$</dd><dt>Pokémon Showdown</dt><dd>Generate $X \in \left[1, 8\right)$</dd></dl> |
731
- | **Bide** (duration) | `Effects.bide` | <dl><dt>Pokémon Red</dt><dd>Last for $\left(X \land 1\right) + 2$ turns</dd><dt>Pokémon Showdown</dt><dd>Last for $X \in \left[2, 4\right)$ turns</dd></dl> |
728
+ | **Bide** (duration) | `Effects.bide` | <dl><dt>Pokémon Red</dt><dd>Last for $\left(X \land 1\right) + 2$ turns</dd><dt>Pokémon Showdown</dt><dd>Last for $X \in \left[2, 4\right)$ turns</dd></dl> |
732
729
  | **Disable** (move) | `Effects.disable` | <dl><dt>Pokémon Red</dt><dd>Continue generating until $X \land 3$ is the index of a non-empty move slot</dd><dt>Pokémon Showdown</dt><dd>Generate $X \in \left[0, \|movesSlots\|\right)$</dd></dl> |
733
730
  | **Disable** (duration) | `Effects.disable` | <dl><dt>Pokémon Red</dt><dd>Last for $\left(X \land 7\right) + 1$ turns</dd><dt>Pokémon Showdown</dt><dd>Last for $X \in \left[1, 9\right)$ turns</dd></dl> |
734
- | **Metronome** (move) | `metronome` | <dl><dt>Pokémon Red</dt><dd>Continue generating until $X$ matches the index of a move which is not Struggle or Metronome</dd><dt>Pokémon Showdown</dt><dd>Generate $X \in \left[0, \|validMoves\|\right)$, where $validMoves$ is ordered set of moves with Struggle and Metronome removed <i>(indexes of moves > Metronome will be shifted down)</i></dd></dl> |
731
+ | **Metronome** (move) | `metronome` | <dl><dt>Pokémon Red</dt><dd>Continue generating until $X$ matches the index of a move which isn't Struggle or Metronome</dd><dt>Pokémon Showdown</dt><dd>Generate $X \in \left[0, \|validMoves\|\right)$, where $validMoves$ is ordered set of moves with Struggle and Metronome removed <i>(indexes of moves > Metronome are shifted down)</i></dd></dl> |
735
732
  | **Mimic** (move) | `Effects.mimic` | <dl><dt>Pokémon Red</dt><dd>Continue generating until $X \land 3$ is the index of a non-empty move slot</dd><dt>Pokémon Showdown</dt><dd>Generate $X \in \left[0, \|movesSlots\|\right)$</dd></dl> |
736
733
  | **Psywave** (power) | `specialDamage` | <dl><dt>Pokémon Red</dt><dd>Continue generating until $X < {3\over2} \cdot level$</dd><dt>Pokémon Showdown</dt><dd>Generate $X \in \left[0, {3\over2} \cdot level\right)$</dd></dl> |
737
734
  | **Thrash** (rampage) | `Effects.thrash` | <dl><dt>Pokémon Red</dt><dd>Last for $\left(X \land 1\right) + 2$ turns</dd><dt>Pokémon Showdown</dt><dd>Last for $X \in \left[2, 4\right)$ turns</dd></dl> |
738
735
  | **Thrash** (confusion) | `beforeMove` | <dl><dt>Pokémon Red</dt><dd>Last for $\left(X \land 3\right) + 2$ turns</dd><dt>Pokémon Showdown</dt><dd>Last for $X \in \left[2, 6\right)$ turns</dd></dl> |
739
- | **Binding** (duration) | `Effects.binding` | <dl><dt>Pokémon Red</dt><dd>Last for $\left(X \land 3\right) + 1$ further turns if $\left(X \land 3\right) < 2$<br /> otherwise last for $\left(Y \land 3\right) + 1$ further turns (reroll)</dd><dt>Pokémon Showdown</dt><dd>Last for $X \in \{2, 2, 3, 3, 4, 5\} - 1$ further turns</dd></dl> |
736
+ | **Binding** (duration) | `Effects.binding` | <dl><dt>Pokémon Red</dt><dd>Last for $\left(X \land 3\right) + 1$ further turns if $\left(X \land 3\right) < 2$<br /> otherwise last for $\left(Y \land 3\right) + 1$ further turns (reroll)</dd><dt>Pokémon Showdown</dt><dd>Last for $X \in \{2, 2, 2, 3, 3, 3, 4, 5\} - 1$ further turns</dd></dl> |
740
737
  | **Multi-Hit** (hits) | `Effects.multiHit` | *Ibid.* |
741
738
  | **Unboost** (chance) | `Effects.unboost` | Trigger if $X < 85$ |
742
739
 
743
- *In the table above,* $X$ *is always in the range* $\left[0, 256\right)$ *for Pokémon Red and for
740
+ *In the preceding table,* $X$ *is always in the range* $\left[0, 256\right)$ *for Pokémon Red and for
744
741
  Pokémon Showdown is always **scaled** from the 32-bit output range of the RNG to either be in that
745
742
  range or to whichever range is specified by the description.*
746
743
 
@@ -783,7 +780,8 @@ table provides a rough mapping between pkmn and Pokémon Red methods:
783
780
  | `handleResidual` | `HandlePoisonBurnLeechSeed` |
784
781
  | `endTurn` / `checkEBC` | - |
785
782
 
786
- Pokémon Red groups move effect handlers together into several groups, these have also been renamed for clarification in the pkmn engine:
783
+ Pokémon Red groups move effect handlers together into several groups, these have also been renamed
784
+ for clarification in the pkmn engine:
787
785
 
788
786
  | pkmn | Pokémon Red (pret) |
789
787
  | --------------- | ------------------------- |
@@ -799,7 +797,7 @@ The pkmn engine attempts to adhere to certain naming conventions:
799
797
  - **`p1`** & **`p2`** always correspond to the `Side` of `Player.P1` and `Player.P2` respectively
800
798
  - **`player`** is the executing turn `Player` (`hWhoseTurn`) and **`player.foe()`** is their
801
799
  opponent
802
- - if `player` (executing turn player) is present then **`side`** will always correspond to their
800
+ - if `player` (executing turn player) is present then **`side`** always corresponds to their
803
801
  `Side` and **`foe`** the opposing `Side`, however `side` can refer to an arbitrary `Side` object
804
802
  if there is no `player` in scope (e.g. in helper functions)
805
803
  - **`target_player`** is a target `Player` whose corresponding `Side` is **`target`**