ai
estávelPrimitivas de árvore de comportamento e blackboard para IA de jogos e tomada de decisão de agentes, com avaliação da árvore por ticks.
use plugin ai::{Blackboard.new, Blackboard.set, Blackboard.get, …} Os snippets podem ser editados no Playground, mas capacidades nativas são executadas localmente com a CLI do Zolo.
Funções (19)
- Blackboard.new Cria um blackboard compartilhado de chave e valor
- Blackboard.set Armazena um valor sob uma chave
- Blackboard.get Recupera o valor de uma chave
- Blackboard.has Verifica se uma chave existe
- Blackboard.remove Remove uma chave
- Blackboard.clear Remove todas as entradas
- Blackboard.keys Lista os nomes de todas as chaves
- Blackboard.to_table Converte o blackboard em uma tabela comum
- create_sequence Cria um nó composto de sequência
- create_selector Cria um nó composto seletor
- create_action Cria um nó folha de ação
- create_condition Cria um nó de condição baseado no blackboard
- create_parallel Cria um nó composto paralelo
- create_inverter Cria um nó decorador inversor
- create_repeater Cria um nó decorador repetidor
- create_succeeder Cria um decorador que sempre produz sucesso
- node_type Lê o tipo de um nó
- reset_tree Reinicia todos os estados da árvore
- tick_tree Avalia um tick da árvore de comportamento
Do import ao resultado
- 01Importe apenas o que usar
- 02Copie o menor exemplo
- 03Execute com a CLI do Zolo
Visão geral¶
O plugin ai reúne dois blocos clássicos da inteligência artificial para jogos e agentes: uma árvore de comportamento e um blackboard. Os nós são tabelas criadas pelos construtores create_* e combinadas em uma árvore. O blackboard é um armazenamento de chave e valor com estado, consultado pelos nós folha durante a avaliação. Cada chamada de tick_tree percorre a árvore uma vez e devolve um de três estados — "success", "failure" ou "running".
Os nós folha são controlados inteiramente pelo blackboard. Um nó condition verifica se o valor da chave é verdadeiro; um nó action converte true em "success", false em "failure", preserva uma string como resultado e trata uma chave ausente como "running". Nós compostos (sequence, selector, parallel) e decoradores (inverter, repeater, succeeder) combinam esses resultados. Como os nós são tabelas, você pode inspecioná-los com node_type e reiniciar o estado com reset_tree.
Padrões comuns¶
Montar e avaliar uma árvore¶
Combine os construtores, prepare o blackboard e execute um tick. O estado final reflete como as folhas foram resolvidas.
use plugin ai::{Blackboard, create_sequence, create_condition, create_action, tick_tree}
let bb = Blackboard.new()
bb.set("enemy_visible", true)
bb.set("attack", true)
let tree = create_sequence([
create_condition("enemy_visible"),
create_action("attack")
])
print(tick_tree(tree, bb))Criar um caminho alternativo¶
Um seletor tenta cada filho até encontrar um que tenha sucesso. É o padrão ideal para “faça A; se não der certo, faça B”.
use plugin ai::{Blackboard, create_selector, create_action, tick_tree}
let bb = Blackboard.new()
bb.set("open_door", false)
bb.set("break_window", true)
let plan = create_selector([
create_action("open_door"),
create_action("break_window")
])
print(tick_tree(plan, bb))Reavaliar entre frames¶
Reinicie o estado dos nós antes de uma nova avaliação e altere o blackboard a cada frame para conduzir o agente.
use plugin ai::{Blackboard, create_sequence, create_action, tick_tree, reset_tree}
let bb = Blackboard.new()
let tree = create_sequence([create_action("patrol"), create_action("rest")])
bb.set("patrol", true)
bb.set("rest", "running")
print(tick_tree(tree, bb))
let tree = reset_tree(tree)
bb.set("rest", true)
print(tick_tree(tree, bb))Cria um blackboard compartilhado de chave e valor
Cria um blackboard vazio e compartilhado. Passe o handle retornado a tick_tree; ele será a fonte de verdade consultada pelos nós folha.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("is_hungry", true)
bb.set("eat", true)Armazena um valor sob uma chave
Armazena value sob key, substituindo a entrada anterior. O valor pode ser qualquer valor Zolo, mas ações e condições interpretam booleanos e strings de forma especial.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("health", 80)
bb.set("alert", true)
bb.set("state", "running")Recupera o valor de uma chave
Retorna o valor armazenado sob key, ou nil quando a chave não existe.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("health", 80)
print(bb.get("health"))
print(bb.get("mana"))Verifica se uma chave existe
Retorna true quando key existe no blackboard e false caso contrário.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("target", "goblin")
print(bb.has("target"))
print(bb.has("ally"))Remove uma chave
Remove key do blackboard. A operação não produz erro quando a chave está ausente.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("stunned", true)
bb.remove("stunned")
print(bb.has("stunned"))Remove todas as entradas
Remove todas as entradas e devolve o blackboard ao estado vazio.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("a", 1)
bb.set("b", 2)
bb.clear()
print(bb.has("a"))Lista os nomes de todas as chaves
Retorna um array com os nomes das chaves atuais. A ordem não é especificada.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("hp", 100)
bb.set("ammo", 30)
for key in bb.keys() {
print(key)
}Converte o blackboard em uma tabela comum
Converte o blackboard em uma tabela comum que associa cada chave ao valor armazenado. É útil para depuração e serialização.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("hp", 100)
bb.set("aware", true)
let snapshot = bb.to_table()
print(snapshot["hp"])
print(snapshot["aware"])Cria um nó composto de sequência
Cria uma sequência que avalia os filhos da esquerda para a direita. Ela só produz "success" quando todos têm sucesso e interrompe no primeiro resultado diferente.
use plugin ai::{create_sequence, create_action, Blackboard, tick_tree}
let bb = Blackboard.new()
bb.set("find_target", true)
bb.set("move_to_target", true)
let seq = create_sequence([create_action("find_target"), create_action("move_to_target")])
print(tick_tree(seq, bb))Cria um nó composto seletor
Cria um seletor que avalia os filhos da esquerda para a direita e produz "success" assim que um deles tem sucesso. Só produz "failure" quando todos falham.
use plugin ai::{create_selector, create_action, Blackboard, tick_tree}
let bb = Blackboard.new()
bb.set("use_door", false)
bb.set("break_window", true)
let sel = create_selector([create_action("use_door"), create_action("break_window")])
print(tick_tree(sel, bb))Cria um nó folha de ação
Cria uma ação folha. Durante tick_tree, o valor da chave name define o estado: true vira "success", false vira "failure", uma string é devolvida diretamente e qualquer outro valor vira "running".
use plugin ai::{create_action, Blackboard, tick_tree}
let bb = Blackboard.new()
bb.set("attack", "running")
let node = create_action("attack")
print(tick_tree(node, bb))Cria um nó de condição baseado no blackboard
Cria uma condição folha que consulta key. Um valor verdadeiro produz "success"; false, nil ou uma chave ausente produzem "failure".
use plugin ai::{create_condition, Blackboard, tick_tree}
let bb = Blackboard.new()
bb.set("enemy_visible", true)
let cond = create_condition("enemy_visible")
print(tick_tree(cond, bb))Cria um nó composto paralelo
Cria um nó que avalia todos os filhos a cada tick. success_threshold define quantos filhos precisam ter sucesso; o padrão -1 exige todos.
use plugin ai::{create_parallel, create_action, Blackboard, tick_tree}
let bb = Blackboard.new()
bb.set("shoot", true)
bb.set("dodge", false)
let par = create_parallel([create_action("shoot"), create_action("dodge")], 1)
print(tick_tree(par, bb))Cria um nó decorador inversor
Cria um decorador que troca "success" por "failure" e vice-versa. O estado "running" não é alterado.
use plugin ai::{create_inverter, create_condition, Blackboard, tick_tree}
let bb = Blackboard.new()
bb.set("is_safe", false)
let inv = create_inverter(create_condition("is_safe"))
print(tick_tree(inv, bb))Cria um nó decorador repetidor
Avalia o filho até max_repeats vezes por tick (o padrão é 1) e devolve o último resultado. A repetição para cedo quando o filho está em "running".
use plugin ai::{create_repeater, create_action, Blackboard, tick_tree}
let bb = Blackboard.new()
bb.set("patrol_step", true)
let rep = create_repeater(create_action("patrol_step"), 3)
print(tick_tree(rep, bb))Cria um decorador que sempre produz sucesso
Cria um decorador que sempre devolve "success", independentemente do resultado do filho. Use-o para impedir que uma etapa opcional interrompa uma sequência.
use plugin ai::{create_succeeder, create_action, create_sequence, Blackboard, tick_tree}
let bb = Blackboard.new()
bb.set("optional_pickup", false)
bb.set("continue_patrol", true)
let seq = create_sequence([
create_succeeder(create_action("optional_pickup")),
create_action("continue_patrol")
])
print(tick_tree(seq, bb))Lê o tipo de um nó
Retorna o tipo do nó como string: "sequence", "selector", "action", "condition", "parallel", "inverter", "repeater" ou "succeeder". Retorna nil se a tabela não tiver o campo type.
use plugin ai::{create_action, node_type}
let node = create_action("jump")
print(node_type(node))Reinicia todos os estados da árvore
Reinicia recursivamente o campo status de todos os nós para "ready" e devolve a árvore. Faça isso antes de recomeçar a avaliação em outro frame.
use plugin ai::{create_sequence, create_action, reset_tree, node_type}
let tree = create_sequence([create_action("step1"), create_action("step2")])
let tree = reset_tree(tree)
print(node_type(tree))Avalia um tick da árvore de comportamento
Avalia um tick da árvore enraizada em node com o blackboard informado. É o ponto de entrada que percorre nós compostos, decoradores e folhas e devolve "success", "failure" ou "running".
use plugin ai::{Blackboard, create_sequence, create_condition, create_action, tick_tree}
let bb = Blackboard.new()
bb.set("target_found", true)
bb.set("move", true)
let tree = create_sequence([
create_condition("target_found"),
create_action("move")
])
print(tick_tree(tree, bb))