for loop bug

I've recently noticed a bug with for() loops. And I've also found it in several stock base scripts as well as community scripts. Usually written like this;
package forloop {
function forloop(%arg)
{
%count = ClientGroup.getCount();
error("-=-=-=-=-= Found " @ %count @ " clients. =-=-=-=-=-");
for (%i = 0; %i < %count; %i++)
{
%client = ClientGroup.getObject(%i);
if ( %client.isAiControlled() && AIClientIsAlive(%client,0) )
{
error("%i = " @ %i @ " and %client = " @ %client @ " : AI - " @ getTaggedString(%client.name));
//%client.listtasks(); // all clients respond when used alone
if(%arg) { %client.drop(); } // only half of clients will respond when this is added
}
else
{
error("%i = " @ %i @ " and %client = " @ %client @ " : Human - " @ getTaggedString(%client.nameBase));
}
}
}
};
activatePackage(forloop);

That is actually a working package that I wrote for my own purposes and it should reproduce the bug that I see here on my machine. The interesting part to notice is the expression "%i < %count" in the middle of the for() line. When it is expressed within parenthesis it works as you would expect it to. For example;
  • for (%i = 0; (%i < %count); %i++)
Another method that seems to work well for me is;
  • for (%i = 0; %i < ClientGroup.getCount(); %i++)
Just some food for thought when you're up late at night chasing after phantoms in your code. ???

Where I got my first hint was in the stock script SiegeGame.cs around line 571.

Has anyone else noticed this before? Are there any other odd scripting behaviors that other people might be interested in?

Comments

  • %client.drop(); in that script is deleting objects that are in the collection that you are iterating over. In languages with proper collections iterators, your code would blow up if you try it.

    To do it properly (and assuming an ordered collection), you'll need to subtract 1 from %i and 1 from %count each time you call the collection manipulation function.

    The bug is not in the loop, it's in the way you're using the collection.
  • I wasn't trying to imply that the bug was in TorqueScript, I was just saying... nevermind. The two bulleted lines that I provided below the quote are working examples that perform without any error that I've noticed. I chose to show the original in the quote rather than attempt to describe it in writing to avoid misinterpretation by other newcomers, like myself.

    Thank you for your feedback. Would you be able to share any similar observations?
  • As far as other things to avoid if writing T2 scripts? There are a handful of real interpreter bugs.

    Beware when using binary operators, because some are broken:
    %a = ~0;
    %b = -1;
    echo(%a);
    echo(%b);
    echo(%a == %b);
    
    This will print: -1, -1, 0. The two -1's are not equal for some reason.

    Any arithmetic operator involving values greater than 10^6 run in floating point, even if you only want integers. Not strictly a bug, but it's not really desirable behavior.

    Performing a modulo operator with a zero divisor will crash the game.
    echo(5 % 0);
    

    If evaluating expressions with local variables, you need to perform some sort of dummy operation using the local variables for them to register.

    The following code will lose the value of %x in the context of the eval() call (e.g. if you have equation = "%x * %x", and x = 2, this will return 0).
    function evalEquation(%equation, %x)
    {
        eval("%ret=" @ %equation @ ";");
        return %ret;
    }
    

    Whereas this will work correctly (and for the example would properly return 4):
    function evalFunction(%equation, %x)
    {
        %x = %x; // dummy operation, required
        eval("%ret=" @ %equation @ ";");
        return %ret;
    }
    
  • That last one seems quite odd. You would think it would work fine without the redundantly obvious x_X.
  • I'm guessing the last one doesn't work is the %x in the function header refers to 'memory1' while a %x in the %equation refers to 'memory2'. To have them work, you create a dummy node, making 'memory2' = 'memory1' or.... 'memory1' = 'memory2'

    I'm getting confuzzled....
Sign In or Register to comment.