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>
This commit is contained in:
Christopher Monsanto
2026-08-23 01:32:25 -04:00
parent f278ed4d73
commit 3a2ecf9e12
55 changed files with 25 additions and 8 deletions

View File

@@ -4,8 +4,8 @@
//
// kind s specie, i item, x literal (Egg, Substitute, ...)
// name the encoded name, [a-z0-9_]+
// flags -o forme -b back -s shiny -a asymmetrical -f female
// -g gmax or -g<game> -v<vendor> -c<slot>
// flags -o forme -k cosmetic -b back -s shiny -a asymmetrical
// -f female -g gmax or -g<game> -v<vendor> -c<slot>
//
// A name is encoded rather than spelled, because the two places these sprites
// are published disagree about what a word boundary is: smogon writes
@@ -48,12 +48,23 @@ export function psid(e: string): string {
// A published name: the name and its forme joined with a dash, then the
// variant flags, which both sides spell the same way.
//
// A cosmetic is its own component rather than part of the forme, because the
// two readings disagree about where a forme's words divide but not about the
// boundary in front of the cosmetic. Alcremie's cream is `caramel-swirl` for
// smogon and `caramelswirl` for PS, while its sweet is `-berry` for both; fold
// the sweet into the forme and whichever reading you spell it for, the other
// one comes out wrong.
export function publishedName(sn: SpriteFilename, part: (e: string) => string): string {
let name = part(sn.name);
let forme = sn.extra.get('o');
if (forme) {
name += `-${part(forme)}`;
}
let cosmetic = sn.extra.get('k');
if (cosmetic) {
name += `-${part(cosmetic)}`;
}
if (sn.extra.has('f')) {
name += '-f';
}
@@ -119,19 +130,25 @@ export function parseFilename(s: string): SpriteFilename {
return {kind, name: first.slice(1), extra};
}
// The flags publishedName() spells into the name, in the order it spells them.
const NAME_PARTS = ['o', 'k'];
export function formatFilename(si: InputSpriteFilename): string {
let s = `${si.kind}${si.name}`;
// The forme leads, so a forme's whole set of sprites sorts together
// instead of interleaving with the base forme's by flag letter.
let forme = si.extra?.get('o');
if (forme !== undefined) {
s += `-o${forme}`;
// The parts of the name lead, in the order they are published, so a
// forme's whole set of sprites sorts together instead of interleaving with
// the base forme's by flag letter.
for (let k of NAME_PARTS) {
let v = si.extra?.get(k);
if (v !== undefined) {
s += `-${k}${v}`;
}
}
let extra = [];
for (let [k, v] of si.extra?.entries() ?? []) {
if (k !== 'o') {
if (!NAME_PARTS.includes(k)) {
extra.push(`-${k}${v}`);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB