Jump to content
Sign in to follow this  
Sefe

A challenge for you all

Recommended Posts

Well, with v1.85 we now have "while... do..." and "if... then... else..." constructs. This is a big step towards structurized programming. Well done BIS, this is what I've been waiting for a long time. Until v1.85 you had to use "goto" to create loops. "Goto" constructs are commonly considered to be a bad style of programming and the new commands give us the opportunity to create block structures like in C or Pascal.

However after a series of tests, I (unfortunately) found out that the current system suffers from some serious deficiencies. I was hoping to be able to rewrite all my scripts with the new scripting commands but for a large number of scripts this is impossible, making the new commands worthless for many cases. I'll give you a little exercise. Let's see if anyone can find a solution.

Could anyone write this simple script for me: It's a script that accepts any integer number > 0 as it's only parameter. Then it visibly counts down from this number to 0 in steps of exactly one second. That's all.

Well, not completely. You may not use the following commands in the script:

goto

exec

drop

It doesn't matter if you execute this script with Number exec "ScriptName.sqs", Number call loadFile "ScriptName.sqf" or Number call preprocessFile "ScriptName.sqf". But it mustn't use a trigger or a game logic during it's execution (ie. it has to run independendly). Apart from that you can use any method: loops, recursion, preprocessors, what you want. And you may use as many files you want.

Share this post


Link to post
Share on other sites

You could do something.sqs with

while "_this > 0" do {hint format["%1",_this];_this = _this - 1;}

But it wouldnt have the 1 sec delay thing, I cant seem to get the ~1 working inside a while loop...

Share this post


Link to post
Share on other sites

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Quote (Kegetys @ Oct. 17 2002,21:07)</td></tr><tr><td id="QUOTE">But it wouldnt have the 1 sec delay thing, I cant seem to get the ~1 working inside a while loop...<span id='postcolor'>

That looks like "while" and "if else then" have the same restrictions as sqfs. ~ and @ do not work. wink.gif

Share this post


Link to post
Share on other sites
Guest

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Quote (Sefe @ Oct. 18 2002,02:58)</td></tr><tr><td id="QUOTE">However after a series of tests, I (unfortunately) found out that the current system suffers from some serious deficiencies. I was hoping to be able to rewrite all my scripts with the new scripting commands but for a large number of scripts this is impossible, making the new commands worthless for many cases. I'll give you a little exercise. Let's see if anyone can find a solution.<span id='postcolor'>

To make the system that was introduced in 1.85 compatible with the OFP scripting interpreter the whole thing had to be implemented in a special way.

The OFP scripting system is executed in real time. The exec function spawns parallel execution of another script and returns immediatelly - therefore reliably returing value from it is not possible. So what is the solution?

The command interpreter processes an atomic block of a script and then switches to the next script. The newly introduced "call" function lets you feed a command to the interpreter that will be taken as an atomic block. The .sqf files do not contain a number of calls to functions, but should be considered as one command. The interpreter executes all of it and then returns the value. While it is being executed all the other scripts are halted.

That's why ~ @ and goto are not allowed.

Share this post


Link to post
Share on other sites

My point is not exactly that ~, @ and goto are not allowed. I don't need goto when I have while and if. And if all other scripts are halted, sqf-files are useless when you want to exectue parallel running scripts (like me). My point is more that the following code is not allowed in a sqs file:

while {_this >= 0} do

{

 Hint format ["%1", _this]

 _this =_this - 1

 ~1

}

The interpreter needs the whole while thing in one line (which makes ~ and @ arguments impossible). Having block structures forced in one line is rather... er... unusual.

BIS has shown that it is possible to interpret arguments broken up in multiple lines (in sqf-files). I know that the ; as seperator makes that possible. That's why C and Pascal want (almost) every argument to end with a semicolon. But I can't imagine it too difficult changing the interpreter code so that it ignores all LF/CR from the while or if to the final }-bracket. You could then force all commands inside the brackets/quotes to end with a semicolon (no compatibility issues here). Most probably this wouldn't even need a change of interpreter code as the semicolon already is a seperator. If you then introduce two new commands to replace ~ and @ (like comment replaces the semicolon), you can interpret the whole code inside the {}-brackets the same way you interpret preprocessors (except that they ere executed in real time).

Maybe I want too much but as long as we don't have block structures in sqs-scripts, we have to solve the whole countdown thing with:

#Loop

 ? _this <= 0 : goto "Skip"

 Hint format ["%1", _this]

 _this = _this - 1

 ~1

goto "Loop"

#Skip

which is a bad style of programming. And it gets even worse if you want to do if... then... else... constructs. With my suggested changes of the interpreter the whole thing would look much neater (presuming that the command that does the same as ~ is called Wait):

while {_this >= 0} do

{

 Hint format ["%1", _this];

 _this =_this - 1;

 Wait 1

}

Share this post


Link to post
Share on other sites
Guest

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Quote (Sefe @ Oct. 18 2002,12:48)</td></tr><tr><td id="QUOTE">The interpreter needs the whole while thing in one line (which makes ~ and @ arguments impossible). Having block structures forced in one line is rather... er... unusual.

BIS has shown that it is possible to interpret arguments broken up in multiple lines (in sqf-files). I know that the ; as seperator makes that possible. That's why C and Pascal want (almost) every argument to end with a semicolon. But I can't imagine it too difficult changing the interpreter code so that it ignores all LF/CR from the while or if to the final }-bracket. You could then force all commands inside the brackets/quotes to end with a semicolon (no compatibility issues here). Most probably this wouldn't even need a change of interpreter code as the semicolon already is a seperator. If you then introduce two new commands to replace ~ and @ (like comment replaces the semicolon), you can interpret the whole code inside the {}-brackets the same way you interpret preprocessors (except that they ere executed in real time).<span id='postcolor'>

The issue is like I said the fact that it the OFP script language is a quais-real-time language. You have only one command line interpreter that is altering between processing the different scripts you might be running.

The ";" operator is just a token separator. The whole sqf file is actually executed as one command. The expressions you write within brackets are actually just strings that are then parsed and presented to the command line interpreter by the call function. These executions have no guarantee in the form of time for execution. That is why all the real time elements have been removed.

Why is it executed as one block? Simply because the main point of the new scripting function was to intruduce functions that return values. This can't be done in real time without introducing a complex system of semaphores and flags which would require segnificant rewrites of the script interpreter, it would not be backwards compatible and it would induce new problems such as deadlocks into OFP scripting.

Share this post


Link to post
Share on other sites

Yeah, I fully understand that. And I will use preprocessors whenever I need return values. This really is a big step ahead. And I understand that you need the timeout to make return values work.

But I was talking about sqs files. I don't need return values when I use an sqs-file. And sqs files are generally processed in real time. The code in sqs-files is even executed in real time within {}-brackets. This sample can prove that:

_MyVariable = ""

if (time > 60) then {_MyVariable="Test"; Goto "Label1"}

Exit

#Label1

Hint Format ["%1", _MyVariable]

will work in a 'regular' sqs-script even though it uses goto (which would cause an error in a preprocessor). You need to init _MyVariable first though, otherwise it would be considered private inside the if construct.

What I actually thought would be good is to introduce the option to have multiple-line while statements in real-time (not preprocessed) scripts.

At the moment two different commands are seperated by either a CR/LF or a semicolon (I'm still talking about 'old style' sqs scripts).

So the codes

_MyVariable = "Test"

Hint Format ["%1", _MyVariable]

and

_MyVariable = "Test"; Hint Format ["%1", _MyVariable]

do exactly the same. And in the first option you don't need a semicolon at the end because CR/LF is as good as a seperator as a semicolon. But you need the semicolon in the second line because you have two commands in one line. But yet the script is still executed in real time, right?

What I suggested was to ignore CR/LF while you are in a while or if construct (like you ignore them in preprocessors). The result would be that while you are in brackets, you couldn't seperate two commands by a CR/LF. But there would still be the semicolon you can use as a seperator. Here's an example:

At the moment, this construct is possible within an sqs file:

if (time>60) then {_MyVariable = "Test"; Hint Format ["%1", _MyVariable]}

while this construct leads to an error:

if (time>60) then

{

 _MyVariable = "Test";

 Hint Format ["%1", _MyVariable]

}

The only difference between these two code snippets is that the second one contains CR/LF. Now if the interpreter would ignore all CR/LF from if to }, both snippets would be interpreted exactly the same. And as we're not in a preprocessor, all of this is executed in real time. Well, we can't have return values for this reason but when we need return values we will use preprocessors, not 'old school' scripts.

But the real problem is that we can't use the ~ and @ in the same line as other scripting commands.

So this is possible:

_MyVariable = "Test"

~1

Hint Format ["%1", _MyVariable]

while this isn't:

_MyVariable = "Test"; ~1; Hint Format ["%1", _MyVariable]

Therefore we need commands that do the same as those operators and that can be executed in a single line. I know that those commands wouldn't work in preprocessors, but why shouldn't they work in a real-time script? If we had the aforementioned Wait command, we could have this construct without even changing the interpeter:

if (time>60) then {_MyVariable = "Test"; Wait 1; Hint Format ["%1", _MyVariable]}

and hence, with the slight changes in the interpreter code that I suggest we could have this construct:

if (time>60) then

{

 _MyVariable = "Test";

 Wait 1;

 Hint Format ["%1", _MyVariable]

}

Voilŕ, ofp scripting language suddenly becomes structural.

And it would still be fully backwards compatible. Nothing that worked in the old interpreter would stop working in the new one.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×