For: Difference between revisions
No edit summary |
Hendricks266 (talk | contribs) No edit summary |
||
(2 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
'''for''' <gamevar> < | '''for''' <gamevar> <iterator> { [...] }<br> | ||
'''for''' <gamevar> < | '''for''' <gamevar> <iterator> <value> { [...] } | ||
Executes the code in the curly braces for every instance of the | Executes the code in the curly braces for every instance of the iterator specified. The <[[gamevar]]> specified will be set to the index ([[sprite]]/[[sector]]/[[wall]]/etc) for that iteration of execution. (In math, this is called the induction variable.) | ||
== | For example, specifying <iterator> as '''allsprites''' will run the code for every [[sprite]] in the game world, and <[[gamevar]]> will be set to the ID number of one particular sprite when it gets its turn. | ||
== Iterators == | |||
{| {{prettytable}} | {| {{prettytable}} | ||
Line 13: | Line 15: | ||
| '''allwalls''' || All walls in the map. | | '''allwalls''' || All walls in the map. | ||
|- | |- | ||
| '''activelights'''<br />'''lights''' || All active | | '''activelights'''<br />'''lights''' || All active Polymer lights. | ||
|- | |- | ||
| '''drawnsprites''' || Only the sprites currently being drawn. | | '''drawnsprites''' || Only the sprites currently being drawn. | ||
|- | |- | ||
| '''spritesofsector'''<sectnum><br /> '''sprofsec'''<sectnum> || All sprites in the given sector. | | '''spritesofsector''' <sectnum><br /> '''sprofsec''' <sectnum> || All sprites in the given sector. | ||
|- | |- | ||
| '''spritesofstatus''' <statnum><br />'''sprofstat''' <statnum> || All sprites with the given [[statnum]]. | | '''spritesofstatus''' <statnum><br />'''sprofstat''' <statnum> || All sprites with the given [[statnum]]. | ||
Line 23: | Line 25: | ||
| '''wallsofsector''' <sectnum><br />'''walofsec''' <sectnum> || The walls of the given sector. | | '''wallsofsector''' <sectnum><br />'''walofsec''' <sectnum> || The walls of the given sector. | ||
|- | |- | ||
| '''loopofwall''' < | | '''loopofwall''' <wallnum> || All walls in the same loop of the given wall. | ||
|- | |- | ||
| '''range''' <num> || | | '''range''' <num> || Every integer starting at 0, up to but not including the number specified. | ||
|} | |} | ||
== Notes == | |||
Unlike other loop forms, the implementation keeps its own internal copy of the induction variable, so if <gamevar> is modified in the loop body, the next iteration will take place as if it had not been changed. Similarly, the conditional statement is ''not'' re-evaluated each iteration. For example, the following loop will log 1 through 10: | |||
var i | |||
var j 10 | |||
for i range j | |||
{ | |||
add i 1 // interpret value as 1..10 instead of 0..9 | |||
[[al]] i // write value to the log file | |||
set j 99999 // useless but harmless operation for demonstration purposes | |||
} | |||
These factors combined make for loops safer than [[whilevarn]] to use in CON, because it avoids accidentally clobbering the gamevars in states that are called, or events that run during operations performed (such as [[EVENT_SPAWN]] during [[spawn]]). | |||
For loops are also strongly preferable for performance reasons. Most users only need to remember that fact, but the technical explanation for those interested is that the loop is implemented as an actual for loop in EDuke32's C++ code, where the induction variable and iteration condition are ordinary local variables on the call stack. In contrast, [[whilevarn]] takes place on the level of commands in the CON interpreter, jumping around locations in the compiled bytecode and operating naively on gamevars. The former paradigm is faster because does not have to load and store the gamevar's value to/from memory for every iteration, which places stress on the data cache and could stall due to RAM access delays, and also because CPU branch prediction will be more effective when the meaning of the loop is more plainly stated to the compiler and in the resulting machine code. | |||
[[Category:EDuke32 specific commands]] | [[Category:EDuke32 specific commands]] |
Latest revision as of 11:44, 15 December 2024
for <gamevar> <iterator> { [...] }
for <gamevar> <iterator> <value> { [...] }
Executes the code in the curly braces for every instance of the iterator specified. The <gamevar> specified will be set to the index (sprite/sector/wall/etc) for that iteration of execution. (In math, this is called the induction variable.)
For example, specifying <iterator> as allsprites will run the code for every sprite in the game world, and <gamevar> will be set to the ID number of one particular sprite when it gets its turn.
Iterators
allsprites | All actors/sprites in-game. |
allsectors | All sectors in the map. |
allwalls | All walls in the map. |
activelights lights |
All active Polymer lights. |
drawnsprites | Only the sprites currently being drawn. |
spritesofsector <sectnum> sprofsec <sectnum> |
All sprites in the given sector. |
spritesofstatus <statnum> sprofstat <statnum> |
All sprites with the given statnum. |
wallsofsector <sectnum> walofsec <sectnum> |
The walls of the given sector. |
loopofwall <wallnum> | All walls in the same loop of the given wall. |
range <num> | Every integer starting at 0, up to but not including the number specified. |
Notes
Unlike other loop forms, the implementation keeps its own internal copy of the induction variable, so if <gamevar> is modified in the loop body, the next iteration will take place as if it had not been changed. Similarly, the conditional statement is not re-evaluated each iteration. For example, the following loop will log 1 through 10:
var i var j 10 for i range j { add i 1 // interpret value as 1..10 instead of 0..9 al i // write value to the log file set j 99999 // useless but harmless operation for demonstration purposes }
These factors combined make for loops safer than whilevarn to use in CON, because it avoids accidentally clobbering the gamevars in states that are called, or events that run during operations performed (such as EVENT_SPAWN during spawn).
For loops are also strongly preferable for performance reasons. Most users only need to remember that fact, but the technical explanation for those interested is that the loop is implemented as an actual for loop in EDuke32's C++ code, where the induction variable and iteration condition are ordinary local variables on the call stack. In contrast, whilevarn takes place on the level of commands in the CON interpreter, jumping around locations in the compiled bytecode and operating naively on gamevars. The former paradigm is faster because does not have to load and store the gamevar's value to/from memory for every iteration, which places stress on the data cache and could stall due to RAM access delays, and also because CPU branch prediction will be more effective when the meaning of the loop is more plainly stated to the compiler and in the resulting machine code.