
IA em JavaScript zera o Snake, mas não repete o feito em 100 testes
IA de neuroevolução feita em JavaScript zerou o Snake com 397 maçãs, mas não repetiu o resultado em 100 partidas novas.
O que o experimento quis descobrir
O projeto nasceu da curiosidade de entender como uma inteligência artificial aprende por dentro, sem depender de uma API ou de bibliotecas de IA. Inspirado por experiências de neuroevolução que ensinam programas a jogar, o autor desenvolveu uma IA para Snake em JavaScript puro, com treinamento distribuído por quatro VPS.
O resultado que chamou atenção foi uma cobra comer 397 maçãs e preencher um tabuleiro de 20 por 20 casas. Mas a verificação posterior mudou a interpretação da conquista: as cobras que chegaram ao fim não repetiram o resultado em cem partidas novas. O caso mostra por que uma vitória isolada não basta para avaliar o desempenho de um modelo.
Neuroevolução e uma rede compacta
O treinamento usa neuroevolução, uma abordagem que aplica seleção e mutação a redes neurais. A cada geração, 500 cobras recebem redes com pesos, jogam e são avaliadas; as melhores têm mais chance de gerar descendentes, que misturam pesos dos pais e recebem pequenas alterações aleatórias.
A rede tem 17 entradas, uma camada oculta com 16 neurônios e três saídas: seguir em frente, virar à esquerda ou virar à direita. A maior saída define a jogada. O modelo reúne 339 pesos, incluindo os valores de bias, armazenados em um Float32Array que ocupa cerca de 1,4 KB.
As entradas descrevem o ambiente em relação à direção da cabeça: distâncias a obstáculos em cinco raios, posição da maçã e da cauda, além do espaço livre alcançável em três direções. Esse último conjunto de sensores foi adicionado depois que a cobra começou a entrar em áreas fechadas pelo próprio corpo.
Treino distribuído entre quatro VPS
Para aproveitar máquinas diferentes, o autor separou a simulação em um arquivo que funciona tanto no navegador quanto no Node.js. Quatro VPS evoluem populações próprias, cada uma com três workers. A cada 90 segundos, as ilhas enviam suas dez melhores cobras a uma central e recebem indivíduos das demais.
As cobras migrantes substituem descendentes menos promissores, enquanto os melhores indivíduos locais são preservados. O processo também salva checkpoints a cada minuto, para que uma reinicialização permita continuar o treinamento. Como as máquinas executam outros serviços, a configuração usa a política de CPU ociosa para ceder recursos quando outro processo precisa deles.
Em uma das ilhas, o autor alterou a avaliação sem reiniciar a população: cada cobra passou a disputar três partidas regulares e uma partida extra, iniciada com a cobra grande em posições retiradas de replays de campeões. A aptidão era a média; na partida extra, só contavam as maçãs conquistadas dali em diante. O peso dos passos caiu de 1 para 0,1, houve um bônus elevado por completar o tabuleiro e o limite de fome subiu para 100 + 5 × tamanho, permitindo que a cobra grande esperasse a cauda liberar o caminho.
Uma vitória não comprovou consistência
Na geração 5.718, uma cobra comeu 397 maçãs em 24.788 passos. O autor repetiu a partida com a mesma semente e confirmou que o tabuleiro foi preenchido; depois, duas outras ilhas também produziram cobras que zeraram. Essa checagem confirmou as partidas registradas, mas não mostrou que as redes conseguiriam repetir a façanha em condições diferentes.
Nos testes com cem partidas novas para cada rede, todas as cobras que haviam zerado tiveram resultado de zero vitórias. A primeira teve média de 254 maçãs e mediana de 312; outra marcou média de 275 e mediana de 323. A rede que zerou na ilha experimental teve mediana de apenas 56, sinal de que sua vitória isolada não representava seu desempenho típico.
Zero acertos em cem tentativas não significa que a probabilidade real seja nula. Pela regra estatística de três, esse resultado indica apenas que a chance pode estar abaixo de aproximadamente 3%. As melhores redes recentes tiveram medianas entre 335 e 348 maçãs, um desempenho relevante, mas distante de demonstrar que sabiam completar o tabuleiro de forma confiável.
O que os obstáculos ensinaram
A primeira versão dos sensores chegou a 116 maçãs e parou de avançar. Os raios detectavam paredes próximas, mas não informavam se a cobra ficaria presa em um bolsão formado pelo próprio corpo. Ao adicionar as medidas de espaço livre, o treinamento passou de 200 maçãs em dez minutos e, mais tarde, chegou ao recorde de 397.
Outros testes mostraram que uma população maior não garantia progresso: em três minutos de execução, populações de dez mil cobras ficaram atrás de uma população de 500, porque cada geração demorava mais. Redes maiores também perderam para a configuração de 16 neurônios no curto prazo. A experiência sugere que dados de entrada adequados podem importar mais do que aumentar a rede.
O autor também identificou um problema de estouro no contador usado pelo flood fill. O Uint32Array dava a volta após 4.294.967.295 marcações; então, as casas pareciam não visitadas e o processo podia entrar em um loop infinito. A correção zera o array antes de o contador atingir esse limite, e um teto de dois milhões de passos por partida foi acrescentado como proteção.
Por fim, o relato alerta que um serviço marcado como ativo não necessariamente está trabalhando: as ilhas ficaram paradas enquanto o painel exibia dados antigos. O experimento, assim, produziu dois resultados distintos: uma partida comprovada com o tabuleiro completo e lições práticas sobre sensores, avaliação e monitoramento para distinguir um recorde ocasional de um comportamento reproduzível.

Comentários
0Comece a conversa.
Seja a primeira pessoa a comentar este conteúdo.