goto – Talk

From Bohemia Interactive Community
Revision as of 18:45, 21 June 2021 by Lou Montana (talk | contribs) (Text replacement - "\[\[Script[ _]syntax\]\]" to "''Script syntax''")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Ok......lets get this clear.

I have always thought that a loop, in most cases, MUST have a delay of some sort, otherwise the loop loops so fast that you cannot interrupt it and end up having to reboot or quit the game.

Lets have the nitty gritty here.

Also, are Label names case sensitive or not, give reasons , evidence.........etc.


Planck


raedor: From what I know they're not case sensitive, I've been using them for years without problems. About the delay: it is correct that you should have delays in your loops, especially "infinite" loops (eg with alive x as condition), as slower computers will CTD without that delay. Also you should think about the length of the delay if you're addon-scripting, because you have to face the fact that your scripts might run 20 times at once. I think it's an interesting fact here, that @ and triggers check with .5 delays.

Delay in a loop

While it is not required to include delay in a loop, loop without a delay can cause the script to slow down the game a lot, as the loop will be executed many times before game engine interruprts the script.

Unless you really want the loop to execute multiple times during a frame, you should include a small delay.

--Suma 12:19, 23 May 2006 (CEST)


Thanks for that Suma, I was always under the impression that at least a small delay was advisable, even if only 0.001.

Planck 17:11, 23 May 2006 (CEST)


Well, .001 is still a bit short as it means 1000 checks per second and this again is 20 checks per frame (if you have 50 FPS... I play on about 20 FPS usually). Everything > 1 check per frame is useless, as you'll see the effect on the next frame at the earliest. You can say a maximum of 70 checks per second (I doubt that anyone plays with 70 FPS... anyway) is okay, so that a minimum of .014 as delay should be clear.

Raedor 17:25, 23 May 2006 (CEST)


Any script when aborted is never executed again until next frame, therefore any delay shorter than frame duration is equivalent, and means 1 check per frame. --Suma 15:34, 1 June 2006 (CEST)


First time here - I hope this is going in the correct place. The point I am making is that loops that look like:

#loop
lots
of
useful
stuff
if (condition) then {goto"loop"}

do not need to have a delay, it is just like a long list of repeated instructions.

I could understand that a loop that looks like:

#wait
if (condition) then {goto"wait"}

Could well cause problems without a small delay. But then unless they really know what they are doing they should use an @ instruction which by my testing runs much smoother. But to say that all loops need a delay is to seriously confuse the punters.

If people are okay with it I will edit the entry tomorrow when I get chance and then let's see if we are in agreement - I can shift all that stuff I put in about forEach as well that is really irrelevant here.

Does that make sense? Have I understood the disconnect?

Evidence

Not knowing about this place until Planck tipped me off I was not aware that the question about evidence for case sensitivity of labels had been asked. Is the script I posted sufficient evidence that labels are not case sensistive?

Would it be better if I moved that script here rather than leave it where it is. I am happy either way.

The previous two messages

Are from me THobosn. I had thought that this would have been automatically recorded.

Just found the signature button. --THobson 00:13, 24 May 2006 (CEST)


Ok thanks for everyones input.

I think we have established that labels are indeed NOT case sensitive.

As for the delay thing I think it must be stressed that when I said, 'in most cases', I should have said 'in many cases'.

There must be, as TH has pointed out, many instances where a delay is not needed.

As for the 0.001, that should have read 0.01, what can I say, I washed my keyboard recently and I can't do a thing with it.......NO honestly.  ;)

Planck 00:27, 24 May 2006 (CEST)


From what I know OFP interprets 100 lines of a script (if not interrupted by @, ~ or exit) before switching to the next job... even if there's lots of useful stuff in the loop, OFP will run through it over and over again, I don't see for what you could need that. Well you better just don't use labels and goTos anyway, forEach and while do a way better job  ;) But okay, we can write it as you said, Planck.

Raedor 00:33, 24 May 2006 (CEST)

My recent Edit

Does this do it for everyone? I have experimented with 5,000 wait loops vs 5,000 @ instructions and for the condition I was using a 0.5 second delay cause the wait loop to perform very poorly compared with the @ instruction. But of course for a more complicated conditon than the one I was using it could be the other way around.

Two comment of the text as it now stands:

  1. I cannot veryfy the statement that a wait loop will cause the ofp engine to be delayed - I am taking you guys on trust on this
  1. I have made a link to @. But there is no @ in the comref to link to. I am really up against it the moment so I can't write it, does anyone else have the energy to have a go at it?

--THobson 08:55, 24 May 2006 (CEST)


I once did some testing to find out whether and when it is better to use @ instead of goto-loops and vice versa. I will just quote my post from OFPEC here:


For that I used a simple boolean as condition, and two different scripts to check. One checked the condition using @COND, the other one with a loop with 0.5 seconds delay and an if statemtent (?!COND : goto ...).

Each test run first started the tested script 5000 times in a while loop (to have them all start at once), waited a random number and changed the condition. I measured the time it took to recognise the condition for each single script and took the average of it. And to make even more sure, I did this 3 times and took the average of the 3 average values.

Here are my test results:


using loops with a delay of 0.5 seconds

• fps
Normal (Desert Island): 54
Script startup: > 16
Scripts running: ~42

• activation time
The average time for the 0.5 sec. loop to recognise the changed condition was 0.212, i.e. approximately the half.


using loops with a delay of 0.25 seconds

• fps
Normal (Desert Island): 54
Script startup: > 16
Scripts running: ~27

• activation time
The average time for the 0.25 sec. loop to recognise the changed condition was 0.091


using loops with a delay of 0.1 seconds

• fps
Normal (Desert Island): 54
Script startup: > 16
Scripts running: ~6

• activation time
The average time for the 0.1 sec. loop to recognise the changed condition was 0


using @

• fps
Normal (Desert Island): 54
Script startup: > 16
Scripts running: ~7

• activation time
The average time for the @ command to recognise the changed condition was exactly 0.


Conclusion:

'@' is equal to a loop with a delay of 0.1 seconds. They both eat a lot of performance, but are the absolutely fastest to get activated. So if something needs to be very precise, the best way is to use @. Avoid it in scripts running parallelly though.

Everything else is better put into loops of delays of 0.25 seconds or bigger (every tenth second more means increase of performance), even if it's the simplest condition, if you run the script over a long time or multiple of the same script parallelly. In the latter case it would even be good to randomise the delay first, keeping a certain minimum.

e.g.:
;;; ~ 0.6
_r = 0.5 + (random 0.2)
~_r

Avoid writing ~(random 0.6), as this may have the effect, that random 0.6 is calculated every frame. I am not sure about this though.

--hardrock 13:56, 24 May 2006 (CEST)


I moved the discussion about case sensitivity to Script syntax discussion page. thanks for all the input

hoz 16:10, 24 May 2006 (CEST)


Just adding 2 cents here folks about our empirical tests that putting goto LABELS at close to top of script file as possible is 'better'.

thus

goto to init

loop .... .... goto loop

init

goto loop

Mikero ook? 20:28, 30 May 2006 (CEST)


Yep, that's because (afaik!) OFP scans the script after a goto from the top and takes the first fitting label -- it scans the script FOR EVERY GOTO! So it's good to have the labels at the top of a script.

--Raedor 00:50, 31 May 2006 (CEST)


@hoz: I think that it is okay now; the only thing we still could mention is that you should put loops, which are executed often, on the top of a script.

--Raedor 07:53, 31 May 2006 (CEST)

I must have missed the "empirical" tests showing that placing labels at the top of scripts makes a significant difference. As I've argued every time that myth comes up, when the OFP loads an .sqs, it goes through the file, eliminates the blank spaces and comments indicated by semicolons. The labels are put in a separate area with a corresponding line number.
When you do a GOTO, the goto searches through the list of labels, not the whole .sqs file.
Consequently, making your script so that the oft-used loops are at the top might improve performance, but not by any significant amount. I have yet to see anyone post anything other than speculation to prove otherwise.

also, does the structure: if (condition) then {GOTO "LABEL"} actually work? I was under the impression that GOTO does not work in functions. Dinger 17:55, 6 August 2006 (CEST)

One other thing -- the "Conclusion" of the test above is a little questionable. With 5000 scripts running, the FPS drops to around 6 or 7. ~.1 is only meaningful if the FPS is above 10. If you test a condition where the FPS is 30, one script is running at ~.1/goto, and the other is an @, you'll see that the @ runs faster.

In other words, a delay/goto loop is more efficient in resource usage than an @ command, as long as the delay is longer than the FPS in that condition. If the delay is shorter, then an @ command is more efficient. Dinger 18:03, 6 August 2006 (CEST)

--UNN 19:53, 13 August 2006 (CEST)

I've used goto within the scope of an If\foreach loop statement, for a couple of years without any problems. Perhaps some confusion comes from the usage of the term function?

Lets assume a function is only written as an sqf file and executed with the call command. Then within the scope of that file, there would be no goto label. So yes, within functions goto might not work.

Now lets take the scope of an If then statement, embedded locally within the scope of a parent script. Again the goto label does not exists with the {} part of the if then statement. But it does exist within the parent scope of the script. So only when it exits the scope of the {} does it move to the label contained within it's parent?

I must admit, I have never tried calling a goto command from within an independent sqf file. While I understand variables can cross scopes, in such a way. As with the discovery of the old case sensitive private command. I can only assume it was some nuance of variables rather than default behaviour of functions.

Perhaps like the old case sensitive private command, it's more of a bug than a rule? I should add, I don't insist this is the most efficient way of calling a goto. It's just I've used it some many times. I think I would have a mental breakdown, if you prove it doesn't work :)



QUOTE: In other words, a delay/goto loop is more efficient in resource usage than an @ command, as long as the delay is longer than the FPS in that condition. If the delay is shorter, then an @ command is more efficient. UNQUOTE

I do not think it is as simple as this. I have used 0.5 second delays in loops and found them to be much more damaging to perfromance than an @ instruction. It really depends on the complexity of the boolean condition being tested. My empirical view is that loops appear to bring in some overhead that an @ command does not have, but because the @ condition will be tested very often if the condition being tested is complex then it will hit performance. Where it is important (lots of scripts running simultaneously etc.) then it is worth doing a specific test using the relevant condition.

I also agree with the sentiment of the previous post

if (condition) then {goto"lable1"} else {hint"condition is not true"}

Is perfectly correct.

--THobson 13:59, 14 August 2006 (CEST)

Delay in Loop continued

I too agree with THobson's take on the @ command. In most cases it depends on the complexity and type of commands being called within it's scope.

If you try and run a script with just a ~, no integer preceding it. You get an interesting error. Which I cant remember off hand, but it suggests that the tilde command does something on long the lines of:

_Waituntil=Time+(The parameter you use with the ~)

@(_Waituntil<Time)

However there are specific features of the @ command that differ greatly from the ~ command. So the above example is not really true, which just goes to show how inacurrate speculation can be. A couple of obvious differences are, for example:

Run a loop like this.

@(Call {Player SideChat Format ["Time %1",Time] ; False})

While the loop is executing, hit escape to bring up the paused game dialog. You will notice the loop is still running.

Now try the same with:

#L

Player SideChat Format ["Time %1",Time]

~0.001

goto "L"

This time the loop will pause. The same behaviour can be seen during the initial stages of Multi Player start-up.

Another feature is accelerated time. The ~ loop will run according to the accelerated time set using the + & - keys. The @ command ignores the accelerated time settings and runs at a constant speed.

Ok finally, if you use CoC's BinView, you will see OFP makes a distinction in the way it stores @ and ~ in the save file. Again I cant remember exact terminology, but one is classed as a Pause, the other as a wait until.

Now I'm not being lazy, by not digging out the correct terminology of these two commands or the error message I mentioned above. I just don't see the point? As the only definitive answer can be given by someone privy to the internal workings of the OFP code.

UNN 12:45, 14 August 2006 (CEST)