@@ -12,10 +12,11 @@ Engine::Engine(PlayerbotAI* ai, AiObjectContext *factory) : PlayerbotAIAware(ai)
1212{
1313 lastRelevance = 0 .0f ;
1414 testMode = false ;
15+ strategiesDirty = false ;
1516}
1617
1718// Executes actions before the main action
18- bool ActionExecutionListeners::Before (Action* action, Event event)
19+ bool ActionExecutionListeners::Before (Action* action, const Event& event)
1920{
2021 bool result = true ;
2122 for (list<ActionExecutionListener*>::iterator i = listeners.begin (); i!=listeners.end (); i++)
@@ -26,7 +27,7 @@ bool ActionExecutionListeners::Before(Action* action, Event event)
2627}
2728
2829// Executes actions after the main action
29- void ActionExecutionListeners::After (Action* action, bool executed, Event event)
30+ void ActionExecutionListeners::After (Action* action, bool executed, const Event& event)
3031{
3132 for (list<ActionExecutionListener*>::iterator i = listeners.begin (); i!=listeners.end (); i++)
3233 {
@@ -35,7 +36,7 @@ void ActionExecutionListeners::After(Action* action, bool executed, Event event)
3536}
3637
3738// Overrides the result of the action execution
38- bool ActionExecutionListeners::OverrideResult (Action* action, bool executed, Event event)
39+ bool ActionExecutionListeners::OverrideResult (Action* action, bool executed, const Event& event)
3940{
4041 bool result = executed;
4142 for (list<ActionExecutionListener*>::iterator i = listeners.begin (); i!=listeners.end (); i++)
@@ -46,7 +47,7 @@ bool ActionExecutionListeners::OverrideResult(Action* action, bool executed, Eve
4647}
4748
4849// Checks if the action execution is allowed
49- bool ActionExecutionListeners::AllowExecution (Action* action, Event event)
50+ bool ActionExecutionListeners::AllowExecution (Action* action, const Event& event)
5051{
5152 bool result = true ;
5253 for (list<ActionExecutionListener*>::iterator i = listeners.begin (); i!=listeners.end (); i++)
@@ -71,6 +72,16 @@ Engine::~Engine(void)
7172{
7273 Reset ();
7374 strategies.clear ();
75+ ClearActionNodeCache ();
76+ }
77+
78+ void Engine::ClearActionNodeCache ()
79+ {
80+ for (unordered_map<string, ActionNode*>::iterator i = actionNodeCache.begin (); i != actionNodeCache.end (); i++)
81+ {
82+ delete i->second ;
83+ }
84+ actionNodeCache.clear ();
7485}
7586
7687// Resets the engine by clearing the action queue, triggers, and multipliers
@@ -79,8 +90,7 @@ void Engine::Reset()
7990 ActionNode* action = NULL ;
8091 do
8192 {
82- action = queue.Pop ();
83- delete action;
93+ action = queue.Pop (); // popped from queue, remain in cache
8494 } while (action != NULL );
8595
8696 for (list<TriggerNode*>::iterator i = triggers.begin (); i != triggers.end (); i++)
@@ -98,10 +108,18 @@ void Engine::Reset()
98108 multipliers.clear ();
99109}
100110
101- // Initializes the engine by resetting it and initializing strategies
111+ // Marks the engine for reinitialization at the next DoNextAction entry
102112void Engine::Init ()
113+ {
114+ strategiesDirty = true ;
115+ }
116+
117+ // Initializes strategies, triggers, multipliers, and default actions
118+ void Engine::InitStrategies ()
103119{
104120 Reset ();
121+ ClearActionNodeCache ();
122+ strategiesDirty = false ;
105123
106124 for (map<string, Strategy*>::iterator i = strategies.begin (); i != strategies.end (); i++)
107125 {
@@ -132,6 +150,11 @@ bool Engine::DoNextAction(Unit* unit, int depth)
132150 bool actionExecuted = false ;
133151 ActionBasket* basket = NULL ;
134152
153+ if (strategiesDirty)
154+ {
155+ InitStrategies ();
156+ }
157+
135158 time_t currentTime = time (0 );
136159 aiObjectContext->Update ();
137160 ProcessTriggers ();
@@ -188,7 +211,6 @@ bool Engine::DoNextAction(Unit* unit, int depth)
188211 LogAction (" A:%s - OK" , action->getName ().c_str ());
189212 MultiplyAndPush (actionNode->getContinuers (), 0 , false , event);
190213 lastRelevance = relevance;
191- delete actionNode;
192214 break ;
193215 }
194216 else
@@ -208,7 +230,6 @@ bool Engine::DoNextAction(Unit* unit, int depth)
208230 lastRelevance = relevance;
209231 LogAction (" A:%s - USELESS" , action->getName ().c_str ());
210232 }
211- delete actionNode;
212233 }
213234 }
214235 while (basket);
@@ -240,23 +261,30 @@ bool Engine::DoNextAction(Unit* unit, int depth)
240261// Creates an action node based on the action name
241262ActionNode* Engine::CreateActionNode (string name)
242263{
264+ unordered_map<string, ActionNode*>::iterator cached = actionNodeCache.find (name);
265+ if (cached != actionNodeCache.end ())
266+ {
267+ return cached->second ;
268+ }
269+
270+ ActionNode* node = NULL ;
243271 for (map<string, Strategy*>::iterator i = strategies.begin (); i != strategies.end (); i++)
244272 {
245- Strategy* strategy = i->second ;
246- ActionNode* node = strategy->GetAction (name);
273+ node = i->second ->GetAction (name);
247274 if (node)
248- {
249- return node;
250- }
275+ break ;
276+ }
277+ if (!node)
278+ {
279+ node = new ActionNode (name, /* P*/ NULL , /* A*/ NULL , /* C*/ NULL );
251280 }
252- return new ActionNode (name,
253- /* P*/ NULL ,
254- /* A*/ NULL ,
255- /* C*/ NULL );
281+
282+ actionNodeCache[name] = node;
283+ return node;
256284}
257285
258286// Multiplies the relevance of actions and pushes them to the queue
259- bool Engine::MultiplyAndPush (NextAction** actions, float forceRelevance, bool skipPrerequisites, Event event)
287+ bool Engine::MultiplyAndPush (NextAction** actions, float forceRelevance, bool skipPrerequisites, const Event& event)
260288{
261289 bool pushed = false ;
262290 if (actions)
@@ -281,11 +309,6 @@ bool Engine::MultiplyAndPush(NextAction** actions, float forceRelevance, bool sk
281309 queue.Push (new ActionBasket (action, k, skipPrerequisites, event));
282310 pushed = true ;
283311 }
284- else
285- {
286- delete action;
287- }
288-
289312 delete nextAction;
290313 }
291314 else
@@ -317,21 +340,18 @@ ActionResult Engine::ExecuteAction(string &name)
317340
318341 if (!action->isPossible ())
319342 {
320- delete actionNode;
321343 return ACTION_RESULT_IMPOSSIBLE;
322344 }
323345
324346 if (!action->isUseful ())
325347 {
326- delete actionNode;
327348 return ACTION_RESULT_USELESS;
328349 }
329350
330351 action->MakeVerbose ();
331352 Event emptyEvent;
332353 result = ListenAndExecute (action, emptyEvent);
333354 MultiplyAndPush (action->getContinuers (), 0 .0f , false , emptyEvent);
334- delete actionNode;
335355 return result ? ACTION_RESULT_OK : ACTION_RESULT_FAILED;
336356}
337357
@@ -487,13 +507,12 @@ string Engine::ListStrategies()
487507}
488508
489509// Pushes an action node to the queue again
490- void Engine::PushAgain (ActionNode* actionNode, float relevance, Event event)
510+ void Engine::PushAgain (ActionNode* actionNode, float relevance, const Event& event)
491511{
492512 NextAction** nextAction = new NextAction*[2 ];
493513 nextAction[0 ] = new NextAction (actionNode->getName (), relevance);
494514 nextAction[1 ] = NULL ;
495515 MultiplyAndPush (nextAction, relevance, true , event);
496- delete actionNode;
497516}
498517
499518// Checks if the engine contains a specific strategy type
@@ -523,7 +542,7 @@ Action* Engine::InitializeAction(ActionNode* actionNode)
523542}
524543
525544// Listens and executes an action
526- bool Engine::ListenAndExecute (Action* action, Event event)
545+ bool Engine::ListenAndExecute (Action* action, const Event& event)
527546{
528547 bool actionExecuted = false ;
529548
0 commit comments