Início › Info de modding › Criar um cérebro
Capítulo 07

Criar um cérebro

Um .oabrain que joga num lugar de computador: a pasta, cada chave do manifesto, as tags, os níveis, a visão total, onde o script roda, as cotas e o que acontece quando ele para.

Este capítulo resume docs/brains/oabrain-standard.md, docs/brains/authoring.md e docs/playing-with-brains.md. Esses documentos são o texto normativo.

O que é um cérebro

O computador do próprio motor continua sendo o padrão e continua no motor. Um cérebro joga num lugar de computador, e só num lugar que um jogador definiu para ele. Um ID de cérebro vazio é esse jogador integrado. Um lugar sem cérebro, um cérebro que não serve e um cérebro que para são todos jogados por esse mesmo jogador. Classic é escrito em Lua e joga como esse jogador. Ele é a documentação desse jogador, não um substituto.

Só a máquina que põe o computador no lugar roda o script, então os outros jogadores não precisam instalar nada. As máquinas deles espelham as unidades do lugar. Uma gravação reproduzida não roda o script. Um cérebro é código-fonte Lua e dados. Ele não tem código nativo, arquivo, rede nem relógio. A visão total é uma flag do manifesto. Um cérebro pode defini-la e pode jogar com ela numa partida em rede, e o lugar mostra a flag.

O pacote

Um cérebro é um arquivo .oabrain, ou a pasta em que esse arquivo se descompacta. O manifesto usa o YAML estrito de um perfil de mod: um documento, um mapeamento de nível superior, sem âncoras e sem escalares de bloco. O topo do pacote contém oabrain.yaml. Ao lado dele, cada arquivo é um destes. Um arquivo fora dessa lista é recusado.

my-brain.oabraino arquivo que um jogador obtém├─ oabrain.yamlobrigatório o manifesto, no máximo 256 KiB├─ brain.luao script de entrada. O nome padrão é brain.lua. entry indica outro, e esse arquivo precisa estar no pacote├─ lua/mais código-fonte Lua. require só lê estes arquivos. Cada parte tem letras minúsculas, dígitos e _├─ nets/uma rede que o manifesto cita, nets/ e um nome-base terminado em .oann├─ data/uma tabela de dados, a uma pasta de profundidade: .csv, .tdf, .json ou .txt├─ icon.pnga imagem, só quando icon a indica. Sem essa chave, o arquivo fica fora da lista├─ README.mduma nota no topo. O jogo não a carrega└─ LICENSEa licença no topo. O nome licence, e um readme numa subpasta, ficam fora da lista

A comparação ignora maiúsculas e minúsculas nas letras ASCII, exceto onde o padrão diz que os bytes precisam coincidir. brain.lua fica fora da lista quando entry indica outro arquivo. Um arquivo Lua tem no máximo 1 MiB. O ícone é um PNG quadrado, com no máximo 256 pixels de lado e 256 KiB. O OA instala um cérebro em Brains/ seguido do ID do manifesto.

O manifesto

O leitor reúne todas as regras violadas e deixa o manifesto inalterado quando alguma é violada. Uma chave que o padrão não lista é recusada. Uma chave de perfil pertence a um mod. Uma chave de mutador é recusada como chave de mutador. Ponha a versão entre aspas, porque um 1.0 solto é um número, e ponha o asterisco entre aspas, porque um asterisco solto é um alias de YAML.

ChaveObrigatórioO que faz
oabrainsimO formato. O inteiro 1. 1.0 e um 1 entre aspas são recusados.
idsimKebab-case em minúsculas, de 1 a 64 bytes. Sem hífen no início, no fim ou duplicado. O nome da pasta em Brains/.
namesimDe 1 a 64 bytes, sem caractere de controle. O nome que os jogadores veem.
versionsimEntre aspas, de uma a três partes, como uma versão de mutador, por exemplo "2.0". Um número simples é recusado. 2, 2.0 e 2.0.0 são considerados iguais.
authorsimUm mapeamento. name é obrigatório, de 1 a 128 bytes. email é opcional.
descriptionsimObrigatória, de 1 a 2.000 bytes. Quebra de linha é permitida. Qualquer outro caractere de controle é recusado. A primeira linha, cortada em 200 bytes, é o resumo.
homepagenãoUm endereço http ou https.
iconnãoSó icon.png, a imagem no topo do pacote. Qualquer outra coisa é recusada.
tagssimDe 1 a 4 das nove tags abaixo, sem repetição.
works-withsimDe 1 a 32 condições, sem ID repetido. Um asterisco significa qualquer mod e o jogo base, e então é a única entrada. ta-3.1c significa o jogo base sem mod. Qualquer outro ID é um mod, com uma faixa de versões opcional.
requiresnãoSó engine e expansions. engine é uma faixa, entre aspas quando começa com o sinal de maior. expansions tem de 1 a 16 IDs de conjunto de conteúdo. Um cérebro não pode exigir um mutador.
levelssimDe 1 a 6 níveis. Cada mapeamento tem exatamente id, name e difficulty.
fullAwarenessnãotrue ou false. Se ausente, vale false. Um true entre aspas é recusado.
networksnãoDe 1 a 16, cada uma com exatamente id, file e sha256. file é nets/ e um nome-base terminado em .oann. sha256 são 64 dígitos hexadecimais minúsculos entre aspas.
optionsnãoNo máximo 16, com as regras de opção do mutador. Uma opção toggle é true ou false, uma number é um número, e uma choice é o seu texto. me.options as lê.
stringsnãoNo máximo 16 idiomas. Um idioma pode conter name, description, options, labels e levels.
entrynãoUm arquivo Lua no topo do pacote, com nome em letras minúsculas, dígitos e _. Se ausente, vale brain.lua.

As nove tags

Uma tag é uma destas nove, comparada byte a byte. Mais de quatro, quando a regra comum de tags já passou, é um problema à parte. Uma tag que não é uma das nove é recusada.

Chave
classic
economy
rush
turtle
air
naval
learned
teaching
experimental

Níveis e dificuldade

levels é uma lista de 1 a 6 mapeamentos. Cada um tem exatamente id, name e difficulty, todos obrigatórios. id é kebab-case em minúsculas, de 1 a 32 bytes, e nenhum id se repete. name tem de 1 a 64 bytes, sem caractere de controle. difficulty é easy, medium ou hard, byte a byte.

Esses três nomes são os valores 0, 1 e 2. Um lugar que escolhe o nível usa esse valor como regra de renda, a mesma dificuldade que o jogo já usa.

Visão total

fullAwareness é true ou false. Se ausente, vale false. Um cérebro com a flag vê unidades que um lugar na névoa não veria, como faz o computador integrado, e suas verificações de local de construção não precisam de um jogador posicionando a construção. A flag é permitida numa partida em rede. A Biblioteca mostra Vê todas as unidades do mapa, como o computador do próprio Total Annihilation. A flag é do próprio manifesto. Ela não é concedida pelo ID do pacote, e não é uma das coisas que só o Classic recebe.

Onde um cérebro roda

Só a máquina que põe o computador no lugar precisa do pacote, e só ela roda o script. Um lugar é um jogador do computador desta máquina. Um lugar humano é recusado. game.mode é skirmish, campaign ou network.

SituaçãoO que roda
EscaramuçaCada lugar de computador que esta máquina joga, quando um jogador definiu um cérebro nele. Um ID vazio é o computador integrado.
Missão de campanhaO lugar da campanha segue o cérebro padrão que o jogador definiu. Uma missão não ignora esse padrão.
Partida em redeA máquina dona do lugar de computador roda o cérebro, inclusive com visão total. As outras máquinas não rodam.
Jogo salvo carregado depoisO jogo salvo registra cada lugar. O padrão diz o que acontece quando o pacote está faltando ou a versão é diferente.
Gravação reproduzidaA gravação guarda o texto dos cérebros. A reprodução aplica os pacotes de rede gravados. Ela não põe nenhum cérebro num lugar e não chama seus hooks.
Deathmatch ou torneioO início da partida não põe nenhum jogador do computador.

O cérebro que um lugar usa não entra no hash da simulação. Duas partidas que diferem só no cérebro escolhido mantêm o mesmo hash do estado da partida. Os valores dos ajustes ai.* do mod fazem parte do perfil do mod que esse hash cobre, então eles continuam chegando a todas as máquinas.

As cotas de execução

Um cérebro roda como Lua num sandbox. Dois cérebros não compartilham módulos, globais nem cotas. O script não tem arquivo, relógio, ambiente, processo nem rede. Todo trecho é carregado como texto. pcall e xpcall não conseguem manter viva uma fase esgotada. Um turno é uma chamada que consome da reserva, no ponto de controle do lugar, depois da varredura de unidades. As ordens que um hook dá valem no tick seguinte.

CotaValor
Instruções em load, fits, start, save e report50,000,000
Instruções que cada tick acrescenta2,000,000
Ticks que a reserva pode acumular, incluindo o atual30, então o saldo começa em 60,000,000
Memória do Lua64 MiB (67,108,864 bytes). Ela não é zerada entre as fases.
Memória das redes64 MiB, separada do teto do Lua
Tempo real de uma fase que não é um turno, em milissegundos10,000
Tempo real de um turno, em milissegundos250
Uma string, em bytes65,536

Quando um cérebro falha

Um cérebro para por um erro num hook ou num timer, uma cota de instruções esgotada, o limite de segurança de tempo real, o teto de memória do Lua, uma string além de 65.536 bytes ou um carregamento que o lugar recusa. Um turno que falha fecha o sandbox e limpa os hooks antes de esse turno retornar. O turno que falhou ainda conta como jogado. O tick de ordens seguinte não tem hooks, então o computador integrado assume. Um cérebro recusado, que não consegue iniciar ou que não serve nunca tem hooks, então esse jogador joga desde o começo. O aviso usa o nome do manifesto e o motivo, cortado em 160 bytes:

- `{brain} stopped ({reason}); the engine plays this seat on`
- `{brain} could not start ({reason}); the engine plays this seat`
- `{brain} does not fit this game ({reason}); the engine plays this seat`

Quando o lugar não tem um motivo próprio, o motivo é the brain could not be seated. Um jogador derrotado simplesmente deixa de ser chamado. O sandbox fecha junto com a partida.