Horizons

Do nada, Lima mandou um link sobre Prince of Persia no grupo de jogos. Tarso contou da experiência de ter visto esse jogo pela primeira vez e eu lembrei que é um clássico que nunca terminei. A conversa demorou pouco a ir pra outro caminho e o assunto ficou esquecido. No final de semana seguinte, resolvi dar uma chance ao jogo. Prince of Persia não é conhecido por ter os controles mais intuitivos do mundo, então logo na primeira fase errei um pulo, voltei pro começo e desisti de tentar de novo. Deixei o jogo pra lá, mas ele ficou do pano de fundo do meu pensamento. Acabei resolvendo dar uma segunda chance e o ritmo engrenou. Fui passando por fases que eu já tinha passado, encontrando detalhes que eu ainda lembrava de ter visto há muito tempo e depois da metade do jogo ficou difícil dizer com certeza se eu já tinha ou não visto aquela fase. Em certa altura eu fiquei curioso pra saber como os passwords funcionavam. O estado do jogo consistia somente em três variáveis: a fase atual, o número de pontos de vida e o tempo restante. Imaginei que não fosse difícil fazer engenharia reversa disso e guardei a tarefa pra depois de terminar o jogo. Compartilhei a curiosidade com Tarso e ele me mandou dois passwords que ele ainda lembrava de cor: TKQSTF! e BQMZXY2. “Testa elas aí pra ver se funcionam”, ele disse. O primeiro me levou pra a fase 10 e o segundo… não funcionou. Tarso se surpreendeu e eu fiquei pensando em como descobrir o que estava errado.

Depois de terminar o jogo, fiz uma busca rápida e encontrei um esquema detalhando como os passwords do jogo são gerados. É muito mais complexo do que eu imaginava. Os passwords de Prince of Persia consistem em uma sequência de sete caracteres dentre um conjunto de vinte e seis possíveis (que não são exatamente o alfabeto) e cada caractere dessa sequência de sete tem uma fórmula específica. Vou explicar aqui apenas a do primeiro, o mais simples, só pra dar uma ideia do trabalho que seria fazer engenharia reversa disso:

Pegue o primeiro bit do contador de fases, o quarto bit do contador de pontos de vida e o primeiro e o oitavo bits do contador de tempo passado desde que o jogo começou (que não é medido em segundos), transforme esses bits em um inteiro e você terá o índice da sequência (não ordenada) de caracteres possíveis no password.

Depois de quase criar um novo gerador de passwords do zero, percebi que o site onde encontrei o esquema já tinha o código que eu precisava. Gerei todos os passwords possíveis (total de fases * intervalo entre mínimo e máximo de pontos de vida * intervalo entre mínimo e máximo de tempo passado desde o início do jogo * possíveis estados de um bit arbitrário usado pra gerar o password). São 20 * 13 * 65536 * 2 possibilidades. Não faça as contas, são 34.078.720 passwords.

Agora só faltava encontrar uma agulha em um palheiro de 34 milhões de possibilidades. Essa foi a parte mais fácil. A Distância de Levenshtein é uma forma de medir a diferença entre duas sequências de caracteres onde cada remoção, adição ou substituição de um único caractere conta um ponto. Era pouco provável que Tarso tivesse confundido vários caracteres do password. A minha hipótese era que seria apenas um. Partindo desse pressuposto, escrevi um pequeno script que buscava e mostrava qualquer password que tivesse uma distância de Levenshtein de BQMZXY2 igual a 1.

Quando rodei o script a saída foi única e o resultado incontestável: BQMZQY2. Olhando praqueles sete caracteres na tela eu tinha a sensação de ter escrito código que devolvia a Tarso uma memória quase perdida. Em troca eu ganhava uma história pra contar.

4 comentários.

Deixe um comentário!





Seu comentário será exibido após moderação.
spinner Enviado! Ops... Verifique se todos os campos estão preenchidos e tente de novo.