class BehaviorTree::NodeBase

A node (abstract class).

Attributes

arbitrary_storage[R]
prev_status[R]
status[R]
tick_count[R]
ticks_running[R]

Public Class Methods

new() click to toggle source
# File lib/behavior_tree/node_base.rb, line 9
def initialize
  @status = NodeStatus.new NodeStatus::SUCCESS
  @prev_status = NodeStatus.new NodeStatus::SUCCESS

  @tick_count = 0
  @ticks_running = 0
  @context = nil

  @status.subscribe { |prev| __on_status_change__(prev) }

  @arbitrary_storage = {}
end

Public Instance Methods

[](key) click to toggle source
# File lib/behavior_tree/node_base.rb, line 77
def [](key)
  @arbitrary_storage[key]
end
[]=(key, value) click to toggle source
# File lib/behavior_tree/node_base.rb, line 73
def []=(key, value)
  @arbitrary_storage[key] = value
end
chainable_node() click to toggle source
# File lib/behavior_tree/node_base.rb, line 69
def chainable_node
  self
end
children() click to toggle source
# File lib/behavior_tree/node_base.rb, line 59
def children
  if @children.is_a?(Array)
    @children
  elsif @child.is_a?(NodeBase)
    [@child]
  else
    []
  end
end
context=(context) click to toggle source
# File lib/behavior_tree/node_base.rb, line 22
def context=(context)
  @context = context

  # Propagate context.
  children.each do |child|
    child.context = context
  end
end
halt!() click to toggle source
# File lib/behavior_tree/node_base.rb, line 87
def halt!
  status.success!
end
size() click to toggle source
# File lib/behavior_tree/node_base.rb, line 31
def size
  1 + children.map(&:size).sum
end
status=(other_status) click to toggle source
# File lib/behavior_tree/node_base.rb, line 81
def status=(other_status)
  status.running! if other_status.running?
  status.failure! if other_status.failure?
  status.success! if other_status.success?
end
tick!() click to toggle source
# File lib/behavior_tree/node_base.rb, line 35
def tick!
  @tick_count += 1
  should_tick = should_tick?
  raise ShouldTickNotBooleanError, should_tick unless [true, false].include? should_tick

  unless (@tick_prevented = !should_tick)
    status.running!
    on_tick
    @ticks_running += 1
  end

  ensure_after_tick

  # NOTE: Make sure this method returns nil. Since 'ensure_after_tick' might return
  #       the node status, it generates some error in IRB (unknown cause).
  #
  #       This error can be replicated by pasting a valid status object in IRB, such as by doing:
  #       BehaviorTree.const_get(:NodeStatus).new(:__running__) # Valid, but IRB crashes.
  #
  #       Ruby 3.0.0 -> Crash
  #       Ruby 2.7.0 -> OK
  nil
end

Protected Instance Methods

ensure_after_tick() click to toggle source
# File lib/behavior_tree/node_base.rb, line 101
def ensure_after_tick; end
on_finished_running() click to toggle source
# File lib/behavior_tree/node_base.rb, line 105
def on_finished_running; end
on_started_running() click to toggle source
# File lib/behavior_tree/node_base.rb, line 103
def on_started_running; end
on_status_change() click to toggle source
# File lib/behavior_tree/node_base.rb, line 107
def on_status_change; end
on_tick() click to toggle source
# File lib/behavior_tree/node_base.rb, line 99
def on_tick; end
should_tick?() click to toggle source

If this value is false, @tick_prevented will be set to true, which can be handled in other tick callbacks.

# File lib/behavior_tree/node_base.rb, line 95
def should_tick?
  true
end

Private Instance Methods

__on_status_change__(prev) click to toggle source

Always prev != current (states that are set to the same aren't notified). The fact that it's set to 0 means that setting to running must be done before increasing the counts (so that @ticks_running becomes 1 after the whole tick lifecycle). This is the non custom on_status_change. Users are expected to override the one without double underscore if they want to execute custom logic.

# File lib/behavior_tree/node_base.rb, line 116
def __on_status_change__(prev)
  prev_status.set(prev)

  if prev_status.running?
    on_finished_running
  elsif status.running?
    @ticks_running = 0
    on_started_running
  end

  on_status_change
end