Volver al Blog
Videojuegos5 de mayo de 20268 min de lectura

Cómo funciona realmente la genética de Pokémon

Un análisis en profundidad de los IVs, EVs y mecánicas de cría: lo que estos sistemas nos pueden enseñar sobre el diseño de progresión de criaturas en videojuegos.

IM
Ignacio MelendezDesarrollador Full-Stack y de Videojuegos
Cómo funciona realmente la genética de Pokémon

Llevo un tiempo reconstruyendo el sistema de estadísticas de un juego de colección de criaturas en el que estoy trabajando.

La primera versión era muy básica (valores fijos por especie, sin variación entre individuos). Funcionaba mecánicamente, pero el bucle de colección se sentía completamente vacío. ¿Para qué capturar un segundo Slime si es idéntico al primero?

Así que volví a la fuente e hice lo que cualquier desarrollador haría: desmonté Pokémon.

Pokémon siempre ha tenido esa dualidad (un RPG simple en la superficie, un sistema absurdamente estratificado por dentro). Una vez que empiezas a profundizar, te das cuenta de que dos Pokémon de la misma especie y nivel pueden tener estadísticas notablemente distintas. Esto no es un bug. Es exactamente el punto.

1. Tres sistemas independientes, un número final

Cada estadística de un Pokémon es el resultado de tres inputs independientes que funcionan juntos. Ninguno es suficiente por sí solo. Entender cada capa por separado es lo que hace que todo encaje.

  • Estadísticas base, definidas por la especie, nunca cambian.
  • IVs, potencial genético fijado en el momento de la creación.
  • EVs, entrenamiento obtenido por el jugador.

Lo que encuentro genuinamente elegante es que cada capa resuelve un problema de diseño diferente. No son tres formas de hacer lo mismo, sino tres tipos de input completamente distintos que resultan combinarse en un único número.

2. Estadísticas base: identidad de especie

Cada especie tiene un conjunto fijo de estadísticas base. Un Garchomp tiene Ataque y Velocidad altos. Un Blissey tiene PS absurdamente elevados. Estos valores no varían entre individuos de la misma especie, son la identidad de la especie, no de la criatura.

En términos de arquitectura de datos, las estadísticas base pertenecen a la definición de especie, no a la instancia individual del Pokémon. En C# podría verse algo así:

C#
1[Serializable]
2public class SpeciesData : ScriptableObject
3{
4    public int baseHP;
5    public int baseAttack;
6    public int baseDefense;
7    public int baseSpAttack;
8    public int baseSpDefense;
9    public int baseSpeed;
10}

Cada instancia de Pokémon referencia estos datos en lugar de almacenar su propia copia. Diseño clásico orientado a datos: cambia las estadísticas base de una especie y todos los Pokémon de esa especie se recalculan automáticamente. Sin migraciones, sin actualizaciones manuales.

3. IVs: la tirada genética

Los IVs (Individual Values) son donde las cosas se ponen interesantes. Cuando se crea un Pokémon (ya sea capturado en la naturaleza o eclosionado de un huevo) cada una de sus seis estadísticas recibe un IV asignado aleatoriamente entre 0 y 31.

Eso es todo. Seis enteros, rango 0-31.

C#
1[Serializable]
2public struct PokemonIVs
3{
4    public int hp;
5    public int attack;
6    public int defense;
7    public int spAttack;
8    public int spDefense;
9    public int speed;
10}

La primera vez que entendí esto correctamente, mi reacción fue algo así: "es casi insultantemente simple." Pero esos seis enteros resuelven un problema de diseño real.

¿Cómo haces que cada instancia de una criatura se sienta significativamente única sin simular nada complejo?

Dos Pokémon de la misma especie al mismo nivel pueden sentirse notablemente distintos de usar, porque uno tiene un 31 en Velocidad y el otro tiene un 12. Sin simulación adicional, sin generación procedural. Solo un entero aleatorio guardado en el momento de la creación.

Desde una perspectiva de diseño de sistemas, esto es extremadamente elegante. Obtienes individualidad significativa con un coste computacional mínimo. El sistema es trivialmente barato de evaluar y sin embargo produce una diversidad enorme.

No necesitas generación procedural para que la individualidad se sienta real. Con un solo entero guardado en el momento de la creación es suficiente, siempre que tu fórmula lo use de forma significativa. La elegancia no está en el número, sino en lo que la fórmula hace con él.

4. EVs: lo que realmente hiciste con ello

Los EVs (Effort Values) son la capa de entrenamiento, y la única sobre la que el jugador tiene control directo.

A diferencia de los IVs, que son fijos desde la creación, los EVs se obtienen derrotando Pokémon específicos. Pelear contra un Machoke da EVs de Ataque. Pelear contra un Gastly da EVs de Ataque Especial. El sistema crea un vínculo directo entre lo que combates y en lo que se convierte tu Pokémon.

El sistema tiene límites estrictos que fuerzan decisiones:

  • 252 EVs máximo por estadística individual.
  • 510 EVs máximo en total entre todas las estadísticas.

No puedes maximizarlo todo, así que la especialización se convierte en una decisión deliberada. No solo estás entrenando, estás comprometiéndote con una build concreta.

La separación entre IVs y EVs es la decisión de diseño más interesante del sistema. Los IVs son suerte. Los EVs son intención. Ambos afectan al mismo número final, pero representan tipos de inversión completamente distintos. Dos Pokémon genéticamente idénticos pueden acabar jugándose diferente dependiendo de cómo se entrenaron, y eso es intencionado.

Los IVs y los EVs resuelven emociones de jugador distintas: uno da razones para seguir cazando, el otro para seguir invirtiendo. Tu juego probablemente necesita ambos, aunque no tengan que parecerse en nada a la implementación de Pokémon.

5. La fórmula de estadísticas

Internamente, el juego calcula las estadísticas usando una fórmula aproximadamente así:

Stat = floor(((2 × Base + IV + EV/4) × Nivel / 100) + 5)

Los PS usan una versión ligeramente diferente. La estructura central es la misma.

Fíjate en el peso relativo. Los IVs contribuyen directamente; los EVs se dividen por 4. Esto significa que la genética establece el techo que el entrenamiento llena, y necesitarías 4 EVs para obtener el mismo beneficio incremental que 1 punto de IV. No es un accidente.

En código, resolver las estadísticas bajo demanda se vería algo así:

C#
1public static class StatResolver
2{
3    public static int Resolve(
4        int baseStat,
5        int iv,
6        int ev,
7        int level)
8    {
9        return Mathf.FloorToInt(
10            ((2f * baseStat + iv + ev / 4f) * level / 100f) + 5f
11        );
12    }
13
14    public static int ResolveHP(
15        int baseStat,
16        int iv,
17        int ev,
18        int level)
19    {
20        return Mathf.FloorToInt(
21            ((2f * baseStat + iv + ev / 4f) * level / 100f) + level + 10f
22        );
23    }
24}

Guardar el valor final de una estadística es el mismo error que cachear datos derivados: parece inofensivo hasta que necesitas rebalancear. Guarda solo los inputs; deriva todo lo demás bajo demanda. Ajusta la fórmula y cada estadística del juego se recalcula sin tocar los datos de ningún Pokémon.

6. La cría no es más que optimización de IVs

Una vez que entiendes los IVs, la cría se vuelve obvia. Es un algoritmo de convergencia.

Cuando dos Pokémon producen un huevo, el hijo hereda algunos IVs de sus padres (tres por defecto, más con mecánicas como el Nudo Destino). El resto se genera aleatoriamente. Los jugadores usan esto para converger progresivamente hacia criaturas con IVs perfectos en todas las estadísticas.

C#
1public class BreedingService
2{
3    private const int InheritedIVCount = 3;
4
5    public PokemonIVs Breed(PokemonIVs parentA, PokemonIVs parentB)
6    {
7        var child = GenerateRandomIVs();
8        var stats = GetAllStatIndices();
9        var inherited = stats.OrderBy(_ => Random.value)
10                             .Take(InheritedIVCount);
11
12        foreach (var stat in inherited)
13        {
14            var source = Random.value > 0.5f ? parentA : parentB;
15            SetIV(ref child, stat, GetIV(source, stat));
16        }
17
18        return child;
19    }
20
21    private PokemonIVs GenerateRandomIVs()
22    {
23        return new PokemonIVs
24        {
25            hp        = Random.Range(0, 32),
26            attack    = Random.Range(0, 32),
27            defense   = Random.Range(0, 32),
28            spAttack  = Random.Range(0, 32),
29            spDefense = Random.Range(0, 32),
30            speed     = Random.Range(0, 32),
31        };
32    }
33}

El algoritmo es simple. Lo que produce es un bucle de optimización a largo plazo: los jugadores crían a lo largo de generaciones, bloqueando lentamente valores perfectos estadística por estadística. La profundidad no está en el código. Está en el objetivo que el sistema crea.

7. Conclusiones

Diseccionar este sistema me dejó tres cosas a las que sigo volviendo:

  • Potencial vs. progresión. Los IVs son lo que tu criatura podría llegar a ser. Los EVs son lo que elegiste hacer con ella. Ambos afectan al mismo número final, pero representan tipos de inversión distintos, y ambos se sienten significativos a su manera. Si tu juego solo tiene uno de estos, probablemente falta algo.
  • La fórmula como declaración de diseño. El hecho de que los IVs pesen más que los EVs no es un detalle de implementación, es una filosofía deliberada. El techo de tu criatura está determinado principalmente al nacer. Puede que no quieras eso en tu propio juego, pero deberías ser consciente de qué comunica tu fórmula.
  • Aleatoriedad pequeña, diversidad grande. Un rango de 0-31 en seis estadísticas cuesta casi nada computacionalmente y produce una variación enorme entre individuos. No necesitas generación procedural compleja para que una colección valga la pena.

Mi sistema de criaturas no se parece al de Pokémon (objetivos distintos, bucle distinto, audiencia distinta). Pero entender exactamente por qué estos sistemas funcionan como funcionan me dio mucha más claridad sobre lo que yo estaba intentando resolver.

A veces lo mejor que puedes hacer antes de diseñar un sistema es dedicar unas horas a desmontar con cuidado uno que ya funciona.

Artículos Relacionados

Ver todos los artículos
Replicando el sistema genético de Mewgenics en Unity

Replicando el sistema genético de Mewgenics en Unity

Un análisis técnico de cómo diseñar un sistema genético flexible en Unity, inspirado en la mecánica de crianza de Mewgenics.

Los stats de Fire Emblem y la ilusión de profundidad táctica

Los stats de Fire Emblem y la ilusión de profundidad táctica

Los growth rates de Fire Emblem son simples tiradas de porcentaje, pero generan una varianza brutal, apego emocional y subculturas enteras de manipulación de guardados.