Topic: Pokemon Species Implications Script

Posted under Tag Alias and Implication Suggestions

Content

Mass update to apply pokemon classifications from pokeapi. The update includes the following:

- Species generation (generation_x_pokemon)
- Species "shape" (x_shaped_pokemon)*
- Species types (x_type_pokemon)**
- Species evolution stage (non_evolving_pokemon, unevolved_pokemon, partially_evolved_pokemon, fully_evolved_pokemon)
- Species baby state (baby_pokemon)
- Species legendary state (legendary_pokemon)
- Species mythical state (mythical pokemon)

* Pokemon classification, not necessarily their actual shape
** Correctly applied to individual forms

In its current form, this script creates 6138 implications, but it can easily be modified for what implications to actually include.

The BUR is too big for me to make here, so you can view it here: https://pastebin.com/w2dxBNcP

Caveats

- The script deliberately does not create implications from forms to the species base form. This often wouldn't work visually and often wouldn't work with types either.
- I haven't checked these for if forms have visual differences, you might want to look at that manually.
- Because this BUR is so big, I cannot post it here. Let me know if you want raw sql instead, not sure if admins can apply larger updates.

Script

The script should run in any recent version of node.js without any other dependencies. The script creates two files:

- implications.txt: The update
- forms.json: The different forms and what pokemon have them

const crypto = require('crypto')
const path = require('path')
const fs = require('fs')

const SKIPPED_FORMS_FUZZY =
[
    '-cap',
    'starter',
    'male',
    'female',
    'large',
    'super',
    'family',
    '-star',
    'gmax',
]

const FORM_TRANSFORMATIONS =
[
    ['alola','alolan'],
    ['hisui','hisuian'],
    ['galar','galarian'],
    ['paldea','paldean'],
]

const STRIPPED_FORMS =
[
    '-standard'
]

const FORM_COMBINER = '-'

async function DownloadJSON(url)
{
    const hash = crypto.hash('md5', url, 'hex')
    const tempPath = path.join('./Downloads', hash + '.json')
    if (fs.existsSync(tempPath))
    {
        return JSON.parse(fs.readFileSync(tempPath, 'utf-8'))
    }
    else
    {
        const json = await (await fetch(url)).json()
        if (!fs.existsSync('./Downloads'))
        {
            fs.mkdirSync('./Downloads')
        }

        fs.writeFileSync(tempPath, JSON.stringify(json,null,4))

        return json
    }
}

let implications = []
const forms = {}
;(async ()=>{
    for (let speciesId = 1; speciesId < 1026; ++speciesId)
    {
        const speciesData = await DownloadJSON('https://pokeapi.co/api/v2/pokemon-species/' + speciesId)
        const generationRoman = speciesData.generation.name.replace('generation-','')
        const generation = generationRoman === 'i' ? 1
            : generationRoman === 'ii' ? 2
            : generationRoman === 'iii' ? 3
            : generationRoman === 'iv' ? 4
            : generationRoman === 'v' ? 5
            : generationRoman === 'vi' ? 6
            : generationRoman === 'vii' ? 7
            : generationRoman === 'viii' ? 8
            : generationRoman === 'ix' ? 9
            : generationRoman === 'x' ? 10
            : NaN

        if (isNaN(generation))
        {
            console.log('invalid generation', generation, 'for pokemon', speciesId)
            continue
        }

        for (const variety of speciesData.varieties)
        {
            let formName = variety.pokemon.name
            for (const stripped of STRIPPED_FORMS)
            {
                formName = formName.split(stripped).join('')
            }

            formName = formName
                .replace(`${speciesData.name}-`,``)
                .replace(`-${speciesData.name}`,``)
                .replace(`${speciesData.name}`,``)

            if (formName.length > 0)
            {
                (forms[formName] || (forms[formName] = [])).push(speciesData.name)
            }

            if (SKIPPED_FORMS_FUZZY.find(skip => formName.includes(skip)))
            {
                continue
            }

            for (const [from, to] of FORM_TRANSFORMATIONS)
            {
                formName = formName.split(from).join(to)
            }

            const formData = await DownloadJSON(variety.pokemon.url)
            const fullName = formName.length > 0 ? `${formName}${FORM_COMBINER}${speciesData.name}` : speciesData.name

            if (formName === 'galarian')
            {
                implications.push(`imply ${fullName} -> galarian_pokemon`)
            }

            if (formName === 'hisuian')
            {
                implications.push(`imply ${fullName} -> hisuian_pokemon`)
            }

            if (formName === 'alolan' || formName === 'totem-alolan')
            {
                implications.push(`imply ${fullName} -> alolan_pokemon`)
            }

            if (formName.length > 0)
            {
                implications.push(`imply ${fullName} -> alternate_form`)
            }

            if (speciesData.is_baby)
            {
                implications.push(`imply ${fullName} -> baby_pokemon`)
            }

            if (speciesData.is_legendary)
            {
                implications.push(`imply ${fullName} -> legendary_pokemon`)
            }

            if (speciesData.is_mythical)
            {
                implications.push(`imply ${fullName} -> mythical_pokemon`)
            }

            const evolutionChain = (await DownloadJSON(speciesData.evolution_chain.url)).chain
            if (evolutionChain.species.name === speciesData.name && evolutionChain.evolves_to.length === 0)
            {
                implications.push(`imply ${fullName} -> non_evolving_pokemon`)
            }

            else if (evolutionChain.species.name === speciesData.name && evolutionChain.evolves_to.length > 0)
            {
                implications.push(`imply ${fullName} -> unevolved_pokemon`)
            }

            else
            {
                const findFinalEvolution = (cur) =>
                {
                    if (cur.evolves_to.length === 0)
                    {
                        return cur.species.name === speciesData.name
                    }

                    for (const evolve of cur.evolves_to)
                    {
                        if (findFinalEvolution(evolve))
                        {
                            return true;
                        }
                    }

                    return false;
                }

                if (findFinalEvolution(evolutionChain))
                {
                    implications.push(`imply ${fullName} -> fully_evolved_pokemon`)
                }
                else
                {
                    implications.push(`imply ${fullName} -> partially_evolved_pokemon`)
                }
            }

            const types = formData.types.map(x=>x.type.name).filter(x=>x !== undefined)
            implications.push(`imply ${fullName} -> generation_${generation}_pokemon`)
            implications.push(`imply ${fullName} -> ${speciesData.shape.name}_shaped_pokemon`)
            for (const type of types)
            {
                implications.push(`imply ${fullName} -> ${type}_type_pokemon`)
            }
        }
    }

    fs.writeFileSync('./implications.txt', implications.join('\n'))
    fs.writeFileSync('./forms.json', JSON.stringify(forms, null, 4))
})()

Updated

  • 1