8000 Return `None` if ticking `BT` after it finishes. by andriyDev · Pull Request #45 · Sollimann/bonsai · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Return None if ticking BT after it finishes. #45

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

Merged
merged 6 commits into from
Jan 22, 2025

Conversation

andriyDev
Copy link
Collaborator
@andriyDev andriyDev commented Jan 18, 2025

Today, ticking a behavior tree after it has finished has confusing results. Looking at the code, it seems the intent was that once a State finishes, it is not expected to tick again. For example, if you tick a Sequence/Select after it has finished, it always returns Running. Here's an example test that shows this strange behavior:

#[test]
fn weird_behavior() {
    let a = 4;

    let mut bt = BT::new(
        Select(vec![
            Invert(Box::new(Action(Dec))),
            Invert(Box::new(Action(Dec))),
            Invert(Box::new(Action(Dec))),
        ]),
        (),
    );

    let (a, s, _) = tick(a, 0.1, &mut bt);
    assert_eq!(a, 1);
    assert_eq!(s, Failure);
    let (a, s, _) = tick(a, 0.1, &mut bt);
    assert_eq!(a, 1);
    assert_eq!(s, Running);
    let (a, s, _) = tick(a, 0.1, &mut bt);
    assert_eq!(a, 1);
    assert_eq!(s, Running);
}

This is clearly wrong. We could fix this particular issue (make Sequence/Select return a finished status if you tick it again), but it's not clear that ticking a finished behavior makes sense at all - so perhaps we should stop that.

This PR solves this by just keeping track of the BT returns a Success or Failure status and then prevents ticking in those cases (returning an Option)

@andriyDev andriyDev requested a review from kaphula January 18, 2025 23:12
@andriyDev
Copy link
Collaborator Author

Some more things to point out: I used Result instead of Option since a None value isn't every descriptive. We also can't add a Finished variant to Status since then any action could return it, so we'd have to handle it everywhere.

@kaphula
Copy link
Collaborator
kaphula commented Jan 19, 2025

I would honestly stick with Option instead of Result and write its meaning to the documentation since for the time being there are no other exceptions or error cases tick can return. It is just "the tree has finished or it has not", and Option should demonstrate that just fine? I am also fan of avoiding any additional dependencies if possible. Any thoughts, @Sollimann ?

@Sollimann
Copy link
Owner

Yes, agree with @kaphula. Return an 'Option' instead fits nicer, also because ticking tree after finish is not an error per se. I'd prefer us not introducing any new dep if not strictly needed.

Thanks for picking up this task @andriyDev, remember to bump version 👍

@andriyDev
Copy link
Collaborator Author

First I don't agree this isn't an error - you clearly shouldn't be ticking a finished tree, and we are exiting early because we're in an "invalid" state. Second, I don't think having no other error cases is a good reason to not have an expressive error case. Adding additional error cases in the future would be much less cumbersome, and debug printing the error even with this can make it clear what's going on (compare "None" to "hey don't tick a finished behavior tree"). Third, while I understand the desire to limit the number of dependencies (a worthy goal in general), thiserror is not some outlandish dependency: it is an incredibly common dependency so is probably already in any application's tree.

All that said, I've still made the commit to switch to Option to move this forward. If my argument hasn't swayed either of you, we can just merge this.

@andriyDev
Copy link
Collaborator Author

@Sollimann also to follow up, we don't need to bump the version since that already happened in #38. We are currently at 0.9.0.

@andriyDev
Copy link
Collaborator Author

Rebased now that #42 is merged.

@andriyDev andriyDev changed the title Return an error if ticking BT after it finishes. Return None if ticking BT after it finishes. Jan 22, 2025
@Sollimann Sollimann self-requested a review January 22, 2025 21:21
Copy link
Owner
@Sollimann Sollimann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved!

TL;DR
I understand where you're coming from, and I appreciate the effort. Returning an Option feels like the most appropriate and lightweight solution for now. It avoids overcomplicating the api and keeps the door open for refactoring later if the need arises.

To your points:

1.) I think we disagree on the semantics here, which is fine. From my point of view ticking a finished tree is not inherently erroneous — it's an unsupported action, but not a failure of execution or logic. The only two possible states here are "tree produces a status" (some value) or "tree is finished" (none). If we ever encounter additional cases where we need more meaningful differentiation down the line, we can always refactor to introduce a more expressive type at that point. However, at the moment, Option is the simplest and most idiomatic fit for the problem we're solving (from my pov).

2.) I agree with this

3.) I also agree that thiserror are one of the more common and stable libs. I want to avoid dependency bloat which is common for so many libs out there. As the code evolves, if we encounter scenarios that truly require advanced error handling, we can reevaluate and introduce a proper error-handling strategy (including dependencies) then

@andriyDev andriyDev merged commit 1aa74af into Sollimann:main Jan 22, 2025
2 checks passed
@andriyDev andriyDev deleted the finish branch January 22, 2025 22:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
< 2A56 /turbo-frame>
0