[ai.error.recursion]: ***** ERROR: AI reactToMessage: recursion in AI TCAT_droneAI.plist, state ATTACK_SHIP, aborting. It is not valid to call reactToMessage: FOO in state FOO.
[ai.error.recursion]: ***** ERROR: AI reactToMessage: recursion in AI TCAT_droneAI.plist, state LOOK_FOR_TARGETS, aborting. It is not valid to call reactToMessage: FOO in state FOO.
This is the last remaining bug I can see in TCAT (other than blocking of auto-docking and docking clearance, but that's trunk-side) but I can't see why I'm getting recursion log entries? OK the reactToAIMessage message is of course in the same overall AI state as the function call, but isn't that was reactToAIMessage is for rather than changing the AI state?
The script is used by multiple ships (all of whom give this error) hence the "unused" functions in this particular case.
in the spawn actions. Probably the log-lines before will give a further clue about the sequence that triggers the recursion.
On testing I did notice a bug: you also use the script for the thargelts. But than you must do an additional check to avoid the thargoid curses on destruction for an inactive tharglet. I even think a tharglet should not send a curse at all.
is inefficient. I think that just looking for scanclass should be enough. (Or the .isThargoid property as you do elsewhere in the code.) The further role checks are only a waist of cpu cycles as something without thargoid scanclass should also not have a thargoid or tharglet role.
The recursion limiter doesn’t actually care about what state or handler is involved, it just cuts you off at 32 levels of nested reactToMessage:es. I’ll add some better diagnostics for tonight’s nightly.
The recursion limiter doesn’t actually care about what state or handler is involved, it just cuts you off at 32 levels of nested reactToMessage:es. I’ll add some better diagnostics for tonight’s nightly.
I forgot. With this knowledge, the recursion is caused by the following sequence:
Under the right conditions it can go indefinitely between both states without hitting a pause.
I think we should also have a normal "message" in the JS environment as alternative to "reactToMessage", like with the plain AI. There is not always the need for an immediately reaction. Reacting on the next UPDATE is often enough.
On testing I did notice a bug: you also use the script for the thargelts. But than you must do an additional check to avoid the thargoid curses on destruction for an inactive tharglet. I even think a tharglet should not send a curse at all.
is inefficient. I think that just looking for scanclass should be enough. (Or the .isThargoid property as you do elsewhere in the code.) The further role checks are only a waist of cpu cycles as something without thargoid scanclass should also not have a thargoid or tharglet role.
TCAT has a few things which are thargoid but without the scanclass (at least as set, although some of them do appear so on the scanner). isThargoid is new I think. The extra checks are needed for example for the jumpgate, which appears thargoid but isn't except by role.
As for the Tharglets, if you're referring to the drones (the ones whose AI I posted) then they only go uncontrolled if no station is around. Effectively they are defense ships in this case.
The recursion limiter doesn’t actually care about what state or handler is involved, it just cuts you off at 32 levels of nested reactToMessage:es. I’ll add some better diagnostics for tonight’s nightly.
OK that's clearer, so what would be the better action to take for an invalid target if we're ending up with nesting in the current set-up? How is the recursion avoidable?
With this knowledge, the recursion is caused by the following sequence:
Bah. Here’s me writing shiny new tools, and they turn out not to be needed. :-p
Eric Walch wrote:
I think we should also have a normal "message" in the JS environment as alternative to "reactToMessage", like with the plain AI. There is not always the need for an immediately reaction. Reacting on the next UPDATE is often enough.
Difficult, so therefor its a good thing its detected by the code with a warning in the log.
Always check if a chain of events stops: setStateTo: will always imediately switch stated and execute the ENTER message in that state. When that ENTER message contains a sendScriptMessage that generates a reactToMessage:, the message it is referring to is also executed immediately. And when that contains a setStateTo: the circle is closed.
Having a plain message: would break the loop because it is not executed immediately but added to the messages that must execute on the next update. (With the risk of loosing it when something else switches states in the meantime).
We did not have this but Ahruman just added a "sendAIMessage" to the trunk code, to send such delayed messages that evaluates after the pauseAI: time.
In your case the circle can be broken by removing the sendScriptMessage from the ENTER message in LOOK_FOR_TARGETS, as it will also be checked in the UPDATE of that state.
Last edited by Eric Walch on Sat Jun 19, 2010 2:06 pm, edited 1 time in total.
I may also look at changing some of the reactToAIMessage entries in the script to AI state changes instead, where that is what the AI message does when it goes back into the AI. See if that helps too.
The one you mention I think is the main culprit, as that one happens repeatedly in the log (I just posted two examples).