diff --git a/README.md b/README.md index 4111f3f..3179c92 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,16 @@ Behavior3的erlang支持库 编译 ---- + $ rebar3 compile - + 使用 ---- + {TitleMaps, TreeMaps, TreeNodeMaps} = behavior_tree:load_tree_file("example.json"), {ok, RootID} = behavior_tree:init_btree_by_title(<<"example_ai"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps), {_BTStatus, _BTState1} = behavior_tree:execute(RootID, BTState = #{}). - + 更多 ---- [behavior3editor](https://github.com/behavior3/behavior3editor) @@ -63,13 +65,14 @@ Build ---- $ rebar3 compile - + Usage ---- + {TitleMaps, TreeMaps, TreeNodeMaps} = behavior_tree:load_tree_file("example.json"), {ok, RootID} = behavior_tree:init_btree_by_title(<<"example_ai"/utf8>>, TitleMaps, TreeMaps, TreeNodeMaps), {_BTStatus, _BTState1} = behavior_tree:execute(RootID, BTState = #{}). - + More ---- diff --git a/examples/action/action_add_rage.erl b/examples/action/action_add_rage.erl index 5991875..d92e927 100644 --- a/examples/action/action_add_rage.erl +++ b/examples/action/action_add_rage.erl @@ -16,6 +16,6 @@ -export([tick/2]). 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}. \ No newline at end of file + 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}. \ No newline at end of file diff --git a/examples/action/action_become_attacking.erl b/examples/action/action_become_attacking.erl index 5947fa7..f791afd 100644 --- a/examples/action/action_become_attacking.erl +++ b/examples/action/action_become_attacking.erl @@ -15,6 +15,6 @@ -export([tick/2]). tick(_BTree, State) -> - State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_ATTACKING)}, - ?INFO("~ts:变为攻击状态", [maps:get(uid, State1)]), - {?BT_SUCCESS, State1}. \ No newline at end of file + State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_ATTACKING)}, + ?INFO("~ts:变为攻击状态", [maps:get(uid, State1)]), + {?BT_SUCCESS, State1}. \ No newline at end of file diff --git a/examples/action/action_become_idle.erl b/examples/action/action_become_idle.erl index 4e4c1eb..248eb16 100644 --- a/examples/action/action_become_idle.erl +++ b/examples/action/action_become_idle.erl @@ -15,6 +15,6 @@ -export([tick/2]). tick(_BTree, State) -> - State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_IDLE)}, - ?INFO("~ts:变为空闲状态", [maps:get(uid, State1)]), - {?BT_SUCCESS, State1}. \ No newline at end of file + State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_IDLE)}, + ?INFO("~ts:变为空闲状态", [maps:get(uid, State1)]), + {?BT_SUCCESS, State1}. \ No newline at end of file diff --git a/examples/action/action_become_patrolling.erl b/examples/action/action_become_patrolling.erl index 1dd8a87..949d3ac 100644 --- a/examples/action/action_become_patrolling.erl +++ b/examples/action/action_become_patrolling.erl @@ -15,6 +15,6 @@ -export([tick/2]). tick(_BTree, State) -> - State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_PATROLLING)}, - ?INFO("~ts:变为巡逻状态", [maps:get(uid, State1)]), - {?BT_SUCCESS, State1}. \ No newline at end of file + State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_PATROLLING)}, + ?INFO("~ts:变为巡逻状态", [maps:get(uid, State1)]), + {?BT_SUCCESS, State1}. \ No newline at end of file diff --git a/examples/action/action_become_recovering.erl b/examples/action/action_become_recovering.erl index e1e56f1..25c9905 100644 --- a/examples/action/action_become_recovering.erl +++ b/examples/action/action_become_recovering.erl @@ -15,6 +15,6 @@ -export([tick/2]). tick(_BTree, State) -> - State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_RECOVERING)}, - ?INFO("~ts:变为恢复状态", [maps:get(uid, State1)]), - {?BT_SUCCESS, State1}. \ No newline at end of file + State1 = State#{cur_state := ?SET_STATE(?STATE_TYPE_RECOVERING)}, + ?INFO("~ts:变为恢复状态", [maps:get(uid, State1)]), + {?BT_SUCCESS, State1}. \ No newline at end of file diff --git a/examples/action/action_collect_dest_path.erl b/examples/action/action_collect_dest_path.erl index 72968aa..703bac5 100644 --- a/examples/action/action_collect_dest_path.erl +++ b/examples/action/action_collect_dest_path.erl @@ -15,46 +15,46 @@ -export([tick/2]). 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) -> - 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}) -> - 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) -> - 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) -> - 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. \ No newline at end of file + 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. \ No newline at end of file diff --git a/examples/action/action_collect_path.erl b/examples/action/action_collect_path.erl index c138266..66bb702 100644 --- a/examples/action/action_collect_path.erl +++ b/examples/action/action_collect_path.erl @@ -16,30 +16,30 @@ 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) -> - 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) -> - 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) -> - Result. + Result. diff --git a/examples/action/action_collect_patrol.erl b/examples/action/action_collect_patrol.erl index c1c5f0f..efd27ce 100644 --- a/examples/action/action_collect_patrol.erl +++ b/examples/action/action_collect_patrol.erl @@ -16,11 +16,11 @@ -export([tick/2]). 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. \ No newline at end of file + 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. \ No newline at end of file diff --git a/examples/action/action_cost_power.erl b/examples/action/action_cost_power.erl index 67aa5e7..a553978 100644 --- a/examples/action/action_cost_power.erl +++ b/examples/action/action_cost_power.erl @@ -16,7 +16,7 @@ -export([tick/2]). 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}. \ No newline at end of file + #{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}. \ No newline at end of file diff --git a/examples/action/action_cost_rage.erl b/examples/action/action_cost_rage.erl index c604624..39e7004 100644 --- a/examples/action/action_cost_rage.erl +++ b/examples/action/action_cost_rage.erl @@ -16,6 +16,6 @@ -export([tick/2]). 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}. \ No newline at end of file + State1 = State#{cur_rage := max(CurRage - CostRage, 0)}, + ?INFO("~ts:怒气值减少~w点", [maps:get(uid, State1), CurRage - maps:get(cur_rage, State1)]), + {?BT_SUCCESS, State1}. \ No newline at end of file diff --git a/examples/action/action_del_dead_target.erl b/examples/action/action_del_dead_target.erl index 87b6a42..5476296 100644 --- a/examples/action/action_del_dead_target.erl +++ b/examples/action/action_del_dead_target.erl @@ -16,5 +16,5 @@ -export([tick/2]). tick(_BTree, #{rival_list := [_ | T]} = State) -> - State1 = State#{rival_list := T}, - {?BT_SUCCESS, State1}. \ No newline at end of file + State1 = State#{rival_list := T}, + {?BT_SUCCESS, State1}. \ No newline at end of file diff --git a/examples/action/action_died.erl b/examples/action/action_died.erl index 7325188..9b7c2be 100644 --- a/examples/action/action_died.erl +++ b/examples/action/action_died.erl @@ -16,6 +16,6 @@ -export([tick/2]). tick(_BTree, #{uid := UID} = State) -> - self() ! {died, UID}, - ?INFO("~ts 被消灭!", [UID]), - {?BT_SUCCESS, State#{cur_state := ?SET_STATE(?STATE_TYPE_DEAD)}}. \ No newline at end of file + self() ! {died, UID}, + ?INFO("~ts 被消灭!", [UID]), + {?BT_SUCCESS, State#{cur_state := ?SET_STATE(?STATE_TYPE_DEAD)}}. \ No newline at end of file diff --git a/examples/action/action_finish.erl b/examples/action/action_finish.erl index ff7151f..39942f4 100644 --- a/examples/action/action_finish.erl +++ b/examples/action/action_finish.erl @@ -16,6 +16,6 @@ -export([tick/2]). tick(#{properties := #{is_win := IsWin}} = _BTree, #{uid := UID} = State) -> - self() ! finish, - ?INFO("游戏结束,~ts~ts!", [UID, IsWin]), - {?BT_SUCCESS, State}. \ No newline at end of file + self() ! finish, + ?INFO("游戏结束,~ts~ts!", [UID, IsWin]), + {?BT_SUCCESS, State}. \ No newline at end of file diff --git a/examples/action/action_move_grid.erl b/examples/action/action_move_grid.erl index a43cab2..37ff7d2 100644 --- a/examples/action/action_move_grid.erl +++ b/examples/action/action_move_grid.erl @@ -15,7 +15,7 @@ -export([tick/2]). 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}. \ No newline at end of file + game_dict:update_map_date(OldGrid, Grid, UID), + State1 = State#{grid_list := T, cur_grid := Grid}, + ?INFO("~ts:移动到了~w格子", [UID, Grid]), + {?BT_SUCCESS, State1}. \ No newline at end of file diff --git a/examples/action/action_recover_power.erl b/examples/action/action_recover_power.erl index 87c257a..94ccf5b 100644 --- a/examples/action/action_recover_power.erl +++ b/examples/action/action_recover_power.erl @@ -16,7 +16,7 @@ -export([tick/2]). 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}. \ No newline at end of file + 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}. \ No newline at end of file diff --git a/examples/action/action_skill_attack.erl b/examples/action/action_skill_attack.erl index ddf4d51..9a8bd82 100644 --- a/examples/action/action_skill_attack.erl +++ b/examples/action/action_skill_attack.erl @@ -16,29 +16,29 @@ -export([tick/2]). 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) -> - #{ - 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. \ No newline at end of file + #{ + 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. \ No newline at end of file diff --git a/examples/condition/cond_is_attacking.erl b/examples/condition/cond_is_attacking.erl index 492d6f1..97f4f4f 100644 --- a/examples/condition/cond_is_attacking.erl +++ b/examples/condition/cond_is_attacking.erl @@ -16,9 +16,9 @@ -export([tick/2]). tick(_BTree, #{cur_state := CurState} = State) -> - case ?IS_STATE(?STATE_TYPE_ATTACKING, CurState) of - true -> - {?BT_SUCCESS, State}; - false -> - {?BT_FAILURE, State} - end. \ No newline at end of file + case ?IS_STATE(?STATE_TYPE_ATTACKING, CurState) of + true -> + {?BT_SUCCESS, State}; + false -> + {?BT_FAILURE, State} + end. \ No newline at end of file diff --git a/examples/condition/cond_is_dest.erl b/examples/condition/cond_is_dest.erl index 363906f..ee47c44 100644 --- a/examples/condition/cond_is_dest.erl +++ b/examples/condition/cond_is_dest.erl @@ -15,9 +15,9 @@ -export([tick/2]). tick(_BTree, State) -> - case State of - #{grid_list := []} -> - {?BT_SUCCESS, State}; - #{} -> - {?BT_FAILURE, State} - end. \ No newline at end of file + case State of + #{grid_list := []} -> + {?BT_SUCCESS, State}; + #{} -> + {?BT_FAILURE, State} + end. \ No newline at end of file diff --git a/examples/condition/cond_is_died.erl b/examples/condition/cond_is_died.erl index c623caf..7c9accb 100644 --- a/examples/condition/cond_is_died.erl +++ b/examples/condition/cond_is_died.erl @@ -15,9 +15,9 @@ -export([tick/2]). tick(_BTree, #{cur_power := CurPower} = State) -> - case CurPower =< 0 of - true -> - {?BT_SUCCESS, State}; - false -> - {?BT_FAILURE, State} - end. \ No newline at end of file + case CurPower =< 0 of + true -> + {?BT_SUCCESS, State}; + false -> + {?BT_FAILURE, State} + end. \ No newline at end of file diff --git a/examples/condition/cond_is_idle.erl b/examples/condition/cond_is_idle.erl index fb86afa..22dc20e 100644 --- a/examples/condition/cond_is_idle.erl +++ b/examples/condition/cond_is_idle.erl @@ -16,9 +16,9 @@ -export([tick/2]). 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. diff --git a/examples/condition/cond_is_patrolling.erl b/examples/condition/cond_is_patrolling.erl index ea33e1c..17d2654 100644 --- a/examples/condition/cond_is_patrolling.erl +++ b/examples/condition/cond_is_patrolling.erl @@ -16,9 +16,9 @@ -export([tick/2]). tick(_BTree, #{cur_state := CurState} = State) -> - case ?IS_STATE(?STATE_TYPE_PATROLLING, CurState) of - true -> - {?BT_SUCCESS, State}; - false -> - {?BT_FAILURE, State} - end. \ No newline at end of file + case ?IS_STATE(?STATE_TYPE_PATROLLING, CurState) of + true -> + {?BT_SUCCESS, State}; + false -> + {?BT_FAILURE, State} + end. \ No newline at end of file diff --git a/examples/condition/cond_is_power_full.erl b/examples/condition/cond_is_power_full.erl index 2d5fa92..da22419 100644 --- a/examples/condition/cond_is_power_full.erl +++ b/examples/condition/cond_is_power_full.erl @@ -16,9 +16,9 @@ -export([tick/2]). tick(_BTree, #{cur_power := CurPower} = State) -> - case CurPower >= ?MAX_POWER of - true -> - {?BT_SUCCESS, State}; - false -> - {?BT_FAILURE, State} - end. \ No newline at end of file + case CurPower >= ?MAX_POWER of + true -> + {?BT_SUCCESS, State}; + false -> + {?BT_FAILURE, State} + end. \ No newline at end of file diff --git a/examples/condition/cond_is_rage_full.erl b/examples/condition/cond_is_rage_full.erl index 038707f..58b974a 100644 --- a/examples/condition/cond_is_rage_full.erl +++ b/examples/condition/cond_is_rage_full.erl @@ -16,9 +16,9 @@ -export([tick/2]). tick(_BTree, #{cur_rage := CurRage} = State) -> - case CurRage >= ?MAX_RAGE of - true -> - {?BT_SUCCESS, State}; - false -> - {?BT_FAILURE, State} - end. \ No newline at end of file + case CurRage >= ?MAX_RAGE of + true -> + {?BT_SUCCESS, State}; + false -> + {?BT_FAILURE, State} + end. \ No newline at end of file diff --git a/examples/condition/cond_is_recovering.erl b/examples/condition/cond_is_recovering.erl index 216b2f6..50c07c8 100644 --- a/examples/condition/cond_is_recovering.erl +++ b/examples/condition/cond_is_recovering.erl @@ -16,9 +16,9 @@ -export([tick/2]). tick(_BTree, #{cur_state := CurState} = State) -> - case ?IS_STATE(?STATE_TYPE_RECOVERING, CurState) of - true -> - {?BT_SUCCESS, State}; - false -> - {?BT_FAILURE, State} - end. \ No newline at end of file + case ?IS_STATE(?STATE_TYPE_RECOVERING, CurState) of + true -> + {?BT_SUCCESS, State}; + false -> + {?BT_FAILURE, State} + end. \ No newline at end of file diff --git a/examples/condition/cond_is_target_died.erl b/examples/condition/cond_is_target_died.erl index 2bb8731..c634de9 100644 --- a/examples/condition/cond_is_target_died.erl +++ b/examples/condition/cond_is_target_died.erl @@ -15,14 +15,14 @@ -export([tick/2]). 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. diff --git a/examples/condition/cond_power_lt.erl b/examples/condition/cond_power_lt.erl index cf413f5..3e2d19b 100644 --- a/examples/condition/cond_power_lt.erl +++ b/examples/condition/cond_power_lt.erl @@ -15,10 +15,10 @@ -export([tick/2]). 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. diff --git a/examples/game_dict.erl b/examples/game_dict.erl index 451807a..68b52fe 100644 --- a/examples/game_dict.erl +++ b/examples/game_dict.erl @@ -13,47 +13,47 @@ %% API -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()]. 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. 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(). get_initiative_btree_id(UID) -> - erlang:get({initiative_btree_id, UID}). + erlang:get({initiative_btree_id, UID}). 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) -> - erlang:erase({initiative_btree_id, UID}). + erlang:erase({initiative_btree_id, UID}). -spec get_passivity_btree_id(uid()) -> bt_uid(). get_passivity_btree_id(UID) -> - erlang:get({passivity_btree_id, UID}). + erlang:get({passivity_btree_id, UID}). 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) -> - erlang:erase({passivity_btree_id, UID}). + erlang:erase({passivity_btree_id, UID}). -spec get_role_state(uid()) -> map(). get_role_state(UID) -> - erlang:get({role_state, UID}). + erlang:get({role_state, UID}). put_role_state(UID, State) -> - erlang:put({role_state, UID}, State). + erlang:put({role_state, UID}, State). erase_role_state(UID) -> - erlang:erase({role_state, UID}). + erlang:erase({role_state, UID}). diff --git a/examples/game_process.erl b/examples/game_process.erl index dbbb443..fdd3d9f 100644 --- a/examples/game_process.erl +++ b/examples/game_process.erl @@ -21,12 +21,12 @@ %%%=================================================================== start_link() -> - gen_server:start_link(?MODULE, [], []). + gen_server:start_link(?MODULE, [], []). 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>>, %% <<"BOMMER"/utf8>>, %% <<"JOCKEY"/utf8>>, @@ -34,94 +34,94 @@ init([]) -> %% <<"SPITTER"/utf8>>, %% <<"CHARGER"/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) -> - {reply, ok, State}. + {reply, ok, State}. handle_cast(_Request, State) -> - {noreply, State}. + {noreply, 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) -> - {stop, normal, State}; + {stop, normal, 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) -> - {noreply, State}. + {noreply, State}. %%%=================================================================== %%% Internal functions %%%=================================================================== 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) -> - {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) -> - ok. + ok. 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) -> - 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. \ No newline at end of file + 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. \ No newline at end of file diff --git a/include/behavior3.hrl b/include/behavior3.hrl index 15259bf..370a946 100644 --- a/include/behavior3.hrl +++ b/include/behavior3.hrl @@ -15,47 +15,47 @@ -type bt_node_id() :: string(). -type bt_state() :: #{ - '$global_maps' => map(), - '$local_maps' => map(), - term() => term() +'$global_maps' => map(), +'$local_maps' => map(), +term() => term() }. -type properties() :: #{atom() => term()}. %% 未初始化的树节点 -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 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() :: #{ - 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, [ - 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])). diff --git a/src/action/error.erl b/src/action/error.erl index 4f45cba..3598921 100644 --- a/src/action/error.erl +++ b/src/action/error.erl @@ -15,7 +15,7 @@ %%-------------------------------------------------------------------- -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. tick(_BTNode, BTState) -> - {?BT_ERROR, BTState}. + {?BT_ERROR, BTState}. %%-------------------------------------------------------------------- %% Internal functions diff --git a/src/action/failer.erl b/src/action/failer.erl index 207c8f4..6a6f3f2 100644 --- a/src/action/failer.erl +++ b/src/action/failer.erl @@ -15,7 +15,7 @@ %%-------------------------------------------------------------------- -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. tick(_BTNode, BTState) -> - {?BT_FAILURE, BTState}. + {?BT_FAILURE, BTState}. %%-------------------------------------------------------------------- %% Internal functions diff --git a/src/action/runner.erl b/src/action/runner.erl index f4d2c3e..c72c9f3 100644 --- a/src/action/runner.erl +++ b/src/action/runner.erl @@ -15,7 +15,7 @@ %%-------------------------------------------------------------------- -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. tick(_BTNode, BTState) -> - {?BT_RUNNING, BTState}. + {?BT_RUNNING, BTState}. %%-------------------------------------------------------------------- %% Internal functions diff --git a/src/action/succeeder.erl b/src/action/succeeder.erl index b93df09..1240809 100644 --- a/src/action/succeeder.erl +++ b/src/action/succeeder.erl @@ -15,7 +15,7 @@ %%-------------------------------------------------------------------- -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. tick(_BTNode, BTState) -> - {?BT_SUCCESS, BTState}. + {?BT_SUCCESS, BTState}. %%-------------------------------------------------------------------- %% Internal functions diff --git a/src/action/wait.erl b/src/action/wait.erl index 8df3a65..f36d0f2 100644 --- a/src/action/wait.erl +++ b/src/action/wait.erl @@ -15,21 +15,21 @@ %%-------------------------------------------------------------------- -spec open(bt_node(), bt_state()) -> bt_state(). 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()}. 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(). close(#{id := ID} = _BTNode, BTState) -> - blackboard:remove(start_time, ID, BTState). + blackboard:remove(start_time, ID, BTState). %%-------------------------------------------------------------------- %% Internal functions diff --git a/src/composite/mem_priority.erl b/src/composite/mem_priority.erl index 3c91363..7e2e32f 100644 --- a/src/composite/mem_priority.erl +++ b/src/composite/mem_priority.erl @@ -15,29 +15,29 @@ %%-------------------------------------------------------------------- -spec open(bt_node(), bt_state()) -> bt_state(). 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()}. 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(). close(#{id := ID} = _BTNode, State) -> - blackboard:remove(running_children, ID, State). + blackboard:remove(running_children, ID, State). %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- 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) -> - {?BT_FAILURE, BTState}. + {?BT_FAILURE, BTState}. diff --git a/src/composite/mem_sequence.erl b/src/composite/mem_sequence.erl index 0d78645..0b548bb 100644 --- a/src/composite/mem_sequence.erl +++ b/src/composite/mem_sequence.erl @@ -15,29 +15,29 @@ %%-------------------------------------------------------------------- -spec open(bt_node(), bt_state()) -> bt_state(). 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()}. 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(). close(#{id := ID} = _BTNode, BTState) -> - blackboard:remove(running_children, ID, BTState). + blackboard:remove(running_children, ID, BTState). %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- 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) -> - {?BT_SUCCESS, BTState}. + {?BT_SUCCESS, BTState}. diff --git a/src/composite/priority.erl b/src/composite/priority.erl index ecec02a..5160b8e 100644 --- a/src/composite/priority.erl +++ b/src/composite/priority.erl @@ -15,17 +15,17 @@ %%-------------------------------------------------------------------- -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. tick(#{children := Children} = _BTNode, BTState) -> - tick_1(Children, BTState). + tick_1(Children, BTState). %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- 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) -> - {?BT_FAILURE, BTState}. + {?BT_FAILURE, BTState}. diff --git a/src/composite/sequence.erl b/src/composite/sequence.erl index 60a58f3..8c47fb7 100644 --- a/src/composite/sequence.erl +++ b/src/composite/sequence.erl @@ -15,17 +15,17 @@ %%-------------------------------------------------------------------- -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. tick(#{children := Children} = _BTNode, BTState) -> - tick_1(Children, BTState). + tick_1(Children, BTState). %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- 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) -> - {?BT_SUCCESS, BTState}. + {?BT_SUCCESS, BTState}. diff --git a/src/core/base_node.erl b/src/core/base_node.erl index 257b83a..868d7b1 100644 --- a/src/core/base_node.erl +++ b/src/core/base_node.erl @@ -35,16 +35,16 @@ %% @doc 执行节点 -spec execute(bt_uid(), bt_state()) -> {bt_status(), bt_state()}. 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 @@ -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()}. 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/2函数实现,则执行open函数, %% 如果树节点已经开启,则跳过 -spec do_open(bt_node(), bt_state()) -> bt_state(). 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函数 -spec do_tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. do_tick(#{name := Mod} = BTNode, BTState) -> - Mod:tick(BTNode, BTState). + Mod:tick(BTNode, BTState). %% @doc 如果树节点有close/2函数实现,则执行close函数 -spec do_close(bt_node(), bt_state()) -> bt_state(). 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) -> - 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) -> - BTState. \ No newline at end of file + BTState. \ No newline at end of file diff --git a/src/core/behavior_tree.erl b/src/core/behavior_tree.erl index f05c67e..47f6730 100644 --- a/src/core/behavior_tree.erl +++ b/src/core/behavior_tree.erl @@ -11,9 +11,9 @@ %% export API %%-------------------------------------------------------------------- -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 @@ -26,94 +26,94 @@ %% 载入行为树文件 -spec load_tree_file(file:name_all()) -> {#{string() => bt_node_id()}, #{bt_node_id() => btree()}, tree_nodes()}|{error, term()}. 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 %% 获取行为树根节点id -spec get_btree_id_by_title(string(), #{string() => bt_node_id()}) -> bt_node_id()|undefined. get_btree_id_by_title(Title, TitleMaps) -> - case TitleMaps of - #{Title := ID} -> - ID; - #{} -> - undefined - end. + case TitleMaps of + #{Title := ID} -> + ID; + #{} -> + undefined + end. %% @doc %% 获取行为树根节点 -spec get_btree(bt_node_id(), #{bt_node_id() => btree()}) -> btree()|undefined. get_btree(BTNodeID, TreeMaps) -> - case TreeMaps of - #{BTNodeID := BTree} -> - BTree; - #{} -> - undefined - end. + case TreeMaps of + #{BTNodeID := BTree} -> + BTree; + #{} -> + undefined + end. %% @doc %% 获取行为树子节点 -spec get_btree_node(bt_node_id(), tree_nodes()) -> uninit_bt_node()|undefined. get_btree_node(BTNodeID, TreeNodeMaps) -> - case TreeNodeMaps of - #{BTNodeID := BTNode} -> - BTNode; - #{} -> - undefined - end. + case TreeNodeMaps of + #{BTNodeID := BTNode} -> + BTNode; + #{} -> + undefined + end. %% @doc %% 根据给定节点名初始化整颗行为树 -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) -> - 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 %% 根据给定节点初始化整颗行为树 -spec init_btree(bt_node_id(), #{bt_node_id() => btree()}, tree_nodes()) -> {ok, bt_uid()}|{error, term()}. 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 %% 执行行为树节点 -spec execute(bt_uid(), bt_state()) -> {bt_status(), bt_state()}. 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 %% 动态执行子节点 -spec execute_child(bt_uid(), bt_state()) -> {bt_status(), bt_state()}. execute_child(NodeID, BTState) -> - base_node:execute(NodeID, BTState). + base_node:execute(NodeID, BTState). %% @doc %% 强制关闭指定节点下的所有子节点 -spec close_btree_node(bt_uid(), bt_state()) -> bt_state(). 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 %% 卸载指定节点下的所有子节点 -spec unload_btree(bt_uid()) -> ok. unload_btree(NodeID) -> - do_unload_btree_node(NodeID). + do_unload_btree_node(NodeID). %%-------------------------------------------------------------------- %% Internal functions @@ -121,95 +121,95 @@ unload_btree(NodeID) -> %% 解析行为树 -spec parse_btree(map()) -> {#{string() => bt_node_id()}, #{bt_node_id() => btree()}, tree_nodes()}. parse_btree(#{<<"trees">> := Trees}) -> - parse_btree_1(Trees, #{}, #{}, #{}). + parse_btree_1(Trees, #{}, #{}, #{}). 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) -> - {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()}. 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) -> - {TreeNodes, TreeNodeMaps}. + {TreeNodes, TreeNodeMaps}. %% 解析子节点属性数据, %% key会转为下划线分割小写atom,value保持不变 -spec parse_properties(map()) -> properties(). 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()]. parse_children(#{<<"child">> := Child} = _Node) -> - [Child]; + [Child]; parse_children(#{<<"children">> := Children} = _Node) -> - Children; + Children; parse_children(_Node) -> - []. + []. %% 模块名转换 %% 例:PlayerID -> player_id Name -> name -spec name_convert(unicode:chardata()) -> atom(). 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(<>) 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(<>) -> - Other1 = name_convert_1(Other), - <>; + Other1 = name_convert_1(Other), + <>; name_convert_1(<<>>) -> - <<>>. + <<>>. %% 执行关闭行为树节点 -spec do_close_btree_node(bt_uid(), bt_state()) -> bt_state(). 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. 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(NodeID), - do_unload_btree_node_1(T); + do_unload_btree_node(NodeID), + do_unload_btree_node_1(T); do_unload_btree_node_1([]) -> - ok. + ok. diff --git a/src/core/blackboard.erl b/src/core/blackboard.erl index a12d464..a8fe2bc 100644 --- a/src/core/blackboard.erl +++ b/src/core/blackboard.erl @@ -9,10 +9,10 @@ %% export API %%-------------------------------------------------------------------- -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 @@ -25,100 +25,100 @@ %% 获取树节点 -spec get_btree_node(bt_uid()) -> bt_node()|undefined. get_btree_node(NodeID) -> - get({btree_node, NodeID}). + get({btree_node, NodeID}). %% @doc %% 设置树节点 -spec set_btree_node(bt_node()) -> ok. set_btree_node(#{id := NodeID} = BTNode) -> - put({btree_node, NodeID}, BTNode), - ok. + put({btree_node, NodeID}, BTNode), + ok. %% @doc %% 移除树节点 -spec erase_btree_node(bt_uid()) -> bt_node(). erase_btree_node(NodeID) -> - erase({btree_node, NodeID}). + erase({btree_node, NodeID}). %% @doc %% 设置全局变量 -spec set_global(term(), term(), bt_state()) -> bt_state(). set_global(Key, Value, #{'$global_maps' := GlobalMaps} = BTState) -> - BTState#{'$global_maps' := GlobalMaps#{Key => Value}}. + BTState#{'$global_maps' := GlobalMaps#{Key => Value}}. %% @doc %% 设置节点变量 -spec set(term(), term(), bt_uid(), bt_state()) -> bt_state(). 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 %% 获取全局变量 -spec get_global(term(), bt_state()) -> term()|undefined. 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 %% 获取全局变量,不存在则返回Default -spec get_global(term(), term(), bt_state()) -> term(). 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 %% 获取节点变量 -spec get(term(), bt_uid(), bt_state()) -> term()|undefined. 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 %% 获取节点变量,不存在则返回Default -spec get(term(), bt_uid(), term(), bt_state()) -> term(). 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 %% 删除全局变量 -spec remove(term(), bt_state()) -> bt_state(). remove(Key, #{'$global_maps' := GlobalMaps} = BTState) -> - BTState#{'$global_maps' := maps:remove(Key, GlobalMaps)}. + BTState#{'$global_maps' := maps:remove(Key, GlobalMaps)}. %% @doc %% 删除节点变量 -spec remove(term(), bt_uid(), bt_state()) -> bt_state(). 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 @@ -126,32 +126,32 @@ remove(Key, NodeID, #{'$local_maps' := LocalMaps} = BTState) -> %% 初始化行为树相关结构 -spec init_maps_keys(bt_state()) -> bt_state(). init_maps_keys(BTState) -> - BTState1 = init_global(BTState), - init_local(BTState1). + BTState1 = init_global(BTState), + init_local(BTState1). 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) -> - 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(). 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(). 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). diff --git a/src/decorator/inverter.erl b/src/decorator/inverter.erl index 2a81ee3..2d88c10 100644 --- a/src/decorator/inverter.erl +++ b/src/decorator/inverter.erl @@ -15,16 +15,16 @@ %%-------------------------------------------------------------------- -spec tick(bt_node(), bt_state()) -> {bt_status(), bt_state()}. 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) -> - {?BT_ERROR, BTState}. + {?BT_ERROR, BTState}. %%-------------------------------------------------------------------- %% Internal functions diff --git a/src/decorator/limiter.erl b/src/decorator/limiter.erl index 3671234..3fa38ba 100644 --- a/src/decorator/limiter.erl +++ b/src/decorator/limiter.erl @@ -15,28 +15,28 @@ %%-------------------------------------------------------------------- -spec open(bt_node(), bt_state()) -> bt_state(). 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()}. 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) -> - {?BT_ERROR, BTState}. + {?BT_ERROR, BTState}. -spec close(bt_node(), bt_state()) -> bt_state(). close(#{id := ID} = _BTNode, BTState) -> - blackboard:remove(i, ID, BTState). + blackboard:remove(i, ID, BTState). %%-------------------------------------------------------------------- %% Internal functions diff --git a/src/decorator/max_time.erl b/src/decorator/max_time.erl index 4cd61cd..9e36ff7 100644 --- a/src/decorator/max_time.erl +++ b/src/decorator/max_time.erl @@ -15,24 +15,24 @@ %%-------------------------------------------------------------------- -spec open(bt_node(), bt_state()) -> bt_state(). 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()}. -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) -> - {?BT_ERROR, BTState}. + {?BT_ERROR, BTState}. -spec close(bt_node(), bt_state()) -> bt_state(). close(#{id := ID} = _BTNode, BTState) -> - blackboard:remove(start_time, ID, BTState). + blackboard:remove(start_time, ID, BTState). %%-------------------------------------------------------------------- %% Internal functions diff --git a/src/decorator/repeat_until_failure.erl b/src/decorator/repeat_until_failure.erl index 77cd287..806822a 100644 --- a/src/decorator/repeat_until_failure.erl +++ b/src/decorator/repeat_until_failure.erl @@ -15,30 +15,30 @@ %%-------------------------------------------------------------------- -spec open(bt_node(), bt_state()) -> bt_state(). 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()}. 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) -> - {?BT_ERROR, BTState}. + {?BT_ERROR, BTState}. -spec close(bt_node(), bt_state()) -> bt_state(). close(#{id := ID} = _BTNode, BTState) -> - blackboard:remove(i, ID, BTState). + blackboard:remove(i, ID, BTState). %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- 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) -> - {I, BTStatus, BTState}. + {I, BTStatus, BTState}. diff --git a/src/decorator/repeat_until_success.erl b/src/decorator/repeat_until_success.erl index bbd8cf1..857c883 100644 --- a/src/decorator/repeat_until_success.erl +++ b/src/decorator/repeat_until_success.erl @@ -16,30 +16,30 @@ %%-------------------------------------------------------------------- -spec open(bt_node(), bt_state()) -> bt_state(). 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()}. 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) -> - {?BT_ERROR, BTState}. + {?BT_ERROR, BTState}. -spec close(bt_node(), bt_state()) -> bt_state(). close(#{id := ID} = _BTNode, BTState) -> - blackboard:remove(i, ID, BTState). + blackboard:remove(i, ID, BTState). %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- 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) -> - {I, BTStatus, BTState}. + {I, BTStatus, BTState}. diff --git a/src/decorator/repeater.erl b/src/decorator/repeater.erl index d36dcfd..396638b 100644 --- a/src/decorator/repeater.erl +++ b/src/decorator/repeater.erl @@ -15,30 +15,30 @@ %%-------------------------------------------------------------------- -spec open(bt_node(), bt_state()) -> bt_state(). 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()}. 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) -> - {?BT_ERROR, BTState}. + {?BT_ERROR, BTState}. -spec close(bt_node(), bt_state()) -> bt_state(). close(#{id := ID} = _BTNode, BTState) -> - blackboard:remove(i, ID, BTState). + blackboard:remove(i, ID, BTState). %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- 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) -> - {I, BTStatus, BTState}. \ No newline at end of file + {I, BTStatus, BTState}. \ No newline at end of file diff --git a/src/eBhv3.app.src b/src/eBhv3.app.src index b6bee20..2aee9e1 100644 --- a/src/eBhv3.app.src +++ b/src/eBhv3.app.src @@ -1,10 +1,10 @@ {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, []} + ]}.