I thought I found a mistake. On the surface it looks like the ant is gathering food before going off to fight the enemy. This doesn’t make any sense given that the Jess documentation states when an auto-focus rule is activated, the module it appears in is automatically pushed onto the focus stack and becomes the focus module. So when an enemy ant appears, the threat module is immediately pushed onto the stack and gains focus. Once the threat module has focus, the
attack-enemy-ant rule fires. To understand why, we must understand that the rule is already on the agenda in the threat module, given that its activation is what caused the activation of the
auto-focus property in the first place.
So the problem must have been in the code. Well, sort of. The problem turned out to be not a problem at all, but a function of the print statements and the order in which certain functions were called. Below is the output of another simulation with similar results, this time with
From this output we can see exactly what is happening and why our output seems to be incorrect when in reality everything is functioning just as it should. In this run of the simulation the ant is in the work module gathering food. In line 4, the
gather-food rule is fired, in the right hand side of the rule the
change-ant-environment function is called which asserts a new food source and an enemy ant.
Line 5 shows the new food source being asserted and the rule
gather-food being activated on line 6. Line 7 shows the enemy ant asserted and the rule
attack-enemy-ant being activated in the threat module, immediately followed by the threat module gaining focus and conversely the work module losing focus, lines 9 and 10. Then the text “Enemy Ant has appeared.” is printed and we fall out of
So now we have two new activations,
THREAT::attack-enemy-ant and we are in the threat module. Since there is an activation in the threat module, that rule will be the next to fire. But not quite yet, we still haven’t finished running the right hand side of the
gather-food rule which fired in line 4. That rule must finish before any new rules are fired. All that’s left in the
gather-food right hand side is to call the
gather-food function. This function is what prints out “Food item gathered OK” on line 13. After the rule finishes firing, Jess checks the agenda , finds
attack-enemy-ant, and fires it. This is exactly what’s happening on line 14. From there you can follow the progression as the ant engages and kills the enemy. The enemy ant is retracted in line 18, and since there are no more activations in the threat module, it falls off the stack, the work module regains focus, and the activations in the work module are fired.
What I had considered a mistake is a consequence of rules calling
change-ant-environment before actually doing the heavy lifting. See the
gather-food rule as and example.
The rule calls
change-ant-environment before calling
(gather-food ?food), this causes the new food sources and enemy ants to appear before our ant gathers the food, giving us the impression that our ant gathers food after an enemy ant appears and before going to fight for the colony.
Now we can follow what was happening in our original output. I will post it here again as reference:
We can see that the ant finished collecting food and was taking out the garbage. While taking out the garbage a new food source appeared and the work module was popped onto the stack, this is evidenced by line 20 text “Still food silly.” which is printed in the
there-is-food rule when a new food source appears while in the chore module. (Notice I forgot to add “crlf” in the print statement in the version I was running at the time.)
The work module gained focus and the
gather-food rule fired. While in the
change-ant-environment call in the right hand side of the rule, an enemy ant appeared, the output corresponds to the remaining text on line 20. Remember, this entails the threat module receiving focus and the
attack-enemy-ant rule activated in the threat module agenda. The
gather-food runs finishes, outputting line 21, and immediately the
attack-enemy-ant rule is fired, which is seen on line 22.
To conclude, there are a few ways to fix this seemingly strange behavior. One way is to include print statements for everything, for example, adding a print statement when a new food source is added would have cleared up the confusion. The most sensible way is make the call to
change-ant-environment the last instruction in the right hand side of the rule it is called in. This way all the environment randomness happens after the rule has already completed its main objective. This experience helped me learn to debug Jess programs and more specifically, come up with useful tips on how to structure Jess programs to ease the pain of debugging.