Bunch more SUGGESTIONs

Started by SSH, Mon 31/01/2005 20:54:53

Previous topic - Next topic

SSH

Third-party preprocessor: before AGS runs its compiler, it could run an arbitrary 3rd party tool on a temporary text file containing all the scripts to allow full preprocessing

Parametrisable #define macros

When a sprite is imported, make part of its property box the name of the original import file (or "Clipboard"): this is becuase it is sometime hard to tell sprites apart!

12

RickJ

SSH, hope you don't mind me adding a suggestion to you list.  I've taken this liberty in light of your subject line and your previous suggestion post. 

The array bounds check is very helpful but is annoying when trying to impliment a while loop.   In the example below the while loop is should stop looping when variable i reaches a value of -1 as detected by the first part of the conditional expression.    In this case the second part of the conditional erpression and the value of buf are irrelevant .  However,  the bounds check creates a runtime error, when i reaches -1 because of the second part of the conditional expression.  The workaround requires additional code complexity to achieve the same functionality. 
while ((i>=0)&&(buf==' ')) {
   buf = 0;
   i--;
}

I know I brought something like this up recently and the answer I got was to make the code work better.   I have been working around, since but now with a better understanding of the issue and the experience working around, I am of the opinion that this is really annoying and that it is legitimate for an array index to exceed the bounds of the array in the context of a while conditional expression. 

Would it be reasonable to disable the bounds check on while loop conditional expressions or perhaps all conditional expressions?  Or is there some other way to achieve the same result? 


Quote
When a sprite is imported, make part of its property box the name of the original import file (or "Clipboard"): this is becuase it is sometime hard to tell sprites apart!
... or make the filename into an enum having the same numerical value as the sprite id number.

 

Gilbert

#2
Code: ags

while ((i>=0)&&(buf[i]==' ')) {
Ã,  Ã, buf[i] = 0;
Ã,  Ã, i--;
}


I think what matters is whether it's really safe to access out-of-bound array elements, it certainly depends on how arrays were implemented in the engine. In my opinion, this can be easily worked around (not as complex as you mentioned), I think it's not worth ditching the check just because someone wants to use it in a while loop (and it's not really practical and consistent to make it check everywhere except in while conditions). For example your piece of code can be worked around like:
Code: ags

while (i>=0) {
Ã,  if (buf[i]==' ') {
Ã,  Ã, buf[i] = 0;
Ã,  Ã, i--;
Ã,  } else i=-1; //breaks out whenever it reaches a nonspace character
}

Which I think is quite readible and safe.
Alternatively, maybe if there's an advance option that experienced coders can turn off is a better thing.

Snarky

Quote from: RickJ on Tue 01/02/2005 00:00:34
In the example below the while loop is should stop looping when variable i reaches a value of -1 as detected by the first part of the conditional expression.Ã,  Ã,  In this case the second part of the conditional erpression and the value of buf are irrelevant .Ã,  However,Ã,  the bounds check creates a runtime error, when i reaches -1 because of the second part of the conditional expression.
while ((i>=0)&&(buf==' '))

Isn't the real problem here that AGS evaluates the right-hand side of an "&&" conditional expression even when the left-hand side failed?

RickJ

Quote
Isn't the real problem here that AGS evaluates the right-hand side of an "&&" conditional expression even when the left-hand side failed?
Yeah.  That occured to me as well but I don't think it's practical.  it seems to me that the entire expression needs to be evaluated before you can know for sure if the final result will be true or false.   Although in this case it doesn't seem all that complicated I don't think that's true for all possibilities.

Quote
Quote
The workaround requires additional code complexity to achieve the same functionality.
this can be easily worked around (not as complex as you mentioned)
Gilbot, your workaround adds an if-else structure and several lines of code.  Further, the index i is not preserved in your example.  If it's needed then an additinal variable is required  to break the loop.   At this point it's easy enough for me to live with but it is never the less annoying.   It will likely be troublesome to the uninitiated.  Although I can't say for certain, I suspect it's not difficult to disable the bounds check for while loop (or other) conditional expressions and that what is lacking is a clear definition of what should be done.  If so I think it is at least worth having a short discussion about it.

As far as access safety is concerned, is not the bounds check a relatively new feature?  I thouhgt it was added to aid in locating array index type bugs rather than preventing memory access exceptions?  If access saftey is indeed an issue then the bounds check could perhaps substitute a value in place of the invalid array element and then allow the evaluation to continue instead of aborting? 

SSH:  I'm sorry for hijacking your thread.  I didn't intend to take up so much space here; I thought this annoyance was worth a mention on your list.  I owe you one.  ;)



Kweepa

Quote from: RickJ on Tue 01/02/2005 03:12:36
Quote from: Snarky
Isn't the real problem here that AGS evaluates the right-hand side of an "&&" conditional expression even when the left-hand side failed?
Yeah.Ã,  That occured to me as well but I don't think it's practical.Ã,  it seems to me that the entire expression needs to be evaluated before you can know for sure if the final result will be true or false.Ã,  Ã, Although in this case it doesn't seem all that complicated I don't think that's true for all possibilities.
It's entirely practical - a lot of C code relies on it.
And I think it's going to cause problems, eg this won't work...
Code: ags

if (ptr != NULL && ptr->Func())
{
  // blah
}

Perhaps it's like the mathematical evaluation that goes right to left :=
Still waiting for Purity of the Surf II

Gilbert

#6
Quote from: RickJ on Tue 01/02/2005 03:12:36
Gilbot, your workaround adds an if-else structure and several lines of code.Ã, 
It's nothing in my opinion, and it's worth it, just to ensure stuff works in order.
Quote
Further, the index i is not preserved in your example.Ã,  If it's needed then an additinal variable is requiredÃ,  to break the loop.Ã,  Ã, At this point it's easy enough for me to live with but it is never the less annoying.Ã,  Ã, It will likely be troublesome to the uninitiated.
True. But I think it helps in general, especially for people not quite familiar in programming, to figure out their mistakes.
Quote
Although I can't say for certain, I suspect it's not difficult to disable the bounds check for while loop (or other) conditional expressions and that what is lacking is a clear definition of what should be done.Ã,  If so I think it is at least worth having a short discussion about it.
Why? I think if there're checkings elsewhere, why leave while (and probably a few things like 'if' conditions, etc.) alone? One mistake that people can make is thing like this:

while (buf!='A') i++; //Store the position of first 'A' in buf. Weee!1!

which can obviously cause problems when there's no 'A' in buf, if the bound checking is not applied to while loops it can kill the programmers finding bugs, unless the compiler is REALLY smart that it can analyse the conditions and decide on which while condition should be checked and which not, which is not practical.

Quote
As far as access safety is concerned, is not the bounds check a relatively new feature?Ã,  I thouhgt it was added to aid in locating array index type bugs rather than preventing memory access exceptions?Ã,  If access saftey is indeed an issue then the bounds check could perhaps substitute a value in place of the invalid array element and then allow the evaluation to continue instead of aborting?Ã, 
Well, maybe aborting is a harsh punishment, but checkings DO help finding bugs, a better compromise, maybe, is to abort the game with an error if it's going to assign/modify the value of an off-bound element, but just add to the warning.log (no aborting) if it's just a reference to it.

SSH

#7
This kind of "only evaluate what you NEED to" is called lazy evaluation and almost every compiler I've seen does it. Even dumb scripting langauges like csh... so I'd be all in favour of it in AGS, espeically since we're going to need to check a whole lot more nulls these days. Of course, if you had paramterisable macros, then you could write a macro to insted the extra if/else structure...

Which bring me back to my sugestions: Rick, I'll forgive you as long as you wholeheartedly endorse eveyrhting I suggested at the top of the thread  :=


EDIT:
And here's another suggestion:

Functions with no paramteres don't need the empty brackets when being called. It's not as if they have a separate namespace, so the compiler could work out that they are functions without the brackets, couldn't it?

12

RickJ

SSH:  Hehe,  Ok.  How's this ...

Quote
When a sprite is imported, make part of its property box the name of the original import file (or "Clipboard"): this is becuase it is sometime hard to tell sprites apart!
This is a really great idea!  I would even go further and generate enum values from the file name so that individual sprites could be accessed by name rather than number. 

Quote
Parametrisable #define macros
This is also a good idea, I support it.   

Quote
Third-party preprocessor: before AGS runs its compiler, it could run an arbitrary 3rd party tool on a temporary text file containing all the scripts to allow full preprocessing.
This is the kind of crazy ideas I usually have and I usually don't talk about them because I don't want people to think I'm crazy  *** mad scientist laugh ***.   So I am uncertain if I should support this or not ;).    Having said that, I am crazy enough to use such a thing if it were available.   

SSH, Steve, Snarky:
[quote  author=SSH]
This kind of "only evaluate what you NEED to" is called lazy evaluation and almost every compiler I've seen does it.
Quote
[quote  author=SteveMcCrea]
It's entirely practical - a lot of C code relies on it.
Quote
I stand corrected.  This is probably the reason I expect to be able to itterate through a list using "while (conditional)"  whithout the need for extra machinations.   I think most programmers would have the same expectation regarding this. 

Gilbot:
I think we have a fundamental disagreement about "while ((i>=0)&&(buf==' '))".  I don't agree that there is an error in the conditional expression.  As the others point out , since in the case i=-1,  the the index i does not meet the first test, the second test is not necessary and so it need not access a non-existent array element.  As the others have said, this is the case in nearly every modern day compiler, so one would think that most programmers expect the above example to work.   As the others point out, these sitiuations will only become more frequent in AGS V2.7 and when the man says "pay me now or pay me later"  it's usually better to pay now, IMHO. 






{
   buf = 0;
   i--;
}

===========

Room and Module Templates
Here is one more suggestion.  If the files  exist in the Have the editor commands "New Room" and "New Module"  populate the newly created room or module with the contents of the corresponding template files template.crm, template scm.  The
files could be located in either the AGS install directory or in the game directory.   The game directory would be searched first and if a template was not found there it could then search the GAS directoy.  If a template file is not found then it would do what it does now.   This would allow people to automatically include header and other comments when making a new module or room. 


Scorpiorus

#9
QuoteI have been working around, since but now with a better understanding of the issue and the experience working around, I am of the opinion that this is really annoying and that it is legitimate for an array index to exceed the bounds of the array in the context of a while conditional expression.
I think, while it is legitimate for an index variable to exceed the bounds, it still shouldn't be legitimate to dereference array index, it should return a value that's really in array rather then something outside. Yeah, it's not important for the example you provided but on the other hand there are circumstances when we should really get an error message, for instance:

while ((i>=0) && SomeFunction(buf[ i ])) ...

this then could cause problems when SomeFunction processes quite a random value which can be both the valid and invalid parameter for the function.


QuoteIsn't the real problem here that AGS evaluates the right-hand side of an "&&" conditional expression even when the left-hand side failed?
I think AGS should always evaluate before applying operator. Personally, I always treat && etc operators as functions that need parameters (two in case of &&) and that return a value. Therefore, both parameters (left and right expressions) must be evaluated first before processing. Some sort of a "lazy" evalution is possible, I think, but in my opinion, besides the hassle to implement it could also lead to many hard to track down errors since they can only be traced at run-time.

And the problem is how to implment it, for instance:

if (func1() && func2()) ...

it is not realy possible to tell which one is needed and which is not (if any), without running at least one function (which function to run is also an issue).


EDIT:

Quote
QuoteAs far as access safety is concerned, is not the bounds check a relatively new feature?Ã,  I thouhgt it was added to aid in locating array index type bugs rather than preventing memory access exceptions?Ã,  If access saftey is indeed an issue then the bounds check could perhaps substitute a value in place of the invalid array element and then allow the evaluation to continue instead of aborting?

Well, maybe aborting is a harsh punishment, but checkings DO help finding bugs, a better compromise, maybe, is to abort the game with an error if it's going to assign/modify the value of an off-bound element, but just add to the warning.log (no aborting) if it's just a reference to it.
I belive, the engine should abort in any case really. Developer can't always track down all the possible run-time errors and it would be worse if instead of run-time error message players started experiencing strange behaviour playing the game.

Kweepa

Quote from: Scorpiorus on Tue 01/02/2005 17:57:51
I think AGS should always evaluate before applying operator. Personally, I always treat && etc operators as functions that need parameters (two in case of &&) and that return a value. Therefore, both parameters (left and right expressions) must be evaluated first before processing. Some sort of a "lazy" evalution is possible, I think, but in my opinion, besides the hassle to implement it could also lead to many hard to track down errors since they can only be traced at run-time.

I'm surprised that
(a) we're having this discussion
(b) there's disagreement over the desired behaviour

"Lazy evaluation" (I don't like to call it that as it sounds rather negative - "short-circuit evaluation" is better I think) is not just in every modern compiler, it's written into the specification of languages.

Quote
And the problem is how to implment it, for instance:

if (func1() && func2()) ...

it is not realy possible to tell which one is needed and which is not (if any), without running at least one function (which function to run is also an issue).

Well, of course you have to run at least one function. Which function to run is trivial. They are evaluated left to right until the result is known - with a sequence of &&s, until one is false; with a sequence of ||s, until one is true. You can verify for yourself that that's a sufficient condition. eg
((a && b && c && d) || e || f)
(a || (b && c) || d)

I see your point about hard to track down errors, but in my opinion there will be many more errors introduced by evaluating everything and then going through the logic. But, maybe that's because I've been programming in C for 15 years.
Still waiting for Purity of the Surf II

Pumaman

Firstly, yes this whole issue is because AGS does not do lazy evaluation on && and ||. (while it's called lazy, it's actually more complicated since the compiler would need to check the first side and generate JUMP instructions depending on the result).

And yes, it's something I would like to fix to make it behave in common with C, especially as you point out, statements like this will become more common and should be valid:

if ((ptr != null) && (ptr.ID > 0))

I do not intend to remove the array bounds checking, because it is for memory access safety as well as for catching bugs. With 2.62 you could do this:
int i[1];
i[50000] = 20;
and crash the game.

QuoteRoom and Module Templates
Here is one more suggestion.  If the files  exist in the Have the editor commands "New Room" and "New Module"  populate the newly created room or module with the contents of the corresponding template files template.crm, template scm.

This is already semi-supported -- if you put a room file called "_blank.crm" in your game folder, it will be used as the template for New Room. Bit of an undocumented feature, oops.

QuoteThird-party preprocessor: before AGS runs its compiler, it could run an arbitrary 3rd party tool on a temporary text file containing all the scripts to allow full preprocessing

Do you have a use in mind for this? It sounds a bit of a far fetched feature, to be honest.

QuoteParametrisable #define macros

That would be nice, but I do try to discourage #define usage since it's not type safe and can make bugs hard to track down.

Quote
When a sprite is imported, make part of its property box the name of the original import file (or "Clipboard"): this is becuase it is sometime hard to tell sprites apart!

Effectively what you're asking for is a way to name sprites, which has been requested before. In fact, it's probably this very request:
http://www.adventuregamestudio.co.uk/tracker.php?action=detail&id=227

RickJ

Quote
Firstly, yes this whole issue is because AGS does not do lazy evaluation on && and ||. (while it's called lazy, it's actually more complicated since the compiler would need to check the first side and generate JUMP instructions depending on the result).
Why not just make comparisons with a non-existent entities always return FALSE?  Well maybe there a couple exceptions but couldn't the bounds check do something like the following when encountered in a conditional expression?   If something doesn't exist it can never be equal to, greater than, etc to anything. 
  (buf[-1]==A)  =  FALSE   
  (buf[-1]!=A)  =  FALSE   
  (buf[-1]>A)   =  FALSE         
  (buf[-1]<A)   =  FALSE                       
  (buf[-1]>=A)  =  FALSE
  (buf[-1]<=A)  =  FALSE
  (buf[-1]&&A)  =  FALSE
  (buf[-1]||A)  =  FALSE

I don't know if this mimic's the behaviour of C in all cases but it may be easier to implement than doing all those partial evals and jumps?  It seems like this would work for the examples given thus far though.  Hmmm,  this would also, on ocassion , negate the need to check pointers for null as well?   For example:
instead of this....
   if ((ptr != null) && (ptr.ID > 0))

if (ptr.ID>0) evaluates to FALSE  when ptr==null, you could 
just do this... 
   if (ptr.ID > 0)


Quote
if you put a room file called "_blank.crm" in your game folder,...
Great!! Maybe one of these days you can get around to doing the same for modules.  Thanks...

Anyway CJ, thanks for taking the time to listen to us.   8)



Gilbert

Quote from: SteveMcCrea on Tue 01/02/2005 20:00:57
"Lazy evaluation" (I don't like to call it that as it sounds rather negative - "short-circuit evaluation" is better I think) is not just in every modern compiler, it's written into the specification of languages.
The problem is, it was not written into the specification of AGS. If the behaviour is written clearly, it poses no problem to anyone, but if not, it's better kept safe as not many people using AGS are actual C programmers (I'm not a programmer of any computer languages, so common programming practice doesn't apply to me as I had never learned about that).
And rick's suggestion does not solve the problem. (And it's actually illogical in mathematical sense to treat these conditions as FALSE, they're actually all TRUE, but that's not important, as what we need is ease in programming). The reason is, if you use a single condition like that it can cause hard to track bugs, like:

while (k[-1]=='a'){...

unless it generates an error or a warning to remind the programmer.

So my suggestion is, either:
1) Leave it alone - safe
2) Really implement lazy-evaluations, and DOCUMENTS the behaviour in the manual, like "When using &&, if the left condition is FALSE the right condition will not be evaluated; when using ||, if the left condition is TRUE the right condition will not be evaluated..." or whatever it should be.

So I think we should leave it alone until lazy-evalution is implemented.

RickJ

Quote
(And it's actually illogical in mathematical sense to treat these conditions as FALSE, they're actually all TRUE ...
I believe that from a rigorous mathematical point of view, the result of operations on non-existent entities is undefined.    So when something like a divide by zero happens in a computer program an exception handler is invoked so that something can be done about it.  If the program was making scientific calculations to model the orbit of a space craft it would perhaps just stop and report what happened.  If it were on board the space craft and actually controling the orbit, instead of stopping, it would likely return a sensible value (likely a really big number)  and continue on.     

From a practical and logical point of view I don't see how a non-existent entity could ever be considerd to be equal to an existing entity of any value.  If it don't exist it can't have that value, whatever it is.  In the example you give "while (k[-1]=='a') {...}" the while loop would never execute because k[-1] is not equal to 'a', so I would think the programmer would realize the loop wasn't executing, and then go figure out why. 

IMHO, the best reason to not use my suggestion is that it may not mimick C as closely as one would desire and could therefore cause some confusion or that there is some unforseen, terrible side affect that's a show stopper.  Oh well, I think we should stop talking about this anyway.  CJ knows about the issue now and will most likely do something we all will be satisfied with as he always does. 

Thaks for the intersting converstion Gilbot, I sincerely enjoyed hashing this out with you.    :)


Gilbert

#15
Quote from: RickJ on Wed 02/02/2005 04:02:29
I believe that from a rigorous mathematical point of view, the result of operations on non-existent entities is undefined.Ã,  Ã,  So when something like a divide by zero happens in a computer program an exception handler is invoked so that something can be done about it.Ã,  If the program was making scientific calculations to model the orbit of a space craft it would perhaps just stop and report what happened.Ã,  If it were on board the space craft and actually controling the orbit, instead of stopping, it would likely return a sensible value (likely a really big number)Ã,  and continue on.Ã,  Ã,  Ã, 
Sorry if I sounded harsh, you're right that in mathematical sense things like 5/0 are usually not defined (you can define it), but not with comparisons involving nonexisting quantities, logically they're always TRUE as a statement.
For example the following statement is TRUE (though it may not make sense):
"My tail is 10 metres long."
simply because I have no tail. (For cases like 5/0 it's not a statement).
However, if it's used practically it can be different, the result can be just designed to suit one's need.

Quote
From a practical and logical point of view I don't see how a non-existent entity could ever be considerd to be equal to an existing entity of any value.Ã,  If it don't exist it can't have that value, whatever it is.Ã,  In the example you give "while (k[-1]=='a') {...}" the while loop would never execute because k[-1] is not equal to 'a', so I would think the programmer would realize the loop wasn't executing, and then go figure out why.Ã, 
It's just a simple example to demonstrate the scenario, there're many possibilities, for example, if there's no 'a' in k:
Code: ags

while (!(k[j]=='a')){ //to find the first 'a' WEEE!
Ã,  j++;
}

Of course he could have coded it (k[j]!='a'), but it's just a demostration and you can't prevent someone write that. In my opinion it should produce an error rather than continuing.
Quote
IMHO, the best reason to not use my suggestion is that it may not mimick C as closely as one would desire and could therefore cause some confusion or that there is some unforseen, terrible side affect that's a show stopper.Ã,  Oh well, I think we should stop talking about this anyway.Ã,  CJ knows about the issue now and will most likely do something we all will be satisfied with as he always does.Ã, 
Well agreed, but what I was just going to point out, was "lazy"-evaluation is a much better solution (though it may be hard to implement) than that workaround of setting it to some fixed value. SInce in lazy-evaluation, it'll ignore a condition only when it's not required to be checked.

SSH

#16
Quote from: Pumaman on Tue 01/02/2005 20:37:35
QuoteThird-party preprocessor: before AGS runs its compiler, it could run an arbitrary 3rd party tool on a temporary text file containing all the scripts to allow full preprocessing

Do you have a use in mind for this? It sounds a bit of a far fetched feature, to be honest.

Well, this really is an alterantive to you havign to implement #defines being parameterisable, or having experssions in array bounds: a preprocessor could pull these out and turn them into valid AGS code. Not just on these features but on any syntactic sugar that might be desired by the programmer. The GNU C COmpiler can be run in a way that only its preprocessor runs, and there are standard macor langauges like m4, or someone could write a perl script that did the processing...

Quote
QuoteParametrisable #define macros

That would be nice, but I do try to discourage #define usage since it's not type safe and can make bugs hard to track down.

Well, then, are you going to implement const declarations. The mechanism is nearl ythere already with enums. In fact, can you use an expression in an enum initalisation? i.e. (oops I foregt the syntax)

enum (myconst = 2+3);

Quote
Quote
When a sprite is imported, make part of its property box the name of the original import file (or "Clipboard"): this is becuase it is sometime hard to tell sprites apart!

Effectively what you're asking for is a way to name sprites, which has been requested before. In fact, it's probably this very request:
http://www.adventuregamestudio.co.uk/tracker.php?action=detail&id=227


No, its different: I want the filename, not some string to be added later. Mayeb though the default name could be the filename. The problem is with multiple sprite import is that the import order may not match the order in the file list (in my experience it tends to be reversed) and if you want to re-imporrt one of those sprites, then you need to know which was which.

Forum SUGGESTION:

Why doesn't the post a reply function warn you if you are double-posting?

12

SSH

#17
Edit by strazer: Needed Scorp's post for another thread, so here's his message:

Quote from: SteveMcCrea"Lazy evaluation" (I don't like to call it that as it sounds rather negative - "short-circuit evaluation" is better I think) is not just in every modern compiler, it's written into the specification of languages...
Yeah, and I'm not against the lazy evaluation, but implementing it now (by means of changing how "&&"/"||" work) would mean the old code may not work as expected. It reminds me the situation with the mathematical operators of the same precedence, you have mentioned, that are evaluated right to left. And, to be honest, I've already written plenty of code relying on '&&' behaviour in AGS. := Ah well, I will then probably replace '&&' with '*' or '&'.

Of course, if '&&', '||' will be non-strict operators it must be very clearly stated in the manual, as Gilbert says, because in that case the order in which expressions are written does matter and, without being thought out, may hide mistakes to be revealed at run-time but only under certain conditions. I don't think many people scripting in AGS think about ordering such expressions at the moment.

'if' statements, on the other hand, make it intuitively clear as it all depends on nesting:

if (a) {
    ...
    if (b) {

    }
    ...
}

but...

if (b) {
    ...
    if (a) {

    }
    ...
}

There is, of course, an advange of lazy operators if we are too lazy to set up if-blocks :) (especially in case of simple "(ptr != null && ptr.Func()") but for a complex stuff, nested 'if's would really save the time and efforts while debugging.


p.s. Just wanted to say that I think there is no disagreement about the desired behaviour in general as it all depends on what we are after, writing a certain portion of code.


/end Scorpiorus



Lazy evaluation should only chnage the behaviour of code using side-effect in function that are used in a && or || expression. One possibility is to change the behaviour only if Force OO scripting is set on, or to have ||| and &&& operators that are lazy.

For an example of side-effects, this code wouldn't work the same way any more, but then I'd never write code like this, given that it tends to be illegal in hardware description languages...

int glob;
function myfun (int x) {
  glob =x;
  return x*2;
}

if (a>5 && glob(x) >6) {
  // do something
}
12

Scorpiorus

Yep, those usually are specific functions that are expected to do something else than just return a value to operator, like, for example, WaitKey that returns a value but also updates the AGS engine state or some function that returns a value as well as fills a 'buffer' string var passed in as parameter.
Those are minority, I believe, but still this should be considered to avoid any possible confusion.

Pumaman

Yes, adding lazy evaluation would cause a problem if you called functions that had side effects as part of the "if" clause. However, you shouldn't really do that since it's bad practice, but I can appreciate it could become a problem.

Some sort of option to enable/disable it would be required, I guess.

SSH

Here's an idea: all games imported into the version that first implements lazy eval have their scripts converted so that all && and || become &&& and ||| (maybe this could be optional, with a dialog saying Yes or No to that conmversion and that the user back-up their game so that if it doesnt work with lazy eval then they can restore it). Then && and || are changed to match their C behaviour of lazy eval, but &&& and ||| exist in case someone wants or needs to have the old behaviour...

That keeps compatibility, but also allows the best behaviour going forward. Lazy eval would also improve game performance a little, I guess, too...

And CJ, you didn't respond to my const, preprocessor and forum suggestions...  :'(

12

Scorpiorus

Yep, an option would be nice. I'm not sure if there is a real need to introduce "new operators" (though I'd find them handy for certain tasks) since I believe their current strict behaviour can be simulated (to a certain degree) with '+' and '*' operators, which I'm going to replace '&&' with in "several" places, to ensure the assertion-handling mechanism I implemented will be working properly when a script compiled with a future version of AGS. :)

strazer

Quote from: Pumaman on Tue 01/02/2005 20:37:35
Firstly, yes this whole issue is because AGS does not do lazy evaluation on && and ||. (while it's called lazy, it's actually more complicated since the compiler would need to check the first side and generate JUMP instructions depending on the result).

And yes, it's something I would like to fix to make it behave in common with C, especially as you point out, statements like this will become more common and should be valid:

if ((ptr != null) && (ptr.ID > 0))

Tracker'd: http://www.adventuregamestudio.co.uk/tracker.php?action=detail&id=509

Kweepa

Sorry to dig up this old thread... (well, kind of sorry). :=

Here's an example of some code that's incredibly ugly without lazy evaluation (found while writing ags3d...)

Code: ags

while (j > numToDrawUnsorted && ShouldSwapPrims(pzj, pzi))
{
  // blah blah
  j--;
}


The solution is:

Code: ags

bool swap = ShouldSwapPrims(pzj, pzi);
while (j > numToDrawUnsorted && swap)
{
  // blah blah
  j--;
  if (j > numToDrawUnsorted)
  {
    swap = ShouldSwapPrims(pzj, pzi);
  }
}


ShouldSwapPrims is a very expensive function that shouldn't be called more than is necessary...
Yuck!
Still waiting for Purity of the Surf II

Gilbert

Though that function is expensive, I think your solution calls that function more or less the same number of times compared to using lazy evaluation already (maybe once more sometimes I guess), and I don't find it ugly.

Maybe you can do this like below to even free if from that possibly extra call?

Code: ags

bool swap = true;
while (j > numToDrawUnsorted && swap)
{
Ã,  Ã,  swap = ShouldSwapPrims(pzj, pzi);
    //Something to update pzj, pzi here?
  Ã,  j--;
}
if (j==numToDrawUnsorted) swap = ShouldSwapPrims(pzj, pzi); //if you need to call this once more to get the correct index, otherwise not required


edmundito

You know I'm obsessed with UI and such, and I thought of these looks for AGS the other day:




Basically is for it to have more of an Outlook 2003 look where the lists are placed to the panel and also remove te frame that gives the name of the section and just have that section highlighted. This way there is a lot more "real state" around the working area....

Of course, I'd like to have things like general settings and the palette editor moved to actual dialog screens, but that's just a whole other suggestion.
The Tween Module now supports AGS 3.6.0!

Rui 'Trovatore' Pires

No offense, but... ugh. Me no likey that look at all.
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

Kweepa

#27
I could give or take the borders to the panels on the left. I think they look nice but they clash with the other buttons on the right.
I like the layout, but what happens when you run out of room for, err, rooms?
It's not like we're generally hurting for screen real estate anyway. I never run AGS maximised.
And what is wrong with the general settings the way they are? This way you can make a change and instantly press Ctrl-T. If you put it in a dialog you'd have to perform the additional step of accepting the changes.

Things I'd find useful:
- the room menu always available (so that Ctrl-I and Ctrl-E work from anywhere)
- a quicker way of starting to script interactions (perhaps an option on the right click menu to avoid the whole New Interaction/Run Script/Edit Script malarkey).
- also, a way to get straight to the script/header of a module under development would be good. Perhaps we could have a checkbox that marks the module as under development, and then some menu items and shortcut keys to go to the code.
Still waiting for Purity of the Surf II

That Guy

#28
Gents,

I would like to mention, although I'm not sure how much bearing it has on the topic at hand, that Java (and J2ME, which is what I'm currently working in) does not perform "lazy" evaluation, either.

I was reminded of it reading this because one of our junior programmers was having trouble reproducing a bug in his game and had it traced to a line that read;

Code: ags

while ((list != null) && (list [x] != "some value"))
Ã,  Ã, doSomething();


And when I pointed out to him that the second list-sub-x test was causing the NullPointerException error QA was reporting, he went off on a tirade about how "that sort of thing works in C, I know it does!", forcing me to tackle him to the carpet and beat him into submission with my coffee mug.Ã,  When he calmed down, I mentioned to him that whether it "works" or not is irrelevant, because it made little sense from a logical point of view; you have no business testing an item in an array if the array itself may be null.

I advised him to restructure his code as such;

Code: ags

if (list != null)
Ã,  Ã, if (list[x] != "some value")
Ã,  Ã,  Ã,  doSomething();


Which, of course, made it work.Ã,  As Java was designed to avoid some of the common pitfalls of C coding conventions, I thought it would be relevant to mention that it doesn't do "lazy" evals.

Regards,
TG

Kweepa

Java definitely has short circuit evaluation. I've written plenty of Java and I'd have run into problems if it didn't. See here:
http://java.sun.com/developer/JDCTechTips/2002/tt1105.html#2
As for J2ME, oh dear. That sucks.
Still waiting for Purity of the Surf II

That Guy

yikes.  good catch.  As J2ME deviates so little from Java I'd have expected them to be identical in this case.  I know it's an issue in J2ME, 'cause it's bit us in the butts several times over the last few years.  ;D

Never mind then, carry on.

edmundito

#31
This is just another random suggestion, so I didn't want to start a new topic...

Let's say I have 4 characters, and I want to change their names to Pepe. Well, currently it's a bit tricky on AGS to do that because if you go to character[5], apparently, it returns some sort of memory addres and I guess it goes up to AGS_MAX_CHARACTERS.

So my suggestion would be for a way to check for it to set anything after the last character to null, that way one can just do something like:

short count = 0;
while(character[count] != nulll) {
  character[count].Name = "Pepe";
  count++;
}

Is that too much to ask?  :-[

And while we're on the topic of array, make the arrays a little more object-esque, so you could do:

int myarray[5];
int count = 0;
while (count < myarray.length) {
  myarray[count] = 0;
  count++;
}

and so on.
The Tween Module now supports AGS 3.6.0!

GarageGothic

Can't you just check for GetGameParameter(GP_NUMCHARACTERS, 0, 0, 0)?

edmundito

I knew I should have looked under GetGameParamenter...  :=
The Tween Module now supports AGS 3.6.0!

Elliott Hird

Quote from: Edmundo on Sun 28/08/2005 17:26:08
You know I'm obsessed with UI and such, and I thought of these looks for AGS the other day:
I like this much more than the suggestion in another thread. I really like the "modular" look it goes for, fits the scripting language with object-orientated scripting and all that.

monkey0506

Well it's actually pretty much the same thing, only on a larger scale.

Elliott Hird

Quote from: monkey_05_06 on Sun 16/10/2005 20:37:24
Well it's actually pretty much the same thing, only on a larger scale.
Actually, it's VERY different. Take a look at both.

monkey0506

It's not necessary to quote the post directly above you just FYI.

I'm not saying it's exactly the same thing, but it's similar, just like I said, on a much larger scale.

Akumayo

OOOOO OOO OOO, I have a suggestion!

PLEASE O' PLEASE CJ, make the Random function expanded.Ã,  Having only a maximum requires "if" and "else" functions just to run the desired result, here's an example of what I mean:

Code: ags

SetGlobalInt(1, Random(2));
if (GetGlobalInt(1)==0) {
 AddInventory(13);
 }
if (GetGlobalInt(1)==1) {
 AddInventory(14);
 }
if (GetGlobalInt(1)==2) {
 AddInventory(15);
 }


BUT if the Random was expanded to include:
Code: ags

Random(int min, int max);


Then you could simply run
Code: ags

AddInventory(Random(13, 15));


And get the same effect!!!
"Power is not a means - it is an end."

edmundito

Oh, I'll fix that for you:

function RandomEx(int min, int max) {
  return Random(max - min) + min;
}


.. I think. Someone, please, confirm my idiocy.
The Tween Module now supports AGS 3.6.0!


Akumayo

"Power is not a means - it is an end."

Rui 'Trovatore' Pires

I'd also like to call attention to something that's also in the qupted thread, Akumayo - you could have just done:

AddInventory(Random(2)+13);
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

edmundito

On GUIs, but this time is the GUIs, you can make on AGS?

I once had an idea of having this notepad in my game where the player could write clues and notes. I never got around to it, but now I'm working on something similar and I've realized that the AGS text box has two limits...

1) It's not multiline.

2) It can't hold enough characters... same for labels.

Is there any way to add these features? I guess I could use a list somehow, but that would confuse the user a lot in my opinion... and before I go through all that effort, it would be nice to make my life a lot easier.
The Tween Module now supports AGS 3.6.0!

GarageGothic

#44
There are ways to get around this through coding. I would think the problem isn't in the textbox or the labels, but rather in the string format. It can only hold 200 characters, so you can't assign any more to the text box/label. Changing that limit probably wouldn't be easy.

What you can do however, is use a listbox with hidden borders. And then do the text entry/linebreaking in code. I did pretty much this for my conversation log and it works fine.

Edit: As an alternative you could put 6 or 8 labels together to form a page. But the coding wouldn't be much different from when using a listbox.

Rui 'Trovatore' Pires

I understand that the new "String" format has no such character limitation... but I'd appreciate confirmation.
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

edmundito

Quote from: GarageGothic on Fri 21/10/2005 21:03:12
What you can do however, is use a listbox with hidden borders. And then do the text entry/linebreaking in code. I did pretty much this for my conversation log and it works fine.

Edit: As an alternative you could put 6 or 8 labels together to form a page. But the coding wouldn't be much different from when using a listbox.

Yep, I thought of that, though it's still kind of weird moving the cursor around... I could have a fake character that you could move to edit the text, but it's quite some work, you know.

Quote from: Rui "Brisby" Pires (a Furry) on Fri 21/10/2005 23:03:37
I understand that the new "String" format has no such character limitation... but I'd appreciate confirmation.

It does have its limits. In fact, I found out about this problem using Strings.
The Tween Module now supports AGS 3.6.0!

GarageGothic

Quote from: Edmundo on Sat 22/10/2005 00:23:28Yep, I thought of that, though it's still kind of weird moving the cursor around... I could have a fake character that you could move to edit the text, but it's quite some work, you know.

I'm not sure I understand the problem. You mean that you want to be able to click anywhere in the previously written text and insert/edit new text there, like you would in notepad? Yes. I suppose that would take some fancy coding but it's not impossible. As for the fake character, I don't know what you're referring to.

edmundito

#48
Oh, the fake character cursor I meant... like the the | that blinks on windows and such. not too difficult to implement.

Now here's a question... how does one insert periods and commas and semicolons into this, then? the ascii table for ags is... limited.

Hmm.. well, I think the best approach would be the following:

Have a list, and add a text box on top of it where you type.. and then it would cleverly read the is key pressed stuff to move it up and down and so on, as well as the list.
The Tween Module now supports AGS 3.6.0!

Rui 'Trovatore' Pires

Sorry, just so I can get it straight (early in the morning, brain still waking up) - I meant that the limit I was under the impression that "String"s don't have is the 200 character limit, is that the limit you were referring to?
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

SSH

Rui: the GUI objects themselves have character limits, too, even if you use Strings.

This sounds like a good thing to have for the coding competition, since there are various way to do it!
12

Gilbert

If only there will be a coding competition. :=

edmundito

Small suggestion:

Change PlayMP3File to PlayAudio or something more general, and this would not only include OGGs, but also midis, mods, xms, wavs... any audio file that AGS supports...

Also, instead of having the tech forum flooded with suggestions, how about we start a suggestion box similar to the tracker? :)
The Tween Module now supports AGS 3.6.0!

Gilbert

The tracker can be used for this purpose already, just that only moderators can add entries to it, so they can scan through suggestions made in the forums and decide if it's a good idea to add to the tracker.

SMF spam blocked by CleanTalk