AI Toolkit is a header-only C++ library which provides tools for building the brain of your game's NPCs.
It provides:
- Finite State Machines
- Behavior Tree
- Utility AI
- Goal Oriented Action Planning
Why this project? Well, I wrote about it here.
Add the include folder of this repository to your include paths.
Or add it as a submodule:
$ git submodule add https://github.com/linkdd/aitoolkit.git
$ g++ -std=c++23 -Iaitoolkit/include main.cpp -o mygame
NB: This library is compatible with C++20.
Or using Shipp, add it to your dependencies:
{
  "name": "myproject",
  "version": "0.1.0",
  "dependencies": [
    {
      "name": "aitoolkit",
      "url": "https://github.com/linkdd/aitoolkit.git",
      "version": "v0.5.1"
    }
  ]
}First, include the header:
#include <aitoolkit/fsm.hpp>
using namespace aitoolkit::fsm;Then, create your blackboard type:
struct blackboard_type {
  // ...
};Then, create a state type for each of your states:
class state_dummy final : public state<blackboard_type> {
  public:
    virtual void enter(blackboard_type& blackboard) override {
      // ...
    }
    virtual void exit(blackboard_type& blackboard) override {
      // ...
    }
    virtual void pause(blackboard_type& blackboard) override {
      // ...
    }
    virtual void resume(blackboard_type& blackboard) override {
      // ...
    }
    virtual void update(blackboard_type& blackboard) override {
      // ...
    }
};Create your simple state machine:
auto simple_bb = blackboard_type{};
auto simple_fsm = simple_machine<blackboard_type>();
simple_fsm.set_state(state_dummy{}, simple_bb);
simple_fsm.pause(simple_bb);
simple_fsm.resume(simple_bb);
simple_fsm.update(simple_bb);Or with a stack state machine:
auto stack_bb = blackboard_type{};
auto stack_fsm = stack_machine<blackboard_type>{};
stack_fsm.push_state(state_dummy{}, stack_bb);
stack_fsm.push_state(state_dummy{}, stack_bb);
stack_fsm.update(stack_bb);
stack_fsm.pop_state(stack_bb);
stack_fsm.pop_state(stack_bb);First, include the header:
#include <aitoolkit/behtree.hpp>
using namespace aitoolkit::bt;Then, create your blackboard type:
struct blackboard_type {
  // ...
};Then, create your tree:
auto tree = seq<blackboard_type>(
  node_list<blackboard_type>(
    check<blackboard_type>([](const blackboard_type& bb) {
      // check some condition
      return true;
    }),
    task<blackboard_type>([](blackboard_type& bb) {
      // perform some action
      return execution_state::success;
    })
  )
);Finally, evaluate it:
auto blackboard = blackboard_type{
  // ...
};
auto state = tree.evaluate(blackboard);For more informations, consult the documentation.
First, include the header file:
#include <aitoolkit/utility.hpp>
using namespace aitoolkit::utility;Then, create a blackboard type:
struct blackboard_type {
  int food{0};
  int wood{0};
  int stone{0};
  int gold{0};
};Next, create a class for each action that you want to be able to perform:
class collect_food final : public action<blackboard_type> {
  public:
    virtual float score(const blackboard_type& blackboard) const override {
      return 50.0f;
    }
    virtual void apply(blackboard_type& blackboard) const override {
      blackboard.food += 1;
    }
};
class collect_wood final : public action<blackboard_type> {
  public:
    virtual float score(const blackboard_type& blackboard) const override {
      return 150.0f;
    }
    virtual void apply(blackboard_type& blackboard) const override {
      blackboard.wood += 1;
    }
};
class collect_stone final : public action<blackboard_type> {
  public:
    virtual float score(const blackboard_type& blackboard) const override {
      return -10.0f;
    }
    virtual void apply(blackboard_type& blackboard) const override {
      blackboard.stone += 1;
    }
};
class collect_gold final : public action<blackboard_type> {
  public:
    virtual float score(const blackboard_type& blackboard) const override {
      return 75.0f;
    }
    virtual void apply(blackboard_type& blackboard) const override {
      blackboard.gold += 1;
    }
};Finally, create an evaluator and run it:
auto evaluator = evaluator<blackboard_type>(
  action_list<blackboard_type>(
    collect_food{},
    collect_wood{},
    collect_stone{},
    collect_gold{}
  )
);
auto blackboard = blackboard_type{};
evaluator.run(blackboard);First, include the header file:
#include <aitoolkit/goap.hpp>
using namespace aitoolkit::goap;Then, create a blackboard class that will hold the state of the planner:
struct blackboard_type {
  bool has_axe{false};
  int wood{0};
};NB: The blackboard needs to be comparable (
a == b) and hashable.
Next, create a class for each action that you want to be able to perform:
class get_axe final : public action<blackboard_type> {
  public:
    virtual float cost(const blackboard_type& blackboard) const override {
      return 1.0f;
    }
    virtual bool check_preconditions(const blackboard_type& blackboard) const override {
      return !blackboard.has_axe;
    }
    virtual void apply_effects(blackboard_type& blackboard, bool dry_run) const override {
      blackboard.has_axe = true;
    }
};
class chop_tree final : public action<blackboard_type> {
  public:
    virtual float cost(const blackboard_type& blackboard) const override {
      return 1.0f;
    }
    virtual bool check_preconditions(const blackboard_type& blackboard) const override {
      return blackboard.has_axe;
    }
    virtual void apply_effects(blackboard_type& blackboard, bool dry_run) const override {
      blackboard.wood += 1;
    }
};Finally, create a plan and run it:
auto initial = blackboard_type{};
auto goal = blackboard_type{
  .has_axe = true,
  .wood = 3
};
auto p = planner<blackboard_type>(
  action_list<blackboard_type>(
    get_axe{},
    chop_tree{}
  ),
  initial,
  goal
);
auto blackboard = initial;
while (p) {
  p.run_next(blackboard); // will mutate the blackboard
}For more informations, consult the documentation.
The documentation is available online here.
You can build it locally using doxygen:
$ make docs
This library is released under the terms of the MIT License.