PDA

View Full Version : A guide to Mathematical programming

riwu
08-20-2012, 11:18 AM
This tutorial will cover different forms of mathematical operations that can be performed in Simba.

1. For the Beginner (http://villavu.com/forum/showpost.php?p=1088549&postcount=2)
Basic mathematical operations

Logarithm functions

2. For the Intermediate (http://villavu.com/forum/showpost.php?p=1088550&postcount=3)
Arithmetic and geometric progression (AP & GP)

Binary System

Bitwise operators
Bit shifts

4. Conclusion (http://villavu.com/forum/showpost.php?p=1088552&postcount=5)

riwu
08-20-2012, 11:19 AM
1. For the Beginner
In this section i'll introduce basic mathematical operations that can be performed in Simba.

Declaration
When creating a variable, you will need to declare them. Whole numbers (-3, -2, -1, 0, 1, 2, 3, 4...) can be declared as Byte, Word etc but the most commonly used type is Integer, which can store whole numbers ranging from -2147483647 to 2147483647, which will be more than sufficient for RS scripting. For decimal numbers (Eg. 5.12343), they are declared as 'Extended'.

Addition, subtraction, multiplication and division are performed using the symbols '+', '-', '*' and '/' respectively.

There are two special operators relating to division:
'DIV': as far as Simba goes, there is no difference between DIV and '/', so you are free to use whichever you prefer.

'MOD': MOD will return the remainder (integer) of a division.
Eg. 3 MOD 2 will return 1.

This can be useful to check whether a number is odd or even.
For instance if you want to perform an action every 2 loads you can do
Action1;
You can also replace 2 with any positive integer, x, for calling Action1 every x loads.

Notes
These operations follow the standard mathematical precedence, that operations in parenthesis '()' are performed first, followed by multiplication and division, and lastly addition and subtraction.

When doing integer divisions ('DIV' or '/'), simba will always return the product integer, rounded down.
Eg. 3 DIV 2 will return 1.

If you want it to return the more accurate decimal number, simply extend either the divisor or the dividend to a floating number.
Eg. 3.0 DIV 2 will return 1.5.
But if you still want it to be a whole number, you can just call 'Round', which will round the decimal number to the nearest whole number. However, Round deviates slightly from the standard math in that for half values it will round towards negative infinity, that is it will round 1.5 to 1, and -1.5 to -2. Hence if you want it to perform the conventional 'Round half up', you can just add a small number, like 0.00001 to make sure it round up.
Eg. Round(5.0/2 + 0.0001) will return 3.

Logarithm, Power and Absolute.
Logarithm functions: ln, logn, log10
Power: pow
Absolute: Abs (in essence, it does this: if a<0 then a:=-a)
Nothing much to explain here.

To sum up all we have learn this far, run the following program:

program MathExamples;
var
A: Integer;
begin
ClearDebug;
A:=2;
// 'ToStr' converts the argument to strings
writeln('A cow has ' + ToStr(A/2) + ' head, ' + ToStr(A*2) + ' legs and ' + ToStr(A) + ' eyes');
writeln('A duck has '+ ToStr(A) + ' legs');
writeln('3 cows and 2 ducks have ' + ToStr(3*(A*2) + 2*A) + ' legs');
writeln('Hence on average, they have ' + ToStr(16/5.0) + ' legs');
writeln('But we want an integer value for legs!');
writeln('Hence, rounding off, they have ' + ToStr(Round(16/5.0 + 0.000001)) + ' legs on average');
writeln('The maximum number of legs we can store in a 32-bit data is ' + ToStr(pow(2,32) DIV 2 - 1));
end.
For a practical use, you can check out my LividFarm Calculator (http://villavu.com/forum/showthread.php?t=77730) that i made a few months ago.

riwu
08-20-2012, 11:20 AM
2. For the Intermediate
In this section i will introduce 2 common types of sequence, AP and GP.

Arithmetic progression (AP)
An AP is simply a sequence of numbers in which the difference between each term is a constant.
Eg.
2,4,6,8,10,....
6,2,-2,-6,-10,....

Let's jump straight into an example:
http://img17.imageshack.us/img17/7171/invx.png
Suppose that we want to drop all the items, a common approach (http://villavu.com/forum/showthread.php?t=68528) would be to create a TIntegerArray and inputting the pattern to drop it [1,5,9,13,17,21,2,6,10,14,18,22,3,7,11,15,19,23,4,8 ,12,16,20,24] (column by column). This approach might be foolproof, but what if in another scenario, there are 100 rows and columns to drop? It would then be a hassle to try input the pattern again (and even prone to errors).

We should then perhaps observe the pattern:
1,5,9,13,17,21
That is in fact an AP! It's first term is 1 and the common difference between each term is 4. Based on the formula of the general term of an AP:
Tn=a + (n-1)d
where a is the first term, d is the common difference and n is the nth term (1,2,3,4,5,6...)
So we will get
1+(n-1)*4
for our first column of inventory.
We can then use a loop to drop the items:
program Example;
{\$i SRL/srl.simba}

procedure MouseKeyDrop;
var
i,x,y,InvSlot: Integer;
begin
for i:=1 to 6 do //if you want to do 6 rows
begin
InvSlot:=(1+(i-1)*4);
Writeln('Moving to InvSlot ' + ToStr(InvSlot));
{MouseItem(InvSlot,mouse_Right);
GetMousePos(x,y);
MoveMouse(x,y+40);
ClickMouse2(mouse_Left); }
end;
end;

begin
MouseKeyDrop;
end.
Run this and you will see how it magically generates the whole sequence ;)

How do we deal with the other 3 columns then? Surely we don't want to create another AP?
Observe this:
1,5,9,13,17,21,...
2,6,10,14,18,22,...
The pattern is obvious now, for the next column, the slot number increases by 1, so we can simply add another loop that adds 1-3 to every InvSlot based on the column number:
program Example;
{\$i SRL/srl.simba}

procedure MouseKeyDrop;
var
k,i,x,y,InvSlot: Integer;
begin
for k:=0 to 3 do
for i:=1 to 6 do
begin
InvSlot:=((1+(i-1)*4)+k);
Writeln('Moving to InvSlot ' + ToStr(InvSlot));
{MouseItem(InvSlot,mouse_Right);
GetMousePos(x,y);
MoveMouse(x,y+40);
ClickMouse2(mouse_Left); }
end;
end;

begin
MouseKeyDrop;
end.
You now officially have the right to brag to YoHoJo that your mousekey procedure is cleaner than his! ;)

Sum of an AP
The sum of an AP is given by
Sn=(n/2)(2a+(n-1)d)
OR
Sn=(n/2)(a+l)
where l is the last term of the sequence. (The other terms are same as AP)
Usually you won't know the last term so the first equation is more commonly used.
I can't think of an example for its application for RS atm, tell me if you have an idea.

Geometric progression (GP)
A GP is another common type of sequence, where the difference between each term is a ratio.
Eg.
1,2,4,8,16,32... (Multiply the previous term by 2 to get the next term)
2, 2/5, 2/25, 2/125,....(ratio=1/5)

General Term
Tn=a(pow(r,n-1))
where r is the common ratio.

Sum of a GP
Sn=(a(1-pow(r,n))) / (1-r)

riwu
08-20-2012, 11:21 AM

The Binary system
In a Binary system, the system can only recognize 0 or 1 (like a true/false boolean), hence it can easily count up to the number 1:
0=0
1=1
How does it carry on counting then? We simply use two bits:
2=10
3=11
And to count further just continue increasing the bits:
4=100
5=101
6=110
And so on.
Hence in a 32-bit system, it can count all the way to 4294967295.

You can use this simple converter to convert from Decimal to Binary, vice versa:
http://i.imgur.com/UbJPp.png

Bitwise operation
Bitwise operation manipulates the individual bits through bitwise operators to change the bit values. All bitwise operations can be done with mathematical operations covered in Section 1. Why then, do we want to perform bitwise operations?
Bitwise operations are primitive actions directly supported by the processor, hence it can be performed much faster while using much less resources!

Bitwise operators
The logic in these operators are pretty much similar to how you use them in checking booleans:

NOT
Returns the complement binary value. For unsigned integers, it simply returns the negative value minus 1.
Eg. NOT 1337=-1338

AND
Compares 2 binary values and if both bits are equal to 1, it returns 1, otherwise it returns 0.
Eg.
1001 AND
0101 =
0001

OR
Compares 2 binary values and if either of the bits equal to 1, it returns 1, otherwise it returns 0.
Eg.
10101 OR
01001 =
11101

XOR
Compares 2 binary values and returns 1 if either the first bit or the second bit is 1, but not both.
Eg.
11010 XOR
01001 =
10011

XOR can be used to swap two integer variables without creating an intermediary variable:
procedure SwapValue;
var
a, b: Integer;
begin
a:=21;
b:=8;
a:=a XOR b; //a is now a XOR b
b:=a XOR b; //b becomes the original value of a
a:=a XOR b; //a becomes the original value of b
writeln('a is now: '+ ToStr(a) + ' and b is now ' + ToStr(b));
end;

Bit shifts
Bit shifts basically shifts the bits to the left/right:

shl (shift left)
Shifts the bits to the left. The shifted bits are replaced by 0.
Eg.
1101 shl 3
=1101000

In decimal terms, this will return the original value multiplied by pow(2,n), where n is the the digits u shifted.
i.e. a shl n = a*(pow(2,n));

shr (shift right)
Shifts the bits to the right. Hence bits shifted are covered up and cease to exist.
Eg.
10101 shr 2
=101

In decimal terms, this will return the original value divided by pow(2,n), rounded down.
i.e. a shr n = floor(a / pow(2,n))

Note that you cannot shift a binary by a negative value, and doing so will return 0.

riwu
08-20-2012, 11:22 AM
4. Conclusion
I know this guide isn't very comprehensive, I will try to expand it when I have more ideas. Please give some ideas on what it's lacking, and don't hesitate to clarify your doubts!
Some things that I can possibly add if there is demand for them:
-Binomial, Poisson and Normal distribution

Footy
08-20-2012, 12:50 PM
Nice guide, I just skimmed over it, I might have some feedback when I have time to read it properly. Rep +!

Joe
08-20-2012, 01:01 PM
I have never seen a proggy so indepth. Thanks a lot for the beginner guide! I'm hopeless past beginner but it looks very clean and professional.

~Joe

P1ng
08-20-2012, 01:32 PM
Great guide!
It would be nice to see how you can implement binary and bitwise operators in a script :)

masterBB
08-20-2012, 01:56 PM
Great guide!
It would be nice to see how you can implement binary and bitwise operators in a script :)

colors for example:

color := 1247920;
red := (1247920 and \$FF);
green := ((1247920 shr 8) and \$FF);
blue := ((1247920 shr 16) and \$FF);

J J
08-25-2012, 08:15 AM
Nice guide so far :) What you could add is the following:
Moving 50 pixels to the east of an object, regardless of the compass. This can be achieved by using cos/sin and converting the angle degrees to radials. Nearly all scripts have the compass forced to north and can simply add to the X value, but what if you want to have different angles during everything and still click on the right spot? ;)

Daniel
08-25-2012, 11:03 AM
Great guide!
It would be nice to see how you can implement binary and bitwise operators in a script :)

I did it all throughout this script (http://villavu.com/forum/showthread.php?t=80546). :)

riwu
08-25-2012, 11:31 AM
Nice guide so far :) What you could add is the following:
Moving 50 pixels to the east of an object, regardless of the compass. This can be achieved by using cos/sin and converting the angle degrees to radials. Nearly all scripts have the compass forced to north and can simply add to the X value, but what if you want to have different angles during everything and still click on the right spot? ;)
Just read through the simba doc and found 1 function that'd accomplish this: