69 Commits

Author SHA1 Message Date
Christopher Monsanto
8233dbfb89 Publish the rest of the bag for the forum
:rare candy: and 281 other items have been dead tokens on the forum since
a55f31b3 (Dec 2021) moved the bag items the smogdex has no use for out of
src/minisprites/items and into src/_uncategorized/items, where their names were
replaced by a fresh numbering and nothing has built them since. The forum
resolves a token against forumsprites' manifest, so an item that isn't in the
manifest is left as literal text.

The names are recoverable exactly: every one of the 285 files matches, byte for
byte, a file in newsrc/minisprites/items at 741c73f2^, which data/items.json
named at that same commit. That reading agrees with the tree the 2020 import
built them from, src/canonical/minisprites/items, on all 285.

They go in src/minisprites/otheritems rather than back into items, because
items is what the smogdex draws on -- the sheet bakes a css class per name --
and the dex has no use for a Bicycle. forumsprites globs both, since a forum
token is a name and nothing else.

Three of the 285 don't come: Unknown, the empty-slot placeholder, would claim
the name the pokemon has (:unknown:, exactly the collision the type labels held
back last commit), and two files are byte-identical second copies of Growth
Mulch and Item Urge, which the 2021 renumber left behind in place of Item Drop
and Oak's Parcel. Those two pictures are in git and nothing here restores them;
the three files stay in _uncategorized.

284 published names, since one envelope answers to Gram 1, 2 and 3. Nothing
else the deploy ships changes: the sheet, minisprites, and the other manifests
are byte for byte what they were.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 20:26:13 -04:00
Christopher Monsanto
79f0ef6497 Lend the borrowed icons to the sheet and forumsprites too
The alias table sat in smogon.build.ts, so only xyicons/ got it. Two other sets
publish the same directory and had the same holes: the smogdex sheet, where the
dex asks for a sprite- class per species it renders, and forumsprites. Neither
had a class or a file for a totem, a Gourgeist size or Mimikyu-Busted.

So the table belongs beside the names, not beside one set that uses them. It
moves to data/lib as ICON_ALIASES with an iconNames() to apply it, which the
sheet calls in place of smogonNames() and the two deploys reach through a
NameOpts on publishedNames(). Keyed by the name holding the icon now, since
that is the direction all three consumers read it in. It stays out of
smogonNames(): src/models has real art for every one of these, and in xy/ the
lending name would be claimed by the base sprite and shadow the forme's own.

Greninja-Bond goes the other way, into SPECIES_ALIASES, because it is not an
icon shortage. Battle Bond's form looks like any other Greninja, and the tree
agrees: all seven -obond files under src/, in gen5, pmd and previews/gen9, are
byte for byte their base, and no model was ever drawn. xy/ was serving the gen 5
rendition of a Greninja; it now serves the animation, and the seven duplicates
go.

The sheet gains 22 classes, forumsprites 22 files. xy/ changes one file,
greninja-bond.gif, which is now greninja.gif.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 02:08:40 -04:00
Christopher Monsanto
7493d948e6 Name the icons that share one, instead of deriving them
The last commit answered "these 22 formes have no icon" with a generated
418-line table of every forme's parent and a loop that walked it, which is a lot
of apparatus for a list that fits on a screen and changes when a generation
does. Write the list.

Same 1556 files out of xyicons/, byte for byte. The two throws are the part the
derivation gave for free: an alias whose source icon has gone, and an alias for
a name that has since been drawn, are both mistakes worth stopping the build
for rather than quietly serving the wrong picture.

data/lib/formes.ts and tools/spritedata/formes.ts go; nothing else read either.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 01:45:36 -04:00
Christopher Monsanto
593f1c5c2d Drop the Alcremie sweets again
Serving alcremie-caramel-swirl-berry is not the same as anything asking for it,
and nothing does. PS's pokedex.js gives Alcremie 8 cosmetic formes, cream only,
and the dex reads no cosmetic forme at all: dex.pokemon_cosmetic_formes is
filled on import and then read by nothing under dex/, so the site never composes
one of these names. The only list of the 54 is chatot's, hardcoded in
chatot/src/helpers/constants.ts under "COSMETIC FORMES", and chatot asks
play.pokemonshowdown.com first and falls back to smogon.com only on a 404, which
for these never comes, because PS serves all 54 itself.

So the 62 files on the server are read by nothing, and pulling them in was the
sync-from-the-server-for-its-own-sake this was meant to avoid. They join the
backlog the deploy clears. The -k axis goes with them: nothing else needed a
cosmetic to publish, and the grammar should not carry an axis on the strength of
one set of files nobody reads.

xy/ is 1651 names, and the backlog coverage.ts accounts for grows from 97 to 151.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 01:38:26 -04:00
Christopher Monsanto
f92f04716a Fall back to the nearest forme with an icon
xyicons/ is built from src/minisprites/pokemon/gen6 alone, which holds no
totem, no Mimikyu-Busted and no Gourgeist or Pumpkaboo size forme. Nor does
anywhere else in the tree: home/ has the size formes as 70x112 HOME renders
against gen6's 20x26 XY icons, and no directory anywhere has a totem icon at
all. There is nothing upstream to take either, since PS ships icons as one
dexnum-indexed sheet rather than as files per name.

That is because the games drew those formes no icon of their own. PS's client
sends each to the nearest forme that has art, and ps-pokemon.sheet.mjs already
carries the list, commented out, under "alt forms with duplicate icons". Walk
the same chain rather than leave 22 names 404ing.

The chain cannot be read off a published name, since a base name carries dashes
too (kommo-o, mr-mime, porygon-z), and dropping one word blindly strands
Toxtricity-Low-Key on a Toxtricity-Low that does not exist. So
tools/spritedata/formes.ts writes data/lib/formes.ts, pointing each forme at the
longest run of its leading words that names a forme of its own, and at the base
species otherwise.

xyicons/ gains 22: the 12 totems, Mimikyu-Busted, the six Gourgeist and
Pumpkaboo sizes, Greninja-Bond, Rockruff-Dusk and Pichu-Spiky-Eared. Each is
byte for byte the sprite it fell back to. Togedemaru-Totem is among them and the
server has never had it, so that one is a gain rather than a restoration. Only
this set walks the chain; xy/ has real art for all 22. The species PS keeps but
nobody ever drew, missingno and the 15 pokestar entries, have no ancestor with
an icon and so still get nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 01:33:32 -04:00
Christopher Monsanto
35102330aa Alias Toxtricity's Low-Key Gigantamax to the Amped one
PS carries the species and the dex asks for toxtricity-low-key-gmax, so the
build owes a picture for it, but the games drew one Gigantamax Toxtricity and
not two. PS's own icon sheet says as much: ps-pokemon.sheet.mjs records
`toxtricitylowkeygmax: 1320 + 69` among the "alt forms with duplicate icons",
the slot toxtricitygmax already sits in, and play.pokemonshowdown.com serves no
low-key gmax animation under any spelling. Nothing under src/ has a
-olow_key-g gif either, so there is nothing to import and nothing worth
drawing.

Publish the Amped sprite under both names. SPECIES_ALIASES exists for exactly
this shape and nothing else claims the name, so it costs one entry, and xy/,
xyicons/, the forumsprites manifest and the smogdex sheet pick it up together
through smogonNames(): 2118 css classes become 2119, and no existing name
moves.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 01:33:16 -04:00
Christopher Monsanto
3a2ecf9e12 Give the grammar a cosmetic axis, and import Alcremie's sweets
The smogon side serves 62 Alcremie animations the build has never made,
alcremie-caramel-swirl-berry and its kin, one per cream and sweet. PS models
the sweet nowhere in pokedex.js, so spriteFiles() will never name one, and
nothing under src/ has ever held one: they live on that server and nowhere
else, which is what --delete-after would have taken.

The sweet cannot ride inside -o. The two readings of a name disagree about
where the cream's words divide, `caramel-swirl` against `caramelswirl`, but
agree about the boundary in front of the sweet, `-berry` for both. Fold the
sweet into the forme and whichever reading you spell it for, the other one
comes out wrong. So -k carries it, published after the forme and before the
variant flags, and formatFilename now leads with every part publishedName
spells rather than with -o alone, for the reason it always led with -o: a
forme's sprites should sort together.

The art comes from play.pokemonshowdown.com/sprites/ani, which serves all 54
combinations the games draw, at the 54x73 the creams here already use. Of the
62 on the smogon server, 8 are <cream>-strawberry: strawberry is the default
sweet, spelled as the bare cream both upstream and in the list chatot keeps, so
nothing asks for those and they go with the other leftovers.

Vanilla cream ships as an explicit -ovanilla_cream, because PS's base Alcremie
publishes as `alcremie` while the sweets are named off the cream.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 01:32:25 -04:00
Christopher Monsanto
bcabe6d37e Publish Meowstic under the name the smogdex asks for
PS calls the male Meowstic just "Meowstic" -- baseForme M, with Meowstic-F
as the alt forme -- and every published name here falls out of the PS data,
so the tree ships meowstic and meowstic-f. The smogdex splits the pair
evenly and calls that entry Meowstic-M: dex-sync's getName renames it on
import, and toAlias turns that into meowstic-m, which is what the page
background, the sprite- sheet class, and the (minisprite:) embeds all ask
for. Nothing produced that name, so the dex has been living off hand-placed
leftovers under xy/ and xyicons/ that no build has touched in years and that
rsync has no reason to delete.

Give the smogon side an alias table, as the items already have, and publish
the sprite under both names. Only that side gets it: PS asks for meowstic
and the filename already says meowstic. This is the whole of the
disagreement -- the other four renames in getName are a move, an accent, and
two spaces that slug back to what we emit -- so one entry covers it.

The sheet had its own copy of publishedName inline; it wants the aliases
too, so it now calls the shared one. No name changes: the two agreed on
every file in the tree, since none carries both -g and -f.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016TEPwEpwMrUFN8Paa9Tb8r
2026-08-23 00:30:28 -04:00
Christopher Monsanto
0bbbc36053 Name sprites by name, and delete the id table
src/ named 48442 sprites by a packed number, s<num*32 + formeNum> for
species and i<num> for items, so s193-b-s.gif is Shiny Charizard-Mega-X's
back sprite and there was no way to know that without looking it up in
data/species.json. The table was the only thing making the tree
navigable, and it existed only because the filenames were opaque.

Put the name in the filename and the table has no job left, so this does
both. A name is encoded rather than spelled: a run of non-alphanumerics
becomes _ when it separates words and vanishes otherwise, decomposing
first so accents are dropped on purpose rather than by accident of how
the source spelled them. Recording where the words divide is what lets
smogon read a name as ho-oh and PS read it as hooh off the same file,
with nothing looking anything up. Formes ride in -o, which keeps the
boundary the two readings differ across and groups a forme's sprites
together under ls.

s/i/x stay, so a directory can hold species and items with rules
matching them apart, and so xatu isn't mistaken for an escape. The x
escape's only other job was telling parseFilename not to resolve a name,
which nothing does now.

Where PS's own formeOrder gives one name to several of the games' forme
slots, nothing tells them apart, so the lowest slot keeps the bare name
and the rest carry -c: 16 files, all in previews/gen9.

The three jobs the table had left, each somewhere narrower now: published
names come off the filename; the 12 items that ship under a second name
are a literal in data/lib; base-forme sheet slots moved to
ps-pokemon.dexnums.mjs last commit. Nothing validates a filename any
more, which get() used to do by throwing; tools/spritedata/names.ts
prints what should exist so a directory can be checked against it.

The smogon and ps deploys materialize byte for byte identically. assets
moves five forumsprites keys, because toSmogonAlias was missing a /g and
so dashed only the first space: deep-seascale, deep-seatooth,
gold-bottlecap, prz-cureberry and psn-cureberry gain their missing
dashes, and the sprite bytes behind them are unchanged. That bug cannot
survive the encoding, which cannot tell which boundary came first. The
smogdex sheet relaid out, since spritesmith packs in glob order; its
2117 css class names are identical.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MQicnpaee6kQXGG7uVExLS
2026-08-23 00:30:23 -04:00
Christopher Monsanto
b8d7aa50eb Replace non-null assertions with explicit checks
Parsers use charAt or check-and-throw; the executor gets a paired()
helper for its parallel arrays; matchSubsets returns {entry, matched}
pairs so the deploy loop stops indexing two arrays; spawn stdin and
pid get real guards.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 01:13:15 -04:00
Christopher Monsanto
73f5954407 Adopt the house import style
Node builtins come in as node:-prefixed namespace imports;
multi-symbol internal imports use short namespace aliases (artifact,
cas, subst, db, api, executor). Single-symbol pulls, types, and the
buildfile DSL names stay braced, matching the sanctioned exceptions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 01:13:14 -04:00
Christopher Monsanto
3ec1abad12 Write let instead of const
Per the house rule, const survives only where TypeScript hangs
behavior off the spelling: the <const T> type parameter in rule()
and the as const option tables.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 01:13:14 -04:00
Christopher Monsanto
ebbb5e6f2e Tighten formatting to the smogon.com house style
Annotation colons are tight (ternaries keep their spaces), plain
double-quoted strings become single-quoted, and .editorconfig comes
over verbatim. Rule cmd values are untouched; the sheet rules reran
once because their tool sources are declared deps, byte-identically.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 01:13:14 -04:00
Christopher Monsanto
75580a962a Run TS sources directly: ESM sprite-root, .ts imports, node:test
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 17:44:51 -04:00
Christopher Monsanto
ac0ef09084 Drop dist mains, thin tsconfigs, bump @types/node and better-sqlite3
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 17:43:53 -04:00
Marty
6b9759b741 Update CAP sprites 2026-05-23 20:55:46 -04:00
Marty
4921ff31a3 Add latest CAP 2026-03-22 17:24:47 -04:00
Marty
99d2a53fae Fix item ids 2026-03-05 18:39:56 -05:00
Christopher Monsanto
0f840b3e18 various fixes 2026-02-22 04:52:18 -05:00
Marty
31fceb806e Update Mega minisprites 2026-02-21 21:17:38 -05:00
Marty
ab767cb8b7 Add new Megas and placeholder minisprites 2025-10-25 18:45:25 -04:00
Marty
c27ef771e8 Add new items 2025-10-21 12:04:32 -04:00
Marty
20d930908d Add latest CAP sprites 2025-07-18 08:47:41 -04:00
Marty
b2a2db3f76 Correct Florges line's form order 2025-05-24 21:40:04 -04:00
Spammernoob69
5308274a10 Add CAP34 prevos (#10) 2025-02-11 20:43:20 -05:00
Marty
953294c29a Add CAP 35 sprites
Closes #9
2024-12-01 21:41:49 -05:00
bingingem
bf36eb65bb Add Chuggalong to species.json 2024-05-19 12:46:57 -05:00
Christopher Monsanto
41f1088224 fix species.json slightly 2024-02-26 20:19:35 -05:00
Marty
23fc0a8717 Update item sprites 2023-12-18 19:40:05 -05:00
Marty
fd74c1a0b2 Update Pokemon sprites 2023-12-18 19:38:29 -05:00
Marty
c49cfe450f Add Cresceidon 2023-11-20 22:06:35 -05:00
Christopher Monsanto
cac5a2664f Update items.json 2023-09-16 11:16:22 -04:00
Marty
218c4a92e9 Add DLC minisprites
and update others
2023-09-16 10:50:45 -04:00
Marty
5465b9ee19 Add Big Nugget 2023-09-07 10:29:08 -04:00
Marty
e9cdd4fc93 Add CAP prevos 2023-08-29 13:29:37 -04:00
Marty
c14a4fad7d Add Gen 9 item sprites 2023-06-29 11:36:01 -04:00
Christopher Monsanto
1a0f7a24f2 Add hemogoblin 2023-05-31 00:47:42 -04:00
Christopher Monsanto
efbcd375d6 Update species.json 2023-02-27 18:45:52 -05:00
Christopher Monsanto
1492b6f10e update species.json 2023-01-23 11:13:48 -05:00
Christopher Monsanto
792fb0d55d Update sprite data 2022-12-13 15:24:54 -05:00
Christopher Monsanto
c0a5d57a47 Update data/ for Gen 9 2022-11-17 18:44:57 -05:00
Marty
326de87b15 Update CAP sprites
Thanks, Wulfanator!
2022-06-26 11:07:38 -04:00
Christopher Monsanto
af374b6295 Fix formatFilename bug 2021-12-28 21:15:53 -05:00
Christopher Monsanto
2902ddeb37 Fix lib for new items JSON 2021-12-21 11:35:16 -05:00
Christopher Monsanto
741c73f2d3 Rename items 2021-12-21 11:26:41 -05:00
Christopher Monsanto
622c97d357 Quick change 2021-12-20 21:26:17 -05:00
Christopher Monsanto
0a20088167 Unify items/pokemon data accessors 2021-12-20 19:10:03 -05:00
Christopher Monsanto
be6de440ba Prefix sids with type 2021-12-20 19:03:51 -05:00
Marty-D
9108719d2c Update recent CAP minisprites 2021-12-18 14:45:40 -05:00
Marty-D
f2eb19ff4e Add CAP 29 minisprite
and update Colossoil
2021-04-25 19:07:41 -04:00