A origem
A Ref 05 do Project Atlas é o estudo dirigido dos dois repositórios clonados pra camada
de IA de combate: LimboAI (decisão — behavior trees + máquina de estados hierárquica) e o
GDQuest Steering AI Framework (movimento — steering behaviors). O combate do Atlas é idle:
o Comandante decide, ninguém pilota — então a IA precisa executar doutrina (formação,
corrida de ataque, retirada justa), não improvisar como inimigo de FPS. Este laboratório pega o
vocabulário dos dois repos e o reimplementa do zero em JavaScript, num único HTML,
determinístico por seed — pra VER cada conceito funcionando, direto no browser.
As referências — e o que cada uma virou
O que é: framework de steering behaviors — a separação agente↔corpo (o behavior calcula aceleração desejada; quem integra no corpo é outra camada), behaviors individuais (Seek/Arrive/Pursue/Evade), composição por Blend/Priority e comportamento de grupo com Proximity.
Virou → modo 🎯 Steering: os 5 behaviors clássicos lado a lado sobre o mesmo alvo móvel — Seek persegue o ponto, Arrive assenta com desaceleração, Pursue lidera o alvo (predição), Evade foge com predição, Wander vagueia com passeio aleatório seeded. Cada nave devolve aceleração; a integração (velocidade, LookWhereYouGo) é camada separada, como no framework.
Virou → modo 🐦 Enxame: Cohesion + Separation + Alignment compostos por Blend com pesos em sliders, vizinhança por raio (o conceito de Proximity: "quem conta como meu grupo"). Os pesos são DADO calibrável — a mesma filosofia registry do canon do Atlas. A vizinhança é recalculada a cada tick, de propósito: o estudo achou que o GSAIRadiusProximity original cacheia por frame da SceneTree e mente em tick fora do _process (armadilha registrada na Ref 05 §6).
Virou → a cunha do modo 🛩️ Formação: Blend[Arrive(slot no referencial do líder), Separation(intra-esquadrão)] — a formalização exata do que o protótipo do Atlas (fatia 21) fazia imperativo.
O que é: addon de behavior trees + máquina de estados hierárquica (HSM) — tasks pequenos com contrato SUCCESS/FAILURE/RUNNING, blackboard com escopo, composites (dynamic selector, parallel, probability) e decorators (cooldown, run-limit, time-limit).
Virou → modo ⚔️ Batalha: cada esquadrão roda um HSM real — FORMAÇÃO → CORRIDA (reta, no ponto travado) → REAGRUPAR → … → RETIRADA — com os decorators como mecânica viva: cooldown entre corridas (BTCooldown), limite de investidas antes de retirar (BTRunLimit), e as alas mantendo a cunha EM PARALELO ao engajamento (BTParallel). O achado mais importante do estudo está aqui: as 4 fases da Operação do canon (Combat.md §1) SÃO um HSM com sub-árvore por fase.
Virou → pesos por facção como DADO (D-48): as duas facções da Batalha (Vermelha agressiva × Azul cautelosa) rodam a MESMA máquina com números diferentes (cooldown ×0.5 vs ×1.6, investidas +1 vs −1) — o padrão da escada de demos do LimboAI: um vocabulário pequeno de tasks + uma árvore por arquétipo, nunca código novo por inimigo.
O spike da cunha (Ref 05 §6) — o achado de design demonstrado ao vivo
O que foi: antes deste laboratório, um spike descartável em Godot 4.7 headless (com o addon GSAI real) mediu o custo da pilha decisão+steering: ~6 µs/nave/tick até ~200 naves — e descobriu de brinde que a ala com a MESMA velocidade do líder nunca fecha o gap do slot (erro estacionário de ~10,5 m).
Virou → o slider "margem de velocidade da ala" do modo Formação: com margem 0% o erro da cunha fica alto e constante; suba pra 10–20% e veja o erro cair — é o achado do spike reproduzido interativamente. O QA automatizado prova: erro médio 25,3px com 0% → 13,4px com 15%. No jogo real, ala precisa de margem de velocidade sobre o líder pra assentar no slot.
⚠️ O que de propósito NÃO está aqui: o Diretor da batalha (composição/drama/ondas) fica no
canon do Atlas (MissionDirector/BattleGeneration) — a Ref 05 é explícita:
nenhum repo substitui essa camada, e importar "diretor" de fora é anti-padrão. Este laboratório
cobre só as camadas 2 (decisão de esquadrão) e 3 (movimento).
O que saiu no fim
🎯 Steering
5 behaviors (Seek/Arrive/Pursue/Evade/Wander) sobre alvo móvel determinístico, com trilhas e rótulos.
🛩️ Formação
Líder em patrulha por waypoints (FollowPath) + alas em cunha via Blend[ArriveSlot, Separation]; slider de margem de velocidade com erro ala→slot medido ao vivo.
⚔️ Batalha
2 esquadrões × HSM (formação→corrida→reagrupar→retirada) com cooldown/limite de investidas; pesos por facção como dado, estados rotulados em tela.
🐦 Enxame
Até 300 boids com Coesão/Separação/Alinhamento em sliders e raio de Proximity ajustável.
Prova de que funciona (QA headless)
| Verificação | Resultado |
| 4 modos simulam 300+ ticks com física estável | OK |
| Determinismo: mesma seed ⇒ canvas idêntico após N ticks (hash de pixels) | OK nos 4 modos |
| Variação: seed diferente ⇒ simulação diferente | OK nos 4 modos |
| HSM transiciona nas 2 facções (60 s simulados) | OK (13 e 10 transições) |
| Achado do spike: margem 15% na ala reduz o erro da cunha | OK (25,3px → 13,4px) |
| Zero erros de JS · falha plantada detectada (selftest) | OK — 21/21 verde, local E no ar |
A suíte Playwright dirige a simulação tick a tick (sem depender de animação), compara
hashes de pixels e sabota a seed de propósito pra provar que o teste gritaria se o determinismo
quebrasse (regra do lab: vigia sem teste que força a falha é mentira verde). O primeiro QA
reprovou o teste do spike — o Arrive clássico não fecha slot móvel — e o fix (casamento de
velocidade do líder + correção) é exatamente a física que o spike previa.