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.
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 →
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.
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.
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.
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.
| Parámetro del barrido | Rango | Significado |
|---|---|---|
| Rampa X | 15 → 85, paso 14 | columnas a lo ancho del campo |
| Rampa Y | 30 → 120, paso 18 | filas hacia abajo en el campo |
| Ángulos probados | 4 | ±0.45 y ±0.8 radianes |
| Prueba por colocación | 1 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
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.