Home   Help Search Login Register  

Author Topic: AI Scripting Tute  (Read 2812 times)

0 Members and 1 Guest are viewing this topic.

Rubble_Maker

  • Guest
AI Scripting Tute
« on: 27 Aug 2002, 15:48:37 »


[attachment deleted by admin]

Gameer_77

  • Guest
Re:AI Scripting Tute
« Reply #1 on: 27 Aug 2002, 20:18:57 »
Holly Moly! :wow: NICE! :afro: Wicked!! :thumbsup:

 8) PEACE

Bremmer

  • Guest
Re:AI Scripting Tute
« Reply #2 on: 27 Aug 2002, 20:35:15 »
Lots of good ideas, and very well explained. Thanks

One quick question - Why is this:

Code: [Select]
_c=100
#loop
   _c=_c-1
   ?_c>=0:goto "loop"

better than this:

Code: [Select]
_c=0
#loop
   _c=_c+1
   ?_c<=100:goto "loop"

I remember seeing this in your dynamic voice engine in 'The Prey', but wrote it off as differnet strokes for different folks.

Cheers


Rubble_Maker

  • Guest
Re:AI Scripting Tute
« Reply #3 on: 27 Aug 2002, 21:29:08 »
Sorry, I totally missed the point here ;)

This *is* faster but only when used to access
arrays:

_c=0
#loop
    _unit=_array select _c
    _c=_c+1
    ?_c<count _array:goto "loop"

Say the array has 100 elements, then the above
code would invoke the "count" function a 100 times.
From what I expect its a pretty slow function, because
of the dynamic way that arrays are handled in OFP. The
fact that you can remove individual elements from an
array, e.g.

_array= _array - [element]

suggests that arrays are actually linked-lists, not just
linear pieces of memory. That means that each element
contains a pointer to the next element (this is totally
invisible to the script tho), and possible even one to
the preceeding element (double-linked list).
Since arrays can be resized by adding/removing elements,
the "count" command can't do anything else but traverse
the list and count the nodes in it (this becomes even
more obvious from the fact that an array can even
contain elements of various different types).

So for each of the 100 cycles in the above example,
the "count" command would run another 100 cycles only to
find out how long the array is!

Thats why a decrementive counter is faster; it puts the
upper limit into the initialization part, not the loop:

_c = (count _array)-1
#loop
    _unit=_array select _c
    _c=_c-1
    ?_c>=0:goto "loop"

The fact that arrays are linked-lists really could be
exploited in a lot of clever ways BTW!

Bremmer

  • Guest
Re:AI Scripting Tute
« Reply #4 on: 27 Aug 2002, 21:57:09 »
Ahh I see  :D

I do a similar technique for incrementing loops, but use an extra variable.

Code: [Select]
_count = count _array
_i = 0
#loop
    _unit=_array select _i
    _i=_i+1
    ?_i < _count : goto "loop"

I'll have to try your method next time.

Cheers

Gameer_77

  • Guest
Re:AI Scripting Tute
« Reply #5 on: 27 Aug 2002, 21:57:37 »
Hmmm...yes I agree. :hmm: :help:

 8)PEACE

Offline toadlife

  • OFPEC Old Skool
  • Former Staff
  • ****
  • Official OFP Editing Center Toad
    • toadlife.net
Keep perishable goods from spoiling your script...
« Reply #6 on: 28 Aug 2002, 08:18:26 »
One thing to think about when processing arrays, is wheather or not item number 65 out of 100 is going to be around when you get to it in the loop.

Here is an example:

#processarray
_c = (count _array)-1
#loop
    _unit=_array select _c
    ?!alive _unit:goto "processarray"
    _c=_c-1
    ?_c>=0:goto "loop"

I ran into this with my grouplink script for Operation Lojack, which qualifies as an "AI" script. I've also run into with simple scripts.

In "The Prey" (great F-ing mission by the way ;) ), I saw a "Zero Divisor" script error which I was able to reproduce a few times, by killing a certain man at the right time.

I'm assuming that the man was part of an array that was being checked by a loop. I most likely killed the man before he was processed in the array, causing the loop to select an invalid number from the array.

Even though the loops are processed very quickly, these type of errors happen as often as they do because when a soldier dies, sometimes it takes the game seconds to realize that they are actually dead.

To complicate matters further, triggers, everyone's favorite source of arrays, will still list dead men for a short time since they take time to update their list.\

Hence, the line I added above and add to any array that contains perishable goods.

"Whenever you want information on the 'net, don't ask a question; just post a wrong answer." -- Cancer Omega.

Offline toadlife

  • OFPEC Old Skool
  • Former Staff
  • ****
  • Official OFP Editing Center Toad
    • toadlife.net
Re:AI Scripting Tute
« Reply #7 on: 28 Aug 2002, 08:37:49 »
Code: [Select]
?(("!alive _x" count _unitarray)==0)
Thats a new one for me. How ever did you figure that out?
"Whenever you want information on the 'net, don't ask a question; just post a wrong answer." -- Cancer Omega.

Bremmer

  • Guest
Re:AI Scripting Tute
« Reply #8 on: 28 Aug 2002, 10:47:31 »
Youn shouldn't get zero divisors if you define the array, then don't change it. Dead units aren't removed from arrays - they can be selected like any other unit.

The only time you should encounter that problem is if you are removing units from the array manually (ie _array = _array - [_unit]).

In effect your code creates an infinite loop if the unit _array select _c is dead.

#processarray
_c = (count _array)-1 ; this value will always be the same unless you manually remove units
#loop
    _unit=_array select _c ; this line will always select the same unit if the last unit in the array is dead
    ?!alive _unit:goto "processarray"
    _c=_c-1
    ?_c>=0:goto "loop"


I could be wrong, and frequently am  :-\
« Last Edit: 28 Aug 2002, 10:50:03 by Bremmer »

Rubble_Maker

  • Guest
Re:AI Scripting Tute
« Reply #9 on: 28 Aug 2002, 12:46:22 »
I know what you mean toadlife, back then you sent me a screenshot of the error message. I haven't tracked this error down yet, well the mission is finished and I dont like to look at the ugly script code again, but this error prolly doesnt have to do with dynamic arrays, but the rather counters that I use to access them. I ran into the same problem during STMPenetration, and I had to rewrite the whole voice generator at least three times to figure out how to make this fuckin thing work.
For my voice generator in "The Prey" I simply used a bunch of arrays which store voice samples for various groups, and on various occasions a random sample is picked from one of the groups. To accomplish this, I randomize the arrays and pick one element at a time by using a counter as an index, then decrement the counter. If the counter reaches zero, I reset it to ((count _array)-1).
Problem is that I had various scripts that needed to play voices from the same group, so they would occasionally mess up the counter by accessing the same array simultaneously. I could have solved this quite easily, but at the time I wasnt familiar with how OFP runs scripts simultaneously. The trick is to make sure that a wrongly set counter wont be used as an index. Example:

_counter=_counter-1
?_counter<0:_counter=(count _array)-1
(*)
?_counter>=0: _unit say (_array select _counter)

The last condition doesnt seem to make any sense coz the previous condition makes sure that only a valid counter would be passed to the say command, right? So wrong! OFP executes scripts line-wise, i.e. one line at a time. That means that another script could kick in where I marked the script with a (*). This script would play a voice as well,and it'd also decrement the counter. The result is that a negative counter is used to index the array, which prolly results in a zero division.
With the last condition, however, the script becomes more or less rock-solid. It still might happen that scripts mess up their counters, but then you only loose one voice, i.e. nothing is played at all, but you dont run into an error. I know its only a dirty down hack :(, but definetely in the interest of better gameplay ;)

Offline toadlife

  • OFPEC Old Skool
  • Former Staff
  • ****
  • Official OFP Editing Center Toad
    • toadlife.net
Re:AI Scripting Tute
« Reply #10 on: 28 Aug 2002, 20:00:21 »
Dead units aren't removed from arrays - they can be selected like any other unit....I could be wrong, and frequently am

No you are right Bremmer. I failed to mention that I was reffereing to using arrays that are dynamically generated such as a triggers or groups.
"Whenever you want information on the 'net, don't ask a question; just post a wrong answer." -- Cancer Omega.