PlayPendium
Contraption · Reflexiones

Un nivel que demuestra ser resoluble

El juego nunca crea un puzle a mano. Lo hace crecer a partir de un solo número y, a continuación, juega ese puzle contra sí mismo para asegurarse de que no es ni trivial ni imposible antes de que tú lo veas.

La fecha de hoy 1 número, convertido en semilla mediante un hash
se convierte en
El puzle diario 1 campo idéntico para todo el mundo

Redactado y editado en inglés. Esta versión en español se ha generado mediante traducción automática; cuando la precisión importe, la versión de referencia es el original en inglés. Leer el original en inglés →

01 · Todo a partir de un solo número

Un mundo entero plegado en una semilla

Un nivel de Contraption no se guarda en ningún sitio. No existe un archivo que liste dónde está la meta o cómo están dispuestos los salientes. En su lugar, todo el nivel, el punto de partida de la pelota, la posición de la meta, el número y la colocación de los muros fijos, el inventario de piezas que te entregan, se calcula a partir de un único número inicial llamado semilla. Dale al generador la misma semilla y obtendrás, byte a byte, el mismo puzle. 1

Eso es posible porque la única fuente de «aleatoriedad» del generador es un pequeño generador determinista de números pseudoaleatorios. El que usa Contraption es mulberry32, un generador compacto de 32 bits creado por Tommy Ettinger; puedes identificarlo por su constante característica, 0x6d2b79f5, que se suma al estado en cada extracción. 2 Es rápido, cabe en unas pocas líneas y, lo que es crucial, no es aleatorio en absoluto: es una secuencia matemática fija que simplemente parece barajada. Dale un punto de partida y producirá el mismo flujo de números para siempre. Luego el generador lee ese flujo para decidir dónde colocar cada cosa.

02 · El puzle diario

Cómo una fecha se convierte en un desafío compartido

El modo Daily se apoya en este determinismo para hacer algo social. Su semilla no es aleatoria: se fabrica a partir del calendario. El juego toma la fecha de hoy en tiempo universal, la escribe en una cadena corta como «contraption:2026-7-28» y pasa ese texto por una función hash para reducirlo a un único número de 32 bits. 1

El hash es FNV-1a, un conocido mezclador no criptográfico: parte de un desplazamiento fijo, el decimal 2166136261, o 0x811c9dc5, y, para cada carácter, incorpora la letra mediante un o-exclusivo (XOR) y luego multiplica por el primo FNV 16777619. 3 Eso deja un número que es estable para un día dado y radicalmente distinto de un día al siguiente, de modo que un cambio de un solo carácter en la fecha dispersa la semilla por completo. Como el calendario es el mismo para todos, también lo es la semilla, y también lo es el puzle. Dos desconocidos en extremos opuestos del mundo abren Daily y se enfrentan a un campo idéntico, que es justo lo que hace que comparar puntuaciones tenga sentido.

El desafío diario es justo no porque un servidor envíe a todos el mismo nivel, sino porque la copia de cada uno recalcula de forma independiente el mismo nivel a partir de la misma fecha.

03 · El generador se cuestiona a sí mismo

Rechazar el puzle que se resuelve solo

La geometría aleatoria es fácil; la buena geometría aleatoria no lo es. Un generador que se limite a esparcir una meta y unos cuantos salientes producirá a veces un nivel en el que la pelota, soltada desde arriba, cae directamente en la meta por sí sola. Eso no es un puzle, es una cinemática. Así que, antes de que Contraption acepte un mundo candidato, ejecuta una prueba discreta que el código llama preSolved: simula el nivel con cero piezas colocadas y comprueba si la pelota, sin ayuda alguna, llega a la meta solo por gravedad. Si lo hace, el nivel se descarta y el generador vuelve a empezar. 1

Esta es una inversión sutil de cómo normalmente se piensa en un motor de física. La misma función simulate() que hace funcionar tu máquina se vuelve hacia dentro, en el momento de la generación, para auditar la dificultad del propio nivel. El motor es a la vez el árbitro de tu solución y el inspector de calidad del puzle.

04 · Un pequeño solucionador integrado

«¿Se puede hacer con una sola pieza?»

Rechazar el nivel demasiado fácil es solo la mitad del trabajo. El otro peligro es el nivel imposible, una meta escondida en algún lugar al que ninguna disposición de piezas puede llegar. Contraption se protege contra esto con un pequeño solucionador por fuerza bruta llamado plausiblySolvable. No piensa con astucia. Se limita a probar. 1

En concreto, barre con una sola rampa una cuadrícula de posiciones sobre el campo y, en cada punto, la prueba inclinada de cuatro maneras distintas. Para cada una de esas colocaciones de prueba ejecuta la simulación completa y pregunta: ¿esa única rampa ha llevado la pelota a casa? En cuanto una colocación tiene éxito, el nivel se declara resoluble y se te entrega. Si ninguna funciona tras el barrido completo, el generador prefiere descartar el nivel y probar con una semilla nueva.

La búsqueda del solucionador de una sola pieza: una cuadrícula gruesa, cuatro inclinaciones en cada punto
Parámetro del barridoRangoSignificado
Rampa X15 → 85, paso 14columnas a lo ancho del campo
Rampa Y30 → 120, paso 18filas hacia abajo en el campo
Ángulos probados4±0.45 y ±0.8 radianes
Prueba por colocación1 simulación completa¿llega la pelota a la meta?

Vale la pena ser honesto sobre lo que esto demuestra, porque el código también lo es: el comentario lo llama una «comprobación de plausibilidad barata … no exhaustiva». Un nivel que pasa tiene, sin duda, al menos una solución tosca de una sola rampa. Un nivel que falla podría seguir siendo resoluble con un ventilador, un engranaje o una rampa más ingeniosa que la cuadrícula nunca probó, así que el generador no trata el fallo como prueba de imposibilidad. Conserva el primer mundo no trivial que encontró como respaldo y, si pasan cuarenta intentos sin una solución limpia de una sola pieza, entrega ese respaldo en lugar de quedarse en bucle para siempre. El resultado es una garantía pragmática: nunca una victoria regalada, casi siempre un camino genuino de entrada, y nunca una espera infinita por el nivel «perfecto». 1

05 · La idea de fondo

Generar y probar, la forma más humilde de inteligencia

Da un paso atrás y verás que el creador de niveles de Contraption es un ejemplo limpio de un patrón de resolución de problemas muy antiguo y muy general: generar y probar. Propón un candidato al azar; compruébalo contra tus requisitos; consérvalo si pasa, descártalo y propón otro si falla. Es el bucle que hay detrás del contenido procedimental de incontables juegos, detrás de buena parte de la computación evolutiva y, entornando un poco los ojos, detrás de la propia selección natural: la mutación propone, el entorno prueba, los supervivientes persisten. 4

Lo que hace elegante la versión de Contraption es que la prueba no es un sustituto barato de la jugabilidad: es la jugabilidad. El generador no estima si un nivel es justo contando salientes o midiendo distancias. Literalmente juega el nivel, dos veces: una vacío, para asegurarse de que no es un regalo, y otra con una rampa de sondeo, para asegurarse de que existe un camino. La misma física determinista que juzgará tu solución es la física que examinó el puzle. No hay un «validador de niveles» aparte que pueda desincronizarse de las reglas reales, porque solo hay un conjunto de reglas, que se usa para todo.

Y como todo es determinista, la auditoría está libre de suerte en ambas direcciones. La semilla diaria no puede conspirar para darle a un jugador un campo más fácil que a otro, y no puede darle a nadie uno injusto, porque, antes de convertirse en un desafío, el nivel ya ha sobrevivido a ser jugado, por el juego, contra sí mismo.

Sources & notes
  1. Seed-to-level generation, the preSolved rejection test, the plausiblySolvable one-ramp solver (grid ranges, four angles, up to 40 attempts, fallback world), and the daily-seed date string are all read directly from Contraption's own game engine and random-number code. Grounded in the game's code, not invented.
  2. mulberry32 is a compact 32-bit pseudo-random generator by Tommy Ettinger; it advances its state with the constant 0x6d2b79f5 and has a period of 2³². Author's reference gist (with his own later caveats on its equidistribution). gist.github.com/tommyettinger/46a874533244883189143505d203312c
  3. "Fowler–Noll–Vo hash function." Wikipedia, the 32-bit FNV offset basis is 2166136261 (0x811c9dc5) and the FNV prime is 16777619 (0x01000193); FNV-1a XORs each byte into the hash first and then multiplies by the prime. en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function
  4. On generate-and-test / "generation followed by evaluation" as a general search and problem-solving strategy, and its kinship with procedural generation and evolutionary methods. See "Procedural generation," Wikipedia. en.wikipedia.org/wiki/Procedural_generation
  5. Further reading on Procedural generation, [2410.15644] Procedural Content Generation in Games: A Survey with Insights on Emerging LLM Integration. arxiv.org.
  6. Further reading on Procedural generation, Procedural Content Generation in Games: A Survey with Insights on Emerging LLM Integration. doi.org.
  7. Further reading on Procedural generation, "Procedural City Generation with Combined Architectures for Real-time V" by Gr. open.clemson.edu.
Was this worth reading?
← Back to Contraption
PlayPendium · About · Contact · Privacy · Terms · Cookies · Accessibility · Copyright · Browse all games · Inspirations · © 2026