simvx.core.ai.agent_node¶
Frame-loop driver that ticks any :class:Brain from a node’s on_update.
This is the dependency-free half of the AI driving layer: it ticks any core
Brain (a hand-rolled behaviour tree, state machine, utility scorer, or the
LLM brain in simvx.ai) and never imports simvx.ai or httpx. Classical
brains are first-class here with zero LLM dependency.
Three primitives, smallest to largest:
- func:
build_ai_context- the free helper that snapshots a node + tree into an :class:AIContextfor one tick.
- class:
BrainRunner- ownsbrain + blackboard + tick_interval; its- meth:
BrainRunner.stepticks at a cadence, passing the elapsed since the last tick (an accumulator), not the raw framedt, so brains see correct deltas regardless of tick rate. Usable from any existingNodesubclass.
- class:
AgentNode- the canonical batteries-included node that builds a Blackboard inon_ready, callsrunner.stepinon_update, and tears the brain down inon_exit_tree.
The driver calls exactly one method per tick: brain.tick(ctx). It never calls
perceive / decide / act directly.
Module Contents¶
Classes¶
Drive a :class: |
|
A node that drives one :class: |
Functions¶
Snapshot a live in-tree node into an :class: |
API¶
- simvx.core.ai.agent_node.build_ai_context(node: simvx.core.node.Node, dt: float, blackboard: simvx.core.ai.blackboard.Blackboard) simvx.core.ai.brain.AIContext[source]¶
Snapshot a live in-tree node into an :class:
AIContextfor one tick.agentis the node,worldis its :class:SceneTree, andnowis the tree’s accumulated sim clock. Must be called while the node is in the tree (node.treeisNonebeforeon_enter_tree); that is a programming error, raised eagerly rather than silently feeding the brainnow=0.
- class simvx.core.ai.agent_node.BrainRunner(brain: simvx.core.ai.brain.Brain, blackboard: simvx.core.ai.blackboard.Blackboard, *, tick_interval: float = 0.0)[source]¶
Drive a :class:
Brainat a fixed cadence from any node’s per-frame update.tick_interval == 0ticks every frame (the classical authoritative cadence).tick_interval > 0ticks everytick_intervalseconds, and thedtthe brain sees is the time elapsed since the previous tick (the accumulator), not the raw framedt.Initialization
- step(node: simvx.core.node.Node, dt: float) None[source]¶
Advance the cadence by
dtand tick the brain if it is due.
- class simvx.core.ai.agent_node.AgentNode(*, brain: simvx.core.ai.brain.Brain | None = None, squad: simvx.core.ai.blackboard.Blackboard | None = None, **kwargs: Any)[source]¶
Bases:
simvx.core.node.NodeA node that drives one :class:
Brainevery frame (or attick_interval).Set
self.brain(in__init__or before the node enters the tree). The node builds its :class:Blackboardinon_ready(optionally achild()of a squad board), creates a :class:BrainRunner, ticks it inon_update, and tears the brain down inon_exit_tree. Withself.brain = Noneit is an inert node, so subclasses can set the brain conditionally.Initialization
- tick_interval¶
‘Property(…)’
- strict_errors: ClassVar[bool]¶
True
- dev_checks: ClassVar[bool]¶
None
- script_error_raised¶
‘Signal(…)’
- dynamic: bool¶
False
- visible¶
‘Property(…)’
- update_mode¶
‘Property(…)’
- __properties__: ClassVar[dict[str, simvx.core.descriptors.Property]]¶
None
- classmethod __init_subclass__(**kwargs)¶
- property name: str¶
- property visible_in_tree: bool¶
- reset_error() None¶
- add_child(node: simvx.core.node.T) simvx.core.node.T¶
- remove_child(node: simvx.core.node.Node) None¶
- reparent(new_parent: simvx.core.node.Node)¶
- node_at(path, default=_NO_DEFAULT)¶
- find(target, *, direct: bool = False)¶
- find_all(target, *, direct: bool = False)¶
- expect(target, *, direct: bool = False)¶
- ancestor(target)¶
- walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]¶
- property path: str¶
- property is_scene_root: bool¶
- add_to_group(group: str)¶
- remove_from_group(group: str)¶
- is_in_group(group: str) bool¶
- on_enter_tree() None¶
- on_fixed_update(dt: float) None¶
- on_draw(renderer) None¶
- on_picked(event: simvx.core.events.InputEvent) None¶
- on_unhandled_input(event: simvx.core.events.TreeInputEvent) None¶
- start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle¶
- stop_coroutine(gen_or_handle)¶
- queue_redraw() None¶
- property render_dirty: bool¶
- clear_children()¶
- destroy()¶
- property destroying: bool¶
- call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None¶
- property app¶
- property tree: simvx.core.scene_tree.SceneTree¶
- property physics¶
- property physics_2d¶
- __getitem__(key: str)¶
- classmethod get_properties() dict[str, simvx.core.descriptors.Property]¶
- __repr__()¶