@pkmn/engine 0.1.0-dev.f3aaee39 → 0.1.0-dev.f3b63b86

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 (85) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +77 -23
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +47 -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 +110 -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 +26 -4
  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 +84 -13
  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 +15 -18
  21. package/build/pkg/gen1.js +30 -21
  22. package/build/pkg/gen1.js.map +1 -1
  23. package/build/pkg/index.d.ts +42 -91
  24. package/build/pkg/index.js +23 -70
  25. package/build/pkg/index.js.map +1 -1
  26. package/build/pkg/protocol.d.ts +20 -1
  27. package/build/pkg/protocol.js +123 -102
  28. package/build/pkg/protocol.js.map +1 -1
  29. package/build/tools/debug.js +69 -74
  30. package/build/tools/debug.js.map +1 -1
  31. package/build/tools/display/debug.jsx +152 -0
  32. package/build/tools/display/debug.jsx.map +1 -0
  33. package/build/tools/display/index.js +152 -0
  34. package/build/tools/display/index.js.map +1 -0
  35. package/build/tools/display/ui.jsx +359 -0
  36. package/build/tools/display/ui.jsx.map +1 -0
  37. package/build/tools/display/util.js +33 -0
  38. package/build/tools/display/util.js.map +1 -0
  39. package/build.zig +273 -120
  40. package/package.json +64 -123
  41. package/src/bin/install-pkmn-engine +47 -21
  42. package/src/bin/pkmn-debug +1 -1
  43. package/src/lib/bindings/c.zig +200 -0
  44. package/src/lib/{binding → bindings}/node.zig +15 -32
  45. package/src/lib/bindings/wasm.zig +50 -0
  46. package/src/lib/common/array.zig +70 -0
  47. package/src/lib/common/data.zig +12 -24
  48. package/src/lib/common/debug.zig +32 -11
  49. package/src/lib/common/js.zig +3 -7
  50. package/src/lib/common/optional.zig +19 -18
  51. package/src/lib/common/options.zig +6 -0
  52. package/src/lib/common/protocol.zig +919 -430
  53. package/src/lib/common/rational.zig +341 -254
  54. package/src/lib/common/rng.zig +22 -15
  55. package/src/lib/common/util.zig +33 -1
  56. package/src/lib/gen1/calc.zig +706 -177
  57. package/src/lib/gen1/chance.zig +428 -302
  58. package/src/lib/gen1/data/moves.zig +193 -183
  59. package/src/lib/gen1/data/species.zig +4 -6
  60. package/src/lib/gen1/data/types.zig +9 -10
  61. package/src/lib/gen1/data.zig +60 -75
  62. package/src/lib/gen1/helpers.zig +90 -563
  63. package/src/lib/gen1/mechanics.zig +682 -600
  64. package/src/lib/gen2/calc.zig +150 -0
  65. package/src/lib/gen2/chance.zig +896 -0
  66. package/src/lib/gen2/data/items.zig +13 -21
  67. package/src/lib/gen2/data/moves.zig +664 -572
  68. package/src/lib/gen2/data/species.zig +2 -4
  69. package/src/lib/gen2/data/types.zig +139 -34
  70. package/src/lib/gen2/data.zig +121 -96
  71. package/src/lib/gen2/generated.zig +801 -0
  72. package/src/lib/gen2/helpers.zig +53 -38
  73. package/src/lib/gen2/mechanics.zig +3580 -29
  74. package/src/lib/napi.h +2 -0
  75. package/src/lib/node.zig +14 -0
  76. package/src/lib/pkmn.zig +125 -29
  77. package/src/lib/wasm.zig +13 -0
  78. package/src/tools/display/dom.ts +93 -0
  79. package/src/tools/display/ui.css +354 -0
  80. package/build/test/display.js +0 -400
  81. package/build/test/display.js.map +0 -1
  82. package/src/lib/binding/wasm.zig +0 -12
  83. package/src/lib/gen1/README.md +0 -892
  84. package/src/lib/gen2/README.md +0 -308
  85. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,308 +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.data.bide` | `PlayerDamageTaken` | `volatiles.bide.totalDamage` |
40
- | `volatiles.data.substitute` | `PlayerSubstituteHP` | `volatiles.substitute.hp` |
41
- | `volatiles.data.rollout` | `PlayerRolloutCount` | `volatiles.rollout.hitCount` |
42
- | `volatiles.data.confusion` | `PlayerConfuseCount` | `volatiles.confusion.duration` |
43
- | `volatiles.data.toxic` | `PlayerToxicCount` | `volatiles.residualdmg.counter` |
44
- | `volatiles.data.disabled` | `PlayerDisableCount` | `moveSlots.disabled` |
45
- | `volatiles.data.encore` | `PlayerEncoreCount` | `volatiles.encore.duration` |
46
- | `volatiles.data.perish_song` | `PlayerPerishCount` | `volatiles.perishsong.duration` |
47
- | `volatiles.data.fury_cutter` | `PlayerFuryCutterCount` | `volatiles.furycutter.multiplier` |
48
- | `volatiles.data.protect` | `PlayerProtectCount` | `volatiles.stall.counter` |
49
- | `volatiles.data.future_sight` | `PlayerFutureSight{Damage,Count}` | `slotConditions[i].futuremove` |
50
- | `volatiles.data.rage` | `PlayerRageCounter` | **BUG** |
51
- | `volatiles.data.bind` | `PlayerWrapCount` | `volatiles.partiallytrapped.duration` |
52
- | | `PlayerCharging` | |
53
- | | `PlayerJustGotFrozen` | |
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
- ==**TODO**==
223
-
224
- ## Protocol
225
-
226
- TODO
227
-
228
- ```txt
229
- -activate: _, damage, move, name, number, of
230
- -anim: _
231
- -block: _
232
- -boost: _, from, silent
233
- -clearallboost: _
234
- -copyboost: from
235
- -crit: _
236
- -curestatus: msg
237
- -cureteam: from
238
- -damage: _, from, of, partiallytrapped
239
- -end: _, from, of, partiallytrapped, silent
240
- -enditem: _, eat
241
- -fail: _, block, weak
242
- -fieldactivate: _
243
- -heal: _, from, of, silent
244
- -hint: _
245
- -hitcount: _
246
- -immune: _, ohko
247
- -item: from, of
248
- -miss: _
249
- -mustrecharge: _
250
- -ohko: _
251
- -prepare: _
252
- -resisted: _
253
- -setboost: from
254
- -sethp: from, silent
255
- -sideend: _, from, of
256
- -sidestart: _
257
- -singlemove: _
258
- -singleturn: _
259
- -start: _, of, silent
260
- -status: _, from, silent
261
- -supereffective: _
262
- -transform: _
263
- -unboost: _
264
- -weather: _, upkeep
265
- cant: _
266
- debug: _
267
- done: _
268
- drag: _
269
- faint: _
270
- gametype: _
271
- gen: _
272
- move: _, from, miss, still
273
- player: _
274
- request: _
275
- rule: _
276
- start: _
277
- switch: _, from
278
- t:: _
279
- teamsize: _
280
- tie: _
281
- tier: _
282
- turn: _
283
- upkeep: _
284
- win: _
285
- ```
286
-
287
- ## Bugs
288
-
289
- - TODO: randomChance rate different than gen 1?
290
- - Twineedle shouldn't be able to inflict poison if it breaks a substitute
291
- - Mail should not be stolen by Thief
292
- - RNG for crit is 1/16 and not 17/256?
293
- - Struggle recoil into Substitute only 1 HP
294
- - Substitute "activates" even though doesnt take damage for jump crash damage
295
- - Pokémon specific items after Transform
296
- - OHKO moves that miss should be Counterable
297
- - Defense lowering after breaking Substitute glitch
298
- - Beserk Gene copies previous mons confusion counter
299
- - Type boosting items w/ Confusion self-hit
300
- - Spikes 0 HP glitch
301
- - PP Up + Disable freeze
302
- - Beat Up partyless should fail but should still be able to trigger Kings Rock
303
- - Beat Up desync
304
- - Lock-on accuracy should be 100 not true, should be passed
305
- - Pain Split 100 accuracy not true
306
- - Foresight ignoring accuracy/evasiveness stages
307
- - Disable duration?
308
- - 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>