@ -0,0 +1,33 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-26 | |||
%% Doc: Wait Action Node | |||
-module(n_wait). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"Wait". | |||
init(_Parameters) -> | |||
{}. | |||
%% only for test | |||
execute(BteStatus, _Node, _IsFromStack) -> | |||
case util:rand(1, 3) of | |||
1 -> | |||
Status = ?BTE_SUCCESS; | |||
2 -> | |||
Status = ?BTE_FAILURE; | |||
_ -> | |||
Status = ?BTE_RUNNING | |||
end, | |||
BteStatus#r_bte_status{status = Status}. | |||
% BteStatus. |
@ -0,0 +1,80 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-26 | |||
%% Doc: main module | |||
-module(bte_behavior). | |||
-include("common.hrl"). | |||
-export([ | |||
init/1, | |||
tick/1 | |||
]). | |||
init(BteConfigData) -> | |||
bte_util:init_rand_seed(), | |||
BteStatus = | |||
#r_bte_status{ | |||
root_id = BteConfigData#r_bte_config_data.root_id, | |||
nodes = dict:new() | |||
}, | |||
CoreNodesModule = bte_node_behaviour:init_nodes_moudle(?MODULE), | |||
AllNodesModule = CoreNodesModule ++ BteConfigData#r_bte_config_data.custom_nodes_moudle, | |||
lists:foldl(fun(E, Acc) -> | |||
case lists:keyfind(E#r_bte_config_node.name, 1, AllNodesModule) of | |||
{ENodeName, EModule} -> | |||
EData = EModule:init(E#r_bte_config_node.parameters), | |||
ENode = | |||
#r_bte_node{ | |||
id = E#r_bte_config_node.id, | |||
name = ENodeName, | |||
child = E#r_bte_config_node.child, | |||
children = E#r_bte_config_node.children, | |||
module = EModule, | |||
data = EData | |||
}, | |||
bte_tick:update_node(Acc, ENode); | |||
_ -> | |||
io:format("init behavior tree Error! undefined node info : ~p~n", [E]), | |||
Acc | |||
end | |||
end, | |||
BteStatus, | |||
BteConfigData#r_bte_config_data.nodes). | |||
tick(BteStatus) -> | |||
?BTE_DEBUG("tick: ~p~n", [length(BteStatus#r_bte_status.active_stack)]), | |||
if | |||
length(BteStatus#r_bte_status.active_stack) > 0 -> | |||
tick_handle_stack(BteStatus); | |||
true -> | |||
tick_handle(BteStatus#r_bte_status{status = undefined}) | |||
end. | |||
tick_handle_stack(BteStatus) -> | |||
if | |||
length(BteStatus#r_bte_status.active_stack) > 0 -> | |||
{BteStatus1, NodeId} = bte_tick:pop_stack(BteStatus), | |||
BteStatus2 = bte_tick:push_stack(BteStatus1, NodeId), | |||
BteStatus3 = bte_tick:execute(BteStatus2, NodeId, true), | |||
if | |||
BteStatus3#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus4, _} = bte_tick:pop_stack(BteStatus3), | |||
tick_handle_stack(BteStatus4); | |||
true -> | |||
BteStatus3 | |||
end; | |||
true -> | |||
BteStatus | |||
end. | |||
tick_handle(BteStatus) -> | |||
BteStatus1 = bte_tick:push_stack(BteStatus, BteStatus#r_bte_status.root_id), | |||
BteStatus2 = bte_tick:execute(BteStatus1, BteStatus1#r_bte_status.root_id), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2), | |||
BteStatus3; | |||
true -> | |||
BteStatus2 | |||
end. |
@ -0,0 +1,68 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-26 | |||
%% Doc: bte node config behaviour | |||
-module(bte_node_behaviour). | |||
-export([ | |||
behaviour_info/1, | |||
init_nodes_moudle/1 | |||
]). | |||
%% define behaviour function | |||
behaviour_info(callbacks) -> | |||
[ | |||
{node_name, 0}, | |||
{init, 1}, | |||
{execute, 3} | |||
]; | |||
behaviour_info(_Other) -> | |||
undefined. | |||
%% init | |||
init_nodes_moudle(Module) -> | |||
Path = filename:dirname(code:which(Module)), | |||
ModuleList = get_all_behaviour_mod(Path, ?MODULE), | |||
lists:map(fun(EModule) -> | |||
{EModule:node_name(), EModule} | |||
end, | |||
ModuleList). | |||
%% find behavior module | |||
get_all_behaviour_mod(Path, Behaviour) -> | |||
lists:filter(fun(Mod)-> check_mod_behaviour(Mod, Behaviour) end, get_path_module(Path)). | |||
check_mod_behaviour(Mod, CheckBehav) -> | |||
check_mod_behaviour1(Mod:module_info('attributes'), CheckBehav). | |||
check_mod_behaviour1([], _CheckBehav)-> false; | |||
check_mod_behaviour1([{'behaviour', Behaviours} | L], CheckBehav)-> | |||
case lists:member(CheckBehav, Behaviours) of | |||
true -> | |||
true; | |||
_ -> | |||
check_mod_behaviour1(L, CheckBehav) | |||
end; | |||
check_mod_behaviour1([_ | L], CheckBehav) -> | |||
check_mod_behaviour1(L, CheckBehav). | |||
get_path_module(Path) -> | |||
{ok, ALLFiles} = file:list_dir(Path), | |||
lists:foldl(fun(EFileName, AccModules)-> | |||
case get_path_module1(EFileName) of | |||
[] -> | |||
AccModules; | |||
ENewModule -> | |||
[ENewModule | AccModules] | |||
end | |||
end, | |||
[], | |||
ALLFiles). | |||
get_path_module1(FileName)-> | |||
case string:right(FileName, 5) of | |||
".beam"-> | |||
erlang:list_to_atom(string:substr(FileName, 1, string:len(FileName) - 5)); | |||
_-> | |||
[] | |||
end. |
@ -0,0 +1,41 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-26 | |||
%% Doc: handle tick | |||
-module(bte_tick). | |||
-include("common.hrl"). | |||
-export([ | |||
push_stack/2, | |||
pop_stack/1, | |||
execute/2, | |||
execute/3, | |||
get_node/2, | |||
update_node/2 | |||
]). | |||
push_stack(BteStatus, Id) -> | |||
BteStatus#r_bte_status{active_stack = [Id | BteStatus#r_bte_status.active_stack]}. | |||
pop_stack(BteStatus) -> | |||
[Id | Left] = BteStatus#r_bte_status.active_stack, | |||
NewBteStatus = BteStatus#r_bte_status{active_stack = Left}, | |||
{NewBteStatus, Id}. | |||
get_node(BteStatus, Id) -> | |||
dict:fetch(Id, BteStatus#r_bte_status.nodes). | |||
update_node(BteStatus, Node) -> | |||
NewNodes = dict:store(Node#r_bte_node.id, Node, BteStatus#r_bte_status.nodes), | |||
BteStatus#r_bte_status{nodes = NewNodes}. | |||
execute(BteStatus, Id) -> | |||
execute(BteStatus, Id, false). | |||
execute(BteStatus, Id, IsFromStack) -> | |||
Node = get_node(BteStatus, Id), | |||
Module = Node#r_bte_node.module, | |||
NewBteStatus = Module:execute(BteStatus, Node, IsFromStack), | |||
?BTE_DEBUG("> ~p execute: ~p~n", [?MODULE, {Node#r_bte_node.name, NewBteStatus#r_bte_status.status}]), | |||
NewBteStatus. |
@ -0,0 +1,21 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-26 | |||
%% Doc: tools | |||
-module(bte_util). | |||
-export([ | |||
init_rand_seed/0, | |||
rand/2 | |||
]). | |||
init_rand_seed() -> | |||
random:seed(erlang:now()). | |||
rand(Min, Max) when Min == Max -> | |||
Min; | |||
rand(Min, Max) when Min >= Max -> | |||
rand(Max, Min); | |||
rand(Min, Max) -> | |||
Min1 = Min - 1, | |||
random:uniform(Max - Min1) + Min1. |
@ -0,0 +1,27 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-26 | |||
%% Doc: Parallel Node | |||
-module(n_parallel). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
-record(r_data, { | |||
tick_index = 0 | |||
}). | |||
node_name() -> | |||
"Parallel". | |||
init(_Parameters) -> | |||
#r_data{}. | |||
execute(BteStatus, _Node, _IsFromStack) -> | |||
BteStatus. |
@ -0,0 +1,72 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-26 | |||
%% Doc: Random Selector Node | |||
-module(n_random_selector). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-record(r_data, { | |||
tick_children = [] | |||
}). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"RandomSelector". | |||
init(_Parameters) -> | |||
#r_data{}. | |||
execute(BteStatus, Node, IsFromStack) -> | |||
?BTE_DEBUG("~p execute: ~p~n", [?MODULE, {IsFromStack, BteStatus#r_bte_status.status, length(Node#r_bte_node.children)}]), | |||
if | |||
IsFromStack -> | |||
if | |||
BteStatus#r_bte_status.status == ?BTE_SUCCESS -> | |||
BteStatus; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end; | |||
true -> | |||
execute1(BteStatus, Node#r_bte_node{data = #r_data{tick_children = Node#r_bte_node.children}}) | |||
end. | |||
execute1(BteStatus, Node) -> | |||
Children = Node#r_bte_node.data#r_data.tick_children, | |||
if | |||
length(Children) > 0 -> | |||
ChildId = lists:nth(bte_util:rand(1, length(Children)), Children), | |||
?BTE_DEBUG("~p execute___1: ~p~n", [?MODULE, {length(Children) - 1}]), | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2); | |||
true -> | |||
BteStatus3 = BteStatus2 | |||
end, | |||
LeftChildren = lists:delete(ChildId, Children), | |||
Data = Node#r_bte_node.data, | |||
if | |||
BteStatus3#r_bte_status.status == ?BTE_SUCCESS -> | |||
NewData = Data#r_data{tick_children = Node#r_bte_node.children}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
bte_tick:update_node(BteStatus3, NewNode); | |||
BteStatus3#r_bte_status.status == ?BTE_RUNNING -> | |||
NewData = Data#r_data{tick_children = LeftChildren}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
bte_tick:update_node(BteStatus3, NewNode); | |||
true -> | |||
NewData = Data#r_data{tick_children = LeftChildren}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
execute1(BteStatus3, NewNode) | |||
end; | |||
true -> | |||
BteStatus | |||
end. |
@ -0,0 +1,72 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-26 | |||
%% Doc: Random Sequence Node | |||
-module(n_random_sequence). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-record(r_data, { | |||
tick_children = [] | |||
}). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"RandomSequence". | |||
init(_Parameters) -> | |||
#r_data{}. | |||
execute(BteStatus, Node, IsFromStack) -> | |||
?BTE_DEBUG("~p execute: ~p~n", [?MODULE, {IsFromStack, BteStatus#r_bte_status.status, length(Node#r_bte_node.children)}]), | |||
if | |||
IsFromStack -> | |||
if | |||
BteStatus#r_bte_status.status == ?BTE_FAILURE -> | |||
BteStatus; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end; | |||
true -> | |||
execute1(BteStatus, Node#r_bte_node{data = #r_data{tick_children = Node#r_bte_node.children}}) | |||
end. | |||
execute1(BteStatus, Node) -> | |||
Children = Node#r_bte_node.data#r_data.tick_children, | |||
if | |||
length(Children) > 0 -> | |||
ChildId = lists:nth(bte_util:rand(1, length(Children)), Children), | |||
?BTE_DEBUG("~p execute___1: ~p~n", [?MODULE, {length(Children) - 1}]), | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2); | |||
true -> | |||
BteStatus3 = BteStatus2 | |||
end, | |||
LeftChildren = lists:delete(ChildId, Children), | |||
Data = Node#r_bte_node.data, | |||
if | |||
BteStatus3#r_bte_status.status == ?BTE_FAILURE -> | |||
NewData = Data#r_data{tick_children = Node#r_bte_node.children}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
bte_tick:update_node(BteStatus3, NewNode); | |||
BteStatus3#r_bte_status.status == ?BTE_RUNNING -> | |||
NewData = Data#r_data{tick_children = LeftChildren}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
bte_tick:update_node(BteStatus3, NewNode); | |||
true -> | |||
NewData = Data#r_data{tick_children = LeftChildren}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
execute1(BteStatus3, NewNode) | |||
end; | |||
true -> | |||
BteStatus | |||
end. |
@ -0,0 +1,73 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-26 | |||
%% Doc: Selector Node | |||
-module(n_selector). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-record(r_data, { | |||
tick_index = 0 | |||
}). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"Selector". | |||
init(_Parameters) -> | |||
#r_data{}. | |||
execute(BteStatus, Node, IsFromStack) -> | |||
?BTE_DEBUG("~p execute: ~p~n", [?MODULE, {IsFromStack, BteStatus#r_bte_status.status, length(Node#r_bte_node.children)}]), | |||
if | |||
IsFromStack -> | |||
if | |||
BteStatus#r_bte_status.status == ?BTE_SUCCESS -> | |||
BteStatus; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end; | |||
true -> | |||
execute1(BteStatus, Node#r_bte_node{data = #r_data{}}) | |||
end. | |||
execute1(BteStatus, Node) -> | |||
execute2(Node#r_bte_node.children, BteStatus, 1, Node). | |||
execute2([], BteStatus, _Index, _Node) -> | |||
BteStatus; | |||
execute2([ChildId | LeftChildren], BteStatus, Index, Node) -> | |||
Data = Node#r_bte_node.data, | |||
TickIndex = Data#r_data.tick_index, | |||
?BTE_DEBUG("~p execute___2: ~p~n", [?MODULE, {TickIndex, Index, length(LeftChildren)}]), | |||
if | |||
Index > TickIndex -> | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2); | |||
true -> | |||
BteStatus3 = BteStatus2 | |||
end, | |||
if | |||
BteStatus3#r_bte_status.status == ?BTE_SUCCESS -> | |||
NewData = Data#r_data{tick_index = 0}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
bte_tick:update_node(BteStatus3, NewNode); | |||
BteStatus3#r_bte_status.status == ?BTE_RUNNING -> | |||
NewData = Data#r_data{tick_index = Index}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
bte_tick:update_node(BteStatus3, NewNode); | |||
true -> | |||
execute2(LeftChildren, BteStatus3, Index + 1, Node) | |||
end; | |||
true -> | |||
execute2(LeftChildren, BteStatus, Index + 1, Node) | |||
end. |
@ -0,0 +1,73 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-26 | |||
%% Doc: Sequence Node | |||
-module(n_sequence). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-record(r_data, { | |||
tick_index = 0 | |||
}). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"Sequence". | |||
init(_Parameters) -> | |||
#r_data{}. | |||
execute(BteStatus, Node, IsFromStack) -> | |||
?BTE_DEBUG("~p execute: ~p~n", [?MODULE, {IsFromStack, BteStatus#r_bte_status.status, length(Node#r_bte_node.children)}]), | |||
if | |||
IsFromStack -> | |||
if | |||
BteStatus#r_bte_status.status == ?BTE_FAILURE -> | |||
BteStatus; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end; | |||
true -> | |||
execute1(BteStatus, Node#r_bte_node{data = #r_data{}}) | |||
end. | |||
execute1(BteStatus, Node) -> | |||
execute2(Node#r_bte_node.children, BteStatus, 1, Node). | |||
execute2([], BteStatus, _Index, _Node) -> | |||
BteStatus; | |||
execute2([ChildId | LeftChildren], BteStatus, Index, Node) -> | |||
Data = Node#r_bte_node.data, | |||
TickIndex = Data#r_data.tick_index, | |||
?BTE_DEBUG("~p execute___2: ~p~n", [?MODULE, {TickIndex, Index, length(LeftChildren)}]), | |||
if | |||
Index > TickIndex -> | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2); | |||
true -> | |||
BteStatus3 = BteStatus2 | |||
end, | |||
if | |||
BteStatus3#r_bte_status.status == ?BTE_FAILURE -> | |||
NewData = Data#r_data{tick_index = 0}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
bte_tick:update_node(BteStatus3, NewNode); | |||
BteStatus3#r_bte_status.status == ?BTE_RUNNING -> | |||
NewData = Data#r_data{tick_index = Index}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
bte_tick:update_node(BteStatus3, NewNode); | |||
true -> | |||
execute2(LeftChildren, BteStatus3, Index + 1, Node) | |||
end; | |||
true -> | |||
execute2(LeftChildren, BteStatus, Index + 1, Node) | |||
end. |
@ -0,0 +1,44 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-27 | |||
%% Doc: | |||
-module(n_init). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
-record(r_data, { | |||
is_init = false | |||
}). | |||
node_name() -> | |||
"Init". | |||
init(_Parameters) -> | |||
#r_data{}. | |||
execute(BteStatus, Node, _IsFromStack) -> | |||
if | |||
Node#r_bte_node.data#r_data.is_init -> | |||
BteStatus; | |||
true -> | |||
?BTE_DEBUG("~p execute: ~p~n", [?MODULE, {BteStatus#r_bte_status.status}]), | |||
ChildId = Node#r_bte_node.child, | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2); | |||
true -> | |||
BteStatus3 = BteStatus2 | |||
end, | |||
NewData = #r_data{is_init = true}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
bte_tick:update_node(BteStatus3, NewNode) | |||
end. |
@ -0,0 +1,23 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-27 | |||
%% Doc: | |||
-module(n_interrupt). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"Interrupt". | |||
init(_Parameters) -> | |||
{}. | |||
execute(BteStatus, _Node, _IsFromStack) -> | |||
BteStatus. |
@ -0,0 +1,54 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-27 | |||
%% Doc: | |||
-module(n_inverter). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"Inverter". | |||
init(_Parameters) -> | |||
{}. | |||
execute(BteStatus, Node, IsFromStack) -> | |||
if | |||
IsFromStack -> | |||
if | |||
BteStatus#r_bte_status.status == ?BTE_SUCCESS -> | |||
BteStatus#r_bte_status{status = ?BTE_FAILURE}; | |||
BteStatus#r_bte_status.status == ?BTE_FAILURE -> | |||
BteStatus#r_bte_status{status = ?BTE_SUCCESS}; | |||
true -> | |||
BteStatus | |||
end; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end. | |||
execute1(BteStatus, Node) -> | |||
ChildId = Node#r_bte_node.child, | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2), | |||
if | |||
BteStatus3#r_bte_status.status == ?BTE_SUCCESS -> | |||
BteStatus3#r_bte_status{status = ?BTE_FAILURE}; | |||
BteStatus3#r_bte_status.status == ?BTE_FAILURE -> | |||
BteStatus3#r_bte_status{status = ?BTE_SUCCESS}; | |||
true -> | |||
BteStatus3 | |||
end; | |||
true -> | |||
BteStatus2 | |||
end. |
@ -0,0 +1,51 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-27 | |||
%% Doc: repeat until return sfailure | |||
-module(n_repeat_until_failure). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"RepeatUntilFailure". | |||
init(_Parameters) -> | |||
{}. | |||
execute(BteStatus, Node, IsFromStack) -> | |||
?BTE_DEBUG("~p execute: ~p~n", [?MODULE, {BteStatus#r_bte_status.status}]), | |||
if | |||
IsFromStack -> | |||
if | |||
BteStatus#r_bte_status.status == ?BTE_FAILURE -> | |||
BteStatus; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end. | |||
execute1(BteStatus, Node) -> | |||
ChildId = Node#r_bte_node.child, | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2), | |||
if | |||
BteStatus3#r_bte_status.status /= ?BTE_FAILURE -> | |||
BteStatus3#r_bte_status{status = ?BTE_RUNNING}; | |||
true -> | |||
BteStatus3 | |||
end; | |||
true -> | |||
BteStatus2 | |||
end. |
@ -0,0 +1,51 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-27 | |||
%% Doc: repeat until return success | |||
-module(n_repeat_until_success). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"RepeatUntilSuccess". | |||
init(_Parameters) -> | |||
{}. | |||
execute(BteStatus, Node, IsFromStack) -> | |||
?BTE_DEBUG("~p execute: ~p~n", [?MODULE, {BteStatus#r_bte_status.status}]), | |||
if | |||
IsFromStack -> | |||
if | |||
BteStatus#r_bte_status.status == ?BTE_SUCCESS -> | |||
BteStatus; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end. | |||
execute1(BteStatus, Node) -> | |||
ChildId = Node#r_bte_node.child, | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2), | |||
if | |||
BteStatus3#r_bte_status.status /= ?BTE_SUCCESS -> | |||
BteStatus3#r_bte_status{status = ?BTE_RUNNING}; | |||
true -> | |||
BteStatus3 | |||
end; | |||
true -> | |||
BteStatus2 | |||
end. |
@ -0,0 +1,60 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-27 | |||
%% Doc: | |||
-module(n_repeater). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
-record(r_data, { | |||
max_loop = 0, | |||
execute_times = 0 | |||
}). | |||
node_name() -> | |||
"Repeater". | |||
init(Parameters) -> | |||
MaxLoop = proplists:get_value("maxLoop", Parameters, 0), | |||
#r_data{max_loop = MaxLoop}. | |||
execute(BteStatus, Node, _IsFromStack) -> | |||
execute1(BteStatus, Node). | |||
execute1(BteStatus, Node) -> | |||
ExecuteTime = Node#r_bte_node.data#r_data.execute_times, | |||
if | |||
ExecuteTime >= Node#r_bte_node.data#r_data.max_loop -> | |||
NewExecuteTime = 0, | |||
NewData = Node#r_bte_node.data#r_data{execute_times = NewExecuteTime}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
bte_tick:update_node(BteStatus, NewNode); | |||
true -> | |||
?BTE_DEBUG("~p execute: ~p~n", [?MODULE, {ExecuteTime + 1, Node#r_bte_node.data#r_data.max_loop}]), | |||
ChildId = Node#r_bte_node.child, | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
NewExecuteTime = ExecuteTime + 1, | |||
NewData = Node#r_bte_node.data#r_data{execute_times = NewExecuteTime}, | |||
NewNode = Node#r_bte_node{data = NewData}, | |||
BteStatus3 = bte_tick:update_node(BteStatus2, NewNode), | |||
if | |||
BteStatus3#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus4, _} = bte_tick:pop_stack(BteStatus3), | |||
if | |||
NewExecuteTime == Node#r_bte_node.data#r_data.max_loop -> | |||
BteStatus4; | |||
true -> | |||
BteStatus4#r_bte_status{status = ?BTE_RUNNING} | |||
end; | |||
true -> | |||
BteStatus3 | |||
end | |||
end. |
@ -0,0 +1,41 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-27 | |||
%% Doc: ever return failure | |||
-module(n_return_failure). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"ReturnFailure". | |||
init(_Parameters) -> | |||
{}. | |||
execute(BteStatus, Node, IsFromStack) -> | |||
if | |||
IsFromStack -> | |||
BteStatus#r_bte_status{status = ?BTE_FAILURE}; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end. | |||
execute1(BteStatus, Node) -> | |||
ChildId = Node#r_bte_node.child, | |||
?BTE_DEBUG("~p execute: ~p~n", [?MODULE, {BteStatus#r_bte_status.status}]), | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2), | |||
BteStatus3#r_bte_status{status = ?BTE_FAILURE}; | |||
true -> | |||
BteStatus2 | |||
end. |
@ -0,0 +1,41 @@ | |||
%% Author: zouv | |||
%% Date: 2016-09-27 | |||
%% Doc: ever return success | |||
-module(n_return_success). | |||
-behaviour(bte_node_behaviour). | |||
-include("common.hrl"). | |||
-export([ | |||
node_name/0, | |||
init/1, | |||
execute/3 | |||
]). | |||
node_name() -> | |||
"ReturnSuccess". | |||
init(_Parameters) -> | |||
{}. | |||
execute(BteStatus, Node, IsFromStack) -> | |||
if | |||
IsFromStack -> | |||
BteStatus#r_bte_status{status = ?BTE_SUCCESS}; | |||
true -> | |||
execute1(BteStatus, Node) | |||
end. | |||
execute1(BteStatus, Node) -> | |||
ChildId = Node#r_bte_node.child, | |||
?BTE_DEBUG("~p execute: ~p~n", [?MODULE, {BteStatus#r_bte_status.status}]), | |||
BteStatus1 = bte_tick:push_stack(BteStatus, ChildId), | |||
BteStatus2 = bte_tick:execute(BteStatus1, ChildId), | |||
if | |||
BteStatus2#r_bte_status.status /= ?BTE_RUNNING -> | |||
{BteStatus3, _} = bte_tick:pop_stack(BteStatus2), | |||
BteStatus3#r_bte_status{status = ?BTE_SUCCESS}; | |||
true -> | |||
BteStatus2 | |||
end. |
@ -0,0 +1,8 @@ | |||
{application, erlbte, | |||
[ | |||
{description, "Behavior Tree for erlang"}, | |||
{vsn, "1.0.0"}, | |||
{registered, []}, | |||
{applications, [kernel, stdlib]}, | |||
{env, []} | |||
]}. |