Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weighted random selectors/sequences #194

Closed
Novark opened this issue Jun 15, 2023 · 4 comments · Fixed by #206
Closed

Weighted random selectors/sequences #194

Novark opened this issue Jun 15, 2023 · 4 comments · Fixed by #206
Labels
🍯 feature A new addition to this addon.

Comments

@Novark
Copy link

Novark commented Jun 15, 2023

Is your feature request related to a problem? Please describe.
In some use-cases (especially procedural generation), it is desired to select a random child node based on a weighted probability. For example:

  • Selector_Random
    -- Child Node One (weight: 5)
    -- Child Node Two (weight: 7)
    -- Child Node Three (weight: 3)

Sum: 5+7+3 = 15

"Child Node One" has a (5/15) = 33% chance of selection
"Child Node Two" has a (7/15) = 47% chance of selection
"Child Node Three" has a (3/15) = 20% chance of selection

Describe the solution you'd like
A way in which to assign a weight to a node, and have the parent composite choose one of the children based on a weighted probability.

One possible solution would be to expose a weight variable in beehave_node.gd which would be 1 by default (it would likely need to be part of this base class in order to apply to all nodes and properly support nested trees). When a composite evaluates its children, it will sum up the weights of all children which inherit from BeehaveNode which, with a weight of 1, will just return the number of children and select one of them at random with equal probability. This matches the existing behaviour of sequence_random / selector_random composites. Changing the weights would skew the random selection according to the sum of weighted values.

Describe alternatives you've considered
The current functionality of Beehave allows for random selectors and sequences, but does not currently support the ability to give weights to nodes in the random selection process.

@bitbrain bitbrain added the 🌺 enhancement New feature or request label Jun 16, 2023
@bitbrain
Copy link
Owner

There has been some discussion about this in #74 before. One reason we decided against a weight property is that it would only be useful for specific use cases but every single node would always have a weighted property even if it is not used 99% of the time.

Another idea we had was to introduce a Weighted decorator node that has the weight on it and you can wrap it as a child for nodes where you want to have a custom weight applied:

Selector_Random
--WeightNode (weight: 5)
   -- Child Node One
--WeightNode (weight: 7)
   -- Child Node Two
--WeightNode (weight: 3)
   -- Child Node Three

@Novark
Copy link
Author

Novark commented Jun 16, 2023

I think having a weighted decorator would be an acceptable compromise between achieving the desired functionality, while keeping the base class relatively clean.

The obvious downside, however, would be an increasingly complex behaviour tree that may be less readable than having an exported weight property.

I do wonder if there's a case to be made for having some sort of "meta-properties" section available to all nodes for things like this (the blackboard comes to mind, but this would be more of a tool thing). The logic would be fully contained within the BeehaveNode class, and since it's a @tool, the weight exports in children nodes could be dynamically added/removed from the inspector based on the parent composite node. This is more of a design-philosophy discussion, however, and would likely depend on what the goals are for future Beehave functionality support. I personally lean slightly towards pragmatic implementations that may be slightly "less clean" if it means adding value to the end-user. In this case, the value-add would be a cleaner / more readable behaviour tree. The "cost" would be a Beehave design-compromise in adding some extra functionality to where it might not necessarily belong (in the BeehaveNode class). Deciding on some sort of "meta-properties" support, however, would at least confine the design decision to something bounded - rather than having to worry about whether adding such a feature would be a "slippery slope" for more additions in the future.

@bitbrain bitbrain changed the title Feature request: Weighted random selectors / sequences Weighted random selectors/sequences Jun 16, 2023
@bitbrain bitbrain added 🍯 feature A new addition to this addon. and removed 🌺 enhancement New feature or request labels Jun 16, 2023
@bitbrain
Copy link
Owner

A dedicated 'meta' section would indeed be useful - it could even sit in its own export category which Godot 4 supports.

One way I try to imagine weights is by thinking about graphs for a moment. Technically, any behavior tree is a directed graph mathematically speaking. Weights are usually a property of the 'edge' or 'connection' but this is not trivial to model in Godot, especially since Beehave is utilizing the node system.

One compromise could be indeed to always add it to the node itself as a property with some options:

  1. add documentation describing what weights actually do affect
  2. somehow visualise that weights are 'actively used' - not 100% how this could be done so this option may not be feasable
  3. potentially hide the weight property conditionally. While this makes sense logically, it opens the door to some strange edge cases: e.g. what if a weight was defined and then I move the node somewhere else - the property is still defined but now invisible? Maybe not the best idea.

I am happy for whoever picks this up to proceed with adding weights as a new property to nodes inside a metadata category. Please also make sure to add extensive tests for this as well as update the beehave docs. Learn more about contributing to this addon here.

@lostptr lostptr mentioned this issue Aug 13, 2023
6 tasks
@lostptr
Copy link
Contributor

lostptr commented Aug 13, 2023

I thought of an alternative: make the weights an "advanced" property of the RandomSelector/Sequence. They would be basically a dictionary of the child nodes with a number between 0.0 and 1.0. I will try to make a PR to show what I mean cause it would be easier to visualize. However, I will probably have to think of a way to make sure it works and the weights are updated when adding nodes at runtime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🍯 feature A new addition to this addon.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants