Esolang experimental inspirado en los 151 Pokémon de la primera generación, con una permutación optimizada de nombres: las operaciones más usadas tienen los nombres más cortos para minimizar el coste textual de los programas.
PokéCode es un lenguaje esotérico inspirado en los 151 Pokémon de la Gen 1. El intérprete implementa 151 instrucciones atómicas con nombre Pokémon (len(NAME_TO_OPCODE) == 151); los 151 son a la vez el motivo temático y el recuento exacto. Hay una permutación real de nombres sobre opcodes: los opcodes y sus semánticas son fijos, y los nombres Pokémon se asignan por frecuencia (operación más usada → nombre más corto). La codificación Mew unario está reservada y no participa en la permutación.
Lo que existe y funciona:
- 151 instrucciones con nombre (semánticas fijas, nombres permutados para minimizar tamaño textual)
- Máquina virtual: memoria, pila, call stack, loop stack, flags, registros, checkpoints
- Parser que descarta líneas de comentario (
#o;) y tokens desconocidos (sin fuzzy-match) - Encoding unario Mew:
Nrepeticiones deMewejecutan el opcodeN-1por valor directo - Motor público genérico:
pokemon_interpreter.py+host.py(todo en uno, sin dependencias internas) ejecutan.pkmc/.pok - Corpus 151
.pkmcenpkmc/— uno por opcode, todos verificados con el motor - Tests: aritmética, bitwise, registros, pila, Mew-encoding, control de flujo, cinta y saltos no acotados (9/9 en pytest) + 151 corpus
| Operación | Opcode | Nombre (len) | Freq |
|---|---|---|---|
| INC | 46 | MUK (3) |
alta |
| MEM_RD | 1 | ABRA (4) |
alta |
| MEM_WR | 2 | JYNX (4) |
alta |
| PTR_INC | 3 | ARBOK (5) |
|
| PTR_DEC | 4 | GENGAR (6) |
|
| DEC | 47 | ONIX (4) |
alta |
| MEM_CLR | 9 | EEVEE (5) |
|
| JZ | 22 | CUBONE (6) |
|
| JNZ | 23 | DODRIO (6) |
|
| PUSH | 77 | GLOOM (5) |
|
| POP | 78 | GOLEM (5) |
|
| IN | 96 | KABUTOPS (8) |
|
| OUT_MEM | 101 | DITTO (5) |
|
| REG_GET | 115 | PARAS (5) |
|
| REG_SET | 116 | SEEL (4) |
|
| PTR_HOME | 15 | ZUBAT (5) |
|
| HALT | 38 | DODUO (5) |
|
| MEW (meta) | 151 | Mew (3) |
especial |
Ahorro textual total observado en el traductor Brainfuck y tests: ~57%. En el programa
+++++[>+<-]>.la traducción a PokéCode pasa de 1114 a 555 chars (-50.2%).
# Hello World POKECODE - imprime Hi!\n
# Patrones: EEVEE ABRA = reset ACC=0 ; MUK*N = INC ; JYNX = store ; ARBOK = ptr++ ; ZUBAT = ptr_home ; DITTO = out_mem ; DODUO = halt
# 'H' = 72
EEVEE ABRA
MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK
MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK
MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK
MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK MUK
JYNX ARBOK
# 'i' = 105 (omitiendo aquí por brevedad, ver hello.pok)
# ZUBAT + 4x (DITTO ARBOK) + DODUO
ZUBAT
DITTO ARBOK DITTO ARBOK DITTO ARBOK DITTO
DODUO
El archivo completo está en hello.pok y se ejecuta así:
python pokemon_interpreter.py hello.pok
# -> Hi!Una secuencia de N Mew consecutivos ejecuta el opcode N-1 (por valor del opcode, no por posición del enum). El opcode 151 sigue siendo Mew (caso especial recursivo).
Una secuencia de más de 151 Mew consecutivos es inválida y el parser la rechaza;
no existe un opcode 152 ni un argumento oculto para Mew.
| Mews | Opcode | Pokémon (nombre actual) | Operación |
|---|---|---|---|
| 1 | 151 | Mew |
META (NOP + flag) |
| 2 | 1 | ABRA |
MEM_RD |
| 3 | 2 | JYNX |
MEM_WR |
| 4 | 3 | ARBOK |
PTR_INC |
| 47 | 46 | MUK |
INC |
| 98 | 97 | HYPNO |
OUT |
| 151 | 151 | Mew |
(recursivo) |
Ejemplo mezclado (ambos estilos coexisten):
ARBOK Mew Mew Mew MUK HYPNO
| Categoría | Instrucciones | Tests |
|---|---|---|
| Memoria | 19 (leer, escribir, mover, copiar, buscar, bloques) | OK |
| Control | 19 (saltos, condicionales, loops, CALL/RET, HALT) | OK |
| Aritmética | 19 (ADD, SUB, MUL, DIV, MOD, INC, DEC, NEG, RAND, etc.) | OK |
| Bitwise | 19 (AND, OR, XOR, NOT, SHL/SHR, rotaciones, bit ops) | OK |
| Pila | 13 (PUSH, POP, DUP, SWP, ROT3, OVER, NIP, TUCK, etc.) | OK |
| I/O | 19 (IN, OUT, OUT_NUM/HEX/BIN, DEBUG, READ_NUM/HEX/LINE, FILE, SLEEP, TIME, RNG, HASH) | OK |
| Registros | 19 (GET, SET, XCHG, INC/DEC, ADD/SUB, MOV, CPY, SWP, ROT, MUL/DIV/MOD, AND/OR, SAVE/REST) | OK |
| Meta | 18 (SYS_EXIT, SYS_ARG, CLONE, MORPH, TRACE, PROFILE, SELF_MOD, CHECKPOINT/RESTORE, TIME_TRAVEL, PARALLEL, ATOMIC, FREEZE/THAW, BURN, META) | Parcial |
PokéCode no está demostrado Turing-completo. Esta sección afirmaba lo contrario "por múltiples reducciones independientes"; sólo una de las cinco tenía artefacto, y estaba rota. Corregido.
bf2pokecode.py traduce Brainfuck a PokéCode y los programas traducidos se
ejecutan y dan el resultado correcto, bucles anidados incluidos:
| BF | salida | instrucciones |
|---|---|---|
+++. |
3 | 10 |
+[-]. |
0 | 47 |
+++++[>+<-]>. |
5 | 65 |
+++++++[>+++++++<-]>. |
49 | 89 |
++[>++[>+<-]<-]>>. |
4 | 108 |
| BF | PokéCode |
|---|---|
> |
ARBOK (PTR_INC) |
< |
GENGAR (PTR_DEC) |
+ |
ABRA MUK JYNX (MEM++) |
- |
ABRA ONIX JYNX (MEM--) |
. |
DITTO (OUT_MEM) |
, |
KABUTOPS (IN) |
[ |
ABRA CUBONE @fin (prueba celda y salta por etiqueta) |
] |
ABRA DODRIO @bucle (prueba celda y vuelve por etiqueta) |
La VM usa una cinta dispersa, bidireccional y sin límite fijo de direcciones.
Las etiquetas del parser permiten que los saltos existentes (CUBONE, DODRIO
y los demás saltos absolutos) tengan destinos de cualquier tamaño:
@bucle:
ABRA CUBONE @fin
# cuerpo
ABRA DODRIO @bucle
@fin:
@bucle: y @fin: son directivas de ensamblador, no instrucciones Pokémon ni
una variante de Mew. Un salto sin etiqueta conserva el destino histórico en
ACC, de 8 bits. El traductor Brainfuck genera etiquetas y ejecuta el Hello
World clásico, además de programas con bucles anidados.
Conclusión: PokéCode contiene una simulación ejecutable de Brainfuck con cinta y control no acotados. Bajo la semántica estándar de Brainfuck, esto demuestra Turing-completitud de esta versión de la VM.
# Programa inline
python pokemon_interpreter.py -c "MUK MUK MUK DITTO DODUO"
python host.py -c "MUK MUK HYPNO DODUO"
# Desde archivo (.pok o .pkmc)
python pokemon_interpreter.py hello.pok
python host.py pkmc/046_MUK.pkmc
python host.py hello.pok --trace
# Solo Mews (47 Mews = MUK)
python pokemon_interpreter.py -c "Mew " * 47
python host.py -c "Mew Mew Mew Mew" # 4 Mews = ARBOK
# Trace
python pokemon_interpreter.py -c "EEVEE ABRA MUK MUK JYNX ZUBAT DITTO DODUO" --trace
# Corpus completo 151
python host.py pkmc/001_ABRA.pkmc
for f in pkmc/*.pkmc; do python host.py "$f" > /dev/null && echo "$f OK"; donepokemon_interpreter.py es el motor todo-en-uno (VM + parser). host.py es un wrapper fino del mismo motor para uso público:
.pkmces la extensión canónica del motor (también acepta.pok)- Lista las 151:
python host.py --list - Mew sigue siendo solo unario por valor (
NMews = opcodeN-1);@etiqueta:es directiva de ensamblador para saltos, no una variante de Mew
python host.py --list
# 46 muk
# 151 mew
python gen_151_pkmc.py # regenera y verifica los 151pkmc/ = canonical opcode examples. Cada archivo:
- corresponde a exactamente un opcode;
- muestra la forma mínima válida de usarlo;
- sirve como referencia para humanos y LLMs;
- puede ejecutarse directamente con el host (
python host.py pkmc/046_MUK.pkmc); - NO sustituye los tests semánticos.
$$ \boxed{ \text{1 opcode} \rightarrow \text{1 ejemplo canónico visible} } $$
Para opcodes complejos el ejemplo es una flashcard ejecutable con contexto:
# PRE: ACC=3
# POST: stack=[3]
GLOOM
DODUO
# demonstrate JZ — expected branch: @zero
EEVEE ABRA
CUBONE @zero
DRATINI
@zero:
DODUO
Separación limpia:
| Carpeta/archivo | Rol |
|---|---|
pkmc/ |
cómo se usa |
tests/ |
cómo sabemos que funciona |
README / SPEC |
qué significa |
host.py + pokemon_interpreter.py |
cómo se ejecuta |
Con 151 nombres Pokémon, esto evita que el siguiente humano o LLM tenga que adivinar la forma correcta.
python -m pytest tests/test_turing.py -q
python tests/test_turing.py
python gen_151_pkmc.py # verifica 151 .pkmcDos programas en examples/ demuestran cómputo no trivial sin traductor:
| Ejemplo | Archivo | Qué prueba | Salida |
|---|---|---|---|
| Fibonacci 10 | examples/fibonacci.pok |
memoria (ABRA/JYNX), puntero (ZUBAT/ARBOK), aritmética (IVYSAUR), pila (GLOOM/GOLEM), saltos etiquetados (CUBONE/DODRIO @loop) |
0 1 1 2 3 5 8 13 21 34 |
| FizzBuzz 1..15 | examples/fizzbuzz.pok |
MACHOKE (MOD), bifurcaciones anidadas, strings en memoria (DITTO x4/x8) |
1 2 Fizz 4 Buzz ... FizzBuzz |
python host.py examples/fibonacci.pok
# -> 0 1 1 2 3 5 8 13 21 34
python host.py examples/fizzbuzz.pok
# -> 1 / 2 / Fizz / 4 / Buzz / Fizz / 7 / 8 / Fizz / Buzz / 11 / Fizz / 13 / 14 / FizzBuzz
python pokemon_interpreter.py --example fib
# usa FIBONACCI integrado (pokemon_interpreter.py:1570)El FIBONACCI anterior era un stub (EEVEE ABRA JYNX...). Ahora es el programa verificado anterior.
| Componente | Estado |
|---|---|
| VM core | OK |
| Parser (comentarios, Mew, sin fuzzy) | OK |
| 151 instrucciones (nombres permutados) | OK |
| Mew encoding unario (por valor) | OK |
Motor público (pokemon_interpreter.py + host.py) |
OK — ejecuta .pkmc / .pok |
Corpus 151 .pkmc (pkmc/001_* … 151_Mew.pkmc) |
151/151 verificados |
| Tests unitarios | 9/9 pasan |
| Traductor Brainfuck | OK (bucles anidados y Hello World) |
Hello World (hello.pok / pkmc/038_DODUO.pkmc etc) |
OK |
Fibonacci (examples/fibonacci.pok + --example fib) |
OK — 0 1 1 2 3 5 8 13 21 34 verificado |
FizzBuzz (examples/fizzbuzz.pok) |
OK — 1..15 con MOD y bifurcaciones verificado |
| Documentación | Este README |
PokéCode es un proyecto independiente y no oficial, creado como experimento/homenaje. No está afiliado, patrocinado ni respaldado por Nintendo, The Pokémon Company o Game Freak. Pokémon y los nombres relacionados pertenecen a sus respectivos propietarios.
MIT License — ver LICENSE para detalles.