The Complete STOS Reference

 pre-release 0.2 Edited By Dr Phibes

Program Optimization Techniques

by L.J.Greenhalgh

 Lookup Tables | Array referencing | Line evaluation
Most stos games require a fair degree of optimization if they are to be remotely playable.This artice describes a few techniques which can be used to wring that last drop of speed out of your programs.

Lookup Tables

Anyone who has used the stos trigometric functions will realise how appallingly slow they are.One option is to precalculate all the values you are going to need and store them in an array .It is also possible to use an integer array to store floating point values , thus saving valuable memory. We can do this by multiplying all the floating point values by a large integer value , 32768 usually surfices.This means all are SIN values for instance can be represented in an array by the values +32768 to -32768 as the values of SIN range from 1 to -1.Note that you only need one table as all the trig functions are related to each other by the rules
COS(angle)=SIN(angle+90)
TAN(angle)=SIN(angle)/COS(angle)
The code to generate a sin table is as follows.
10 dim sn_table(360)
20 for angle=0 to 359
30 result#=sin(rad(angle))*32768.0
40 sn_table(angle)=result#
50 next angle
to get a value from the table you use the following code
10 rem sin (angle)
20 result#=sn_table(angle)/32768.0
30 rem cos (angle)
40 result#=sn_table((angle+90) mod 360)/32768.0
Line 40 needs some explanation.

We use the mod function to ensure that (angle+90) is in the range 0-359.The a mod b function returns the remainder when a is devided by b.So 450 mod 360 is 90 , 4 mod 2 is 0 etc.We now have a super fast way of getting at trig values.

Array referencing

Much Stos code is concerned with manipulating the contents of arrays.Integer arrays are stored in memory as consecutive longwords (4 bytes).Say we have an array called missile_x(10) which holds the x coordinates of a number of missiles in a game .When ever you reference the array Stos does the following calculation.You can speed up your code by doing it directly.
missile_x(number)=leek(varptr(missile_x(0))+number*4)
Substituting the above code has a negligable speed increase on 1 dimensional arrays , however for 2 dimensional arrays and above it is about twice as fast! For instance :-
dim alien_property(number_x,number_y)
v=alien_property(x,y)
is equivalent to
v=leek(varptr(alien_property(0,0))+x*4+(y*number_y)*4)
When ever you start multiplying positive integers by powers of 2 , this little trick should spring to mind.You can use the rol function to multiply an integer by a power of 2.Moving an integer by 1 place to the left is equivalent to multiplying by 2.Moving by 2 places is equivalent to multiplying to 4 etc.Be careful not to multiply very large or negative values as you may start moving bits outside of the long word and you will end up with garbage.You can also use the ror function to divide by powers of two.So the above example becomes.
v=alien_property(x,y) is equivalent to
x=rol 2,x
y=rol 2,y
v=leek(varptr(alien_property(0,0))+x+y*number_y)
and alien_property(x,y)=v is equivalent to
x=rol 2,x
y=rol 2,y
loke varptr(alien_property(0,0))+x+y*number_y,v
You can speed up the above even more by assigning a variable to varptr(alien_property(0,0)) so it doesn't have to be worked out every time.By careful as with the above code it is possible to go outside the bounds of the array without an error!

Line evaluation

Beware of writing long lines with many conditions and complex expressions because stos will always evaluate the whole line.This is very inefficient if some of the conditionds are rarely true .For instance:-
10 if a>b and instr(c$,"wibble",5)>0 and b>65536 then print "Oh my God this is horrible code!" else print "Is there a better way?"
If a is rarely greater than b or b rarely greater than 65536 then the code below is much more efficient.
10 if not(a>b and b>65536) then 30
20 if instr(c$,"wibble",5)>0 then print "Oh my God this code is even worse! ":goto 40
30 print "Is there a better way"
40 rest of program .....
Now we only have to evaluate instr$(c$,"wibble",5) occassionally.Although the above code is harder to understand it is much faster and at the end of the day that is what is important when programming games! Check out the file OPTIMZE.BAS for examples of the above techniques in practice.

Happy Stosing.

Les Greenhalgh