Diario de desarrollo

Medir la dificultad de un puzle con bots

4 min de lectura

La dificultad no es algo que se pueda sentir de forma fiable en un juego que has diseñado tú. Sunny Sort la mide haciendo que seis jugadores distintos jueguen cada nivel y leyendo el desacuerdo entre ellos: cada bot está construido para fallar de una manera concreta, así que cuál de ellos gana te dice qué clase de nivel es.

Los seis jugadores

LevelAnalyzer los ejecuta todos en cada nivel y cruza los resultados.

Jugador Qué hace Qué revela
Solucionador de haz la mejor línea que encuentra si el nivel se puede ganar, con cuánto margen, usando cuánto tablero
FirstFit el primer movimiento legal si gana, no hay puzle
Hoard siempre junto a la pila más gorda si gana desde una esquina, hay una estrategia dominante viva
Greedy el mejor movimiento mirando uno por delante si gana siempre, el juego es plano; si no gana nunca, es injusto o exige planificar
Spread siempre lo más lejos posible un control: demuestra que la colocación tiene consecuencias
Random aleatorio el suelo de dificultad

El veredicto es el peor problema encontrado, no una media:

impossible → trivial → dominated → harsh → good

Un nivel precioso en cuatro dimensiones y trivialmente ganable en la quinta es trivial. Promediar escondería justo lo que merece saberse.

La puntuación de 0 a 100 penaliza después las victorias de bots tontos, el uso del tablero concentrado en una esquina y un margen demasiado generoso; premia las cascadas y las líneas ganadoras que de verdad necesitan todo el tablero.

Una métrica que mentía

La primera versión medía "celdas tocadas" y se saturaba cerca del 100% en todas partes.

El motivo es estructural: un bot solo pierde cuando el tablero se llena, así que toda derrota acaba habiendo tocado todas las celdas jugables. La métrica medía la condición de derrota, no la estrategia.

La concentración se mide ahora en la línea ganadora del solucionador y en las decisiones individuales de los bots, nunca en sus totales. Es la clase de error que merece anotarse, porque una métrica saturada no parece rota: parece un resultado consistente.

Que gane un bot tonto es concluyente. Que pierda uno bueno, no.

Un informe anterior clasificó nueve niveles como deep porque el bot voraz no los ganaba, y yo leí eso como profundidad. Era una conclusión floja: "el voraz pierde" es ausencia de superficialidad, no presencia de decisión.

Así que medí la cosa directamente. Si un nivel exige planificar, tiene que existir algún momento en que un movimiento legal pierda el nivel y otro lo mantenga vivo. Sondeando los niveles 4 a 20, muestreando turnos a lo largo de toda la partida y no solo en la apertura:

Métrica Resultado
Profundidad estratégica (menor anticipación que gana) 1 en todos
Anchura de decisión (movimientos legales que mantienen la victoria) 100% en todos
Turnos forzados (≤ 1 movimiento ganador) 0%
Recuperación tras un movimiento no óptimo 100%

No había movimiento equivocado. En cualquier momento, cualquier cosa que hiciera el jugador seguía ganando. Aquellos niveles deep derrotaban a ese bot voraz concreto por una debilidad de su heurística —no valoraba mantener alta la cima de una pila— y no porque exigieran planificar. Un bot de un movimiento con mejor heurística los ganó todos.

Esa lectura cambió lo que vino después. Tres direcciones que parecían el siguiente paso obvio —elección de bandeja, geometría del tablero, preparar cascadas— no pueden producir decisiones mientras no haya presión. Una decisión solo existe cuando opciones distintas llevan a resultados distintos.

Lo que valen las mediciones

El sentido de todo esto es que ningún cambio de diseño entra sin un número que lo sostenga. El efecto conjunto de los cambios que las mediciones justificaron:

Métrica Antes Después
Puntuación media, niveles 1-24 55,2 81,8
Niveles valorados como good 11 de 20 21 de 24
Niveles imposibles 3 0
Niveles triviales 5, por accidente 3, los tutoriales, a propósito
Movimientos del tutorial 8-15 5-7

Cada uno de esos números sale del mismo comando, que puede ejecutar cualquiera que tenga el repositorio:

dotnet run --project src/StackSort.Tools -- analyze --from 1 --to 24

La medición no es un informe que alguien escribió una vez. Es una herramienta que vuelve a ejecutarse, y eso es lo que hace posible darse cuenta de cuándo un cambio empeora la curva.

Todas las entradas