joeycumines / go-behaviortree

Package behaviortree provides a simple and powerful Go implementation of behavior trees without fluff.
Apache License 2.0
64 stars 9 forks source link

Other Composite and Decorator Nodes #16

Closed xescugc closed 5 months ago

xescugc commented 5 months ago

Is your feature request related to a problem? Please describe.

I'm new to BT but one thing I've seen is that there are much more Composite nodes than the Sequence and Selector, for example Random Selectors / Sequences.

And there are also the Decorators:

For what I read there much more but those look like the main ones also

Describe the solution you'd like

To consider the option of adding them

Describe alternatives you've considered

As long as you are ok on adding them I could take a look into doing it myself :)

Additional context

Another GO lib that has some of the Composites and Deocrators: https://github.com/askft/go-behave?tab=readme-ov-file#composite-nodes

A blog also mentioning some of those https://www.gamedeveloper.com/programming/behavior-trees-for-ai-how-they-work

As I said before, anyone can add anything but looks like those are common.

xescugc commented 5 months ago

I've read a bit the code and found that maybe you actually have some of them (or all). But they are not mentioned/documented on the README and the sames used are not the ones I've read on other parts.

For example you have:

If that's the case, is there a reason on the names? Just curious, again I don't know much about this and I want to know if there are no "references" on names.

joeycumines commented 5 months ago

Hey @xescugc :)

Yep, you'll find that the terminology varies.

re: Contributing, feel free to put a PR up if you feel like it'd be useful. I'd recommend opening an issue to discuss it first though, as it will increase the chances that I'll merge it, and I wouldn't want you wasting your time.

This implementation is more closely based on the academic definition of what a behavior tree is, rather than what I have seen in game dev literature. I started with the wikipedia page - just Sequence and Selector, and built it out as I needed. The only feature that didn't come from an immediate use case was Memorize, which has effectively replaced the Sync function, in my own personal projects, baring one or two specific use cases, and came from the whitepaper/book linked in the README.

In other words, my primary goal has been to solve problems I was facing, and the implementation reflects that. For the most part, the names were simply what I felt fit at the time, and don't necessarily align with any well-defined concept, in either academia or game dev. Beyond exceptions including Sequence, Selector, and Memorize, that is.

You might find it interesting to read this documentation, from BehaviorTree/BehaviorTree.CPP, which is aimed at robotics, and is the second most starred behavior tree implementation on GitHub (the highest in C++ by a large margin). I'll go section by section because I'm invested in this explanation now lol.

Sequences: They provide 3 types, Sequence, SequenceWithMemory, ReactiveSequence. In comparison to this module, bt.New(bt.Sequence, children...) behaves like ReactiveSequence, bt.New(bt.Memorize(bt.Sequence), children...) behaves like Sequence, and SequenceWithMemory doesn't have an analogue, but you could trivially emulate it by wrapping each child to map bt.Failure to bt.Running, and use those children within bt.New(bt.Memorize(bt.Sequence), children...). More on what I've termed "tick wrappers" in a bit.

Fallbacks: As above except bt.Selector instead of bt.Sequence, and no "run only once until all succeed" variant.

Decorators: Are simply for convenience in this module. They are much more important if your trees are defined in XML, rather than code. You'll notice that, bt.Not, for example, is extremely trivial. I only included it because I found myself reimplementing it multiple times.

To quote their docs:

A decorator is a node that must have a single child.

It is up to the Decorator to decide if, when and how many times the child should be ticked.

Is the entirety of their preamble, before jumping into the types of decorators they support out of the box. The "decorators" that this module provides are simply closures that implement or wrap bt.Tick values. I did not deliberately design in the concept, it was basically just an emergent pattern that I found worked well. The bt.Memorize function is a "tick wrapper" in the same vein, though it doesn't fit the definition of a decorator used by BehaviorTree.CPP. I've documented the general rules I've followed to implement tick wrappers in the readme (I think?).

xescugc commented 5 months ago

re: Contributing, feel free to put a PR up if you feel like it'd be useful. I'd recommend opening an issue to discuss it first though, as it will increase the chances that I'll merge it, and I wouldn't want you wasting your time.

Yes ofc an issue will always be first haha. But I always ask before doing anything just in case.

Thanks you for the explanation, it's fine for me to have whatever names but I was wondering if that was a difference between gaming/robotics/academics haha.

I'll close the issue as everything is clear :) (I'll open another one/two for something I want to add hehe)