ai
establePrimitivas de árbol de comportamiento y blackboard para IA de juegos y toma de decisiones de agentes, con evaluación del árbol por ticks.
use plugin ai::{Blackboard.new, Blackboard.set, Blackboard.get, …} Los snippets se pueden editar en el Playground, pero las capacidades nativas se ejecutan localmente con la CLI de Zolo.
Funciones (19)
- Blackboard.new Crea un blackboard compartido de clave y valor
- Blackboard.set Guarda un valor bajo una clave
- Blackboard.get Recupera el valor de una clave
- Blackboard.has Comprueba si existe una clave
- Blackboard.remove Elimina una clave
- Blackboard.clear Elimina todas las entradas
- Blackboard.keys Enumera los nombres de todas las claves
- Blackboard.to_table Convierte el blackboard en una tabla común
- create_sequence Crea un nodo compuesto de secuencia
- create_selector Crea un nodo compuesto selector
- create_action Crea un nodo hoja de acción
- create_condition Crea un nodo de condición basado en el blackboard
- create_parallel Crea un nodo compuesto paralelo
- create_inverter Crea un nodo decorador inversor
- create_repeater Crea un nodo decorador repetidor
- create_succeeder Crea un decorador que siempre produce éxito
- node_type Lee el tipo de un nodo
- reset_tree Reinicia todos los estados del árbol
- tick_tree Evalúa un tick del árbol de comportamiento
Del import al resultado
- 01Importa solo lo que uses
- 02Copia el ejemplo mínimo
- 03Ejecuta con la CLI de Zolo
Descripción general¶
El plugin ai reúne dos bloques clásicos de la inteligencia artificial para juegos y agentes: un árbol de comportamiento y un blackboard. Los nodos son tablas creadas por los constructores create_* y combinadas en un árbol. El blackboard es un almacén con estado de clave y valor que consultan los nodos hoja durante la evaluación. Cada llamada a tick_tree recorre el árbol una vez y devuelve uno de tres estados: "success", "failure" o "running".
Los nodos hoja se controlan por completo desde el blackboard. Un nodo condition comprueba si el valor de su clave es verdadero; un nodo action convierte true en "success", false en "failure", conserva una cadena como resultado y trata una clave ausente como "running". Los nodos compuestos (sequence, selector, parallel) y los decoradores (inverter, repeater, succeeder) combinan esos resultados. Como los nodos son tablas, puedes inspeccionarlos con node_type y reiniciar su estado con reset_tree.
Patrones habituales¶
Construir y evaluar un árbol¶
Combina los constructores, prepara el blackboard y ejecuta un tick. El estado final refleja cómo se resolvieron las hojas.
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))Crear una ruta alternativa¶
Un selector prueba cada hijo hasta que uno tiene éxito. Es el patrón ideal para “haz A; si falla, haz 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))Volver a evaluar entre frames¶
Reinicia el estado de los nodos antes de una nueva evaluación y modifica el blackboard en cada frame para dirigir al 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))Crea un blackboard compartido de clave y valor
Crea un blackboard vacío y compartido. Pasa el handle devuelto a tick_tree; será la fuente de verdad que consulten los nodos hoja.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("is_hungry", true)
bb.set("eat", true)Guarda un valor bajo una clave
Guarda value bajo key y reemplaza la entrada anterior. Puede almacenar cualquier valor Zolo, aunque las acciones y condiciones interpretan booleanos y cadenas de manera especial.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("health", 80)
bb.set("alert", true)
bb.set("state", "running")Recupera el valor de una clave
Devuelve el valor almacenado bajo key, o nil cuando la clave no existe.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("health", 80)
print(bb.get("health"))
print(bb.get("mana"))Comprueba si existe una clave
Devuelve true cuando key existe en el blackboard y false en caso contrario.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("target", "goblin")
print(bb.has("target"))
print(bb.has("ally"))Elimina una clave
Elimina key del blackboard. La operación no produce un error si la clave está ausente.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("stunned", true)
bb.remove("stunned")
print(bb.has("stunned"))Elimina todas las entradas
Elimina todas las entradas y devuelve el blackboard a su estado vacío.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("a", 1)
bb.set("b", 2)
bb.clear()
print(bb.has("a"))Enumera los nombres de todas las claves
Devuelve un array con los nombres de las claves actuales. El orden no está especificado.
use plugin ai::{Blackboard}
let bb = Blackboard.new()
bb.set("hp", 100)
bb.set("ammo", 30)
for key in bb.keys() {
print(key)
}Convierte el blackboard en una tabla común
Convierte el blackboard en una tabla común que asocia cada clave con su valor. Resulta útil para depuración y serialización.
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"])Crea un nodo compuesto de secuencia
Crea una secuencia que evalúa los hijos de izquierda a derecha. Solo produce "success" cuando todos tienen éxito y se detiene en el primer 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))Crea un nodo compuesto selector
Crea un selector que evalúa los hijos de izquierda a derecha y produce "success" en cuanto uno tiene éxito. Solo produce "failure" cuando todos fallan.
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))Crea un nodo hoja de acción
Crea una acción hoja. Durante tick_tree, el valor de la clave name determina el estado: true se convierte en "success", false en "failure", una cadena se devuelve directamente y cualquier otro valor se convierte en "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))Crea un nodo de condición basado en el blackboard
Crea una condición hoja que consulta key. Un valor verdadero produce "success"; false, nil o una clave ausente producen "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))Crea un nodo compuesto paralelo
Crea un nodo que evalúa todos los hijos en cada tick. success_threshold define cuántos deben tener éxito; el valor predeterminado -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))Crea un nodo decorador inversor
Crea un decorador que cambia "success" por "failure" y viceversa. El estado "running" no se modifica.
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))Crea un nodo decorador repetidor
Evalúa el hijo hasta max_repeats veces por tick (el valor predeterminado es 1) y devuelve el último resultado. La repetición termina antes si el hijo está en "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))Crea un decorador que siempre produce éxito
Crea un decorador que siempre devuelve "success", sin importar el resultado del hijo. Úsalo para impedir que una etapa opcional interrumpa una secuencia.
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))Lee el tipo de un nodo
Devuelve el tipo del nodo como cadena: "sequence", "selector", "action", "condition", "parallel", "inverter", "repeater" o "succeeder". Devuelve nil si la tabla no contiene el campo type.
use plugin ai::{create_action, node_type}
let node = create_action("jump")
print(node_type(node))Reinicia todos los estados del árbol
Reinicia de forma recursiva el campo status de todos los nodos a "ready" y devuelve el árbol. Hazlo antes de comenzar de nuevo la evaluación en otro 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))Evalúa un tick del árbol de comportamiento
Evalúa un tick del árbol con raíz en node usando el blackboard indicado. Es el punto de entrada que recorre nodos compuestos, decoradores y hojas y devuelve "success", "failure" o "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))