Diário de desenvolvimento

Medir dificuldade de puzzle com bots

4 min de leitura

Dificuldade não é coisa que se sinta de forma confiável num jogo que você mesmo projetou. O Sunny Sort mede isso fazendo seis jogadores diferentes jogarem cada nível e lendo a discordância entre eles: cada bot é construído para falhar de um jeito específico, então qual deles vence diz que tipo de nível aquele é.

Os seis jogadores

O LevelAnalyzer roda todos eles em cada nível e cruza os resultados.

Jogador O que faz O que revela
Beam solver a melhor linha que encontra o nível é vencível, com quanta folga, usando quanto do tabuleiro
FirstFit a primeira jogada válida se vence, não há puzzle
Hoard sempre ao lado da pilha mais gorda se vence a partir de um canto, há estratégia dominante viva
Greedy melhor jogada olhando um lance se vence sempre, o jogo é raso; se nunca vence, é injusto ou exige planejamento
Spread sempre o mais longe possível um controle: mostra que a posição tem consequência
Random aleatório o piso de dificuldade

O veredito é o pior problema encontrado, não uma média:

impossible → trivial → dominated → harsh → good

Um nível bonito em quatro dimensões e trivialmente vencível na quinta é trivial. Tirar média esconderia justamente o que vale saber.

A nota de 0 a 100 então penaliza vitória de bot burro, uso do tabuleiro concentrado num canto e folga generosa demais; premia cascatas e linhas vencedoras que realmente precisam do tabuleiro inteiro.

Uma métrica que mentia

A primeira versão media "células tocadas" e ela saturava perto de 100% em todo lugar.

O motivo é estrutural: um bot só perde quando o tabuleiro enche, então toda derrota termina tendo tocado todas as células jogáveis. A métrica estava medindo a condição de derrota, não a estratégia.

Concentração passou a ser medida na linha vencedora do solver e nas escolhas individuais dos bots, nunca no total deles. É o tipo de erro que vale registrar, porque uma métrica saturada não parece quebrada — parece um resultado consistente.

Bot burro vencendo é conclusivo. Bot bom perdendo não é.

Um relatório anterior classificou nove níveis como deep porque o bot greedy não os vencia, e eu li aquilo como profundidade. Era conclusão frouxa: "o greedy perde" é ausência de rasidão, não presença de decisão.

Então medi a coisa direto. Se um nível exige planejamento, tem que existir algum momento em que uma jogada válida perde o nível e outra o mantém vivo. Sondando os níveis 4 a 20, amostrando turnos ao longo de toda a partida e não só na abertura:

Métrica Resultado
Profundidade estratégica (menor lookahead que vence) 1 em todos
Largura de decisão (jogadas válidas que mantêm a vitória) 100% em todos
Turnos forçados (≤ 1 jogada vencedora) 0%
Recuperação depois de uma jogada não ótima 100%

Não existia jogada errada. Em qualquer momento, qualquer coisa que o jogador fizesse ainda vencia. Aqueles níveis deep derrotavam aquele bot greedy específico por causa de uma fraqueza na heurística dele — ele não valorizava manter o topo da pilha alto — e não porque exigissem planejamento. Um bot de um lance com heurística melhor venceu todos.

Essa leitura mudou o que veio depois. Três direções que pareciam o próximo passo óbvio — escolha de esteira, geometria do tabuleiro, preparar cascata — não têm como produzir decisão enquanto não houver pressão. Uma decisão só existe quando escolhas diferentes levam a resultados diferentes.

O que as medições valem

O sentido de tudo isso é que nenhuma mudança de design entra sem número que a sustente. O efeito conjunto das mudanças que as medições justificaram:

Métrica Antes Depois
Nota média, níveis 1-24 55,2 81,8
Níveis avaliados como good 11 de 20 21 de 24
Níveis impossíveis 3 0
Níveis triviais 5, por acidente 3, os tutoriais, de propósito
Jogadas do tutorial 8-15 5-7

Cada um desses números sai do mesmo comando, que qualquer pessoa com o repositório roda:

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

A medição não é um relatório que alguém escreveu uma vez. É uma ferramenta que roda de novo, e é isso que torna possível perceber quando uma mudança piora a curva.

Todas as publicações