Edit by strazer:
AGS 2.7 Beta 8 introduced the Maths.Sqrt function.
In case anyone needs to find the square root of something or the distance between two points (how far apart two characters are, for instance) I thought I'd post these.
I needed to find the square root of something for a gui, and since ags doesn't have a sqrt() function, and there isn't a plugin for it I had to write one, so with the help of Annie, and Newton here it is
(along with abs() sqr() and point_distance() which I just find save time)
function abs(int number) { if(number<0) number=number*(-1); return number;}
function sqr(int number) {
return (number*number);
}
function sqrt(int number) {
number=abs(number);
if(number==0)number=1;
int guess=Random(number)+1;
int previousguess;
int result= -1;
int maxiterations=10;
while(result!=previousguess && maxiterations>0) {
result = (number/guess+guess)/2;
previousguess=guess;
guess=result;
maxiterations--;
}
return result;
}
function point_distance(int x1,int y1,int x2,int y2) {
return sqrt((sqr(x1-x2)+sqr(y1-y2)));
}
I am terrible at maths.. so they may well be scripted extremely badly but they seem to work in my game.
Of course, you can just work with the squared numbers most of the time. Why bother finding the root? If you want to know if the distance is less than 46
if (srq(x1-x2)+sqr(y1+y2) < srq(40)) ...
or comparing two calculated distances, etc.
So make sure you're not slowing things down by making things too difficult for yourself!
In my test I realized that your algorithm can e.g. give 3 as sqrt (8), because 2 and 3 are alternating in result until maxiterations is zero.
Also sqrt(0) should be zero not one.
Instead of using a maximum number of iterations, the algorithm below stops when alternating values in result are detected.
function sqrt(int number)
{
int result = 0;
if(number > 0)
{
int previousguess = -1;
int guess = -1;
result = 1;
while((result != previousguess) && (result != guess))
{
previousguess = guess;
guess = result;
result = (number / guess + guess) / 2;
}
if (guess < result) { result = guess; }
}
else if (number < 0)
{
result = -1; // error
}
return result;
}
Thanks a-v-o :)
If I recal there is an exact forula for determining square roots, but it involves using the natural log.
Yes, but neither AGS nor the math plugin has any capability for log() functions. That's why I recommended Newton's method. :)
And the lack of decimals.
Anyway, here is a way to do it without using iterations (so can be slow for LARGE numbers, but should work for most cases), it can return the square root rounded to the nearest integer (tested):
function sqrt(int num){
num=abs(num); //well you may use the same abs()
int i=0;
while (i*i<num) i++;
int temp = i*i-num;
if (temp){
i--;
temp = (num-(i*i))*4;
if (temp>(4*i)+1)i++;
}
return i;
}
Hey Gilbot,
Quote
int i=0;
while (i*i<num) i++;
This is really the easiest way to get the integer square root and I used it in the flashlight plugin to calculate the circle.
Strange that I haven't thought at it at my last post. ???
Just another modification of Newton's formula. Returns the rounded value. Good at large values where it takes about 3-4 iterations to calculate the root:
function abs(int a) { if (a<0) return -a; else return a; }
function mod(int a, int b) { return a - (b*(a/b)); }
function sqrt_fast(int L) {
int temp, div, result = abs(L);
if (L <= 0) return 0;
else if (L < 5 ) div = L;
else if (L < 256 ) div = 7;
else if (L < 65536 ) div = 63;
else if (L < 16777216) div = 1023;
else div = 16383;
while (1) {
temp = L/div + div;
div = temp/2;
div += temp & 1;
if (result > div) result = div;
else {
if (L/result == result-1 && mod(L,result)==0) result--;
return result;
}
}
}
~Cheers