Recarregando o Design de Jogo a Quente Como Código
A maioria dos engines entrega binários opacos. O RakuAI entrega texto que você pode comparar por diff, revisar, e recarregar a quente — com o sistema nervoso de IA endereçável bem ali no arquivo. Essa escolha é o que permite que um time inteiro de agentes construa ao seu lado.
Fim de semana de formato de arquivo. IA é um primitivo de runtime neste engine, não um recurso encaixado ao lado dele. Esse é o argumento arquitetural que já fiz antes. Este post é sobre o formato de arquivo que torna isso concreto.
Se você constrói um jogo na maioria dos engines, o artefato que você entrega é um binário, um pacote de projeto, um banco de dados de assets, ou alguma combinação dos três. O que você autora vive dentro de um editor proprietário. O que você entrega é opaco às ferramentas que seu time já usa. Comparar duas versões de uma experiência por diff significa abrir o mesmo editor duas vezes e esperar que o changelog seja honesto.
Nós tomamos o outro caminho. Uma experiência do RakuAI é um arquivo .raku. O arquivo é JSON. Você pode abri-lo em qualquer editor. Você pode comparar duas versões por diff em qualquer ferramenta de revisão de código. Você pode validá-lo contra um schema. Você pode versioná-lo no git. Você pode revisá-lo em um PR. Você pode recarregá-lo a quente. Você pode escrever uma experiência à mão se quiser.
O formato de arquivo não é glamouroso. Ele sustenta a estrutura.
Como é um arquivo .raku real
Aqui está uma definição de jogo real, reduzida para o post:
{
"schema_version": "1.0",
"game": {
"title": "My Space Shooter",
"genre": "space_shooter",
"template": "space_shooter",
"mode": "prototype",
"max_players": 1
},
"ai": {
"dda_enabled": true,
"target_flow_state": 0.7,
"profiler_mode": "active",
"emotional_tracking": true,
"adaptive_music": true
},
"entities": [
{
"type": "player_ship",
"health": 100,
"shield": 80,
"speed": 22.0,
"fire_rate": 0.09
},
{
"type": "enemy_wave",
"count": 8,
"health": 15,
"ai_behavior": "strafe",
"properties": { "enemy_id": "interceptor" }
},
{
"type": "boss",
"health": 500,
"ai_behavior": "boss_pattern"
}
]
}
Isso é a maior parte de uma experiência. Um cabeçalho versionado por schema. Um bloco game com os metadados de superfície. Um bloco ai com a configuração de IA do runtime. Um array entities descrevendo o que está no mundo e como cada entidade se comporta.
Algumas coisas que vale a pena apontar.
O bloco ai é o contrato do runtime
Olhe para esta parte de novo:
"ai": {
"dda_enabled": true,
"target_flow_state": 0.7,
"profiler_mode": "active",
"emotional_tracking": true,
"adaptive_music": true
}
É aqui que o arquivo diz “o sistema nervoso de IA está ligado.” Não “peça ao GPT para me escrever um nível.” Ligado. Na camada de runtime, a cada quadro, enquanto o jogador está jogando.
dda_enabled liga o ajuste dinâmico de dificuldade. O runtime perfila o que o jogador está fazendo e remodela encontros em tempo real. target_flow_state: 0.7 é a faixa de dificuldade que o runtime mira. profiler_mode: "active" diz que a IA está lendo o comportamento do jogador, não apenas amostrando-o. emotional_tracking e adaptive_music são a mesma ideia aplicada a outros subsistemas.
Um engine de padrão fábrica não poderia ter esses controles no nível do arquivo. Não há IA de runtime para o arquivo endereçar. No nosso engine, esses controles são como um autor diz ao sistema nervoso que tipo de experiência ser.
Você pode revisar esse bloco em um PR. Você pode fazer teste A/B com dois valores na CI. Um produtor que nunca viu um editor pode ler isso e ter uma conversa com a engenharia sobre o que significa um estado de fluxo alvo. O formato de arquivo torna a decisão de design visível.
O comportamento de IA por entidade é uma string, não uma integração
Cada entidade no arquivo pode carregar um campo ai_behavior:
{
"type": "enemy_wave",
"count": 8,
"ai_behavior": "strafe"
}
"strafe" não é uma invocação de modelo. É um comportamento registrado no runtime que a camada de sistema nervoso conduz. A mesma entidade pode ser "patrol" ou "boss_pattern" ou qualquer outra coisa que o runtime saiba fazer. O arquivo não importa um modelo. Ele endereça uma capacidade.
É assim que você desacopla o formato de arquivo de um modelo específico. O autor escreve a intenção. O runtime decide qual modelo, quais pesos, qual fallback determinístico usar para entregar essa intenção. Troque o modelo no próximo trimestre e os arquivos .raku não mudam.
Essa separação importa mais do que parece. Todo time com quem conversei que fixou um LLM específico em um engine teve que refazer a integração quando o fornecedor do modelo mudou. Nós não temos.
Por que JSON
Essa é a pergunta que mais recebo quando mostro o formato de arquivo. Por que JSON e não uma DSL personalizada com uma sintaxe mais bonita para expressões matemáticas e scripting inline e bindings reativos?
Três razões.
Um: toda ferramenta já fala JSON. Revisão de código. Ferramentas de diff. Controle de versão. Linters. Validadores de schema. Pipelines de CI. Análise estática. Todo editor em toda plataforma. Não tivemos que construir nada disso. Ganhamos de graça.
Dois: humanos leem JSON bem o suficiente. O arquivo acima não é bonito, mas um designer sênior consegue lê-lo sem treinamento. Compare isso a uma DSL que leva uma semana para aprender antes que qualquer um consiga revisar um PR.
Três: assistentes de IA leem JSON extremamente bem. Esse importa mais em 2026 do que importava três anos atrás. Quando um designer pede a um assistente de IA para “deixar o chefão parecendo mais assustador,” o assistente pode ler o arquivo, propor um diff, e o humano pode aceitar ou rejeitar o diff. Uma DSL personalizada exigiria ensinar a todo assistente uma gramática nova.
O custo é real. JSON é verboso. Não tem matemática inline, comentários, ou abreviações. Abrimos mão de expressividade em troca de onipresença de ferramental. Até agora a troca se pagou muitas vezes.
O que isso viabiliza
Algumas coisas mudam uma vez que sua experiência é texto.
Revisão de PR para design de jogo. Um designer muda target_flow_state de 0.7 para 0.5. A mudança aparece como um diff de uma linha em um pull request. Engenharia e design revisam a mudança juntos. A conversa no PR é um registro de por que a experiência joga do jeito que joga. Seis meses depois, quando alguém pergunta por que a curva de dificuldade parece do jeito que parece, a resposta está no log de commits.
CI para experiências. Um arquivo .raku falha na validação de schema. O build falha antes da mudança ser entregue. A mesma CI que roda seus testes de unidade roda suas definições de experiência.
Recarga a quente. O arquivo muda no disco. O runtime percebe. O mundo se atualiza sem um reinício. O loop de desenvolvimento se aperta para segundos.
Reversão. Uma mudança quebrou a luta contra o chefão. Reverta o commit. A experiência reverte. Nenhum editor, nenhuma reconstrução de asset, nenhuma volta de uma semana.
Autoria por IA. Um membro do time descreve o que quer em linguagem natural. Um assistente de IA escreve o diff do .raku. Um revisor humano aprova. O diff é auditável, versionável, e cai sob a mesma disciplina de revisão que qualquer outra mudança de código.
Essas não são capacidades exóticas. São o que todo time de software moderno considera garantido para o resto da sua base de código. Nós as estendemos ao design de jogo.
O que é difícil
Os custos honestos.
JSON não tem comentários. Compensamos com arquivos .md auxiliares para a intenção de design e com nomes de campo descritivos, mas é um atrito real.
O schema precisa evoluir com cuidado. Passamos de schema_version: 1.0 para 2.0 uma vez quando a geração de mundo cresceu além da forma original. Todo arquivo existente no mundo real precisou de um caminho de migração. Esse trabalho faz parte do serviço, e não é de graça.
Há a tentação de continuar adicionando campos. Resistimos a isso com mais força do que parece. Todo campo adicionado é um contrato que o runtime precisa honrar para sempre. A tendência é manter o arquivo pequeno e colocar a complexidade no runtime, não no arquivo.
E finalmente: definições de experiência baseadas em texto só importam se o runtime realmente faz algo interessante com elas. O formato de arquivo é subordinado à decisão arquitetural por trás dele. Se o engine trata IA como uma fábrica de conteúdo, o arquivo é só um manifesto. Se o engine trata IA como um primitivo de runtime, o arquivo é a partitura.
Se você quiser ler o formato de ponta a ponta, o schema vive na documentação pública e os arquivos de exemplo são entregues no repositório. Abra um. Leia como código, porque é isso que ele é.
Dois dias de trabalho em formato de arquivo no banco. De volta ao engine no próximo fim de semana.
Autore experiências que sua IA consegue ler e escrever
O RakuAI trata IA como um primitivo de runtime e experiências como código. Abra o formato .raku, compare por diff, recarregue a quente — e deixe seu assistente construir no mundo real com você.