Using event chains
Using event chains
The AI scripts are based on events that are called based on defined triggers. This gives basically three ways to get any piece of code run. The first is the classic Pumpkin approach of repeat triggers, where you define that an event should be called every N seconds. Then you define lots of these with varying degrees of delay, for all kinds of tasks. Soon after this project started, support was added for ordinary subroutines, which meant that you could reuse code between events by calling functions. This is the second approach.
However, both the above approaches have significant drawbacks. The repeat trigger approach gives delays between the AI objects being done with a task, and a repeat trigger giving them something new to do. If you set the repeat interval very low, the delay also becomes low but at the cost of quite significant CPU consumption and possible frame rate stutter. The subroutine approach also has the problem of frame rate stutter, as the scripting engine relies on each call into it being quite quick, because the whole game freezes and does nothing while the scripts execute.
There is a third approach that solves both these problems. Instead of calling subroutines, you can trigger events from inside other events. I call this event chaining. You can utilize the game specified triggers to know when your AI objects are likely done with tasks, and fire off an event to check on them the next script frame with a (wait, 1) trigger. This has the advantage of pretty much immediate reaction, but without clogging up the frames. I have been implementing this approach in the current AI, and the results have been quite good so far, with significant improvements to AI reaction times.
However, both the above approaches have significant drawbacks. The repeat trigger approach gives delays between the AI objects being done with a task, and a repeat trigger giving them something new to do. If you set the repeat interval very low, the delay also becomes low but at the cost of quite significant CPU consumption and possible frame rate stutter. The subroutine approach also has the problem of frame rate stutter, as the scripting engine relies on each call into it being quite quick, because the whole game freezes and does nothing while the scripts execute.
There is a third approach that solves both these problems. Instead of calling subroutines, you can trigger events from inside other events. I call this event chaining. You can utilize the game specified triggers to know when your AI objects are likely done with tasks, and fire off an event to check on them the next script frame with a (wait, 1) trigger. This has the advantage of pretty much immediate reaction, but without clogging up the frames. I have been implementing this approach in the current AI, and the results have been quite good so far, with significant improvements to AI reaction times.
Re: Using event chains
Hrm. What about receiving gifted units? Can the AI handle that?
Re: Using event chains
There should be no problem handling that. It is just another trigger. I can check. I know that the AI won't use units given by cheating, but that should be easy to fix.Zarel wrote:Hrm. What about receiving gifted units? Can the AI handle that?
Re: Using event chains
I don't understand how you can test AI changes if it is nondeterministic.
Re: Using event chains
Can you provide an example of how to do this because I do not understand it. Usually to check if AI objects are done I check their order status with droid.order=somethingPer wrote: You can utilize the game specified triggers to know when your AI objects are likely done with tasks, and fire off an event to check on them the next script frame with a (wait, 1) trigger.
You mean replacing the current:Per wrote: There is a third approach that solves both these problems. Instead of calling subroutines, you can trigger events from inside other events. I call this event chaining.
Code: Select all
event doSomething (every,50)
{
...code
doSomeTask();
...code
}
function void doSomeTask()
{
...code
}
Code: Select all
event doSomething (every,50)
{
...code
setEventTrigger(doSomeTask,waitAlmostZeroTr ); //where waitAlmostZeroTr = (wait,1)
...code
}
event doSomeTask (inactive)
{
...code
}
Re: Using event chains
Yes, precisely.
Re: Using event chains
What about functions which returns some values and which accept parameters?
This function return a BASEOBJ within a range in the given coordinates
Code: Select all
function BASEOBJ objStrTargetInRange(int _xCoord,int _yCoord, int _Range)
{
local BASEOBJ _objTarget;
local int _x,_y,_x1,_y1;
local int _xx, _yy, _targetPlayer;
_objTarget = NULLOBJECT;
_Range = _Range/2 ;
_xx = (mapWidth*128)-(128*2);
_yy = (mapHeight*128)-(128*2);
_x = min( _xCoord + _Range , _xx );
_y = min( _yCoord + _Range , _yy );
_x1 = max( _xCoord - _Range , 256);
_y1 = max( _yCoord - _Range , 256);
_targetPlayer = 0;
while ( _targetPlayer < MAX_PLAYERS and _objTarget == NULLOBJECT){
if ( _targetPlayer != player and !friendlyPlayer(_targetPlayer) )
{
_objTarget = structTargetInArea(_targetPlayer, player, _x, _y, _x1, _y1);
if (_objTarget != NULLOBJECT)
{
//displayMsg("objStrTargetInRange: dist("& distBetweenTwoPoints(_xCoord, _yCoord, _objTarget.x, _objTarget.y)/TILE &") range ("& _Range/TILE &") - ("& _xCoord/TILE &") ("& _yCoord/TILE &") ");
if ( distBetweenTwoPoints(_xCoord, _yCoord, _objTarget.x, _objTarget.y) > _Range )
{
_objTarget = NULLOBJECT;
}
}
}
_targetPlayer++;
}
return _objTarget;
}
Re: Using event chains
I am not saying never to use functions, just be careful not to suck up too much CPU time in one event.
It would also be nice if we could pass parameters to events from within scripts as well, but I am not going to touch the script interpreter code to add that.
It would also be nice if we could pass parameters to events from within scripts as well, but I am not going to touch the script interpreter code to add that.
Re: Using event chains
how can you tell how much CPU time it uses?Per wrote:I am not saying never to use functions, just be careful not to suck up too much CPU time in one event.
It would also be nice if we could pass parameters to events from within scripts as well, but I am not going to touch the script interpreter code to add that.
what happens if you go over that time limit?
Re: Using event chains
it just needs more time to jump here and there to search what to do nextcrux wrote:how can you tell how much CPU time it uses?Per wrote:I am not saying never to use functions, just be careful not to suck up too much CPU time in one event.
It would also be nice if we could pass parameters to events from within scripts as well, but I am not going to touch the script interpreter code to add that.
what happens if you go over that time limit?
what happens if the cpu only has to search what to do, but can't find anything else than "jump to"?
nothing, or in other words: it freezes!
Re: Using event chains
I got the point. I replace all functions which returns nothing with an event and try to follow your advice.Per wrote:I am not saying never to use functions, just be careful not to suck up too much CPU time in one event.
It would also be nice if we could pass parameters to events from within scripts as well, but I am not going to touch the script interpreter code to add that.
Re: Using event chains
You can't easily tell exactly, but you will notice that on slower systems or when you get lots of objects that the AI controls, that framerates drop or become uneven, and things like scrolling become jerky rather than smooth.crux wrote:how can you tell how much CPU time it uses?
what happens if you go over that time limit?
I am not sure what you are talking about here. It will not freeze.Thyranim wrote: it just needs more time to jump here and there to search what to do next
what happens if the cpu only has to search what to do, but can't find anything else than "jump to"?
nothing, or in other words: it freezes!
Re: Using event chains
is there a rough estimate how big or complex the scripts can get?Per wrote: You can't easily tell exactly, but you will notice that on slower systems or when you get lots of objects that the AI controls, that framerates drop or become uneven, and things like scrolling become jerky rather than smooth.
is there any limitation on their size?
Re: Using event chains
I don't think so. I know that some scripts (eg Aivolution) are very large (16k+ lines of code each), and yet worked fine.crux wrote:is there a rough estimate how big or complex the scripts can get?
is there any limitation on their size?