@pkmn/engine 0.1.0-dev.f918c3bd → 0.1.0-dev.fb6653d6

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.
Files changed (83) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +51 -23
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +44 -0
  5. package/build/pkg/addon/browser.js.map +1 -0
  6. package/build/pkg/addon/node.d.ts +3 -0
  7. package/build/pkg/addon/node.js +97 -0
  8. package/build/pkg/addon/node.js.map +1 -0
  9. package/build/pkg/addon/wasm.d.ts +2 -0
  10. package/build/pkg/addon/wasm.js +53 -0
  11. package/build/pkg/addon/wasm.js.map +1 -0
  12. package/build/pkg/addon.d.ts +25 -3
  13. package/build/pkg/addon.js +39 -71
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/ids.json +12 -12
  16. package/build/pkg/data/layout.json +17 -4
  17. package/build/pkg/data/protocol.json +23 -9
  18. package/build/pkg/data.d.ts +27 -5
  19. package/build/pkg/data.js.map +1 -1
  20. package/build/pkg/gen1.d.ts +13 -17
  21. package/build/pkg/gen1.js +8 -12
  22. package/build/pkg/gen1.js.map +1 -1
  23. package/build/pkg/index.d.ts +40 -91
  24. package/build/pkg/index.js +6 -63
  25. package/build/pkg/index.js.map +1 -1
  26. package/build/pkg/protocol.d.ts +20 -1
  27. package/build/pkg/protocol.js +109 -107
  28. package/build/pkg/protocol.js.map +1 -1
  29. package/build/tools/debug.js +36 -69
  30. package/build/tools/debug.js.map +1 -1
  31. package/build/tools/display/debug.jsx +141 -0
  32. package/build/tools/display/debug.jsx.map +1 -0
  33. package/build/tools/display/index.js +142 -0
  34. package/build/tools/display/index.js.map +1 -0
  35. package/build/tools/display/ui.jsx +349 -0
  36. package/build/tools/display/ui.jsx.map +1 -0
  37. package/build/tools/display/util.js +18 -0
  38. package/build/tools/display/util.js.map +1 -0
  39. package/build.zig +303 -101
  40. package/package.json +61 -132
  41. package/src/bin/install-pkmn-engine +30 -20
  42. package/src/bin/pkmn-debug +1 -1
  43. package/src/lib/{binding → bindings}/node.zig +8 -21
  44. package/src/lib/bindings/wasm.zig +58 -0
  45. package/src/lib/common/array.zig +77 -0
  46. package/src/lib/common/data.zig +8 -8
  47. package/src/lib/common/debug.zig +39 -8
  48. package/src/lib/common/js.zig +4 -2
  49. package/src/lib/common/optional.zig +21 -10
  50. package/src/lib/common/options.zig +6 -0
  51. package/src/lib/common/protocol.zig +421 -393
  52. package/src/lib/common/rational.zig +131 -35
  53. package/src/lib/common/rng.zig +16 -9
  54. package/src/lib/common/util.zig +50 -1
  55. package/src/lib/gen1/calc.zig +687 -160
  56. package/src/lib/gen1/chance.zig +434 -307
  57. package/src/lib/gen1/data/moves.zig +26 -14
  58. package/src/lib/gen1/data/species.zig +4 -6
  59. package/src/lib/gen1/data/types.zig +7 -8
  60. package/src/lib/gen1/data.zig +44 -47
  61. package/src/lib/gen1/helpers.zig +91 -562
  62. package/src/lib/gen1/mechanics.zig +641 -557
  63. package/src/lib/gen2/calc.zig +153 -0
  64. package/src/lib/gen2/chance.zig +902 -0
  65. package/src/lib/gen2/data/items.zig +13 -21
  66. package/src/lib/gen2/data/moves.zig +67 -47
  67. package/src/lib/gen2/data/species.zig +2 -4
  68. package/src/lib/gen2/data/types.zig +134 -32
  69. package/src/lib/gen2/data.zig +56 -54
  70. package/src/lib/gen2/generated.zig +801 -0
  71. package/src/lib/gen2/helpers.zig +46 -25
  72. package/src/lib/gen2/mechanics.zig +2778 -362
  73. package/src/lib/node.zig +18 -0
  74. package/src/lib/pkmn.zig +37 -15
  75. package/src/lib/wasm.zig +17 -0
  76. package/src/tools/display/dom.ts +96 -0
  77. package/src/tools/display/ui.css +354 -0
  78. package/build/test/display.js +0 -400
  79. package/build/test/display.js.map +0 -1
  80. package/src/lib/binding/wasm.zig +0 -12
  81. package/src/lib/gen1/README.md +0 -894
  82. package/src/lib/gen2/README.md +0 -328
  83. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,328 +0,0 @@
1
- # Pokémon Generation II: GSC
2
-
3
- ## Data Structures
4
-
5
- The following information is required to simulate a Generation II Pokémon battle:
6
-
7
- ==**TODO**==
8
-
9
- | pkmn | Pokémon Crystal (pret) | Pokémon Showdown |
10
- | ------------------------------ | --------------------------------- | ------------------------------------- |
11
- | `battle.seed` | `Random{Add,Sub}` | `battle.seed` |
12
- | `battle.turn` | | `battle.turn` |
13
- | `field.weather.id` | `BattleWeather` | `field.weather` |
14
- | `field.weather.duration` | `WeatherCount` | `field.weatherState.duration` |
15
- | `side.{active,pokemon}` | `BattleMon` | `side.active` |
16
- | `side.team` | `PartyMons`/`PartySpecies` | `side.pokemon` |
17
- | `side.conditions` | `PlayerScreens` | `side.sideConditions` |
18
- | `conditions.data.safeguard` | `PlayerSafeguardCount` | `sideConditions.safeguard.duration` |
19
- | `conditions.data.light_screen` | `PlayerLightScreenCount` | `sideConditions.lightscreen.duration` |
20
- | `conditions.data.reflect` | `PlayerReflectCount` | `sideConditions.reflect.duration` |
21
- | `pokemon.stats` | `TODO unmodified` | `pokemon.baseStoredStats` |
22
- | `pokemon.position` | `TODO` | `pokemon.position` |
23
- | `pokemon.moves` | `party_struct.{Moves,PP}` | `pokemon.baseMoveSlots` |
24
- | `{pokemon,active}.hp` | `{party,battle}_struct.HP` | `pokemon.hp` |
25
- | `{pokemon,active}.status` | `{party,battle}_struct.Status` | `pokemon.status` |
26
- | `{pokemon,active}.level` | `TODO unmodified` | `pokemon.level` |
27
- | `{pokemon,active}.happiness` | `{box,battle}_struct.Happiness` | `pokemon.happiness` |
28
- | `{pokemon,active}.ivs.gender` | `{box,battle}_struct.DVs` | `pokemon.gender` |
29
- | `{pokemon,active}.ivs.type` | `{box,battle}_struct.DVs` | `pokemon.hpType` |
30
- | `{pokemon,active}.ivs.power` | `{box,battle}_struct.DVs` | `pokemon.hpPower` |
31
- | `{pokemon,active}.item` | `{box,battle}_struct.Item` | `pokemon.item` |
32
- | `pokemon.species` | `party_struct.Species` | `pokemon.baseSpecies` |
33
- | `active.species` | `battle_struct.Species` | `pokemon.species` |
34
- | `active.stats` | `TODO modified` | `pokemon.storedStats` |
35
- | `active.trapped FIXME` | `PlayerTrappingMove` | `pokemon.trapped` |
36
- | `active.switching` | `PlayerIsSwitching` | `pokemon.switchFlag` |
37
- | `active.boosts` | `PlayerStatLevels` | `pokemon.boosts` |
38
- | `active.volatiles` | `PlayerBattleStatus{1,2,3}` | `pokemon.volatiles` |
39
- | `volatiles.bide` | `PlayerDamageTaken` | `volatiles.bide.totalDamage` |
40
- | `volatiles.substitute` | `PlayerSubstituteHP` | `volatiles.substitute.hp` |
41
- | `volatiles.rollout` | `PlayerRolloutCount` | `volatiles.rollout.hitCount` |
42
- | `volatiles.confusion` | `PlayerConfuseCount` | `volatiles.confusion.duration` |
43
- | `volatiles.toxic` | `PlayerToxicCount` | `volatiles.residualdmg.counter` |
44
- | `volatiles.disabled` | `PlayerDisableCount` | `moveSlots.disabled` |
45
- | `volatiles.encore` | `PlayerEncoreCount` | `volatiles.encore.duration` |
46
- | `volatiles.perish_song` | `PlayerPerishCount` | `volatiles.perishsong.duration` |
47
- | `volatiles.fury_cutter` | `PlayerFuryCutterCount` | `volatiles.furycutter.multiplier` |
48
- | `volatiles.protect` | `PlayerProtectCount` | `volatiles.stall.counter` |
49
- | `volatiles.future_sight` | `PlayerFutureSight{Damage,Count}` | `slotConditions[i].futuremove` |
50
- | `volatiles.rage` | `PlayerRageCounter` | **BUG** |
51
- | `volatiles.bind` | `PlayerWrapCount` | `volatiles.partiallytrapped.duration` |
52
- | | `PlayerCharging` | |
53
- | `volatiles.frozen` | `PlayerJustGotFrozen` | `volatiles.frozen` |
54
- | | | |
55
- | `active.last_used_move` | `PlayerUsedMove` | `side.lastMove` |
56
-
57
- - Pokémon Showdown doesn't implement the correct Generation II RNG and as such its `seed` is
58
- different
59
- - `battle.turn` only needs to be tracked to be compatible with the Pokémon Showdown protocol
60
- - Battle results (win, lose, draw) or request states are communicated via the return code of
61
- `Battle.update`
62
- - Nicknames (`BattleMonNick`/`pokemon.name`) aren't handled by the pkmn engine as they're expected
63
- to be handled by driver code if required
64
-
65
- ==**TODO**==
66
-
67
- wPlayerMinimized
68
-
69
- ### `Battle` / `Side`
70
-
71
- `Battle` and `Side` are analogous to the classes of the
72
- [same](https://github.com/smogon/pokemon-showdown/blob/master/sim/battle.ts)
73
- [name](https://github.com/smogon/pokemon-showdown/blob/master/sim/side.ts) in Pokémon Showdown and
74
- store general information about the battle. Unlike in Pokémon Showdown there is a distinction
75
- between the data structure for the "active" Pokémon and its party members (see below).
76
-
77
- ### `Pokemon` / `ActivePokemon`
78
-
79
- Similar to the cartridge, to save space different information is stored depending on whether a
80
- [Pokémon](https://pkmn.cc/bulba/Pok%c3%a9mon_data_structure_%28Generation_II%29) is actively
81
- participating in battle vs. is switched out (pret's [`battle_struct` vs.
82
- `party_struct`](https://pkmn.cc/pokecrystal/macros/ram.asm)). In Pokémon Showdown, all the Pokemon
83
- are represented by the same
84
- [`Pokemon`](https://github.com/smogon/pokemon-showdown/blob/master/sim/pokemon.ts) class, and static
85
- party information is saved in fields beginning with "`stored`" or "`base`".
86
-
87
- ==**TODO**==
88
-
89
- #### `MoveSlot`
90
-
91
- A `MoveSlot` is a data-type for a `(move, current pp)` pair. A pared down version of Pokémon
92
- Showdown's `Pokemon#moveSlot`, it also stores data from the cartridge's `battle_struct::Move` macro
93
- and can be used to replace the `PlayerMove*` data. Move PP is stored as a full byte instead of how
94
- the cartridge (`battle_struct::PP`) stores it (6 bits for current PP and the remaining 2 bits used
95
- to store the number of applied PP Ups). PP Up bits don't actually need to be stored on move slot
96
- as max PP is never relevant in Generation II (the Mystery Berry always increases PP from 0 -> 5).
97
-
98
- #### `Status`
99
-
100
- Bitfield representation of a Pokémon's major [status
101
- condition](https://pkmn.cc/bulba/Status_condition), mirroring how it's stored on the cartridge. A
102
- value of `0x00` means that the Pokémon isn't affected by any major status, otherwise the lower 3
103
- bits represent the remaining duration for Sleep. Other status are denoted by the presence of
104
- individual bits - at most one status should be set at any given time.
105
-
106
- In Generation I & II, the "badly poisoned" status (Toxic) is instead treated as a volatile (see
107
- below).
108
-
109
- #### `Volatile` / `VolatileData`
110
-
111
- Active Pokémon can have ["volatile" status
112
- conditions](https://pkmn.cc/bulba/Status_condition#Volatile_status) (called ['sub
113
- status'](https://pkmn.cc/pokecrystal/constants/battle_constants.asm#L166-L212) bits in pret), all of
114
- which are boolean flags that are cleared when the Pokémon faints or switches out:
115
-
116
- | pkmn | Pokémon Crystal (pret) | Pokémon Showdown |
117
- | ------------- | ----------------------- | ---------------- |
118
- | `Bide` | `BIDE` | `bide` |
119
- | `Thrashing` | `RAMPAGE` | `lockedmove` |
120
- | `Flinch` | `FLINCHED` | `flinch` |
121
- | `Charging` | `CHARGED` | `twoturnmove` |
122
- | `Underground` | `UNDERGROUND` | `dig` |
123
- | `Flying` | `FLYING` | `fly` |
124
- | `Confusion` | `CONFUSED` | `confusion` |
125
- | `Mist` | `MIST` | `mist` |
126
- | `FocusEnergy` | `FOCUS_ENERGY` | `focusenergy` |
127
- | `Substitute` | `SUBSTITUTE` | `substitute` |
128
- | `Recharging` | `RECHARGE` | `mustrecharge` |
129
- | `Rage` | `RAGE` | `rage` |
130
- | `LeechSeed` | `LEECH_SEED` | `leechseed` |
131
- | `Toxic` | `TOXIC` | `toxic` |
132
- | `Transform` | `TRANSFORMED` | `transform` |
133
- | | | |
134
- | `Nightmare` | `NIGHTMARE` | `nightmare` |
135
- | `Cure` | `CURSE` | `curse` |
136
- | `Protect` | `PROTECT` | `protect` |
137
- | `Foresight` | `IDENTIFIED` | `foresight` |
138
- | `PerishSong` | `PERISH` | `perishsong` |
139
- | `Endure` | `ENDURE` | `endure` |
140
- | `Rollout` | `ROLLOUT` | `rollout` |
141
- | `Attract` | `IN_LOVE` | `attract` |
142
- | `DefenseCurl` | `CURLED` | `defensecurl` |
143
- | `Encore` | `ENCORED` | `encore` |
144
- | `LockOn` | `LOCK_ON` | `lockon` |
145
- | `DestinyBond` | `DESTINY_BOND` | `destinybond` | |
146
-
147
- ==**TODO**==
148
-
149
- - `IN_LOOP` (beatup)
150
-
151
- #### `Stats` / `Boosts`
152
-
153
- [Stats](https://pkmn.cc/bulba/Stat) and [boosts (stat
154
- modifiers)](https://pkmn.cc/bulba/Stat#Stat_modifiers) are stored logically, with the exception that
155
- boosts should always range from `-6`...`6` instead of `1`...`13` as on the cartridge.
156
-
157
- ==**TODO**==
158
-
159
- ### `Move` / `Moves`
160
-
161
- `Moves` serves as an identifier for a unique [Pokémon move](https://pkmn.cc/bulba/Move) that can be
162
- used to retrieve a `Move` with information regarding base power, accuracy and type. As covered
163
- earlier, PP information isn't strictly necessary in Generation I, but fits neatly into the 4 bits of
164
- padding after noticing that all PP values are multiples of 5. `Moves.None` exists as a special
165
- sentinel value to indicate `null`.
166
-
167
- ### `Species`
168
-
169
- `Species` just serves as an identifier for a unique [Pokémon
170
- species](https://pkmn.cc/bulba/Pokémon_species_data_structure_(Generation_II)) as the base
171
- stats of a species are already accounted for in the computed stats in the `Pokemon` structure and
172
- nothing in battle requires these to be recomputed. Similarly, Type is unnecessary to include as it
173
- is also already present in the `Pokemon` struct. `Species.None` exists as a special sentinel value
174
- to indicate `null`.
175
-
176
- ### `Type` / `Types` / `Effectiveness`
177
-
178
- The [Pokémon types](https://pkmn.cc/bulba/Type) are enumerated by `Type`. `Types` represents a tuple
179
- of 2 types, which takes the form of a packed struct instead of `[2]Type` for symmetry with
180
- Generation I. `Effectiveness` serves as an enum for tracking a moves effectiveness - like the
181
- cartridge, effectiveness is stored as `0`, `5`, `10`, and `20` (technically only a 4-bit value is
182
- required, but Zig only allows a minimum of a byte to be stored at each address of an array).
183
-
184
- Type effectiveness modifiers are applied based off of the ordering of the effectiveness table as
185
- opposed to first applying modifiers for a species's first type and then second type. The engine
186
- maintains a `Type.PRECEDENCE` table to allow for reordering type effectiveness modifier application
187
- where necessary.
188
-
189
- ## Information
190
-
191
- The information of each field (in terms of [bits of
192
- entropy](https://en.wikipedia.org/wiki/Entropy_(information_theory))) is as follows:
193
-
194
- ==**TODO**==
195
-
196
- | Data | Range | Bits | | Data | Range | Bits |
197
- | -------------- | ------- | ---- | --- | ----------------- | -------- | ---- |
198
- | **seed** | 0...255 | 8 | | **turn** | 1...1000 | 7 |
199
- | **team index** | 1...6 | 3 | | **move index** | 1...4 | 2 |
200
- | **species** | 1...251 | 8 | | **move** | 1...251 | 8 |
201
- | **stat** | 1...999 | 10 | | **boost** | 0...13 | 4 |
202
- | **level** | 1...100 | 7 | | **volatiles** | *27* | 27 |
203
- | **bide** | 0...703 | 11 | | **substitute** | 0...179 | 8 |
204
- | **multi hits** | 0...5 | 3 | | **base power** | 0...50 | 6 |
205
- | **base PP** | 1...8 | 3 | | **PP Ups** | 0...3 | 2 |
206
- | **PP** | 0...64 | 7 | | **HP / damage** | 0...704 | 10 |
207
- | **status** | 0...10 | 4 | | **effectiveness** | 0...3 | 2 |
208
- | **type** | 0...18 | 5 | | **accuracy** | 6...20 | 4 |
209
- | **disabled** | 0...7 | 3 | | **DVs** | 0...15 | 4 |
210
- | **rollout** | 0...5 | 3 | | **fury cutter** | 0..4 | 3 |
211
- | **confusion** | 0...5 | 3 | | **toxic** | 0...15 | 4 |
212
- | **encore** | 0...6 | 3 | | **future sight** | 0...2 | 2 |
213
- | **protect** | 0...9 | 4 | | **rage** | 0...255 | 8 |
214
- | **wrap** | 0...5 | 3 | | **perish song** | 0...4 | 3 |
215
- | **item** | TODO | 5? | | **gender** | 0..1 | 1 |
216
-
217
- From this one can determine the minimum bits required to store each data structure to determine how
218
- much overhead the preceding representations have after taking into consideration [alignment &
219
- padding](https://en.wikipedia.org/wiki/Data_structure_alignment) and
220
- [denormalization](https://en.wikipedia.org/wiki/Denormalization):
221
-
222
- ## Details
223
-
224
- | pkmn | Pokémon Crystal (pret) |
225
- | ------------------------- | ------------------------------------------------- |
226
- | `start` | `DoBattle` |
227
- | `update` | `BattleTurn` |
228
- | `selectMove` / `saveMove` | `CheckPlayerLockedIn` / `ParsePlayerAction` |
229
- | `switchIn` | `SwitchPlayerMon` / `SendOutPlayerMon` |
230
- | `turnOrder` | `DetermineMoveOrder` |
231
- | `doTurn` | `DoTurn` |
232
- | `executeMove` | `DoMove` |
233
- | `beforeMove` | `CheckTurn` |
234
- | `canMove` | |
235
- | `decrementPP` | |
236
- | `doMove` | |
237
- | `checkCriticalHit` | `BattleCommand_Critical` |
238
- | `calcDamage` | `BattleCommand_DamageCalc` / `PlayerAttackDamage` |
239
- | `adjustDamage` | `BattleCommand_Stab` |
240
- | `randomizeDamage` | `BattleCommand_DamageVariation` |
241
- | `specialDamage` | `BattleCommand_ConstantDamage` |
242
- | `applyDamage` | `BattleCommand_ApplyDamage` |
243
- | `checkHit` | `BattleCommand_CheckHit` |
244
- | `checkFaint` | `CheckFaint` |
245
- | `handleResidual` | `ResidualDamage` |
246
- | `endTurn` | `EndTurn` |
247
-
248
- DoBattle
249
- BattleTurn
250
- - HandleBerserkGene
251
- - CheckPlayerLockedIn
252
- - BattleMenu
253
- - ParsePlayerAction
254
- - DetermineMoveOrder
255
- - CompareMovePriority
256
- - GetMovePriority
257
- - Battle_*
258
- - Handle*Switch
259
- - SwitchPlayerMon
260
- - BreakAttraction
261
- - SendOutPlayerMon
262
- - SpikesDamage
263
- - *Turn_EndOpponentProtectEndureDestinyBond
264
- - EndUserDestinyBond
265
- - Do*Turn
266
- - EndOpponentProtectEndureDestinyBond
267
- - ResidualDamage
268
- - CheckFaint_*
269
- - HandleBetweenTurnEffects
270
- - HandleFutureSight
271
- - HandleWeather
272
- - HandleWrap
273
- - HandlePerishSong
274
- - HandleLeftovers
275
- - HandleMysteryBerry
276
- - HandleDefrost
277
- - HandleSafeguard
278
- - HandleScreens
279
- - HandleStatBoostingHeldItems
280
- - HandleHealingItems
281
- - HandleEncore
282
-
283
- DoTurn
284
- DoMove = executeMove
285
- CheckTurn = beforeMove
286
- BattleCommand_Critical = checkCriticalHit
287
- BattleCommand_Stab = adjustDamage
288
- BattleCommand_DamageVariation = randomizeDamage
289
- BattleCommand_CheckHit = checkHit
290
- BattleCommand_ApplyDamage = applyDamage
291
- BattleCommand_CheckFaint
292
- BattleCommand_BuildOpponentRage = buildRage
293
- BattleCommand_DamageCalc (PlayerAttackDamage / EnemyAttackDamage) = calcDamage
294
- BattleCommand_ConstantDamage = specialDamage
295
- DoEnemyDamage / DoPlayerDamage / DoSubstituteDamage
296
-
297
- ==**TODO**==
298
-
299
- ## Protocol
300
-
301
- TODO
302
-
303
- ```txt
304
- -activate: _, move, name, number
305
- ```
306
-
307
- ## Bugs
308
-
309
- - TODO: randomChance rate different than gen 1?
310
- - Twineedle shouldn't be able to inflict poison if it breaks a substitute
311
- - Mail should not be stolen by Thief
312
- - RNG for crit is 1/16 and not 17/256?
313
- - Struggle recoil into Substitute only 1 HP
314
- - Substitute "activates" even though doesnt take damage for jump crash damage
315
- - Pokémon specific items after Transform
316
- - OHKO moves that miss should be Counterable
317
- - Defense lowering after breaking Substitute glitch
318
- - Beserk Gene copies previous mons confusion counter
319
- - Type boosting items w/ Confusion self-hit
320
- - Spikes 0 HP glitch
321
- - PP Up + Disable freeze
322
- - Beat Up partyless should fail but should still be able to trigger Kings Rock
323
- - Beat Up desync
324
- - Lock-on accuracy should be 100 not true, should be passed
325
- - Pain Split 100 accuracy not true
326
- - Foresight ignoring accuracy/evasiveness stages
327
- - Disable duration?
328
- - type effectiveness precedence
@@ -1,368 +0,0 @@
1
- <!doctype html>
2
- <html lang=en>
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <link rel="icon" href="https://pkmn.cc/favicon.ico">
7
- <title>@pkmn/engine</title>
8
- <style>
9
- #content {
10
- font-family: "Roboto", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
11
- margin: 4em auto;
12
- max-width: 1300px;
13
- line-height: 1.4em;
14
- --hp-bar: 151px;
15
- --hp-text: 32px;
16
- }
17
- details > summary {
18
- list-style: none;
19
- }
20
- details > summary::-webkit-details-marker {
21
- display: none;
22
- }
23
- .battle > .details {
24
- background: #eee;
25
- border-bottom: 3px solid black;
26
- padding: 0 0.5em;
27
- display: flex;
28
- justify-content: space-between;
29
- }
30
- .inner {
31
- display: flex;
32
- justify-content: center;
33
- flex-direction: column;
34
- }
35
- .side > .details {
36
- padding: 0.5em;
37
- display: flex;
38
- justify-content: space-between;
39
- text-align: center;
40
- flex: 0 1 auto;
41
- }
42
- .active {
43
- flex: 1 1 auto;
44
- }
45
- details {
46
- flex: 0 1 auto;
47
- }
48
- .sides {
49
- display: flex;
50
- }
51
- .side {
52
- flex: 1;
53
- display: flex;
54
- flex-flow: column;
55
- }
56
- .side.p1 {
57
- border-right: 1px solid black;
58
- }
59
- .battle {
60
- border: 3px solid black;
61
- }
62
- summary {
63
- border-top: 1px solid black;
64
- text-align: center;
65
- padding: 0.25em;
66
- }
67
- .good {
68
- color: green;
69
- }
70
- .bad {
71
- color: red;
72
- }
73
- .pokemon {
74
- position: relative;
75
- padding: 0.5em;
76
- border-top: 1px solid black;
77
- display: flex;
78
- }
79
- table {
80
- border-collapse: collapse;
81
- border-style: hidden;
82
- border-spacing: 0px;
83
- line-height: 1.5em;
84
- }
85
- th, td {
86
- border: 1px solid black;
87
- padding: 0 0.5em;
88
- }
89
- .statbar {
90
- display: none;
91
- width: calc(var(--hp-bar) + var(--hp-text));
92
- padding: 2px 0;
93
- line-height: normal;
94
- }
95
- .statbar .name {
96
- display: block;
97
- text-align: center;
98
- line-height: 1.25em;
99
- }
100
- .statbar strong {
101
- color: #222222;
102
- text-shadow:
103
- #FFFFFF 1px 1px 0, #FFFFFF 1px -1px 0,
104
- #FFFFFF -1px 1px 0, #FFFFFF -1px -1px 0;
105
- }
106
- .statbar strong small {
107
- font-weight: normal;
108
- }
109
- .statbar .hpbar {
110
- position: relative;
111
- border: 1px solid #777777;
112
- background: #FCFEFF;
113
- padding: 1px;
114
- height: 8px;
115
- margin: 0 0 0 0;
116
- width: calc(var(--hp-bar) + var(--hp-text) + 1px);
117
- border-radius: 4px;
118
- }
119
- .statbar .hpbar .hp {
120
- height: 4px;
121
- border-top: 2px solid #00dd60;
122
- background: #00bb51;
123
- border-bottom: 2px solid #007734;
124
- border-right: 1px solid #007734;
125
- border-radius: 3px;
126
- }
127
- .statbar .hpbar .hp-yellow {
128
- border-top-color: #f8e379;
129
- background-color: #f5d538;
130
- border-bottom-color: #be9f0a;
131
- border-right-color: #be9f0a;
132
- }
133
- .statbar .hpbar .hp-red {
134
- border-top-color: #f37f67;
135
- background-color: #ee4928;
136
- border-bottom-color: #a3260d;
137
- border-right-color: #a3260d;
138
- }
139
- .statbar .hpbar .prevhp {
140
- background: #BBEECC;
141
- height: 8px;
142
- border-radius: 3px;
143
- }
144
- .statbar .hpbar .prevhp-yellow {
145
- background-color: #fcf4ca;
146
- }
147
- .statbar .hpbar .prevhp-red {
148
- background-color: #facec5;
149
- }
150
- .statbar .hpbar .hptext {
151
- position: absolute;
152
- background: #777777;
153
- color: #EEEEEE;
154
- text-shadow: #000000 0 1px 0;
155
- font-size: 10px;
156
- width: 32px;
157
- height: 12px;
158
- top: -1px;
159
- text-align: center;
160
- }
161
- .status, .volatile {
162
- padding: 0px 1px;
163
- border: 1px solid #FF4400;
164
- border-radius: 3px;
165
- }
166
- .status {
167
- min-height: 10px;
168
- font-size: 7pt;
169
- vertical-align: middle;
170
- padding: 1px 2px;
171
- border: 0;
172
- border-radius: 3px;
173
- text-transform: uppercase;
174
- margin: 0 2px;
175
- }
176
- .status.brn {
177
- background: #EE5533;
178
- color: #FFFFFF;
179
- }
180
- .status.psn {
181
- background: #A4009A;
182
- color: #FFFFFF;
183
- }
184
- .status.par {
185
- background: #9AA400;
186
- color: #FFFFFF;
187
- }
188
- .status.slp {
189
- background: #AA77AA;
190
- color: #FFFFFF;
191
- }
192
- .status.frz {
193
- background: #009AA4;
194
- color: #FFFFFF;
195
- }
196
- .volatile {
197
- display: inline-block;
198
- padding: 0 5px;
199
- margin: 2px
200
- }
201
- .volatile.bad {
202
- background: #FFE5E0;
203
- color: #FF4400;
204
- border-color: #FF4400;
205
- }
206
- .volatile.good {
207
- background: #E5FFE0;
208
- color: #33AA00;
209
- border-color: #33AA00;
210
- }
211
- .volatile.neutral {
212
- background: #F0F0F0;
213
- color: #555555;
214
- border-color: #555555;
215
- }
216
- .rstatbar .hpbar .hptext {
217
- right: 0px;
218
- border-radius: 0 4px 4px 0;
219
- }
220
- .moves ul {
221
- column-count: 2;
222
- column-gap: 2em;
223
- }
224
- .left {
225
- padding-right: 32px;
226
- display: flex;
227
- flex-direction: column;
228
- align-items: center;
229
- }
230
- .stats {
231
- display: flex;
232
- padding: 0 1em;
233
- justify-content: space-between;
234
- text-align: center;
235
- width: 100%;
236
- }
237
- .types {
238
- display: inherit;
239
- }
240
- .disabled {
241
- color: #AAAAAA;
242
- }
243
- .log {
244
- display: flex;
245
- justify-content: center;
246
- padding-bottom: 2em;
247
- }
248
- .position {
249
- position: absolute;
250
- right: 10px;
251
- color: #AAAAAA;
252
- }
253
- .left .position {
254
- display: none;
255
- }
256
- .right .position {
257
- display: block;
258
- }
259
- .teamicons {
260
- display: inline-block;
261
- }
262
- @media(max-width: 1300px) {
263
- #content {
264
- font-size: 0.85em;
265
- max-width: 95%;
266
- margin: 2em auto;
267
- }
268
- }
269
- @media(max-width: 1200px) {
270
- .moves ul {
271
- column-count: 1;
272
- }
273
- }
274
- @media(max-width: 1100px) {
275
- .pokemon {
276
- flex-direction: column;
277
- }
278
- .stats {
279
- justify-content: center;
280
- padding: 0;
281
- }
282
- .boosts {
283
- margin-left: 5px;
284
- }
285
- .moves ul {
286
- column-count: 2;
287
- }
288
- .left {
289
- padding-right: 0;
290
- }
291
- .right {
292
- padding-top: 1em;
293
- }
294
- .volatiles {
295
- display: flex;
296
- justify-content: center;
297
- flex-wrap: wrap;
298
- }
299
- .left .position {
300
- display: block;
301
- }
302
- .right .position {
303
- display: none;
304
- }
305
- }
306
- @media(max-width: 800px) {
307
- .moves {
308
- display: flex;
309
- justify-content: center;
310
- }
311
- .moves ul {
312
- column-count: 1;
313
- display: inline-block;
314
- padding: 0;
315
- }
316
- }
317
- @media(max-width: 680px) {
318
- .stats {
319
- flex-direction: column;
320
- padding: 0;
321
- }
322
- .boosts {
323
- display: flex;
324
- justify-content: space-between;
325
- margin-top: 0.5em;
326
- }
327
- }
328
- @media(max-width: 550px) {
329
- #content {
330
- font-size: 0.65em;
331
- max-width: 95%;
332
- margin: 1em auto;
333
- --hp-bar: 101px;
334
- }
335
- }
336
- @media(max-width: 425px) {
337
- .stats {
338
- font-size: 0.9em;
339
- }
340
- }
341
- h1 {
342
- text-align: center;
343
- }
344
- .error {
345
- overflow: auto;
346
- scrollbar-width: none;
347
- padding: 10px 20px;
348
- border: 3px solid #DD4422;
349
- background: #FFF8F2;
350
- }
351
- .error::-webkit-scrollbar {
352
- display: none;
353
- }
354
- </style>
355
- </head>
356
- <body>
357
- <div id="content">{{{ content }}}</div>
358
- <script>
359
- for (const details of document.getElementsByTagName('details')) {
360
- details.addEventListener('toggle', e => {
361
- for (const d of details.parentElement.parentElement.getElementsByTagName('details')) {
362
- if (d.open !== details.open) d.open = details.open;
363
- }
364
- });
365
- }
366
- </script>
367
- </body>
368
- </html>