Переглянути джерело

st: 代码格式化

master
SisMaker 4 роки тому
джерело
коміт
f2219da05e
49 змінених файлів з 697 додано та 694 видалено
  1. +7
    -4
      README.md
  2. +3
    -3
      examples/action/action_add_rage.erl
  3. +3
    -3
      examples/action/action_become_attacking.erl
  4. +3
    -3
      examples/action/action_become_idle.erl
  5. +3
    -3
      examples/action/action_become_patrolling.erl
  6. +3
    -3
      examples/action/action_become_recovering.erl
  7. +35
    -35
      examples/action/action_collect_dest_path.erl
  8. +21
    -21
      examples/action/action_collect_path.erl
  9. +8
    -8
      examples/action/action_collect_patrol.erl
  10. +4
    -4
      examples/action/action_cost_power.erl
  11. +3
    -3
      examples/action/action_cost_rage.erl
  12. +2
    -2
      examples/action/action_del_dead_target.erl
  13. +3
    -3
      examples/action/action_died.erl
  14. +3
    -3
      examples/action/action_finish.erl
  15. +4
    -4
      examples/action/action_move_grid.erl
  16. +4
    -4
      examples/action/action_recover_power.erl
  17. +24
    -24
      examples/action/action_skill_attack.erl
  18. +6
    -6
      examples/condition/cond_is_attacking.erl
  19. +6
    -6
      examples/condition/cond_is_dest.erl
  20. +6
    -6
      examples/condition/cond_is_died.erl
  21. +6
    -6
      examples/condition/cond_is_idle.erl
  22. +6
    -6
      examples/condition/cond_is_patrolling.erl
  23. +6
    -6
      examples/condition/cond_is_power_full.erl
  24. +6
    -6
      examples/condition/cond_is_rage_full.erl
  25. +6
    -6
      examples/condition/cond_is_recovering.erl
  26. +11
    -11
      examples/condition/cond_is_target_died.erl
  27. +7
    -7
      examples/condition/cond_power_lt.erl
  28. +22
    -22
      examples/game_dict.erl
  29. +70
    -70
      examples/game_process.erl
  30. +22
    -22
      include/behavior3.hrl
  31. +1
    -1
      src/action/error.erl
  32. +1
    -1
      src/action/failer.erl
  33. +1
    -1
      src/action/runner.erl
  34. +1
    -1
      src/action/succeeder.erl
  35. +9
    -9
      src/action/wait.erl
  36. +14
    -14
      src/composite/mem_priority.erl
  37. +14
    -14
      src/composite/mem_sequence.erl
  38. +8
    -8
      src/composite/priority.erl
  39. +8
    -8
      src/composite/sequence.erl
  40. +76
    -76
      src/core/base_node.erl
  41. +99
    -99
      src/core/behavior_tree.erl
  42. +65
    -65
      src/core/blackboard.erl
  43. +9
    -9
      src/decorator/inverter.erl
  44. +15
    -15
      src/decorator/limiter.erl
  45. +12
    -12
      src/decorator/max_time.erl
  46. +14
    -14
      src/decorator/repeat_until_failure.erl
  47. +14
    -14
      src/decorator/repeat_until_success.erl
  48. +14
    -14
      src/decorator/repeater.erl
  49. +9
    -9
      src/eBhv3.app.src

+ 7
- 4
README.md Переглянути файл

@ -13,14 +13,16 @@ Behavior3的erlang支持库
编译 编译
---- ----
$ rebar3 compile $ rebar3 compile
使用 使用
---- ----
{TitleMaps, TreeMaps, TreeNodeMaps} = behavior_tree:load_tree_file("example.json"), {TitleMaps, TreeMaps, TreeNodeMaps} = behavior_tree:load_tree_file("example.json"),
{ok, RootID} = behavior_tree:init_btree_by_title(<<"example_ai"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps), {ok, RootID} = behavior_tree:init_btree_by_title(<<"example_ai"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps),
{_BTStatus, _BTState1} = behavior_tree:execute(RootID, BTState = #{}). {_BTStatus, _BTState1} = behavior_tree:execute(RootID, BTState = #{}).
更多 更多
---- ----
[behavior3editor](https://github.com/behavior3/behavior3editor) [behavior3editor](https://github.com/behavior3/behavior3editor)
@ -63,13 +65,14 @@ Build
---- ----
$ rebar3 compile $ rebar3 compile
Usage Usage
---- ----
{TitleMaps, TreeMaps, TreeNodeMaps} = behavior_tree:load_tree_file("example.json"), {TitleMaps, TreeMaps, TreeNodeMaps} = behavior_tree:load_tree_file("example.json"),
{ok, RootID} = behavior_tree:init_btree_by_title(<<"example_ai"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps), {ok, RootID} = behavior_tree:init_btree_by_title(<<"example_ai"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps),
{_BTStatus, _BTState1} = behavior_tree:execute(RootID, BTState = #{}). {_BTStatus, _BTState1} = behavior_tree:execute(RootID, BTState = #{}).
More More
---- ----

+ 3
- 3
examples/action/action_add_rage.erl Переглянути файл

@ -16,6 +16,6 @@
-export([tick/2]). -export([tick/2]).
tick(#{properties := #{add_rage := AddRage}} = _BTree, #{cur_rage := CurRage} = State) -> tick(#{properties := #{add_rage := AddRage}} = _BTree, #{cur_rage := CurRage} = State) ->
State1 = State#{cur_rage := min(CurRage + AddRage, ?MAX_RAGE)},
?INFO("~ts:怒气值增加~w点 总怒气~w", [maps:get(uid, State1), AddRage, maps:get(cur_rage, State1)]),
{?BT_SUCCESS, State1}.
State1 = State#{cur_rage := min(CurRage + AddRage, ?MAX_RAGE)},
?INFO("~ts:怒气值增加~w点 总怒气~w", [maps:get(uid, State1), AddRage, maps:get(cur_rage, State1)]),
{?BT_SUCCESS, State1}.

+ 3
- 3
examples/action/action_become_attacking.erl Переглянути файл

@ -15,6 +15,6 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, State) -> tick(_BTree, State) ->
State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_ATTACKING)},
?INFO("~ts:变为攻击状态", [maps:get(uid, State1)]),
{?BT_SUCCESS, State1}.
State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_ATTACKING)},
?INFO("~ts:变为攻击状态", [maps:get(uid, State1)]),
{?BT_SUCCESS, State1}.

+ 3
- 3
examples/action/action_become_idle.erl Переглянути файл

@ -15,6 +15,6 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, State) -> tick(_BTree, State) ->
State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_IDLE)},
?INFO("~ts:变为空闲状态", [maps:get(uid, State1)]),
{?BT_SUCCESS, State1}.
State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_IDLE)},
?INFO("~ts:变为空闲状态", [maps:get(uid, State1)]),
{?BT_SUCCESS, State1}.

+ 3
- 3
examples/action/action_become_patrolling.erl Переглянути файл

@ -15,6 +15,6 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, State) -> tick(_BTree, State) ->
State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_PATROLLING)},
?INFO("~ts:变为巡逻状态", [maps:get(uid, State1)]),
{?BT_SUCCESS, State1}.
State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_PATROLLING)},
?INFO("~ts:变为巡逻状态", [maps:get(uid, State1)]),
{?BT_SUCCESS, State1}.

+ 3
- 3
examples/action/action_become_recovering.erl Переглянути файл

@ -15,6 +15,6 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, State) -> tick(_BTree, State) ->
State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_RECOVERING)},
?INFO("~ts:变为恢复状态", [maps:get(uid, State1)]),
{?BT_SUCCESS, State1}.
State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_RECOVERING)},
?INFO("~ts:变为恢复状态", [maps:get(uid, State1)]),
{?BT_SUCCESS, State1}.

+ 35
- 35
examples/action/action_collect_dest_path.erl Переглянути файл

@ -15,46 +15,46 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{cur_grid := CurGrid, grid_list := GirdList} = State) -> tick(_BTree, #{cur_grid := CurGrid, grid_list := GirdList} = State) ->
case GirdList of
[] ->
EndGrid = get_end_grid(CurGrid),
State1 = State#{grid_list := get_grid_path(CurGrid, EndGrid)},
?INFO("~ts:找到穿传说中的“大蒜”的位置,要尽快到达那里!", [maps:get(uid, State1)]),
{?BT_SUCCESS, State1};
_ ->
?INFO("~ts:天要黑了,要尽快到达那里!", [maps:get(uid, State)]),
{?BT_SUCCESS, State}
end.
case GirdList of
[] ->
EndGrid = get_end_grid(CurGrid),
State1 = State#{grid_list := get_grid_path(CurGrid, EndGrid)},
?INFO("~ts:找到穿传说中的“大蒜”的位置,要尽快到达那里!", [maps:get(uid, State1)]),
{?BT_SUCCESS, State1};
_ ->
?INFO("~ts:天要黑了,要尽快到达那里!", [maps:get(uid, State)]),
{?BT_SUCCESS, State}
end.
get_end_grid(CurGrid) -> get_end_grid(CurGrid) ->
EndGridList = [{0, 0}, {0, ?MAX_X}, {?MAX_Y, ?MAX_X}, {?MAX_Y, 0}],
{_, EndGrid} = hd(lists:sort([{calc_distance(CurGrid, Grid), Grid} || Grid <- EndGridList])),
EndGrid.
EndGridList = [{0, 0}, {0, ?MAX_X}, {?MAX_Y, ?MAX_X}, {?MAX_Y, 0}],
{_, EndGrid} = hd(lists:sort([{calc_distance(CurGrid, Grid), Grid} || Grid <- EndGridList])),
EndGrid.
calc_distance({X1, Y1}, {X2, Y2}) -> calc_distance({X1, Y1}, {X2, Y2}) ->
math:sqrt(math:pow(X1 - X2, 2) + math:pow(Y1 - Y2, 2)).
math:sqrt(math:pow(X1 - X2, 2) + math:pow(Y1 - Y2, 2)).
get_grid_path(CurGrid, EndGrid) -> get_grid_path(CurGrid, EndGrid) ->
case EndGrid of
{0, 0} ->
get_grid_path(CurGrid, [EndGrid], 1, 1);
{0, ?MAX_X} ->
get_grid_path(CurGrid, [EndGrid], 1, -1);
{?MAX_Y, ?MAX_X} ->
get_grid_path(CurGrid, [EndGrid], -1, -1);
{?MAX_Y, 0} ->
get_grid_path(CurGrid, [EndGrid], -1, 1)
end.
case EndGrid of
{0, 0} ->
get_grid_path(CurGrid, [EndGrid], 1, 1);
{0, ?MAX_X} ->
get_grid_path(CurGrid, [EndGrid], 1, -1);
{?MAX_Y, ?MAX_X} ->
get_grid_path(CurGrid, [EndGrid], -1, -1);
{?MAX_Y, 0} ->
get_grid_path(CurGrid, [EndGrid], -1, 1)
end.
get_grid_path(CurGrid, GridPath, XInc, YInc) -> get_grid_path(CurGrid, GridPath, XInc, YInc) ->
case GridPath of
[CurGrid | _] ->
GridPath;
[{X, Y} | _] ->
case Y + YInc of
Y1 when Y1 == 0 orelse Y1 == ?MAX_X ->
get_grid_path(CurGrid, [{X + XInc, Y1}, {X, Y1} | GridPath], XInc, bnot YInc + 1);
Y1 ->
get_grid_path(CurGrid, [{X, Y1} | GridPath], XInc, YInc)
end
end.
case GridPath of
[CurGrid | _] ->
GridPath;
[{X, Y} | _] ->
case Y + YInc of
Y1 when Y1 == 0 orelse Y1 == ?MAX_X ->
get_grid_path(CurGrid, [{X + XInc, Y1}, {X, Y1} | GridPath], XInc, bnot YInc + 1);
Y1 ->
get_grid_path(CurGrid, [{X, Y1} | GridPath], XInc, YInc)
end
end.

+ 21
- 21
examples/action/action_collect_path.erl Переглянути файл

@ -16,30 +16,30 @@
tick(_BTree, #{cur_grid := CurGrid} = State) -> tick(_BTree, #{cur_grid := CurGrid} = State) ->
State1 = State#{grid_list := get_grid_path(CurGrid)},
{?BT_SUCCESS, State1}.
State1 = State#{grid_list := get_grid_path(CurGrid)},
{?BT_SUCCESS, State1}.
get_grid_path(CurGrid) -> get_grid_path(CurGrid) ->
List = [{1, 0}, {-1, 0}, {0, 1}, {0, -1}],
Max = length(List),
List1 = [E || {_, E} <- lists:sort([{?RAND(1, Max), E} || E <- List])],
case get_grid_path_1(List1, CurGrid, []) of
[] ->
get_grid_path(CurGrid);
Result ->
Result
end.
List = [{1, 0}, {-1, 0}, {0, 1}, {0, -1}],
Max = length(List),
List1 = [E || {_, E} <- lists:sort([{?RAND(1, Max), E} || E <- List])],
case get_grid_path_1(List1, CurGrid, []) of
[] ->
get_grid_path(CurGrid);
Result ->
Result
end.
get_grid_path_1([{X, Y} | T], {CurX, CurY}, Result) -> get_grid_path_1([{X, Y} | T], {CurX, CurY}, Result) ->
X1 = CurX + X,
Y1 = CurY + Y,
Grid = {X1, Y1},
case X1 >= 0 andalso X1 =< ?MAX_X andalso Y1 >= 0 andalso Y1 =< ?MAX_Y of
true ->
get_grid_path_1(T, Grid, [Grid | Result]);
false ->
[]
end;
X1 = CurX + X,
Y1 = CurY + Y,
Grid = {X1, Y1},
case X1 >= 0 andalso X1 =< ?MAX_X andalso Y1 >= 0 andalso Y1 =< ?MAX_Y of
true ->
get_grid_path_1(T, Grid, [Grid | Result]);
false ->
[]
end;
get_grid_path_1([], _, Result) -> get_grid_path_1([], _, Result) ->
Result.
Result.

+ 8
- 8
examples/action/action_collect_patrol.erl Переглянути файл

@ -16,11 +16,11 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{cur_grid := CurGrid, rival_list := RivalList} = State) -> tick(_BTree, #{cur_grid := CurGrid, rival_list := RivalList} = State) ->
Fun = fun(UID) -> maps:get(type, game_dict:get_role_state(UID)) == ?HUMAN end,
case lists:filter(Fun, game_dict:get_map_data(CurGrid)) of
UIDList when UIDList /= [] ->
?INFO("~ts:嗅到了人类的味道,将要对[~ts]发起攻击", [maps:get(uid, State), lists:join(",", UIDList)]),
{?BT_SUCCESS, State#{rival_list := UIDList ++ RivalList}};
[] ->
{?BT_FAILURE, State}
end.
Fun = fun(UID) -> maps:get(type, game_dict:get_role_state(UID)) == ?HUMAN end,
case lists:filter(Fun, game_dict:get_map_data(CurGrid)) of
UIDList when UIDList /= [] ->
?INFO("~ts:嗅到了人类的味道,将要对[~ts]发起攻击", [maps:get(uid, State), lists:join(",", UIDList)]),
{?BT_SUCCESS, State#{rival_list := UIDList ++ RivalList}};
[] ->
{?BT_FAILURE, State}
end.

+ 4
- 4
examples/action/action_cost_power.erl Переглянути файл

@ -16,7 +16,7 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, State) -> tick(_BTree, State) ->
#{cur_power := CurPower, misc := #{atk_dmg := {AtkType, Dmg}} = Misc} = State,
State1 = State#{cur_power := max(CurPower - Dmg, 0), misc := maps:remove(atk_dmg, Misc)},
?INFO("~ts:受到~ts攻击,体力值减少~w点 剩余体力~w", [maps:get(uid, State1), AtkType, Dmg,maps:get(cur_power, State1)]),
{?BT_SUCCESS, State1}.
#{cur_power := CurPower, misc := #{atk_dmg := {AtkType, Dmg}} = Misc} = State,
State1 = State#{cur_power := max(CurPower - Dmg, 0), misc := maps:remove(atk_dmg, Misc)},
?INFO("~ts:受到~ts攻击,体力值减少~w点 剩余体力~w", [maps:get(uid, State1), AtkType, Dmg, maps:get(cur_power, State1)]),
{?BT_SUCCESS, State1}.

+ 3
- 3
examples/action/action_cost_rage.erl Переглянути файл

@ -16,6 +16,6 @@
-export([tick/2]). -export([tick/2]).
tick(#{properties := #{cost_rage := CostRage}} = _BTree, #{cur_rage := CurRage} = State) -> tick(#{properties := #{cost_rage := CostRage}} = _BTree, #{cur_rage := CurRage} = State) ->
State1 = State#{cur_rage := max(CurRage - CostRage, 0)},
?INFO("~ts:怒气值减少~w", [maps:get(uid, State1), CurRage - maps:get(cur_rage, State1)]),
{?BT_SUCCESS, State1}.
State1 = State#{cur_rage := max(CurRage - CostRage, 0)},
?INFO("~ts:怒气值减少~w", [maps:get(uid, State1), CurRage - maps:get(cur_rage, State1)]),
{?BT_SUCCESS, State1}.

+ 2
- 2
examples/action/action_del_dead_target.erl Переглянути файл

@ -16,5 +16,5 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{rival_list := [_ | T]} = State) -> tick(_BTree, #{rival_list := [_ | T]} = State) ->
State1 = State#{rival_list := T},
{?BT_SUCCESS, State1}.
State1 = State#{rival_list := T},
{?BT_SUCCESS, State1}.

+ 3
- 3
examples/action/action_died.erl Переглянути файл

@ -16,6 +16,6 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{uid := UID} = State) -> tick(_BTree, #{uid := UID} = State) ->
self() ! {died, UID},
?INFO("~ts 被消灭!", [UID]),
{?BT_SUCCESS, State#{cur_state := ?SET_STATE(?STATE_TYPE_DEAD)}}.
self() ! {died, UID},
?INFO("~ts 被消灭!", [UID]),
{?BT_SUCCESS, State#{cur_state := ?SET_STATE(?STATE_TYPE_DEAD)}}.

+ 3
- 3
examples/action/action_finish.erl Переглянути файл

@ -16,6 +16,6 @@
-export([tick/2]). -export([tick/2]).
tick(#{properties := #{is_win := IsWin}} = _BTree, #{uid := UID} = State) -> tick(#{properties := #{is_win := IsWin}} = _BTree, #{uid := UID} = State) ->
self() ! finish,
?INFO("游戏结束,~ts~ts!", [UID, IsWin]),
{?BT_SUCCESS, State}.
self() ! finish,
?INFO("游戏结束,~ts~ts!", [UID, IsWin]),
{?BT_SUCCESS, State}.

+ 4
- 4
examples/action/action_move_grid.erl Переглянути файл

@ -15,7 +15,7 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{uid := UID, cur_grid := OldGrid, grid_list := [Grid | T]} = State) -> tick(_BTree, #{uid := UID, cur_grid := OldGrid, grid_list := [Grid | T]} = State) ->
game_dict:update_map_date(OldGrid, Grid, UID),
State1 = State#{grid_list := T, cur_grid := Grid},
?INFO("~ts:移动到了~w格子", [UID, Grid]),
{?BT_SUCCESS, State1}.
game_dict:update_map_date(OldGrid, Grid, UID),
State1 = State#{grid_list := T, cur_grid := Grid},
?INFO("~ts:移动到了~w格子", [UID, Grid]),
{?BT_SUCCESS, State1}.

+ 4
- 4
examples/action/action_recover_power.erl Переглянути файл

@ -16,7 +16,7 @@
-export([tick/2]). -export([tick/2]).
tick(#{properties := #{max_power := MaxPower, min_power := MinPower}} = _BTree, #{cur_power := CurPower} = State) -> tick(#{properties := #{max_power := MaxPower, min_power := MinPower}} = _BTree, #{cur_power := CurPower} = State) ->
RecoverPower = ?RAND(MinPower, MaxPower),
State1 = State#{cur_power := min(CurPower + RecoverPower, ?MAX_POWER)},
?INFO("~ts:体力值增加了~w点 当前体力:~w", [maps:get(uid, State1), RecoverPower, maps:get(cur_power, State1)]),
{?BT_SUCCESS, State1}.
RecoverPower = ?RAND(MinPower, MaxPower),
State1 = State#{cur_power := min(CurPower + RecoverPower, ?MAX_POWER)},
?INFO("~ts:体力值增加了~w点 当前体力:~w", [maps:get(uid, State1), RecoverPower, maps:get(cur_power, State1)]),
{?BT_SUCCESS, State1}.

+ 24
- 24
examples/action/action_skill_attack.erl Переглянути файл

@ -16,29 +16,29 @@
-export([tick/2]). -export([tick/2]).
tick(#{properties := Prop} = _BTree, #{uid := UID, rival_list := [RivalUID | _]} = State) -> tick(#{properties := Prop} = _BTree, #{uid := UID, rival_list := [RivalUID | _]} = State) ->
BTreeID = game_dict:get_passivity_btree_id(RivalUID),
RivalState = get_be_attacker_rival_state(Prop, UID, RivalUID),
{_, RivalState1} = behavior_tree:execute_sub_tree(BTreeID, RivalState),
game_dict:put_role_state(RivalUID, RivalState1),
{?BT_SUCCESS, State}.
BTreeID = game_dict:get_passivity_btree_id(RivalUID),
RivalState = get_be_attacker_rival_state(Prop, UID, RivalUID),
{_, RivalState1} = behavior_tree:execute_sub_tree(BTreeID, RivalState),
game_dict:put_role_state(RivalUID, RivalState1),
{?BT_SUCCESS, State}.
get_be_attacker_rival_state(Prop, UID, RivalUID) -> get_be_attacker_rival_state(Prop, UID, RivalUID) ->
#{
skill_type := SkillType,
min_power := MinPower, max_power := MaxPower,
min_rate := MinRate, max_rate := MaxRate
} = Prop,
#{rival_list := RivalList} = RivalState = game_dict:get_role_state(RivalUID),
case lists:member(UID, RivalList) of
true ->
RivalList1 = RivalList;
false ->
RivalList1 = RivalList ++ [UID]
end,
RivalState1 = RivalState#{
rival_list := RivalList1,
misc := #{atk_dmg => {SkillType, ?RAND(MinPower, MaxPower) * ?RAND(MinRate, MaxRate)}}
},
game_dict:put_role_state(RivalUID, RivalState1),
?INFO("~ts:发动了~ts攻击", [UID, SkillType]),
RivalState1.
#{
skill_type := SkillType,
min_power := MinPower, max_power := MaxPower,
min_rate := MinRate, max_rate := MaxRate
} = Prop,
#{rival_list := RivalList} = RivalState = game_dict:get_role_state(RivalUID),
case lists:member(UID, RivalList) of
true ->
RivalList1 = RivalList;
false ->
RivalList1 = RivalList ++ [UID]
end,
RivalState1 = RivalState#{
rival_list := RivalList1,
misc := #{atk_dmg => {SkillType, ?RAND(MinPower, MaxPower) * ?RAND(MinRate, MaxRate)}}
},
game_dict:put_role_state(RivalUID, RivalState1),
?INFO("~ts:发动了~ts攻击", [UID, SkillType]),
RivalState1.

+ 6
- 6
examples/condition/cond_is_attacking.erl Переглянути файл

@ -16,9 +16,9 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{cur_state := CurState} = State) -> tick(_BTree, #{cur_state := CurState} = State) ->
case ?IS_STATE(?STATE_TYPE_ATTACKING, CurState) of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.
case ?IS_STATE(?STATE_TYPE_ATTACKING, CurState) of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.

+ 6
- 6
examples/condition/cond_is_dest.erl Переглянути файл

@ -15,9 +15,9 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, State) -> tick(_BTree, State) ->
case State of
#{grid_list := []} ->
{?BT_SUCCESS, State};
#{} ->
{?BT_FAILURE, State}
end.
case State of
#{grid_list := []} ->
{?BT_SUCCESS, State};
#{} ->
{?BT_FAILURE, State}
end.

+ 6
- 6
examples/condition/cond_is_died.erl Переглянути файл

@ -15,9 +15,9 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{cur_power := CurPower} = State) -> tick(_BTree, #{cur_power := CurPower} = State) ->
case CurPower =< 0 of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.
case CurPower =< 0 of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.

+ 6
- 6
examples/condition/cond_is_idle.erl Переглянути файл

@ -16,9 +16,9 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{cur_state := CurState} = State) -> tick(_BTree, #{cur_state := CurState} = State) ->
case ?IS_STATE(?STATE_TYPE_IDLE, CurState) of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.
case ?IS_STATE(?STATE_TYPE_IDLE, CurState) of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.

+ 6
- 6
examples/condition/cond_is_patrolling.erl Переглянути файл

@ -16,9 +16,9 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{cur_state := CurState} = State) -> tick(_BTree, #{cur_state := CurState} = State) ->
case ?IS_STATE(?STATE_TYPE_PATROLLING, CurState) of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.
case ?IS_STATE(?STATE_TYPE_PATROLLING, CurState) of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.

+ 6
- 6
examples/condition/cond_is_power_full.erl Переглянути файл

@ -16,9 +16,9 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{cur_power := CurPower} = State) -> tick(_BTree, #{cur_power := CurPower} = State) ->
case CurPower >= ?MAX_POWER of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.
case CurPower >= ?MAX_POWER of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.

+ 6
- 6
examples/condition/cond_is_rage_full.erl Переглянути файл

@ -16,9 +16,9 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{cur_rage := CurRage} = State) -> tick(_BTree, #{cur_rage := CurRage} = State) ->
case CurRage >= ?MAX_RAGE of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.
case CurRage >= ?MAX_RAGE of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.

+ 6
- 6
examples/condition/cond_is_recovering.erl Переглянути файл

@ -16,9 +16,9 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, #{cur_state := CurState} = State) -> tick(_BTree, #{cur_state := CurState} = State) ->
case ?IS_STATE(?STATE_TYPE_RECOVERING, CurState) of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.
case ?IS_STATE(?STATE_TYPE_RECOVERING, CurState) of
true ->
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.

+ 11
- 11
examples/condition/cond_is_target_died.erl Переглянути файл

@ -15,14 +15,14 @@
-export([tick/2]). -export([tick/2]).
tick(_BTree, State) -> tick(_BTree, State) ->
case State of
#{rival_list := [RivalUID | _]} ->
case game_dict:get_role_state(RivalUID) of
#{cur_state := CurState} when ?IS_STATE(?STATE_TYPE_DEAD, CurState) ->
{?BT_SUCCESS, State};
#{} ->
{?BT_FAILURE, State}
end;
#{} ->
{?BT_FAILURE, State}
end.
case State of
#{rival_list := [RivalUID | _]} ->
case game_dict:get_role_state(RivalUID) of
#{cur_state := CurState} when ?IS_STATE(?STATE_TYPE_DEAD, CurState) ->
{?BT_SUCCESS, State};
#{} ->
{?BT_FAILURE, State}
end;
#{} ->
{?BT_FAILURE, State}
end.

+ 7
- 7
examples/condition/cond_power_lt.erl Переглянути файл

@ -15,10 +15,10 @@
-export([tick/2]). -export([tick/2]).
tick(#{properties := #{power := LTPower}} = _BTree, #{cur_power := CurPower} = State) -> tick(#{properties := #{power := LTPower}} = _BTree, #{cur_power := CurPower} = State) ->
case CurPower < LTPower of
true ->
?INFO("~ts:当前体力低于~w点,必须要尽快休息恢复体力!", [maps:get(uid, State), LTPower]),
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.
case CurPower < LTPower of
true ->
?INFO("~ts:当前体力低于~w点,必须要尽快休息恢复体力!", [maps:get(uid, State), LTPower]),
{?BT_SUCCESS, State};
false ->
{?BT_FAILURE, State}
end.

+ 22
- 22
examples/game_dict.erl Переглянути файл

@ -13,47 +13,47 @@
%% API %% API
-export([ -export([
get_map_data/1, update_map_date/3,
get_initiative_btree_id/1, put_initiative_btree_id/2, erase_initiative_btree_id/1,
get_passivity_btree_id/1, put_passivity_btree_id/2, erase_passivity_btree_id/1,
get_role_state/1, put_role_state/2, erase_role_state/1
get_map_data/1, update_map_date/3,
get_initiative_btree_id/1, put_initiative_btree_id/2, erase_initiative_btree_id/1,
get_passivity_btree_id/1, put_passivity_btree_id/2, erase_passivity_btree_id/1,
get_role_state/1, put_role_state/2, erase_role_state/1
]). ]).
-spec get_map_data(grid()) -> [uid()]. -spec get_map_data(grid()) -> [uid()].
get_map_data(Grid) -> get_map_data(Grid) ->
case erlang:get(Grid) of
undefined ->
[];
L ->
L
end.
case erlang:get(Grid) of
undefined ->
[];
L ->
L
end.
-spec update_map_date(grid(), grid(), uid()) -> ok. -spec update_map_date(grid(), grid(), uid()) -> ok.
update_map_date(OldGrid, NewGrid, UID) -> update_map_date(OldGrid, NewGrid, UID) ->
erlang:put(OldGrid, lists:delete(UID, get_map_data(OldGrid))),
erlang:put(NewGrid, [UID | get_map_data(NewGrid)]),
ok.
erlang:put(OldGrid, lists:delete(UID, get_map_data(OldGrid))),
erlang:put(NewGrid, [UID | get_map_data(NewGrid)]),
ok.
-spec get_initiative_btree_id(uid()) -> bt_uid(). -spec get_initiative_btree_id(uid()) -> bt_uid().
get_initiative_btree_id(UID) -> get_initiative_btree_id(UID) ->
erlang:get({initiative_btree_id, UID}).
erlang:get({initiative_btree_id, UID}).
put_initiative_btree_id(UID, BTreeID) -> put_initiative_btree_id(UID, BTreeID) ->
erlang:put({initiative_btree_id, UID}, BTreeID).
erlang:put({initiative_btree_id, UID}, BTreeID).
erase_initiative_btree_id(UID) -> erase_initiative_btree_id(UID) ->
erlang:erase({initiative_btree_id, UID}).
erlang:erase({initiative_btree_id, UID}).
-spec get_passivity_btree_id(uid()) -> bt_uid(). -spec get_passivity_btree_id(uid()) -> bt_uid().
get_passivity_btree_id(UID) -> get_passivity_btree_id(UID) ->
erlang:get({passivity_btree_id, UID}).
erlang:get({passivity_btree_id, UID}).
put_passivity_btree_id(UID, BTreeID) -> put_passivity_btree_id(UID, BTreeID) ->
erlang:put({passivity_btree_id, UID}, BTreeID).
erlang:put({passivity_btree_id, UID}, BTreeID).
erase_passivity_btree_id(UID) -> erase_passivity_btree_id(UID) ->
erlang:erase({passivity_btree_id, UID}).
erlang:erase({passivity_btree_id, UID}).
-spec get_role_state(uid()) -> map(). -spec get_role_state(uid()) -> map().
get_role_state(UID) -> get_role_state(UID) ->
erlang:get({role_state, UID}).
erlang:get({role_state, UID}).
put_role_state(UID, State) -> put_role_state(UID, State) ->
erlang:put({role_state, UID}, State).
erlang:put({role_state, UID}, State).
erase_role_state(UID) -> erase_role_state(UID) ->
erlang:erase({role_state, UID}).
erlang:erase({role_state, UID}).

+ 70
- 70
examples/game_process.erl Переглянути файл

@ -21,12 +21,12 @@
%%%=================================================================== %%%===================================================================
start_link() -> start_link() ->
gen_server:start_link(?MODULE, [], []).
gen_server:start_link(?MODULE, [], []).
init([]) -> init([]) ->
{TitleMaps, TreeMaps, TreeNodeMaps} = behavior_tree:load_tree_file("examples/example.json"),
{TitleMaps, TreeMaps, TreeNodeMaps} = behavior_tree:load_tree_file("examples/example.json"),
ZombieList = [
ZombieList = [
%% <<"HUNTER"/utf8>>, %% <<"HUNTER"/utf8>>,
%% <<"BOMMER"/utf8>>, %% <<"BOMMER"/utf8>>,
%% <<"JOCKEY"/utf8>>, %% <<"JOCKEY"/utf8>>,
@ -34,94 +34,94 @@ init([]) ->
%% <<"SPITTER"/utf8>>, %% <<"SPITTER"/utf8>>,
%% <<"CHARGER"/utf8>>, %% <<"CHARGER"/utf8>>,
%% <<"TANK"/utf8>>, %% <<"TANK"/utf8>>,
<<"WITCH"/utf8>>
],
init_zombie(ZombieList, TitleMaps, TreeMaps, TreeNodeMaps),
<<"WITCH"/utf8>>
],
init_zombie(ZombieList, TitleMaps, TreeMaps, TreeNodeMaps),
UID = <<"凯恩"/utf8>>,
init_patrol(UID, TitleMaps, TreeMaps, TreeNodeMaps),
erlang:put(uid_list, ZombieList ++ [UID]),
self() ! run,
{ok, #{frame => 1}}.
UID = <<"凯恩"/utf8>>,
init_patrol(UID, TitleMaps, TreeMaps, TreeNodeMaps),
erlang:put(uid_list, ZombieList ++ [UID]),
self() ! run,
{ok, #{frame => 1}}.
handle_call(_Request, _From, State) -> handle_call(_Request, _From, State) ->
{reply, ok, State}.
{reply, ok, State}.
handle_cast(_Request, State) -> handle_cast(_Request, State) ->
{noreply, State}.
{noreply, State}.
handle_info(run, #{frame := Frame} = State) -> handle_info(run, #{frame := Frame} = State) ->
try
?INFO("~w分钟", [Frame]),
Fun = fun(UID) -> run(UID) end,
lists:foreach(Fun, get(uid_list)),
erlang:send_after(1000, self(), run),
{noreply, State#{frame := Frame + 1}}
catch
Error:Reason:StackTrace ->
?INFO("Error:~w Reason:~w ~n StackTrace:~p", [Error, Reason, StackTrace]),
{stop, normal, State}
end;
try
?INFO("~w分钟", [Frame]),
Fun = fun(UID) -> run(UID) end,
lists:foreach(Fun, get(uid_list)),
erlang:send_after(1000, self(), run),
{noreply, State#{frame := Frame + 1}}
catch
Error:Reason:StackTrace ->
?INFO("Error:~w Reason:~w ~n StackTrace:~p", [Error, Reason, StackTrace]),
{stop, normal, State}
end;
handle_info(finish, State) -> handle_info(finish, State) ->
{stop, normal, State};
{stop, normal, State};
handle_info({died, UID}, State) -> handle_info({died, UID}, State) ->
erlang:put(uid_list, lists:delete(UID, erlang:get(uid_list))),
{noreply, State};
erlang:put(uid_list, lists:delete(UID, erlang:get(uid_list))),
{noreply, State};
handle_info(_Info, State) -> handle_info(_Info, State) ->
{noreply, State}.
{noreply, State}.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions
%%%=================================================================== %%%===================================================================
new_state(UID, Type, CurGrid) -> new_state(UID, Type, CurGrid) ->
case Type of
?HUMAN ->
Power = ?MAX_POWER;
?ZOMBIE ->
Power = ?RAND(?MAX_POWER div 2, ?MAX_POWER)
end,
State = #{
uid => UID,
type => Type,
cur_state => ?STATE_TYPE_IDLE,
cur_power => Power,
cur_rage => 0,
grid_list => [],
cur_grid => CurGrid,
rival_list => [],
misc => #{}
},
?INFO("生成单位:~tp", [State]),
State.
case Type of
?HUMAN ->
Power = ?MAX_POWER;
?ZOMBIE ->
Power = ?RAND(?MAX_POWER div 2, ?MAX_POWER)
end,
State = #{
uid => UID,
type => Type,
cur_state => ?STATE_TYPE_IDLE,
cur_power => Power,
cur_rage => 0,
grid_list => [],
cur_grid => CurGrid,
rival_list => [],
misc => #{}
},
?INFO("生成单位:~tp", [State]),
State.
init_zombie([UID | T], TitleMaps, TreeMaps, TreeNodeMaps) -> init_zombie([UID | T], TitleMaps, TreeMaps, TreeNodeMaps) ->
{ok, InitiativeBTreeID} = behavior_tree:init_btree_by_title(<<"丧尸主动AI"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps),
{ok, PassivityBTreeID} = behavior_tree:init_btree_by_title(<<"丧尸被动AI"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps),
game_dict:put_initiative_btree_id(UID, InitiativeBTreeID),
game_dict:put_passivity_btree_id(UID, PassivityBTreeID),
Grid = {?RAND(0, ?MAX_X), ?RAND(0, ?MAX_Y)},
game_dict:put_role_state(UID, new_state(UID, ?ZOMBIE, Grid)),
init_zombie(T, TitleMaps, TreeMaps, TreeNodeMaps);
{ok, InitiativeBTreeID} = behavior_tree:init_btree_by_title(<<"丧尸主动AI"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps),
{ok, PassivityBTreeID} = behavior_tree:init_btree_by_title(<<"丧尸被动AI"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps),
game_dict:put_initiative_btree_id(UID, InitiativeBTreeID),
game_dict:put_passivity_btree_id(UID, PassivityBTreeID),
Grid = {?RAND(0, ?MAX_X), ?RAND(0, ?MAX_Y)},
game_dict:put_role_state(UID, new_state(UID, ?ZOMBIE, Grid)),
init_zombie(T, TitleMaps, TreeMaps, TreeNodeMaps);
init_zombie([], _TitleMaps, _TreeMaps, _TreeNodeMaps) -> init_zombie([], _TitleMaps, _TreeMaps, _TreeNodeMaps) ->
ok.
ok.
init_patrol(UID, TitleMaps, TreeMaps, TreeNodeMaps) -> init_patrol(UID, TitleMaps, TreeMaps, TreeNodeMaps) ->
{ok, InitiativeBTreeID} = behavior_tree:init_btree_by_title(<<"巡逻兵主动AI"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps),
{ok, PassivityBTreeID} = behavior_tree:init_btree_by_title(<<"巡逻兵被动AI"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps),
game_dict:put_initiative_btree_id(UID, InitiativeBTreeID),
game_dict:put_passivity_btree_id(UID, PassivityBTreeID),
Grid = {?RAND(0, ?MAX_X), ?RAND(0, ?MAX_Y)},
game_dict:put_role_state(UID, new_state(UID, ?HUMAN, Grid)).
{ok, InitiativeBTreeID} = behavior_tree:init_btree_by_title(<<"巡逻兵主动AI"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps),
{ok, PassivityBTreeID} = behavior_tree:init_btree_by_title(<<"巡逻兵被动AI"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps),
game_dict:put_initiative_btree_id(UID, InitiativeBTreeID),
game_dict:put_passivity_btree_id(UID, PassivityBTreeID),
Grid = {?RAND(0, ?MAX_X), ?RAND(0, ?MAX_Y)},
game_dict:put_role_state(UID, new_state(UID, ?HUMAN, Grid)).
run(UID) -> run(UID) ->
BTreeID = game_dict:get_initiative_btree_id(UID),
#{cur_state := CurState} = State = game_dict:get_role_state(UID),
case ?IS_STATE(?STATE_TYPE_DEAD, CurState) of
true ->
ok;
false ->
{_, State1} = behavior_tree:execute(BTreeID, State),
game_dict:put_role_state(UID, State1)
end.
BTreeID = game_dict:get_initiative_btree_id(UID),
#{cur_state := CurState} = State = game_dict:get_role_state(UID),
case ?IS_STATE(?STATE_TYPE_DEAD, CurState) of
true ->
ok;
false ->
{_, State1} = behavior_tree:execute(BTreeID, State),
game_dict:put_role_state(UID, State1)
end.

+ 22
- 22
include/behavior3.hrl Переглянути файл

@ -15,47 +15,47 @@
-type bt_node_id() :: string(). -type bt_node_id() :: string().
-type bt_state() :: #{ -type bt_state() :: #{
'$global_maps' => map(),
'$local_maps' => map(),
term() => term()
'$global_maps' => map(),
'$local_maps' => map(),
term() => term()
}. }.
-type properties() :: #{atom() => term()}. -type properties() :: #{atom() => term()}.
%% %%
-type uninit_bt_node() :: #{ -type uninit_bt_node() :: #{
id => bt_node_id(),
name => atom() | bt_node_id(),
category => atom(),
properties => properties(),
children => [bt_node_id()]
id => bt_node_id(),
name => atom() | bt_node_id(),
category => atom(),
properties => properties(),
children => [bt_node_id()]
}. }.
-type tree_nodes() :: #{bt_node_id() => uninit_bt_node()}. -type tree_nodes() :: #{bt_node_id() => uninit_bt_node()}.
%% %%
-type btree() :: #{ -type btree() :: #{
id => bt_node_id(),
root => bt_node_id(),
properties => properties(),
tree_nodes => tree_nodes()
id => bt_node_id(),
root => bt_node_id(),
properties => properties(),
tree_nodes => tree_nodes()
}. }.
%% %%
-type bt_node() :: #{ -type bt_node() :: #{
id := bt_uid(),
bt_node_id := bt_node_id(),
parent_id := bt_uid(),
name := atom(),
category := atom(),
properties := properties(),
children := [bt_uid()]
id := bt_uid(),
bt_node_id := bt_node_id(),
parent_id := bt_uid(),
name := atom(),
category := atom(),
properties := properties(),
children := [bt_uid()]
}. }.
-define(BI_MOD_LIST, [ -define(BI_MOD_LIST, [
error, failer, runner, succeeder, wait,
mem_priority, mem_sequence, priority, sequence,
inverter, limiter, max_time, repeat_until_failure, repeat_until_success, repeater
error, failer, runner, succeeder, wait,
mem_priority, mem_sequence, priority, sequence,
inverter, limiter, max_time, repeat_until_failure, repeat_until_success, repeater
]). ]).
-define(BT_LOG(Format), io:format("~w:~w:~w [debug] ~p: " ++ Format ++ "~n", tuple_to_list(time()) ++ [?MODULE])). -define(BT_LOG(Format), io:format("~w:~w:~w [debug] ~p: " ++ Format ++ "~n", tuple_to_list(time()) ++ [?MODULE])).

+ 1
- 1
src/action/error.erl Переглянути файл

@ -15,7 +15,7 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(_BTNode, BTState) -> tick(_BTNode, BTState) ->
{?BT_ERROR, BTState}.
{?BT_ERROR, BTState}.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions

+ 1
- 1
src/action/failer.erl Переглянути файл

@ -15,7 +15,7 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(_BTNode, BTState) -> tick(_BTNode, BTState) ->
{?BT_FAILURE, BTState}.
{?BT_FAILURE, BTState}.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions

+ 1
- 1
src/action/runner.erl Переглянути файл

@ -15,7 +15,7 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(_BTNode, BTState) -> tick(_BTNode, BTState) ->
{?BT_RUNNING, BTState}.
{?BT_RUNNING, BTState}.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions

+ 1
- 1
src/action/succeeder.erl Переглянути файл

@ -15,7 +15,7 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(_BTNode, BTState) -> tick(_BTNode, BTState) ->
{?BT_SUCCESS, BTState}.
{?BT_SUCCESS, BTState}.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions

+ 9
- 9
src/action/wait.erl Переглянути файл

@ -15,21 +15,21 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec open(bt_node(), bt_state()) -> bt_state(). -spec open(bt_node(), bt_state()) -> bt_state().
open(#{id := ID}, BTState) -> open(#{id := ID}, BTState) ->
blackboard:set(start_time, erlang:system_time(millisecond), ID, BTState).
blackboard:set(start_time, erlang:system_time(millisecond), ID, BTState).
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{id := ID, properties := #{milliseconds := EndTime}} = _BTNode, BTState) -> tick(#{id := ID, properties := #{milliseconds := EndTime}} = _BTNode, BTState) ->
StartTime = blackboard:get(start_time, ID, BTState),
case erlang:system_time(millisecond) - StartTime > EndTime of
true ->
{?BT_SUCCESS, BTState};
false ->
{?BT_RUNNING, BTState}
end.
StartTime = blackboard:get(start_time, ID, BTState),
case erlang:system_time(millisecond) - StartTime > EndTime of
true ->
{?BT_SUCCESS, BTState};
false ->
{?BT_RUNNING, BTState}
end.
-spec close(bt_node(), bt_state()) -> bt_state(). -spec close(bt_node(), bt_state()) -> bt_state().
close(#{id := ID} = _BTNode, BTState) -> close(#{id := ID} = _BTNode, BTState) ->
blackboard:remove(start_time, ID, BTState).
blackboard:remove(start_time, ID, BTState).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions

+ 14
- 14
src/composite/mem_priority.erl Переглянути файл

@ -15,29 +15,29 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec open(bt_node(), bt_state()) -> bt_state(). -spec open(bt_node(), bt_state()) -> bt_state().
open(#{id := ID, children := Children} = _BTNode, BTState) -> open(#{id := ID, children := Children} = _BTNode, BTState) ->
blackboard:set(running_children, Children, ID, BTState).
blackboard:set(running_children, Children, ID, BTState).
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{id := ID} = _BTNode, BTState) -> tick(#{id := ID} = _BTNode, BTState) ->
RunningChildren = blackboard:get(running_children, ID, BTState),
tick_1(RunningChildren, ID, BTState).
RunningChildren = blackboard:get(running_children, ID, BTState),
tick_1(RunningChildren, ID, BTState).
-spec close(bt_node(), bt_state()) -> bt_state(). -spec close(bt_node(), bt_state()) -> bt_state().
close(#{id := ID} = _BTNode, State) -> close(#{id := ID} = _BTNode, State) ->
blackboard:remove(running_children, ID, State).
blackboard:remove(running_children, ID, State).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
tick_1([ChildID | T] = Children, ID, BTState) -> tick_1([ChildID | T] = Children, ID, BTState) ->
case base_node:execute(ChildID, BTState) of
{?BT_FAILURE, BTState1} ->
tick_1(T, ID, BTState1);
{?BT_RUNNING, BTState1} ->
BTState2 = blackboard:set(running_children, Children, ID, BTState1),
{?BT_RUNNING, BTState2};
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
case base_node:execute(ChildID, BTState) of
{?BT_FAILURE, BTState1} ->
tick_1(T, ID, BTState1);
{?BT_RUNNING, BTState1} ->
BTState2 = blackboard:set(running_children, Children, ID, BTState1),
{?BT_RUNNING, BTState2};
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
tick_1([], _ID, BTState) -> tick_1([], _ID, BTState) ->
{?BT_FAILURE, BTState}.
{?BT_FAILURE, BTState}.

+ 14
- 14
src/composite/mem_sequence.erl Переглянути файл

@ -15,29 +15,29 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec open(bt_node(), bt_state()) -> bt_state(). -spec open(bt_node(), bt_state()) -> bt_state().
open(#{id := ID, children := Children} = _BTNode, BTState) -> open(#{id := ID, children := Children} = _BTNode, BTState) ->
blackboard:set(running_children, Children, ID, BTState).
blackboard:set(running_children, Children, ID, BTState).
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{id := ID} = _BTNode, BTState) -> tick(#{id := ID} = _BTNode, BTState) ->
RunningChildren = blackboard:get(running_children, ID, BTState),
tick_1(RunningChildren, ID, BTState).
RunningChildren = blackboard:get(running_children, ID, BTState),
tick_1(RunningChildren, ID, BTState).
-spec close(bt_node(), bt_state()) -> bt_state(). -spec close(bt_node(), bt_state()) -> bt_state().
close(#{id := ID} = _BTNode, BTState) -> close(#{id := ID} = _BTNode, BTState) ->
blackboard:remove(running_children, ID, BTState).
blackboard:remove(running_children, ID, BTState).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
tick_1([ChildID | T] = Children, ID, BTState) -> tick_1([ChildID | T] = Children, ID, BTState) ->
case base_node:execute(ChildID, BTState) of
{?BT_SUCCESS, BTState1} ->
tick_1(T, ID, BTState1);
{?BT_RUNNING, BTState1} ->
BTState2 = blackboard:set(running_children, Children, ID, BTState1),
{?BT_RUNNING, BTState2};
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
case base_node:execute(ChildID, BTState) of
{?BT_SUCCESS, BTState1} ->
tick_1(T, ID, BTState1);
{?BT_RUNNING, BTState1} ->
BTState2 = blackboard:set(running_children, Children, ID, BTState1),
{?BT_RUNNING, BTState2};
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
tick_1([], _ID, BTState) -> tick_1([], _ID, BTState) ->
{?BT_SUCCESS, BTState}.
{?BT_SUCCESS, BTState}.

+ 8
- 8
src/composite/priority.erl Переглянути файл

@ -15,17 +15,17 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{children := Children} = _BTNode, BTState) -> tick(#{children := Children} = _BTNode, BTState) ->
tick_1(Children, BTState).
tick_1(Children, BTState).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
tick_1([ChildID | T], BTState) -> tick_1([ChildID | T], BTState) ->
case base_node:execute(ChildID, BTState) of
{?BT_FAILURE, BTState1} ->
tick_1(T, BTState1);
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
case base_node:execute(ChildID, BTState) of
{?BT_FAILURE, BTState1} ->
tick_1(T, BTState1);
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
tick_1([], BTState) -> tick_1([], BTState) ->
{?BT_FAILURE, BTState}.
{?BT_FAILURE, BTState}.

+ 8
- 8
src/composite/sequence.erl Переглянути файл

@ -15,17 +15,17 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{children := Children} = _BTNode, BTState) -> tick(#{children := Children} = _BTNode, BTState) ->
tick_1(Children, BTState).
tick_1(Children, BTState).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
tick_1([ChildID | T], BTState) -> tick_1([ChildID | T], BTState) ->
case base_node:execute(ChildID, BTState) of
{?BT_SUCCESS, BTState1} ->
tick_1(T, BTState1);
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
case base_node:execute(ChildID, BTState) of
{?BT_SUCCESS, BTState1} ->
tick_1(T, BTState1);
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
tick_1([], BTState) -> tick_1([], BTState) ->
{?BT_SUCCESS, BTState}.
{?BT_SUCCESS, BTState}.

+ 76
- 76
src/core/base_node.erl Переглянути файл

@ -35,16 +35,16 @@
%% @doc %% @doc
-spec execute(bt_uid(), bt_state()) -> {bt_status(), bt_state()}. -spec execute(bt_uid(), bt_state()) -> {bt_status(), bt_state()}.
execute(NodeID, BTState) -> execute(NodeID, BTState) ->
BTNode = blackboard:get_btree_node(NodeID),
BTState1 = do_open(BTNode, BTState),
{BTStatus, BTState2} = do_tick(BTNode, BTState1),
case BTStatus of
?BT_RUNNING ->
{?BT_RUNNING, BTState2};
BTStatus ->
BTState3 = do_close(BTNode, BTState2),
{BTStatus, BTState3}
end.
BTNode = blackboard:get_btree_node(NodeID),
BTState1 = do_open(BTNode, BTState),
{BTStatus, BTState2} = do_tick(BTNode, BTState1),
case BTStatus of
?BT_RUNNING ->
{?BT_RUNNING, BTState2};
BTStatus ->
BTState3 = do_close(BTNode, BTState2),
{BTStatus, BTState3}
end.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
@ -52,86 +52,86 @@ execute(NodeID, BTState) ->
%% %%
-spec do_init(bt_uid()|undefined, bt_node_id(), #{bt_node_id() => btree()}, tree_nodes()) -> {ok, bt_uid()}|{error, term()}. -spec do_init(bt_uid()|undefined, bt_node_id(), #{bt_node_id() => btree()}, tree_nodes()) -> {ok, bt_uid()}|{error, term()}.
do_init(ParentNodeID, BTNodeID, TreeMaps, TreeNodeMaps) -> do_init(ParentNodeID, BTNodeID, TreeMaps, TreeNodeMaps) ->
case behavior_tree:get_btree_node(BTNodeID, TreeNodeMaps) of
#{name := Name, category := tree} ->
#{root := Root} = behavior_tree:get_btree(Name, TreeMaps),
do_init(ParentNodeID, Root, TreeMaps, TreeNodeMaps);
#{name := Name, children := Children} = BTNode ->
case code:ensure_loaded(Name) of
{module, Mod} ->
case erlang:function_exported(Mod, init, 1) of
true ->
BTNode1 = Mod:init(BTNode);
false ->
BTNode1 = BTNode
end,
ID = make_ref(),
BTNode2 = BTNode1#{
id => ID,
bt_node_id => BTNodeID,
parent_id => ParentNodeID,
children => [do_init(ID, ChildBTNodeID, TreeMaps, TreeNodeMaps) || ChildBTNodeID <- Children]
},
blackboard:set_btree_node(BTNode2),
{ok, ID};
_ ->
{error, {btree_node_not_implement, Name}}
end
end.
case behavior_tree:get_btree_node(BTNodeID, TreeNodeMaps) of
#{name := Name, category := tree} ->
#{root := Root} = behavior_tree:get_btree(Name, TreeMaps),
do_init(ParentNodeID, Root, TreeMaps, TreeNodeMaps);
#{name := Name, children := Children} = BTNode ->
case code:ensure_loaded(Name) of
{module, Mod} ->
case erlang:function_exported(Mod, init, 1) of
true ->
BTNode1 = Mod:init(BTNode);
false ->
BTNode1 = BTNode
end,
ID = make_ref(),
BTNode2 = BTNode1#{
id => ID,
bt_node_id => BTNodeID,
parent_id => ParentNodeID,
children => [do_init(ID, ChildBTNodeID, TreeMaps, TreeNodeMaps) || ChildBTNodeID <- Children]
},
blackboard:set_btree_node(BTNode2),
{ok, ID};
_ ->
{error, {btree_node_not_implement, Name}}
end
end.
%% open/2open函数 %% open/2open函数
%% %%
-spec do_open(bt_node(), bt_state()) -> bt_state(). -spec do_open(bt_node(), bt_state()) -> bt_state().
do_open(#{id := ID, parent_id := ParentID, name := Mod} = BTNode, BTState) -> do_open(#{id := ID, parent_id := ParentID, name := Mod} = BTNode, BTState) ->
case blackboard:get('$is_open', ID, false, BTState) of
true ->
BTState;
false ->
case erlang:function_exported(Mod, open, 2) of
true ->
BTState1 = Mod:open(BTNode, BTState);
false ->
BTState1 = BTState
end,
BTState2 = blackboard:set('$is_open', true, ID, BTState1),
case is_reference(ParentID) of
true ->
Children = blackboard:get('$children', ParentID, [], BTState2),
blackboard:set('$children', [ID | Children], ParentID, BTState2);
false ->
BTState2
end
end.
case blackboard:get('$is_open', ID, false, BTState) of
true ->
BTState;
false ->
case erlang:function_exported(Mod, open, 2) of
true ->
BTState1 = Mod:open(BTNode, BTState);
false ->
BTState1 = BTState
end,
BTState2 = blackboard:set('$is_open', true, ID, BTState1),
case is_reference(ParentID) of
true ->
Children = blackboard:get('$children', ParentID, [], BTState2),
blackboard:set('$children', [ID | Children], ParentID, BTState2);
false ->
BTState2
end
end.
%% tick函数 %% tick函数
-spec do_tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec do_tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
do_tick(#{name := Mod} = BTNode, BTState) -> do_tick(#{name := Mod} = BTNode, BTState) ->
Mod:tick(BTNode, BTState).
Mod:tick(BTNode, BTState).
%% @doc close/2close函数 %% @doc close/2close函数
-spec do_close(bt_node(), bt_state()) -> bt_state(). -spec do_close(bt_node(), bt_state()) -> bt_state().
do_close(#{id := ID, name := Mod} = BTNode, BTState) -> do_close(#{id := ID, name := Mod} = BTNode, BTState) ->
Children = blackboard:get('$children', ID, [], BTState),
BTState1 = do_close_1(Children, BTState),
case erlang:function_exported(Mod, close, 2) of
true ->
BTState2 = Mod:close(BTNode, BTState1);
false ->
BTState2 = BTState1
end,
BTState3 = blackboard:set('$is_open', false, ID, BTState2),
BTState4 = blackboard:set('$children', [], ID, BTState3),
blackboard:erase_node_local(ID, BTState4).
Children = blackboard:get('$children', ID, [], BTState),
BTState1 = do_close_1(Children, BTState),
case erlang:function_exported(Mod, close, 2) of
true ->
BTState2 = Mod:close(BTNode, BTState1);
false ->
BTState2 = BTState1
end,
BTState3 = blackboard:set('$is_open', false, ID, BTState2),
BTState4 = blackboard:set('$children', [], ID, BTState3),
blackboard:erase_node_local(ID, BTState4).
do_close_1([NodeID | T], BTState) -> do_close_1([NodeID | T], BTState) ->
BTState1 = do_close_1(T, BTState),
case blackboard:get('$is_open', NodeID, false, BTState1) of
true ->
BTNode = blackboard:get_btree_node(NodeID),
do_close(BTNode, BTState1);
false ->
BTState1
end;
BTState1 = do_close_1(T, BTState),
case blackboard:get('$is_open', NodeID, false, BTState1) of
true ->
BTNode = blackboard:get_btree_node(NodeID),
do_close(BTNode, BTState1);
false ->
BTState1
end;
do_close_1([], BTState) -> do_close_1([], BTState) ->
BTState.
BTState.

+ 99
- 99
src/core/behavior_tree.erl Переглянути файл

@ -11,9 +11,9 @@
%% export API %% export API
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-export([ -export([
load_tree_file/1,
init_btree_by_title/4, init_btree/3,
execute/2, execute_child/2, close_btree_node/2, unload_btree/1
load_tree_file/1,
init_btree_by_title/4, init_btree/3,
execute/2, execute_child/2, close_btree_node/2, unload_btree/1
]). ]).
%% Internal API %% Internal API
@ -26,94 +26,94 @@
%% %%
-spec load_tree_file(file:name_all()) -> {#{string() => bt_node_id()}, #{bt_node_id() => btree()}, tree_nodes()}|{error, term()}. -spec load_tree_file(file:name_all()) -> {#{string() => bt_node_id()}, #{bt_node_id() => btree()}, tree_nodes()}|{error, term()}.
load_tree_file(JsonConfig) -> load_tree_file(JsonConfig) ->
case file:read_file(JsonConfig) of
{ok, Json} ->
JsonTerm = jsx:decode(Json, [return_maps]),
parse_btree(JsonTerm);
{error, Reason} ->
?BT_LOG("Error:~w Reason:~w JsonConfig:~w", [error, Reason, JsonConfig]),
{error, Reason}
end.
case file:read_file(JsonConfig) of
{ok, Json} ->
JsonTerm = jsx:decode(Json, [return_maps]),
parse_btree(JsonTerm);
{error, Reason} ->
?BT_LOG("Error:~w Reason:~w JsonConfig:~w", [error, Reason, JsonConfig]),
{error, Reason}
end.
%% @doc %% @doc
%% id %% id
-spec get_btree_id_by_title(string(), #{string() => bt_node_id()}) -> bt_node_id()|undefined. -spec get_btree_id_by_title(string(), #{string() => bt_node_id()}) -> bt_node_id()|undefined.
get_btree_id_by_title(Title, TitleMaps) -> get_btree_id_by_title(Title, TitleMaps) ->
case TitleMaps of
#{Title := ID} ->
ID;
#{} ->
undefined
end.
case TitleMaps of
#{Title := ID} ->
ID;
#{} ->
undefined
end.
%% @doc %% @doc
%% %%
-spec get_btree(bt_node_id(), #{bt_node_id() => btree()}) -> btree()|undefined. -spec get_btree(bt_node_id(), #{bt_node_id() => btree()}) -> btree()|undefined.
get_btree(BTNodeID, TreeMaps) -> get_btree(BTNodeID, TreeMaps) ->
case TreeMaps of
#{BTNodeID := BTree} ->
BTree;
#{} ->
undefined
end.
case TreeMaps of
#{BTNodeID := BTree} ->
BTree;
#{} ->
undefined
end.
%% @doc %% @doc
%% %%
-spec get_btree_node(bt_node_id(), tree_nodes()) -> uninit_bt_node()|undefined. -spec get_btree_node(bt_node_id(), tree_nodes()) -> uninit_bt_node()|undefined.
get_btree_node(BTNodeID, TreeNodeMaps) -> get_btree_node(BTNodeID, TreeNodeMaps) ->
case TreeNodeMaps of
#{BTNodeID := BTNode} ->
BTNode;
#{} ->
undefined
end.
case TreeNodeMaps of
#{BTNodeID := BTNode} ->
BTNode;
#{} ->
undefined
end.
%% @doc %% @doc
%% %%
-spec init_btree_by_title(string(), #{string() => bt_node_id()}, #{bt_node_id() => btree()}, tree_nodes()) -> {ok, bt_uid()}|{error, term()}. -spec init_btree_by_title(string(), #{string() => bt_node_id()}, #{bt_node_id() => btree()}, tree_nodes()) -> {ok, bt_uid()}|{error, term()}.
init_btree_by_title(Title, TitleMaps, TreeMaps, TreeNodeMaps) -> init_btree_by_title(Title, TitleMaps, TreeMaps, TreeNodeMaps) ->
BTNodeID = get_btree_id_by_title(Title, TitleMaps),
init_btree(BTNodeID, TreeMaps, TreeNodeMaps).
BTNodeID = get_btree_id_by_title(Title, TitleMaps),
init_btree(BTNodeID, TreeMaps, TreeNodeMaps).
%% @doc %% @doc
%% %%
-spec init_btree(bt_node_id(), #{bt_node_id() => btree()}, tree_nodes()) -> {ok, bt_uid()}|{error, term()}. -spec init_btree(bt_node_id(), #{bt_node_id() => btree()}, tree_nodes()) -> {ok, bt_uid()}|{error, term()}.
init_btree(BTNodeID, TreeMaps, TreeNodeMaps) -> init_btree(BTNodeID, TreeMaps, TreeNodeMaps) ->
#{root := Root} = behavior_tree:get_btree(BTNodeID, TreeMaps),
#{id := NodeID} = behavior_tree:get_btree_node(Root, TreeNodeMaps),
base_node:do_init(undefined, NodeID, TreeMaps, TreeNodeMaps).
#{root := Root} = behavior_tree:get_btree(BTNodeID, TreeMaps),
#{id := NodeID} = behavior_tree:get_btree_node(Root, TreeNodeMaps),
base_node:do_init(undefined, NodeID, TreeMaps, TreeNodeMaps).
%% @doc %% @doc
%% %%
-spec execute(bt_uid(), bt_state()) -> {bt_status(), bt_state()}. -spec execute(bt_uid(), bt_state()) -> {bt_status(), bt_state()}.
execute(NodeID, BTState) -> execute(NodeID, BTState) ->
BTState1 = blackboard:init_maps_keys(BTState),
case base_node:execute(NodeID, BTState1) of
{?BT_RUNNING, BTState2} ->
{?BT_RUNNING, BTState2};
{BTStatus, BTState2} ->
BTState3 = blackboard:erase_btree(BTState2),
{BTStatus, BTState3}
end.
BTState1 = blackboard:init_maps_keys(BTState),
case base_node:execute(NodeID, BTState1) of
{?BT_RUNNING, BTState2} ->
{?BT_RUNNING, BTState2};
{BTStatus, BTState2} ->
BTState3 = blackboard:erase_btree(BTState2),
{BTStatus, BTState3}
end.
%% @doc %% @doc
%% %%
-spec execute_child(bt_uid(), bt_state()) -> {bt_status(), bt_state()}. -spec execute_child(bt_uid(), bt_state()) -> {bt_status(), bt_state()}.
execute_child(NodeID, BTState) -> execute_child(NodeID, BTState) ->
base_node:execute(NodeID, BTState).
base_node:execute(NodeID, BTState).
%% @doc %% @doc
%% %%
-spec close_btree_node(bt_uid(), bt_state()) -> bt_state(). -spec close_btree_node(bt_uid(), bt_state()) -> bt_state().
close_btree_node(NodeID, BTState) -> close_btree_node(NodeID, BTState) ->
BTState1 = do_close_btree_node(NodeID, BTState),
blackboard:erase_btree(BTState1).
BTState1 = do_close_btree_node(NodeID, BTState),
blackboard:erase_btree(BTState1).
%% @doc %% @doc
%% %%
-spec unload_btree(bt_uid()) -> ok. -spec unload_btree(bt_uid()) -> ok.
unload_btree(NodeID) -> unload_btree(NodeID) ->
do_unload_btree_node(NodeID).
do_unload_btree_node(NodeID).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
@ -121,95 +121,95 @@ unload_btree(NodeID) ->
%% %%
-spec parse_btree(map()) -> {#{string() => bt_node_id()}, #{bt_node_id() => btree()}, tree_nodes()}. -spec parse_btree(map()) -> {#{string() => bt_node_id()}, #{bt_node_id() => btree()}, tree_nodes()}.
parse_btree(#{<<"trees">> := Trees}) -> parse_btree(#{<<"trees">> := Trees}) ->
parse_btree_1(Trees, #{}, #{}, #{}).
parse_btree_1(Trees, #{}, #{}, #{}).
parse_btree_1([Node | T], TitleMaps, TreeMaps, TreeNodeMaps) -> parse_btree_1([Node | T], TitleMaps, TreeMaps, TreeNodeMaps) ->
#{<<"id">> := ID, <<"title">> := Title, <<"root">> := Root, <<"nodes">> := Nodes} = Node,
Iterator = maps:iterator(Nodes),
{TreeNodes, TreeNodeMaps1} = parse_btree_node(maps:next(Iterator), #{}, TreeNodeMaps),
BTree = #{
id => ID,
root => Root,
properties => parse_properties(Node),
tree_nodes => TreeNodes
},
parse_btree_1(T, TitleMaps#{Title => ID}, TreeMaps#{ID => BTree}, TreeNodeMaps1);
#{<<"id">> := ID, <<"title">> := Title, <<"root">> := Root, <<"nodes">> := Nodes} = Node,
Iterator = maps:iterator(Nodes),
{TreeNodes, TreeNodeMaps1} = parse_btree_node(maps:next(Iterator), #{}, TreeNodeMaps),
BTree = #{
id => ID,
root => Root,
properties => parse_properties(Node),
tree_nodes => TreeNodes
},
parse_btree_1(T, TitleMaps#{Title => ID}, TreeMaps#{ID => BTree}, TreeNodeMaps1);
parse_btree_1([], TitleMaps, TreeMaps, TreeNodeMaps) -> parse_btree_1([], TitleMaps, TreeMaps, TreeNodeMaps) ->
{TitleMaps, TreeMaps, TreeNodeMaps}.
{TitleMaps, TreeMaps, TreeNodeMaps}.
%% %%
-spec parse_btree_node({bt_node_id(), map(), maps:iterator()}|none, tree_nodes(), tree_nodes()) -> {tree_nodes(), tree_nodes()}. -spec parse_btree_node({bt_node_id(), map(), maps:iterator()}|none, tree_nodes(), tree_nodes()) -> {tree_nodes(), tree_nodes()}.
parse_btree_node({ID, Node, NextIterator}, TreeNodes, TreeNodeMaps) -> parse_btree_node({ID, Node, NextIterator}, TreeNodes, TreeNodeMaps) ->
#{<<"name">> := Name, <<"category">> := Category} = Node,
case Category of
<<"tree">> ->
Name1 = Name;
_ ->
Name1 = name_convert(Name)
end,
TreeNode = #{
id => ID,
name => Name1,
category => binary_to_atom(Category, utf8),
properties => parse_properties(Node),
children => parse_children(Node)
},
parse_btree_node(maps:next(NextIterator), TreeNodes#{ID => TreeNode}, TreeNodeMaps#{ID => TreeNode});
#{<<"name">> := Name, <<"category">> := Category} = Node,
case Category of
<<"tree">> ->
Name1 = Name;
_ ->
Name1 = name_convert(Name)
end,
TreeNode = #{
id => ID,
name => Name1,
category => binary_to_atom(Category, utf8),
properties => parse_properties(Node),
children => parse_children(Node)
},
parse_btree_node(maps:next(NextIterator), TreeNodes#{ID => TreeNode}, TreeNodeMaps#{ID => TreeNode});
parse_btree_node(none, TreeNodes, TreeNodeMaps) -> parse_btree_node(none, TreeNodes, TreeNodeMaps) ->
{TreeNodes, TreeNodeMaps}.
{TreeNodes, TreeNodeMaps}.
%% %%
%% key会转为下划线分割小写atomvalue保持不变 %% key会转为下划线分割小写atomvalue保持不变
-spec parse_properties(map()) -> properties(). -spec parse_properties(map()) -> properties().
parse_properties(#{<<"properties">> := Properties} = _Node) -> parse_properties(#{<<"properties">> := Properties} = _Node) ->
Fun = fun(K, V, Map) -> Map#{name_convert(K) => V} end,
maps:fold(Fun, #{}, Properties).
Fun = fun(K, V, Map) -> Map#{name_convert(K) => V} end,
maps:fold(Fun, #{}, Properties).
%% %%
-spec parse_children(map()) -> [bt_node_id()]. -spec parse_children(map()) -> [bt_node_id()].
parse_children(#{<<"child">> := Child} = _Node) -> parse_children(#{<<"child">> := Child} = _Node) ->
[Child];
[Child];
parse_children(#{<<"children">> := Children} = _Node) -> parse_children(#{<<"children">> := Children} = _Node) ->
Children;
Children;
parse_children(_Node) -> parse_children(_Node) ->
[].
[].
%% %%
%% PlayerID -> player_id Name -> name %% PlayerID -> player_id Name -> name
-spec name_convert(unicode:chardata()) -> atom(). -spec name_convert(unicode:chardata()) -> atom().
name_convert(Name) -> name_convert(Name) ->
case name_convert_1(Name) of
<<"_"/utf8, NewName/binary>> ->
binary_to_atom(NewName, utf8);
NewName ->
binary_to_atom(NewName, utf8)
end.
case name_convert_1(Name) of
<<"_"/utf8, NewName/binary>> ->
binary_to_atom(NewName, utf8);
NewName ->
binary_to_atom(NewName, utf8)
end.
name_convert_1(<<C/utf8, Other/binary>>) when $A =< C, C =< $Z -> name_convert_1(<<C/utf8, Other/binary>>) when $A =< C, C =< $Z ->
Other1 = name_convert_1(Other),
<<"_"/utf8, (C + 32)/utf8, Other1/binary>>;
Other1 = name_convert_1(Other),
<<"_"/utf8, (C + 32)/utf8, Other1/binary>>;
name_convert_1(<<C/utf8, Other/binary>>) -> name_convert_1(<<C/utf8, Other/binary>>) ->
Other1 = name_convert_1(Other),
<<C/utf8, Other1/binary>>;
Other1 = name_convert_1(Other),
<<C/utf8, Other1/binary>>;
name_convert_1(<<>>) -> name_convert_1(<<>>) ->
<<>>.
<<>>.
%% %%
-spec do_close_btree_node(bt_uid(), bt_state()) -> bt_state(). -spec do_close_btree_node(bt_uid(), bt_state()) -> bt_state().
do_close_btree_node(NodeID, BTState) -> do_close_btree_node(NodeID, BTState) ->
BTNode = blackboard:get_btree_node(NodeID),
base_node:do_close(BTNode, BTState).
BTNode = blackboard:get_btree_node(NodeID),
base_node:do_close(BTNode, BTState).
%% %%
-spec do_unload_btree_node(bt_uid()) -> ok. -spec do_unload_btree_node(bt_uid()) -> ok.
do_unload_btree_node(NodeID) -> do_unload_btree_node(NodeID) ->
#{children := Children} = blackboard:get_btree_node(NodeID),
do_unload_btree_node_1(Children),
blackboard:erase_btree_node(NodeID),
ok.
#{children := Children} = blackboard:get_btree_node(NodeID),
do_unload_btree_node_1(Children),
blackboard:erase_btree_node(NodeID),
ok.
do_unload_btree_node_1([NodeID | T]) -> do_unload_btree_node_1([NodeID | T]) ->
do_unload_btree_node(NodeID),
do_unload_btree_node_1(T);
do_unload_btree_node(NodeID),
do_unload_btree_node_1(T);
do_unload_btree_node_1([]) -> do_unload_btree_node_1([]) ->
ok.
ok.

+ 65
- 65
src/core/blackboard.erl Переглянути файл

@ -9,10 +9,10 @@
%% export API %% export API
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-export([ -export([
get_btree_node/1, set_btree_node/1, erase_btree_node/1,
set_global/3, set/4,
get_global/2, get_global/3, get/3, get/4,
remove/2, remove/3
get_btree_node/1, set_btree_node/1, erase_btree_node/1,
set_global/3, set/4,
get_global/2, get_global/3, get/3, get/4,
remove/2, remove/3
]). ]).
%% Internal API %% Internal API
@ -25,100 +25,100 @@
%% %%
-spec get_btree_node(bt_uid()) -> bt_node()|undefined. -spec get_btree_node(bt_uid()) -> bt_node()|undefined.
get_btree_node(NodeID) -> get_btree_node(NodeID) ->
get({btree_node, NodeID}).
get({btree_node, NodeID}).
%% @doc %% @doc
%% %%
-spec set_btree_node(bt_node()) -> ok. -spec set_btree_node(bt_node()) -> ok.
set_btree_node(#{id := NodeID} = BTNode) -> set_btree_node(#{id := NodeID} = BTNode) ->
put({btree_node, NodeID}, BTNode),
ok.
put({btree_node, NodeID}, BTNode),
ok.
%% @doc %% @doc
%% %%
-spec erase_btree_node(bt_uid()) -> bt_node(). -spec erase_btree_node(bt_uid()) -> bt_node().
erase_btree_node(NodeID) -> erase_btree_node(NodeID) ->
erase({btree_node, NodeID}).
erase({btree_node, NodeID}).
%% @doc %% @doc
%% %%
-spec set_global(term(), term(), bt_state()) -> bt_state(). -spec set_global(term(), term(), bt_state()) -> bt_state().
set_global(Key, Value, #{'$global_maps' := GlobalMaps} = BTState) -> set_global(Key, Value, #{'$global_maps' := GlobalMaps} = BTState) ->
BTState#{'$global_maps' := GlobalMaps#{Key => Value}}.
BTState#{'$global_maps' := GlobalMaps#{Key => Value}}.
%% @doc %% @doc
%% %%
-spec set(term(), term(), bt_uid(), bt_state()) -> bt_state(). -spec set(term(), term(), bt_uid(), bt_state()) -> bt_state().
set(Key, Value, NodeID, #{'$local_maps' := LocalMaps} = BTState) -> set(Key, Value, NodeID, #{'$local_maps' := LocalMaps} = BTState) ->
case LocalMaps of
#{NodeID := ValueMaps} ->
LocalMaps1 = LocalMaps#{NodeID := ValueMaps#{Key => Value}};
#{} ->
LocalMaps1 = LocalMaps#{NodeID => #{Key => Value}}
end,
BTState#{'$local_maps' := LocalMaps1}.
case LocalMaps of
#{NodeID := ValueMaps} ->
LocalMaps1 = LocalMaps#{NodeID := ValueMaps#{Key => Value}};
#{} ->
LocalMaps1 = LocalMaps#{NodeID => #{Key => Value}}
end,
BTState#{'$local_maps' := LocalMaps1}.
%% @doc %% @doc
%% %%
-spec get_global(term(), bt_state()) -> term()|undefined. -spec get_global(term(), bt_state()) -> term()|undefined.
get_global(Key, BTState) -> get_global(Key, BTState) ->
case BTState of
#{'$global_maps' := #{Key := Value}} ->
Value;
#{} ->
undefined
end.
case BTState of
#{'$global_maps' := #{Key := Value}} ->
Value;
#{} ->
undefined
end.
%% @doc %% @doc
%% Default %% Default
-spec get_global(term(), term(), bt_state()) -> term(). -spec get_global(term(), term(), bt_state()) -> term().
get_global(Key, Default, BTState) -> get_global(Key, Default, BTState) ->
case BTState of
#{'$global_maps' := #{Key := Value}} ->
Value;
#{} ->
Default
end.
case BTState of
#{'$global_maps' := #{Key := Value}} ->
Value;
#{} ->
Default
end.
%% @doc %% @doc
%% %%
-spec get(term(), bt_uid(), bt_state()) -> term()|undefined. -spec get(term(), bt_uid(), bt_state()) -> term()|undefined.
get(Key, NodeID, BTState) -> get(Key, NodeID, BTState) ->
case BTState of
#{'$local_maps' := #{NodeID := #{Key := Value}}} ->
Value;
#{} ->
undefined
end.
case BTState of
#{'$local_maps' := #{NodeID := #{Key := Value}}} ->
Value;
#{} ->
undefined
end.
%% @doc %% @doc
%% Default %% Default
-spec get(term(), bt_uid(), term(), bt_state()) -> term(). -spec get(term(), bt_uid(), term(), bt_state()) -> term().
get(Key, NodeID, Default, BTState) -> get(Key, NodeID, Default, BTState) ->
case BTState of
#{'$local_maps' := #{NodeID := #{Key := Value}}} ->
Value;
#{} ->
Default
end.
case BTState of
#{'$local_maps' := #{NodeID := #{Key := Value}}} ->
Value;
#{} ->
Default
end.
%% @doc %% @doc
%% %%
-spec remove(term(), bt_state()) -> bt_state(). -spec remove(term(), bt_state()) -> bt_state().
remove(Key, #{'$global_maps' := GlobalMaps} = BTState) -> remove(Key, #{'$global_maps' := GlobalMaps} = BTState) ->
BTState#{'$global_maps' := maps:remove(Key, GlobalMaps)}.
BTState#{'$global_maps' := maps:remove(Key, GlobalMaps)}.
%% @doc %% @doc
%% %%
-spec remove(term(), bt_uid(), bt_state()) -> bt_state(). -spec remove(term(), bt_uid(), bt_state()) -> bt_state().
remove(Key, NodeID, #{'$local_maps' := LocalMaps} = BTState) -> remove(Key, NodeID, #{'$local_maps' := LocalMaps} = BTState) ->
case LocalMaps of
#{NodeID := ValueMap} ->
LocalMaps1 = LocalMaps#{NodeID := maps:remove(Key, ValueMap)},
BTState#{'$local_maps' := LocalMaps1};
#{} ->
BTState
end.
case LocalMaps of
#{NodeID := ValueMap} ->
LocalMaps1 = LocalMaps#{NodeID := maps:remove(Key, ValueMap)},
BTState#{'$local_maps' := LocalMaps1};
#{} ->
BTState
end.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
@ -126,32 +126,32 @@ remove(Key, NodeID, #{'$local_maps' := LocalMaps} = BTState) ->
%% %%
-spec init_maps_keys(bt_state()) -> bt_state(). -spec init_maps_keys(bt_state()) -> bt_state().
init_maps_keys(BTState) -> init_maps_keys(BTState) ->
BTState1 = init_global(BTState),
init_local(BTState1).
BTState1 = init_global(BTState),
init_local(BTState1).
init_global(BTState) -> init_global(BTState) ->
case maps:is_key('$global_maps', BTState) of
true ->
BTState;
false ->
BTState#{'$global_maps' => #{}}
end.
case maps:is_key('$global_maps', BTState) of
true ->
BTState;
false ->
BTState#{'$global_maps' => #{}}
end.
init_local(BTState) -> init_local(BTState) ->
case maps:is_key('$local_maps', BTState) of
true ->
BTState;
false ->
BTState#{'$local_maps' => #{}}
end.
case maps:is_key('$local_maps', BTState) of
true ->
BTState;
false ->
BTState#{'$local_maps' => #{}}
end.
%% %%
-spec erase_node_local(bt_uid(), bt_state()) -> bt_state(). -spec erase_node_local(bt_uid(), bt_state()) -> bt_state().
erase_node_local(NodeID, #{'$local_maps' := LocalMaps} = BTState) -> erase_node_local(NodeID, #{'$local_maps' := LocalMaps} = BTState) ->
BTState#{'$local_maps' := maps:remove(NodeID, LocalMaps)}.
BTState#{'$local_maps' := maps:remove(NodeID, LocalMaps)}.
%% %%
-spec erase_btree(bt_state()) -> bt_state(). -spec erase_btree(bt_state()) -> bt_state().
erase_btree(BTState) -> erase_btree(BTState) ->
BTState1 = maps:remove('$global_maps', BTState),
maps:remove('$local_maps', BTState1).
BTState1 = maps:remove('$global_maps', BTState),
maps:remove('$local_maps', BTState1).

+ 9
- 9
src/decorator/inverter.erl Переглянути файл

@ -15,16 +15,16 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{children := [ChildID]} = _BTNode, BTState) -> tick(#{children := [ChildID]} = _BTNode, BTState) ->
case base_node:execute(ChildID, BTState) of
{?BT_SUCCESS, BTState1} ->
{?BT_FAILURE, BTState1};
{?BT_FAILURE, BTState1} ->
{?BT_SUCCESS, BTState1};
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
case base_node:execute(ChildID, BTState) of
{?BT_SUCCESS, BTState1} ->
{?BT_FAILURE, BTState1};
{?BT_FAILURE, BTState1} ->
{?BT_SUCCESS, BTState1};
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
tick(_BTNode, BTState) -> tick(_BTNode, BTState) ->
{?BT_ERROR, BTState}.
{?BT_ERROR, BTState}.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions

+ 15
- 15
src/decorator/limiter.erl Переглянути файл

@ -15,28 +15,28 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec open(bt_node(), bt_state()) -> bt_state(). -spec open(bt_node(), bt_state()) -> bt_state().
open(#{id := ID} = _BTNode, BTState) -> open(#{id := ID} = _BTNode, BTState) ->
blackboard:set(i, 0, ID, BTState).
blackboard:set(i, 0, ID, BTState).
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{id := ID, children := [ChildID], properties := #{max_loop := MaxLoop}} = _BTNode, BTState) -> tick(#{id := ID, children := [ChildID], properties := #{max_loop := MaxLoop}} = _BTNode, BTState) ->
case blackboard:get(i, ID, BTState) of
I when I < MaxLoop ->
case base_node:execute(ChildID, BTState) of
{BTStatus, BTState1} when BTStatus =:= ?BT_SUCCESS orelse BTStatus =:= ?BT_FAILURE ->
BTState2 = blackboard:set(i, I + 1, ID, BTState1),
{BTStatus, BTState2};
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
_I ->
{?BT_FAILURE, BTState}
end;
case blackboard:get(i, ID, BTState) of
I when I < MaxLoop ->
case base_node:execute(ChildID, BTState) of
{BTStatus, BTState1} when BTStatus =:= ?BT_SUCCESS orelse BTStatus =:= ?BT_FAILURE ->
BTState2 = blackboard:set(i, I + 1, ID, BTState1),
{BTStatus, BTState2};
{BTStatus, BTState1} ->
{BTStatus, BTState1}
end;
_I ->
{?BT_FAILURE, BTState}
end;
tick(_BTNode, BTState) -> tick(_BTNode, BTState) ->
{?BT_ERROR, BTState}.
{?BT_ERROR, BTState}.
-spec close(bt_node(), bt_state()) -> bt_state(). -spec close(bt_node(), bt_state()) -> bt_state().
close(#{id := ID} = _BTNode, BTState) -> close(#{id := ID} = _BTNode, BTState) ->
blackboard:remove(i, ID, BTState).
blackboard:remove(i, ID, BTState).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions

+ 12
- 12
src/decorator/max_time.erl Переглянути файл

@ -15,24 +15,24 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec open(bt_node(), bt_state()) -> bt_state(). -spec open(bt_node(), bt_state()) -> bt_state().
open(#{id := ID} = _BTNode, BTState) -> open(#{id := ID} = _BTNode, BTState) ->
blackboard:set(start_time, erlang:system_time(millisecond), ID, BTState).
blackboard:set(start_time, erlang:system_time(millisecond), ID, BTState).
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{id := ID, children := [ChildID] , properties := #{max_time := MaxTime}} = _BTNode, BTState) ->
StartTime = blackboard:get(start_time, ID, BTState),
{BTStatus, BTState1} = base_node:execute(ChildID, BTState),
case MaxTime > erlang:system_time(millisecond) - StartTime of
true ->
{BTStatus, BTState1};
false ->
{?BT_FAILURE, BTState}
end;
tick(#{id := ID, children := [ChildID], properties := #{max_time := MaxTime}} = _BTNode, BTState) ->
StartTime = blackboard:get(start_time, ID, BTState),
{BTStatus, BTState1} = base_node:execute(ChildID, BTState),
case MaxTime > erlang:system_time(millisecond) - StartTime of
true ->
{BTStatus, BTState1};
false ->
{?BT_FAILURE, BTState}
end;
tick(_BTNode, BTState) -> tick(_BTNode, BTState) ->
{?BT_ERROR, BTState}.
{?BT_ERROR, BTState}.
-spec close(bt_node(), bt_state()) -> bt_state(). -spec close(bt_node(), bt_state()) -> bt_state().
close(#{id := ID} = _BTNode, BTState) -> close(#{id := ID} = _BTNode, BTState) ->
blackboard:remove(start_time, ID, BTState).
blackboard:remove(start_time, ID, BTState).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions

+ 14
- 14
src/decorator/repeat_until_failure.erl Переглянути файл

@ -15,30 +15,30 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec open(bt_node(), bt_state()) -> bt_state(). -spec open(bt_node(), bt_state()) -> bt_state().
open(#{id := ID} = _BTNode, BTState) -> open(#{id := ID} = _BTNode, BTState) ->
blackboard:set(i, 0, ID, BTState).
blackboard:set(i, 0, ID, BTState).
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{id := ID, children := [ChildID], properties := #{max_loop := MaxLoop}} = _BTNode, BTState) -> tick(#{id := ID, children := [ChildID], properties := #{max_loop := MaxLoop}} = _BTNode, BTState) ->
I = blackboard:get(i, ID, BTState),
{I1, BTStatus, BTState1} = tick_1(MaxLoop, I, ChildID, ?BT_ERROR, BTState),
BTState2 = blackboard:set(i, I1, ID, BTState1),
{BTStatus, BTState2};
I = blackboard:get(i, ID, BTState),
{I1, BTStatus, BTState1} = tick_1(MaxLoop, I, ChildID, ?BT_ERROR, BTState),
BTState2 = blackboard:set(i, I1, ID, BTState1),
{BTStatus, BTState2};
tick(_BTNode, BTState) -> tick(_BTNode, BTState) ->
{?BT_ERROR, BTState}.
{?BT_ERROR, BTState}.
-spec close(bt_node(), bt_state()) -> bt_state(). -spec close(bt_node(), bt_state()) -> bt_state().
close(#{id := ID} = _BTNode, BTState) -> close(#{id := ID} = _BTNode, BTState) ->
blackboard:remove(i, ID, BTState).
blackboard:remove(i, ID, BTState).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
tick_1(MaxLoop, I, ChildID, _BTStatus, BTState) when MaxLoop < 0 orelse I < MaxLoop -> tick_1(MaxLoop, I, ChildID, _BTStatus, BTState) when MaxLoop < 0 orelse I < MaxLoop ->
case base_node:execute(ChildID, BTState) of
{?BT_SUCCESS, BTState1} ->
tick_1(MaxLoop, I + 1, ChildID, ?BT_SUCCESS, BTState1);
{BTStatus, BTState1} ->
{I, BTStatus, BTState1}
end;
case base_node:execute(ChildID, BTState) of
{?BT_SUCCESS, BTState1} ->
tick_1(MaxLoop, I + 1, ChildID, ?BT_SUCCESS, BTState1);
{BTStatus, BTState1} ->
{I, BTStatus, BTState1}
end;
tick_1(_MaxLoop, I, _ChildID, BTStatus, BTState) -> tick_1(_MaxLoop, I, _ChildID, BTStatus, BTState) ->
{I, BTStatus, BTState}.
{I, BTStatus, BTState}.

+ 14
- 14
src/decorator/repeat_until_success.erl Переглянути файл

@ -16,30 +16,30 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec open(bt_node(), bt_state()) -> bt_state(). -spec open(bt_node(), bt_state()) -> bt_state().
open(#{id := ID} = _BTNode, BTState) -> open(#{id := ID} = _BTNode, BTState) ->
blackboard:set(i, 0, ID, BTState).
blackboard:set(i, 0, ID, BTState).
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{id := ID, children := [ChildID], properties := #{max_loop := MaxLoop}} = _BTNode, BTState) -> tick(#{id := ID, children := [ChildID], properties := #{max_loop := MaxLoop}} = _BTNode, BTState) ->
I = blackboard:get(i, ID, BTState),
{I1, BTStatus, BTState1} = tick_1(MaxLoop, I, ChildID, ?BT_ERROR, BTState),
BTState2 = blackboard:set(i, I1, ID, BTState1),
{BTStatus, BTState2};
I = blackboard:get(i, ID, BTState),
{I1, BTStatus, BTState1} = tick_1(MaxLoop, I, ChildID, ?BT_ERROR, BTState),
BTState2 = blackboard:set(i, I1, ID, BTState1),
{BTStatus, BTState2};
tick(_BTNode, BTState) -> tick(_BTNode, BTState) ->
{?BT_ERROR, BTState}.
{?BT_ERROR, BTState}.
-spec close(bt_node(), bt_state()) -> bt_state(). -spec close(bt_node(), bt_state()) -> bt_state().
close(#{id := ID} = _BTNode, BTState) -> close(#{id := ID} = _BTNode, BTState) ->
blackboard:remove(i, ID, BTState).
blackboard:remove(i, ID, BTState).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
tick_1(MaxLoop, I, ChildID, _BTStatus, BTState) when MaxLoop < 0 orelse I < MaxLoop -> tick_1(MaxLoop, I, ChildID, _BTStatus, BTState) when MaxLoop < 0 orelse I < MaxLoop ->
case base_node:execute(ChildID, BTState) of
{?BT_FAILURE, BTBTState1} ->
tick_1(MaxLoop, I + 1, ChildID, ?BT_FAILURE, BTBTState1);
{BTStatus, BTBTState1} ->
{I, BTStatus, BTBTState1}
end;
case base_node:execute(ChildID, BTState) of
{?BT_FAILURE, BTBTState1} ->
tick_1(MaxLoop, I + 1, ChildID, ?BT_FAILURE, BTBTState1);
{BTStatus, BTBTState1} ->
{I, BTStatus, BTBTState1}
end;
tick_1(_MaxLoop, I, _ChildID, BTStatus, BTState) -> tick_1(_MaxLoop, I, _ChildID, BTStatus, BTState) ->
{I, BTStatus, BTState}.
{I, BTStatus, BTState}.

+ 14
- 14
src/decorator/repeater.erl Переглянути файл

@ -15,30 +15,30 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec open(bt_node(), bt_state()) -> bt_state(). -spec open(bt_node(), bt_state()) -> bt_state().
open(#{id := ID} = _BTNode, BTState) -> open(#{id := ID} = _BTNode, BTState) ->
blackboard:set(i, 0, ID, BTState).
blackboard:set(i, 0, ID, BTState).
-spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}.
tick(#{id := ID, children := [ChildID], properties := #{max_loop := MaxLoop}} = _BTNode, BTState) -> tick(#{id := ID, children := [ChildID], properties := #{max_loop := MaxLoop}} = _BTNode, BTState) ->
I = blackboard:get(i, ID, BTState),
{I1, BTStatus, BTState1} = tick_1(MaxLoop, I, ChildID, ?BT_SUCCESS, BTState),
BTState2 = blackboard:set(i, I1, ID, BTState1),
{BTStatus, BTState2};
I = blackboard:get(i, ID, BTState),
{I1, BTStatus, BTState1} = tick_1(MaxLoop, I, ChildID, ?BT_SUCCESS, BTState),
BTState2 = blackboard:set(i, I1, ID, BTState1),
{BTStatus, BTState2};
tick(_BTNode, BTState) -> tick(_BTNode, BTState) ->
{?BT_ERROR, BTState}.
{?BT_ERROR, BTState}.
-spec close(bt_node(), bt_state()) -> bt_state(). -spec close(bt_node(), bt_state()) -> bt_state().
close(#{id := ID} = _BTNode, BTState) -> close(#{id := ID} = _BTNode, BTState) ->
blackboard:remove(i, ID, BTState).
blackboard:remove(i, ID, BTState).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
tick_1(MaxLoop, I, ChildID, _BTStatus, BTState) when MaxLoop < 0 orelse I < MaxLoop -> tick_1(MaxLoop, I, ChildID, _BTStatus, BTState) when MaxLoop < 0 orelse I < MaxLoop ->
case base_node:execute(ChildID, BTState) of
{BTStatus, BTState1} when BTStatus =:= ?BT_SUCCESS; BTStatus =:= ?BT_FAILURE ->
tick_1(MaxLoop, I + 1, ChildID, BTStatus, BTState1);
{BTStatus, BTState1} ->
{I, BTStatus, BTState1}
end;
case base_node:execute(ChildID, BTState) of
{BTStatus, BTState1} when BTStatus =:= ?BT_SUCCESS; BTStatus =:= ?BT_FAILURE ->
tick_1(MaxLoop, I + 1, ChildID, BTStatus, BTState1);
{BTStatus, BTState1} ->
{I, BTStatus, BTState1}
end;
tick_1(_MaxLoop, I, _ChildID, BTStatus, BTState) -> tick_1(_MaxLoop, I, _ChildID, BTStatus, BTState) ->
{I, BTStatus, BTState}.
{I, BTStatus, BTState}.

+ 9
- 9
src/eBhv3.app.src Переглянути файл

@ -1,10 +1,10 @@
{application, eBhv3, {application, eBhv3,
[{description, "An OTP library"},
{vsn, "0.1.0"},
{registered, []},
{applications, [kernel, stdlib]},
{env,[]},
{modules, []},
{licenses, ["MIT"]},
{links, []}
]}.
[{description, "An OTP library"},
{vsn, "0.1.0"},
{registered, []},
{applications, [kernel, stdlib]},
{env, []},
{modules, []},
{licenses, ["MIT"]},
{links, []}
]}.

Завантаження…
Відмінити
Зберегти