behavior_tree 0.1.10 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile.lock +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +25 -15
- data/lib/behavior_tree/concerns/node_iterators/prioritize_running.rb +8 -2
- data/lib/behavior_tree/concerns/tree_structure/printer.rb +10 -18
- data/lib/behavior_tree/decorator_nodes/force_failure.rb +4 -0
- data/lib/behavior_tree/decorator_nodes/force_success.rb +4 -0
- data/lib/behavior_tree/tasks/task_base.rb +4 -0
- data/lib/behavior_tree/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6eb178547f7b18faf513a60dc91f785a977e5fe7e2884d77ec8f365dd37e55da
|
4
|
+
data.tar.gz: 64e1f312b7028ec33749389e8ee13329c33712d35dc85afc9a0ebe84a5edf8a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f553d35fc13a331543cd1df25a169f20c1bbf0cf8fef526b081e5243411087cd7a0f0cdc797e59e78e83cb070a228c98cbf21fe32cd3206162f9dda1ab8b0c2
|
7
|
+
data.tar.gz: 43e2ec00bf7cc6f860dc35852853fbb7e6ae879267ca2848acd7c7c8428c7fefbf6e60ec18f4f79db53cc3bf3623528a413224324cba8f57b1b027397af471c5
|
data/CODE_OF_CONDUCT.md
CHANGED
@@ -59,7 +59,7 @@ representative at an online or offline event.
|
|
59
59
|
## Enforcement
|
60
60
|
|
61
61
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
62
|
-
reported to the community leaders responsible for enforcement at
|
62
|
+
reported to the community leaders responsible for enforcement at developer@chrisvilches.com.
|
63
63
|
All complaints will be reviewed and investigated promptly and fairly.
|
64
64
|
|
65
65
|
All community leaders are obligated to respect the privacy and security of the
|
data/Gemfile.lock
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -5,7 +5,11 @@
|
|
5
5
|
A robust and customizable Ruby gem for creating Behavior Trees, used in games, AI, robotics, and more.
|
6
6
|
|
7
7
|
<p align="center">
|
8
|
-
<img src="https://github.com/
|
8
|
+
<img src="https://github.com/ChrisVilches/ruby-behavior-tree/blob/main/assets/logo.png?raw=true" />
|
9
|
+
</p>
|
10
|
+
|
11
|
+
<p align="center">
|
12
|
+
<img src="https://github.com/ChrisVilches/ruby-behavior-tree/blob/main/assets/tree_animation.gif?raw=true" />
|
9
13
|
</p>
|
10
14
|
|
11
15
|
## Quick start
|
@@ -157,8 +161,8 @@ another_tree.print
|
|
157
161
|
* [Custom condition](#custom-condition)
|
158
162
|
- [Node API](#node-api)
|
159
163
|
* [Status](#status)
|
160
|
-
* [tick!](#tick
|
161
|
-
* [halt!](#halt
|
164
|
+
* [tick!](#tick)
|
165
|
+
* [halt!](#halt)
|
162
166
|
* [Status related callbacks and hooks](#status-related-callbacks-and-hooks)
|
163
167
|
- [Add custom nodes to the DSL](#add-custom-nodes-to-the-dsl)
|
164
168
|
- [Troubleshoot and debug your trees](#troubleshoot-and-debug-your-trees)
|
@@ -181,6 +185,8 @@ In simple words, it's a modular way to describe your program's control flow, in
|
|
181
185
|
|
182
186
|
### Ticking the tree
|
183
187
|
|
188
|
+
The tick is the most important part of using a behavior tree. When you tick the root node of a tree, it will propagate it by ticking its children, which in turn will tick their children. Tasks (leaf nodes) are executed when the tick reaches them. Non-leaf nodes would execute their own logic when they are ticked (e.g. decoration logic, executing a sequence, etc).
|
189
|
+
|
184
190
|
```ruby
|
185
191
|
my_tree.tick!
|
186
192
|
|
@@ -191,7 +197,7 @@ my_tree.tick!
|
|
191
197
|
|
192
198
|
Each node has a status, which can have three possible values:
|
193
199
|
|
194
|
-
1. `success` which is
|
200
|
+
1. `success` which is returned in certain situations depending on the node type, but usually indicating that the operation they are in charge of was completed. Tasks usually return `success` when they execute/complete successfully, sequences return `success` when the entire sequence is executed successfully, and so on. Since this is the default status of all nodes, a node is in `success` status if it has never been ticked, or if it has been halted (using `halt!`).
|
195
201
|
2. `running` which is returned by nodes that are currently executing.
|
196
202
|
3. `failure` which is returned to signal that execution failed.
|
197
203
|
|
@@ -259,11 +265,11 @@ end
|
|
259
265
|
|
260
266
|
#### Control nodes
|
261
267
|
|
262
|
-
A control node decides the flow of the execution. In simpler words, it uses a certain logic to decide which branch to execute.
|
268
|
+
A control node decides the flow of the execution. In simpler words, it uses a certain logic to decide which branch to execute. It could be one branch, multiple branches, or all of them.
|
263
269
|
|
264
270
|
A control node cannot be a leaf (i.e. it must have children).
|
265
271
|
|
266
|
-
|
272
|
+
By default, there are two types of control nodes, and custom ones can be easily created. (See: [Examples of custom control nodes](#custom-control-node)).
|
267
273
|
|
268
274
|
1. **Sequence:**
|
269
275
|
a. Begins executing the first child node.
|
@@ -277,7 +283,7 @@ There are two types of control nodes, and custom ones can be easily created ([se
|
|
277
283
|
d. If child returns `failure`, then continue with the next child.
|
278
284
|
e. If no node ever returned `success`, then return `failure`.
|
279
285
|
|
280
|
-
[Learn about "halting nodes" and what it means.](#halt
|
286
|
+
[Learn about "halting nodes" and what it means.](#halt)
|
281
287
|
|
282
288
|
When a control node is ticked, by default it traverses children and ticks them using this logic:
|
283
289
|
|
@@ -327,7 +333,7 @@ By default the decorator nodes present in this library are:
|
|
327
333
|
| Repeater | `BehaviorTree::Decorators::Repeater` | `repeater` or `rep` | Ticks the child again N times while it's returning `success`. |
|
328
334
|
| Retry | `BehaviorTree::Decorators::Retry` | `re_try` | Ticks the child again N times while it's returning `failure`. |
|
329
335
|
|
330
|
-
**Example #1: Creating a tree with
|
336
|
+
**Example #1: Creating a tree with some decorators**
|
331
337
|
|
332
338
|
```ruby
|
333
339
|
my_tree = BehaviorTree::Builder.build do
|
@@ -523,7 +529,7 @@ class AllOrNothing < ControlNodeBase
|
|
523
529
|
end
|
524
530
|
```
|
525
531
|
|
526
|
-
Note that under the hood, `tick_each_children` uses the strategy defined (i.e. `shuffle` method), and traverses its children while also ticking them. You don't need to send `tick!` manually to the child. The code
|
532
|
+
Note that under the hood, `tick_each_children` uses the strategy defined (i.e. `shuffle` method), and traverses its children while also ticking them. You don't need to send `tick!` manually to the child. The code in the block given to `tick_each_children` is executed *right after* the child is ticked.
|
527
533
|
|
528
534
|
### Custom decorator
|
529
535
|
|
@@ -560,7 +566,7 @@ class CustomCondition < BehaviorTree::Decorators::Condition
|
|
560
566
|
end
|
561
567
|
```
|
562
568
|
|
563
|
-
Or using inline
|
569
|
+
Or create condition nodes using inline lambdas in the DSL. When using the DSL, before starting the block (i.e. where the child is defined), you must pass a `lambda` which receives two parameters (both optional), `context` and `node` (which is the `self` of the condition node).
|
564
570
|
|
565
571
|
```ruby
|
566
572
|
my_tree = BehaviorTree::Builder.build do
|
@@ -583,7 +589,7 @@ my_tree.print
|
|
583
589
|
# └─task success (0 ticks)
|
584
590
|
```
|
585
591
|
|
586
|
-
**Note:** Other behavior tree implementations prefer the use of `sequence` control nodes, and placing conditional nodes as
|
592
|
+
**Note:** Other behavior tree implementations prefer the use of `sequence` control nodes, and placing conditional nodes as leaves, but with the role of simply returning `failure` or `success`. Since sequences execute the next node only if the previous one succeeded, it would also behave like a conditional node, preventing the next nodes in the sequence from executing if the condition failed. In this implementation, however, both patterns are available and you are free to choose which one to use.
|
587
593
|
|
588
594
|
## Node API
|
589
595
|
|
@@ -698,12 +704,16 @@ The second line of the output is the `puts` of the actual task logic. The third
|
|
698
704
|
|
699
705
|
**on_started_running**
|
700
706
|
|
701
|
-
Similar to `on_status_change`, but only triggers when the node has been set to `running`.
|
707
|
+
Similar to `on_status_change`, but only triggers when the node has been set to `running` (changed from a status other than `running`.
|
708
|
+
|
709
|
+
In some implementations, this is called `initialization`.
|
702
710
|
|
703
711
|
**on_finished_running**
|
704
712
|
|
705
713
|
Similar to `on_status_change`, but only triggers when the node has been set to a status other than `running`.
|
706
714
|
|
715
|
+
In some implementations, this is called `shutdown`.
|
716
|
+
|
707
717
|
## Add custom nodes to the DSL
|
708
718
|
|
709
719
|
You can register new nodes to be used in the DSL, take for example the following code:
|
@@ -790,7 +800,7 @@ my_tree.print
|
|
790
800
|
The above code generates the following output:
|
791
801
|
|
792
802
|
<p align="center">
|
793
|
-
<img src="https://github.com/
|
803
|
+
<img src="https://github.com/ChrisVilches/ruby-behavior-tree/blob/main/assets/printed_tree.jpg?raw=true" width="400"/>
|
794
804
|
</p>
|
795
805
|
|
796
806
|
In the example above, you can see that the bottom nodes haven't been ticked at all. Node starvation might occur for various reasons, such as having a `force_failure` node as one of the children of a `sequence` (the nodes after the `force_failure` would all be prevented from executing).
|
@@ -830,7 +840,7 @@ Keep in mind this is only for development purposes, and the generated trees don'
|
|
830
840
|
|
831
841
|
## Contributing
|
832
842
|
|
833
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
843
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ChrisVilches/ruby-behavior-tree. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/ChrisVilches/ruby-behavior-tree/blob/main/CODE_OF_CONDUCT.md).
|
834
844
|
|
835
845
|
|
836
846
|
## License
|
@@ -839,4 +849,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
839
849
|
|
840
850
|
## Code of Conduct
|
841
851
|
|
842
|
-
Everyone interacting in the Behavior Tree project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
852
|
+
Everyone interacting in the Behavior Tree project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ChrisVilches/ruby-behavior-tree/blob/main/CODE_OF_CONDUCT.md).
|
@@ -5,15 +5,21 @@ module BehaviorTree
|
|
5
5
|
# If there's at least one node with 'running' status, then iterate starting from there, in order.
|
6
6
|
# Else, iterate all nodes.
|
7
7
|
module PrioritizeRunning
|
8
|
+
private
|
9
|
+
|
8
10
|
def prioritize_running
|
9
|
-
|
11
|
+
@first_running_idx = children.find_index { |child| child.status.running? }.to_i if must_recompute_idx?
|
10
12
|
|
11
13
|
Enumerator.new do |y|
|
12
|
-
|
14
|
+
children[@first_running_idx..].each do |child|
|
13
15
|
y << child
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
19
|
+
|
20
|
+
def must_recompute_idx?
|
21
|
+
!@first_running_idx || !children[@first_running_idx].status.running?
|
22
|
+
end
|
17
23
|
end
|
18
24
|
end
|
19
25
|
end
|
@@ -7,6 +7,10 @@ module BehaviorTree
|
|
7
7
|
# Algorithm to print tree.
|
8
8
|
module Printer
|
9
9
|
def print
|
10
|
+
puts to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
10
14
|
lines = []
|
11
15
|
lines << '∅' # Style for the root node.
|
12
16
|
lines += tree_lines
|
@@ -15,8 +19,7 @@ module BehaviorTree
|
|
15
19
|
lines << uniq_nodes_string
|
16
20
|
lines << size_string
|
17
21
|
lines << tree_tick_count_string
|
18
|
-
|
19
|
-
puts lines.join "\n"
|
22
|
+
lines.join "\n"
|
20
23
|
end
|
21
24
|
|
22
25
|
private
|
@@ -34,7 +37,7 @@ module BehaviorTree
|
|
34
37
|
space = (0...depth).map { |d| vertical_lines_continues.include?(d) ? '│ ' : ' ' }.join
|
35
38
|
connector = last_child ? '└─' : '├─'
|
36
39
|
|
37
|
-
"#{space}#{connector}#{
|
40
|
+
"#{space}#{connector}#{resolve_display_name(node)} #{status_string(node)} #{tick_count_string(node)}"
|
38
41
|
end
|
39
42
|
end
|
40
43
|
|
@@ -83,22 +86,11 @@ module BehaviorTree
|
|
83
86
|
.downcase
|
84
87
|
end
|
85
88
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
# Changes the name of some classes (maps it to a better name).
|
91
|
-
# Mapping is simply based on taste.
|
92
|
-
def pretty_name(name)
|
93
|
-
case name
|
94
|
-
when 'task_base'
|
95
|
-
'task'
|
96
|
-
when 'force_success'
|
97
|
-
'forcesuccess'
|
98
|
-
when 'force_failure'
|
99
|
-
'forcefailure'
|
89
|
+
def resolve_display_name(node)
|
90
|
+
if node.respond_to?(:display_name)
|
91
|
+
node.display_name
|
100
92
|
else
|
101
|
-
name
|
93
|
+
snake_case(node.class.name.split('::').last)
|
102
94
|
end
|
103
95
|
end
|
104
96
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: behavior_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felo Vilches
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.8.1
|
27
|
-
description:
|
27
|
+
description:
|
28
28
|
email:
|
29
29
|
- felovilches@gmail.com
|
30
30
|
executables: []
|
@@ -82,7 +82,7 @@ homepage: https://github.com/FeloVilches/Ruby-Behavior-Tree
|
|
82
82
|
licenses:
|
83
83
|
- MIT
|
84
84
|
metadata: {}
|
85
|
-
post_install_message:
|
85
|
+
post_install_message:
|
86
86
|
rdoc_options: []
|
87
87
|
require_paths:
|
88
88
|
- lib
|
@@ -97,8 +97,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
97
|
- !ruby/object:Gem::Version
|
98
98
|
version: '0'
|
99
99
|
requirements: []
|
100
|
-
rubygems_version: 3.
|
101
|
-
signing_key:
|
100
|
+
rubygems_version: 3.3.7
|
101
|
+
signing_key:
|
102
102
|
specification_version: 4
|
103
103
|
summary: A robust and customizable Ruby gem for creating Behavior Trees.
|
104
104
|
test_files: []
|