GithubHelp home page GithubHelp logo

cryptiklemur / fluent-behavior-tree Goto Github PK

View Code? Open in Web Editor NEW
72.0 6.0 11.0 59 KB

Typescript/Javascript behavior tree library with a fluent API

License: MIT License

TypeScript 100.00%
behavior-trees behavior-tree behaviour-tree behaviour-trees typescript typescript-library

fluent-behavior-tree's Introduction

Fluent Behavior Tree

Build Status npm version

This is a Typescript/Javascript implementation of https://github.com/codecapers/Fluent-Behaviour-Tree

JS/TS behaviour tree library with a fluent API.

For a background and walk-through please see the accompanying article.

Understanding Behaviour Trees

Here are some resources to help you understand behaviour trees:

Installation

Install with npm:

npm install -s fluent-behavior-tree

Usage

A behavior tree is created through BehaviorTreeBuilder. The tree is returned when the build function is called.

import {BehaviorTreeBuilder, BehaviorTreeStatus, TimeData} from "fluent-behavior-tree";

// ...

const builder = new BehaviorTreeBuilder();
this.tree = builder
    .sequence("my-sequence")
        .do("action1", async (t) => {
            // Action 1.

            return BehaviorTreeStatus.Success;
        })
        .do("action2", async (t) => {
            //Action 2.

            return BehaviorTreeStatus.Failure;
        })
    .end()
    .build();

Then, Tick the behavior tree on each update of your loop

public async update(deltaTime: number): Promise<void> {
    await this.tree.tick(new TimeData(deltaTime));
}

Behavior Tree Status

Behavior tree nodes must return the following status codes:

  • BehaviorTreeStatus.Success: The node has finished what it was doing and succeeded.
  • BehaviorTreeStatus.Failure: The node has finished, but failed.
  • BehaviorTreeStatus.Running: The node is still working on something.

Node Types

Action / Leaf-Node

Call the do function to create an action node at the leaves of the behavior tree.

.do("do-something", async (t) => {
    // ... Do something ...

    return BehaviorTreeStatus.Success;
});

The return value defines the status of the node. Return one of the statuses from above.

Sequence

Runs each child node in sequence. Fails for the first child node that fails. Moves to the next child when the current running child succeeds. Stays on the current child node while it returns running. Succeeds when all child nodes have succeeded.

.sequence("my-sequence")
    .do("action1", async (t) => { // Run this.
        // Action 1.

        return BehaviorTreeStatus.Success;
    })
    .do("action2", async (t) => { // Then run this.
        //Action 2.

        return BehaviorTreeStatus.Failure;
    })
.end()

Parallel

Runs all child nodes in parallel. Continues to run until a required number of child nodes have either failed or succeeded.

let numRequiredToFail: number = 2;
let numRequiredToSuccess: number = 2;

.parallel("my-parallel"m numRequiredtoFail, numRequiredToSucceed)
    .do("action1", async (t) => { // Run this at the same time as action2
        // Parallel action 1

        return BehaviorTreeStatus.Running;
    })
    .do("action12, async (t) => { // Run this at the same time as action1
        // Parallel action 2

        return BehaviorTreeStatus.Running;
    })
.end();

Selector

Runs child nodes in sequence until it finds one that succeeds. Succeeds when it finds the first child that succeeds. For child nodes that fail, it moves forward to the next child node. While a child is running it stays on that child node without moving forward.

.selector("my-selector")
    .do("action1", async (t) => {
        // Action 1

        return BehaviorTreeStatus.Failure; // Fail, move onto the next child
    })
    .do("action2", async (t) => {
        // Action 2

        return BehaviorTreeStatus.Success; // Success, stop here.
    })
    .do("action3", async (t) => {
        // Action 3

        return BehaviorTreeStatus.Success; // Doesn't get this far.
    })
.end();

Condition

The condition function is syntatic sugar for the do function. It allows the return of a boolean value that is then converted to success or failure. It is intended to be used with Selector.

.selector("my-selector")
    .Condition("condition1", async (t) => this.someBooleanConditional()) // Predicate that returns *true* or *false*
    .do("action1", async (t) => this.someAction()) // Action to run if the predicate evaluates to *true*
.end()

Inverter

Inverts the success or failure of the child node. Continues running while the child node is running.

.inverter("inverter1")
    .do("action1", async (t) => BehaviourTreeStatus.Success) // *Success* will be inverted to *failure*.
.end()


.inverter("inverter1")
    .do("action1", async (t) => BehaviourTreeStatus.Failure) // *Failure* will be inverted to *success*.
.end()

Nesting Behaviour Trees

Behaviour trees can be nested to any depth, for example:

.selector("parent")
    .sequence("child-1")
        ...
        .parallel("grand-child")
            ...
        .end()
        ...
    .end()
    .sequence("child-2")
        ...
    .end()
.end()

Splicing a Sub-tree

Separately created sub-trees can be spliced into parent trees. This makes it easy to build behaviour trees from reusable components.

private createSubTree(): BehaviorTreeNodeInterface
{
    return new BehaviourTreeBuilder()
        .sequence("my-sub-tree")
            .do("action1", async (t) => {
                // Action 1.

                return BehaviourTreeStatus.Success;
            })
            .Do("action2", async (t) => {
                // Action 2.

                return BehaviourTreeStatus.Success;
            });
        .end()
        .build();
}

public startup(): void
{
    this.tree = new BehaviourTreeBuilder()
        .sequence("my-parent-sequence")
            .Splice(this.createSubTree()) // Splice the child tree in.
            .Splice(this.createSubTree()) // Splice again.
        .end()
        .build();
}

fluent-behavior-tree's People

Contributors

cryptiklemur avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

fluent-behavior-tree's Issues

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.

Add tree visualization

Could we get some way of visualizing the current tree? For example:

.selector('wander around')
  .do('do nothing if unit is already moving', CheckMotion.checkIfMoving())
  .sequence('perform wander sequence')
    .do('wait for some time', Wait.wait())
    .do('locate a fitting tile', Tile.locateFitting())
    .do('go to tile', Tile.goToPoint())
    .do('reset wait cycle', Wait.reset())
  .end()
.end()
.build();
const tree = wanderBehavior.tick();
const treeLooksLike = {
  'wander around': {
    name: 'wander around',
    result: 'RUNNING',
    children: {
      'do nothing if already moving': {
        name: 'do nothing if already moving',
        result: 'FAILURE'
      },
      'perform wander sequence': {
        name: 'perform wander sequence',
        result: 'RUNNING',
        children: {
          'wait for some time': {
             name: 'wait for some time',
             result: 'SUCCESS'
          },
          'locate fitting tile': {
             ...,
             result: 'SUCCESS'
          },
          'go to tile': {
            ...,
            result: 'RUNNING'
          },
          'reset wait cycle': {
            ...,
            result: 'SUCCESS' //or maybe 'UNREACHED'? since the tree hasn't reached this point yet, as the previous action is still RUNNING
          }
        }
      }
    }
  }
}

Then you can feed this into your console.log or your tree visualizer package.

I'll see if I can put together a PR if you're interested in having this in the main branch.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.