[C#] TreeSharp Usage menu

Shout-Out

User Tag List

Results 1 to 13 of 13
  1. #1
    Harland's Avatar Member
    Reputation
    8
    Join Date
    Oct 2007
    Posts
    50
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [C#] TreeSharp Usage

    Has anyone had a chance to look into Apoc's implementation of a Behaviour Tree known as TreeSharp? I've been using FSM's too long now and it was indeed turning into the Flying Spaghetti Monster Apoc pointed it out to be.

    I didn't have any luck finding a documented interface for the library, so I'm a little unsure if I am using the library as intended. I'm afraid maybe I am thinking along the lines of FSM's still. For example lets say I created some arbitrary Sequence.

    Code:
    Sequence _navigate = new Sequence(
    //Set next Hotpot to path to and create a path.
    new Decorator(ret => Waypoints.CycleHotSpots(),
    new Action(delegate { })),
    //Verify that a path is set.
    new Decorator(ret => Waypoints.IsPathSet,
    new Action(delegate { })),
    //Cycle through the path points.
    new Decorator(ret => Waypoints.CyclePath())
    new Action(delegate { }))
    );
    Now if I wanted to Pulse the tree I would invoke method _navigate.Execute, but I am unsure as to what the context parameter is.

    Also just out of curiosity in Apoc's old implementation of an FSM we had Start and Exit method's which fired during the entry and exiting of a transition. To emulate this same approach, is it a safe bet to use a Decorator to check if it's child returned a Success status and perform our once only code there (and also the same deal for once only exit method, but with the condition of a return status of Failure instead).

    Thanks if anyone can give me some tips and pointers to using this library correctly. Oh an also sexy implementation as always Apoc, very elegant.

    Cheers,
    Harland.

    [C#] TreeSharp Usage
  2. #2
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Harland View Post
    Has anyone had a chance to look into Apoc's implementation of a Behaviour Tree known as TreeSharp? I've been using FSM's too long now and it was indeed turning into the Flying Spaghetti Monster Apoc pointed it out to be.

    I didn't have any luck finding a documented interface for the library, so I'm a little unsure if I am using the library as intended. I'm afraid maybe I am thinking along the lines of FSM's still. For example lets say I created some arbitrary Sequence.

    Code:
    Sequence _navigate = new Sequence(
    //Set next Hotpot to path to and create a path.
    new Decorator(ret => Waypoints.CycleHotSpots(),
    new Action(delegate { })),
    //Verify that a path is set.
    new Decorator(ret => Waypoints.IsPathSet,
    new Action(delegate { })),
    //Cycle through the path points.
    new Decorator(ret => Waypoints.CyclePath())
    new Action(delegate { }))
    );
    Now if I wanted to Pulse the tree I would invoke method _navigate.Execute, but I am unsure as to what the context parameter is.

    Also just out of curiosity in Apoc's old implementation of an FSM we had Start and Exit method's which fired during the entry and exiting of a transition. To emulate this same approach, is it a safe bet to use a Decorator to check if it's child returned a Success status and perform our once only code there (and also the same deal for once only exit method, but with the condition of a return status of Failure instead).

    Thanks if anyone can give me some tips and pointers to using this library correctly. Oh an also sexy implementation as always Apoc, very elegant.

    Cheers,
    Harland.
    The implementation was originally amadmonk's. I simply fixed some bugs, and expanded on it. (By quite a bit)

  3. #3
    Harland's Avatar Member
    Reputation
    8
    Join Date
    Oct 2007
    Posts
    50
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hats off to both Amadmonk and Apoc then

  4. #4
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I moved on to Lua for the coroutines love... but I'm coming back to the C# fold, lately...
    Don't believe everything you think.

  5. #5
    Harland's Avatar Member
    Reputation
    8
    Join Date
    Oct 2007
    Posts
    50
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Has anyone actually managed to implement TreeSharp into their project. I don't understand how to continue execution of a particular behaviour that has previously succeeded. I can see that the yield return is used to store the current position in the enumeration, and that should allow us to just execute the behaviour from that position without having to research the entire tree.

    Can anyone suggest how the tree can be pulsed without having to enumerate the tree from the very start again? Calling Start() followed Tick() is not the way to go.
    Last edited by Harland; 12-26-2010 at 02:35 AM. Reason: Bump

  6. #6
    Harland's Avatar Member
    Reputation
    8
    Join Date
    Oct 2007
    Posts
    50
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just bumping this thread in hopes that Apoc or someone else, familiar with this library may have some tips.

  7. #7
    MaiN's Avatar Elite User
    Reputation
    335
    Join Date
    Sep 2006
    Posts
    1,047
    Thanks G/R
    0/10
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Harland View Post
    Has anyone actually managed to implement TreeSharp into their project. I don't understand how to continue execution of a particular behaviour that has previously succeeded. I can see that the yield return is used to store the current position in the enumeration, and that should allow us to just execute the behaviour from that position without having to research the entire tree.

    Can anyone suggest how the tree can be pulsed without having to enumerate the tree from the very start again? Calling Start() followed Tick() is not the way to go.
    That's what RunStatus.Running is for. When you return it, the tree will continue from the same behavior the next time the tree is pulsed. It does this because most of the behaviors are implemented like:
    Code:
    do
    {
      child.Tick(ctx);
    } while (child.LastStatus == RunStatus.Running);
    [16:15:41] Cypher: caus the CPU is a dick
    [16:16:07] kynox: CPU is mad
    [16:16:15] Cypher: CPU is all like
    [16:16:16] Cypher: whatever, i do what i want

  8. #8
    Harland's Avatar Member
    Reputation
    8
    Join Date
    Oct 2007
    Posts
    50
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Then comes the question again, am I using the incorrect method to pulse the tree?

    Code:
            static Sequence _ps;
    
            static bool test1 = true;
            static bool test2 = true;
    
    
            [STAThread]
            static void Main()
            {
                _ps = new Sequence(
                    new Decorator(canRun => test1,
                        new Action(delegate { Console.WriteLine("Action1"); })),
                    new Decorator(canRun => test2,
                        new Action(delegate { Console.WriteLine("Action2"); }))
                    );
    
                object context = new object();
    
                _ps.Start(context);           
    
                while (true)
                {
                    Console.WriteLine();
                    var input = Console.ReadLine();
    
                    if (input == "1")
                    {
                        test1 = !test1;
                    }
                    if (input == "2")
                    {
                        test2 = !test2;
                    }
    
                    //Pulse the tree
                    _ps.Tick(context);
                }
            }
    If I was to implement the above code and we do the initial pulse, we would get the output:
    Code:
    Action1
    Action2
    On the second pulse, I would expect the output:
    Code:
    Action2
    If I was to set the test1 boolean variable to false for the third pulse, I would still expect the output:
    Code:
    Action2
    This is not the case however, I am instead observing the output below, with every subsequent pulse not running any actions.
    Code:
    Action1
    Action2
    ...
    
    ...
    
    ...
    Last edited by Harland; 12-26-2010 at 09:29 AM.

  9. #9
    MaiN's Avatar Elite User
    Reputation
    335
    Join Date
    Sep 2006
    Posts
    1,047
    Thanks G/R
    0/10
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The sequence stops executing its children as soon as it reaches as child that returns Failure. A Decorator returns success if the CanRun is true, and Failure if it is false. So if test1 is false, the first decorator will return failure and the sequence will stop executing and return failure.
    Note that in your case (which seems like implementing an FSM with the BT ??) you probably want to use a PrioritySelector, which keeps executing children until one of them returns success and then returns. If you do want to use a decorator in the sequence, you have to create a composite that works like Decorator but returns success no matter what.
    Basically copy paste Decorator.cs, but change it to return success when CanRun is false.
    [16:15:41] Cypher: caus the CPU is a dick
    [16:16:07] kynox: CPU is mad
    [16:16:15] Cypher: CPU is all like
    [16:16:16] Cypher: whatever, i do what i want

  10. #10
    Harland's Avatar Member
    Reputation
    8
    Join Date
    Oct 2007
    Posts
    50
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the reply Main. I was just curious about your previous comment then:

    That's what RunStatus.Running is for. When you return it, the tree will continue from the same behavior the next time the tree is pulsed.
    I've never actually seen a RunStatus of Running ever returned from Tick during some tests. Which still makes me think I am pulsing the BT incorrectly.

    Also added to the fact I can't find where the TreeSharp project would ever return a status of Running. Perhaps TreeSharp was uploaded with the intention that it is not suppose to work without some tweaks...I don't know. When using the PrioritySelector the only time I can see that a RunStatus of Running is yielded, is if the RunStatus is already equal to Running.

    Yet again still confused, there must be some coding magic hidden somewhere for return the running status, or I just suck and don't know how to pulse the tree correctly.

    P.S. I tried to pulse the tree using:

    Code:
    while(true)
    {
    BT.Start(ctx);
    BT.Tick(ctx);
    }
    and

    Code:
    BT.Start(ctx);
    while (true)
    {
    BT.Tick(ctx);
    }
    where the first method is the only method that seems to pulse the tree again and runs the successful actions. The latter does not do anything besides return the RunStatus of Success.
    Last edited by Harland; 12-26-2010 at 09:47 PM.

  11. #11
    caytchen's Avatar Contributor
    Reputation
    138
    Join Date
    Apr 2007
    Posts
    162
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Included in TreeSharp are only primitives, like a sequence or a selector, things you end up using regardless of your final tree. They do however work primarily from the RunStatus you provide them through a delegate or by deriving from them and overriding functions; e.g. an Action only works if you pass it an delegate (which returns a RunStatus!) or override its Run function, which again returns a RunStatus.

    The reason you don't see any of these logic primitives returning "Running" is because something that returns Running is most likely stateful; the primitives included in TreeSharp either only act as proxies or are stateless.

  12. #12
    Harland's Avatar Member
    Reputation
    8
    Join Date
    Oct 2007
    Posts
    50
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you everyone. I guess I misinterpreted one of the other threads on this forum that seemed to indicate that the TreeSharp primitives did maintain state. It all makes sense now cheers for the help :P

  13. #13
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    They can maintain state. I'm not sure if the build I have on googlecode includes the 2nd proxy delegate. By default, most actions are stateless. However, you can return a RunStatus from actions, to keep them running.

Similar Threads

  1. Make HUGE cities- With NO load times, Network usage, or processor taken.
    By EmuGod in forum WoW EMU Guides & Tutorials
    Replies: 22
    Last Post: 03-29-2008, 06:52 AM
  2. Reduce the RAM usage
    By Dalla90 in forum World of Warcraft Guides
    Replies: 2
    Last Post: 03-27-2008, 03:08 AM
  3. Sapper Charge Usage w/o Item Decrease
    By Ryukishen in forum World of Warcraft Exploits
    Replies: 2
    Last Post: 12-27-2007, 03:14 PM
  4. New usage of Tele to Plane hack
    By Varoze in forum World of Warcraft Bots and Programs
    Replies: 15
    Last Post: 03-19-2007, 09:03 PM
All times are GMT -5. The time now is 07:40 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search