MIT License

项目介绍

linkdd/aitoolkit 是一个托管在 GitHub 上的开源项目,主要使用 C++ 编写,采用 MIT License 许可证,目前获得 531 个 Star、29 次 Fork。

仓库全名
linkdd/aitoolkit
开源许可证
MIT License
Star 数
531
Fork 数
29

README 摘要

AI Toolkit 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. Installation Add the include folder of this repository to your include paths. Or add it as a submodule: NB: This library is compatible with C++20. Or using Shipp, add…

完整内容见 GitHub 原始 README 或本页 。

常见问题

aitoolkit 用什么语言开发?

主要使用 C++ 编写,采用 MIT License 许可证,目前有 531 个 Star。

aitoolkit 可以免费商用吗?

仓库采用 MIT License 许可证,可免费使用与修改,商业使用请遵守许可证条款(例如保留版权声明与许可声明)。

如何获取 aitoolkit 的源码?

可以直接克隆仓库:git clone https://github.com/linkdd/aitoolkit.git,默认分支为 main;安装与运行步骤见仓库 README。

aitoolkit 最近还在维护吗?

仓库最近一次更新为 2024年5月8日,当前没有未关闭的 Issue;Star 数为 531,可作为社区活跃度的参考。

关于

Give a brain to your game's NPCs

描述取自 GitHub 官方 API,中文内容由 GitRead 中文社区 编辑团队整理。

简要分析

热度分
595
价值分
327
活跃状态
活跃

语言占比

C++
Makefile

Release

README

AI Toolkit

tests docs license version

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.

Installation

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"
    }
  ]
}

Usage

Finite State Machine

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);

Behavior Tree

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.

Utility AI

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);

Goal Oriented Action Planning

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.

Documentation

The documentation is available online here.

You can build it locally using doxygen:

$ make docs

License

This library is released under the terms of the MIT License.

评论

暂无评论