Undertale In Extremis
TeX

Undertale In Extremis

Project for Computer Organization (Organização de Computadores). Undertale-like Assembly Risc-V RPG battle simulator.

Projeto universitário (ORG 2026.1). Um simulador de combate de RPG e um mecanismo de Monte Carlo escritos inteiramente em linguagem de montagem RISC-V.

A Configuração

Criei um mecanismo de combate de RPG do zero em linguagem assembly RISC-V. O objetivo era escrever três máquinas de estados de IA distintas, colocá-las em um emulador sem interface gráfica e executar 10.000 partidas automatizadas para ver qual estratégia saía vencedora.

O combate gira em torno de uma economia de ação rigorosa. O MP se regenera lentamente, mas pode ser recarregado usando habilidades específicas.

Habilidade Custo O que faz
Ataque gratuito Lança um 1d20. < 10 erra, 10+ acerta, 20 causa dano crítico com o dobro do dano.
Defesa gratuito Bloqueia o dano recebido. Resultados altos acionam um contra-ataque.
Determinação Absoluta 20 MP Ignora o dado para garantir um acerto crítico.
Sugador de Almas grátis O lançador sofre 1–12 de dano de recuo, drena a mesma quantidade do MP do inimigo e ganha 4× essa quantidade para si mesmo. A única maneira de contornar o limite de 100 MP.
Execução Final 150 MP Um ataque nuclear com 800% de dano. Falha se o alvo estiver com mais de 50% de HP.
Escudo Espelhado 30 MP Reflete o próximo ataque recebido de volta para o atacante.

Os Concorrentes

Escrevi três bots, cada um com uma lógica completamente diferente:

Flowey (O Caos): Puro RNG. Ele não avalia nada e apenas gera um número aleatório para escolher seu próximo movimento.

decision_random:
  li a0, 6
  call randomizer  # escolhe um número entre 1 e 6, essa é toda a estratégia
  j decision_end

Chara (A Esforçada): Ela otimiza para um combo: usar Soul Suck repetidamente até atingir 150 MP, reduzir o HP do inimigo para menos de 50% e lançar o Final Execution. No código, a estratégia também é chamada de “inteligente”, mas não é bem assim.

decision_smart:
  # eu escrevi essa estratégia
  # ela consiste em usar *Soul Suck* até poder usar *Final Execution*
  # só que, para isso, também precisamos sobreviver e reduzir a vida do inimigo para 50%
  # sem morrer
  ...
  li t6, 150 # custo do execute
  blt t4, t6, decision_smart_my_mana_is_low   # MP < 150? ir farmar
  bge a2, t6, decision_smart_enemy_hp_high    # HP do inimigo > 50? ir atacar
  j decision_smart_i_can_kill # caso contrário, executar

decision_smart_my_mana_is_low:
  li a0, 4  # sugar alma
decision_smart_enemy_hp_high:
  li a0, 2  # determinação absoluta
decision_smart_i_can_kill:
  li a0, 5  # execução final

Toby (O Contra-ataque): Criado especificamente para farmar Chara. Ele observa tanto sua própria barra de HP quanto a barra de MP do inimigo. Se ele estiver com menos de 50 HP e o inimigo tiver 150 MP, ele levanta seu Escudo Espelhado e deixa o ataque nuclear voltar. Fora dessa janela, ele alterna entre ataques e Sugação de Alma, e também pode disparar a Execução Final ele mesmo quando as condições se alinharem.

decision_troll_checks:
  li t6, 50
  ble t5, t6, decision_troll_check_enemy_mp  # estou com HP baixo o suficiente para me preocupar?
  j decision_troll_not_execute
decision_troll_check_enemy_mp:
  li t6, 150
  bge a3, t6, decision_troll_prepare_against_execute  # o inimigo está perto de 150 mp?
  j decision_troll_not_execute
decision_troll_prepare_against_execute:
  li a0, 6  # escudo espelhado
  ret

Os resultados do benchmark

Após executar 10.000 partidas no Terminal usando o rars.jar, o arquivo jar do simulador RARS baseado em Java para Risc-V, os resultados foram obtidos.

Personagem Taxa de vitórias
Flowey ~52%
Toby ~29%
Chara ~17%

A IA mais burra venceu a maioria absoluta das partidas.

A taxa de vitórias de 17% de Chara expõe o problema com combos rígidos e gananciosos. Para atingir 150 MP, ela precisa sofrer dano de recuo do Soul Suck. Muitas vezes, Toby simplesmente levanta o escudo, e o script de Chara a força a continuar drenando sua própria vida até que ela literalmente se mate antes mesmo de conseguir lançar sua ultimate.

Os 29% de Toby vêm de ter conseguido atrair Chara com sucesso. Contra Flowey, a história é diferente: a condição do escudo exige que o inimigo esteja perto de 150 MP, e Flowey nunca se prepara deliberadamente para isso. O contra-ataque nunca é acionado, então Toby simplesmente joga seu estilo padrão de atacar e sugar almas, o que não lhe dá nenhuma vantagem real sobre o caos.

Flowey venceu 52% das vezes porque não ter estratégia torna impossível antecipar suas jogadas de forma consistente. Ele nunca sofre dano de recuo ao tentar montar uma jogada massiva; ele simplesmente lança jogadas de alto valor por acidente. Acontece que, se toda a sua base de código depende de prever o comportamento do inimigo, você perde automaticamente para um inimigo que faz coisas sem motivo.

Isso é realmente surpreendente?

Provavelmente não. Agentes aleatórios dominando os determinísticos é um resultado bem documentado em simulações de estratégia.

Uma simulação do Citadel que encontrei em um grupo de estudo produziu o mesmo padrão: algumas estratégias venciam consistentemente o aleatório, outras eram esmagadas por ele, e outras ainda venciam certos oponentes, mas perdiam para outros. A dinâmica de pedra, papel e tesoura estava presente, mas o aleatório ainda se mantinha firme contra a maioria delas.

A diferença é que, em um ambiente mais rico (mais estratégias, mais variáveis de decisão, mais maneiras de um agente inteligente explorar um aleatório), os resultados tendem a se dispersar mais. Uma estratégia determinística bem ajustada pode conquistar uma vantagem confiável se o espaço de ação lhe der o suficiente para trabalhar.

Aqui, provavelmente não é o caso. Com apenas seis ações possíveis e um sistema de combate em que um único golpe crítico de sorte pode encerrar a partida independentemente da estratégia, a diferença entre o planejamento cuidadoso de Chara e o apertar aleatório de botões de Flowey simplesmente não é tão grande. O combo de Chara requer várias rodadas de preparação, e o RNG tem ampla oportunidade de matá-la antes que ela chegue lá. O espaço de ação pode simplesmente ser pequeno demais e instável demais para que uma estratégia ambiciosa supere consistentemente o caos.

Em outras palavras: a vitória de Flowey é menos uma descoberta e mais uma restrição de design. Uma Chara mais inteligente precisaria de um jogo mais inteligente para provar isso.

Por que esses números não são totalmente confiáveis

Antes de tirar conclusões do benchmark, há alguns vieses estruturais que vale a pena reconhecer.

Os confrontos não são isolados. Ambos os jogadores recebem uma estratégia atribuída aleatoriamente a cada partida, o que significa que as taxas de vitória são agregadas entre todos os pares possíveis, não estatísticas 1v1 puras. Os 52% de Flowey incluem partidas em que Flowey lutou contra outro Flowey, e nessas uma das partes tinha que vencer. Para saber de fato se Chara vence Toby ou se Flowey vence todos igualmente, seria necessário fixar o confronto e executar cada emparelhamento separadamente.

A ordem dos turnos nunca é alternada. O jogador 1 sempre joga primeiro. Em um sistema onde um único golpe crítico pode encerrar uma partida, jogar primeiro é uma vantagem real. Os resultados não levam isso em conta de forma alguma.

O RNG é um xorshift personalizado com semente baseada na hora do sistema. Funciona bem o suficiente para um projeto universitário, mas não é um gerador validado estatisticamente. Se a distribuição dos resultados for desigual entre as 6 ações possíveis, os resultados de Flowey são diretamente afetados, já que toda a sua estratégia consiste apenas em chamar essa função.

O espaço de ação é muito pequeno. Seis ações possíveis significam que qualquer estratégia tem espaço limitado para se diferenciar do caos. Em um sistema mais complexo, o combo de Chara poderia ser mais difícil de interromper, ou poderia haver opções de recuperação que reduzissem o custo de sua preparação. Aqui, o jogo é punitivo o suficiente para que o dano de recuo dela frequentemente encerre a jogada antes que a recompensa chegue.

Chara provavelmente não foi projetada de forma adequada. Sua estratégia não possui um plano B defensivo. Se as condições do combo não forem atendidas e ela estiver sofrendo dano pesado, ela simplesmente continua acumulando MP de qualquer maneira. Uma versão mais robusta mudaria para o modo de sobrevivência quando estivesse abaixo de um certo limite de HP, o que provavelmente melhoraria significativamente seus números.

Os resultados são direcionalmente interessantes, mas devem ser interpretados como um instantâneo dessa configuração específica, não como uma afirmação geral sobre estratégia versus aleatoriedade.

Pesquisas Futuras

O próximo passo óbvio é abandonar completamente o RARS. Esta versão roda em um emulador RISC-V baseado em Java, o que impõe um limite rígido à velocidade da simulação. Uma segunda versão voltada para RISC-V compilado de verdade com chamadas de sistema Linux em vez de chamadas ecalls do RARS deve ser drasticamente mais rápida, o que importa muito quando o número de partidas começar a chegar aos milhões.

Além do desempenho, as direções mais interessantes estão no lado do design:

Mais jogadores por partida. No momento, é sempre 1 contra 1. Adicionar um terceiro ou quarto participante muda completamente o panorama estratégico. De repente, uma contra-estratégia precisa levar em conta o fato de ser atacada de duas direções ao mesmo tempo, e a aleatoriedade pura se torna mais difícil de sustentar.

Aprendizado de máquina dentro da montagem. A ideia é implementar um algoritmo mínimo de ML diretamente no RISC-V, usando operações matriciais para permitir que um bot atualize seus próprios pesos com base nos resultados das partidas. Sem bibliotecas externas, sem tempo de execução de alto nível, apenas matemática matricial inteira nos registros. Se isso é prático ou apenas um desafio interessante de implementar faz parte do apelo.

Mais estratégias e um mecanismo mais profundo. O espaço de ação atual é pequeno demais para que qualquer estratégia consiga superar significativamente o acaso. Inspirar-se mais diretamente no World of Warcraft (tempos de recarga, trocas de recursos, efeitos de posicionamento, interações de habilidades mais variadas) daria a estratégias bem projetadas espaço real para provar seu valor em meio ao caos.

A infraestrutura de benchmark já está pronta. O gargalo é o jogo ser profundo o suficiente para que os resultados tenham significado.

Executando

Para compilar a montagem e executar o mecanismo localmente:

make simulate