View Full Version : Withing Itself
Its possible to call a procedure/function within itself(probably not recommended), but what rules does it follow? After the procedure is over does the original one that called it continue?
TomTuff
03-06-2011, 10:39 PM
program New;
procedure Proc;
begin
Writeln('Proc');
if (Random(4) = 0) then
Proc;
end;
begin
ClearDebug;
Proc;
end.
Proc
Proc
Successfully executed.
Sabzi
03-06-2011, 10:39 PM
What you are asking about is called a recursive function.
You have to think about it twice before using it because it's easy to make it infinitive and most of the time the problem can be solved easier with iterative solutions. There are things easier with recursive functions tho.
But yeah, it's possible.
Second question: yes.
It's a wise idea making recursive functions a function.(in pascal this sentence makes sense ...)
So it would return something which you can check in the function itself so you can control how deep you go.(in the stack)
That is a recursive function I believe. Yes you can do it using a multiple of ways. One way is labels :p. Although I don't think there really is a reason to do so. Almost anything requiring this can be avoided by changing the way you do it. Give us an example for why you would want this :).
I'm trying to implement a new system of walking for my cooker cause its giving me a headache. Heres what im doing:
Procedure StaircaseTo(Route: String);
var
Counter1, Counter2, Counter3: Integer;
UpText: Boolean;
begin
WriteLn('Running Staircase(' + Route + ').');
case Route of
'Up':
begin
case GetPlaneIndex of
0:
begin
Counter1 := 0;
Counter2 := 0;
if (MouseStaircase(True)) then //MouseStaircase Clicks on the staircase and check if it clicked on the staircase or if there is a menu
begin
repeat
Inc(Counter1);
Writeln('Counter1 Is ' + IntToStr(Counter1) + '.');
repeat
Inc(Counter2);
Wait(100);
until (GetPlaneIndex = 1) or (GetPlaneIndex = 2) or (Counter2 >= 25);
if (Counter2 >= 25) then
begin
Writeln('Counter2 Is >= 25. Will Try Again.');
end
else if (GetPlaneIndex = 0) then
begin
Break;
end
else
begin
StaircaseTo(Route);
end;
until (Counter1 >= 5) or (GetPlaneIndex = 2);
begin
if (Counter1 >= 5) then
begin
WriteLn('Could Not Get To The ' + Route + ' Floor.');
TerminateScript;
end
else
begin
WriteLn('Successfully Reached The ' + Route + ' Floor.');
end;
end;
end
else
begin
TerminateScript;
end;
end;
1:
begin
Counter1 := 0;
Counter2 := 0;
Counter3 := 0;
WriteLn('On The Middle Floor Continuing.');
repeat
Inc(Counter2);
if (MouseStaircase(False)) then
begin
repeat
Inc(Counter1);
if R_ChooseOption(Route) then
if DidRedClick then
WriteLn('Clicked On Option ' + Route + '.');
UpText := True;
until (UpText = True) or (Counter1 >= 20);
if (Counter1 >= 20) then
begin
WriteLn('Counter1 Equals ' + IntToStr(Counter1) + '.');
WriteLn('Unable To Go To Choose An Option. Will Try Again.');
end
else
WriteLn('Counter2 Equals ' + IntToStr(Counter2) + '.');
if (UpText = True) then
repeat
Inc(Counter3);
Wait(100);
until (GetPlaneIndex = 2) or (Counter3 >= 15)
else
begin
WriteLn('Unable To Get The Correct Staircase Uptext.');
TerminateScript;
end;
end
else
begin
TerminateScript;
end;
until (GetPlaneIndex = 2) or (Counter2 >=10);
If (Counter2 >= 10) Then
begin
WriteLn('Counter2 Equals ' + IntToStr(Counter2) + '.');
WriteLn('Unable To Go To The ' + Route + ' Floor. Will Try Again.');
end;
end;
2:
begin
Writeln('Already On The Top Floor.');
end;
end;
end;
I dont see how this thing could infiniteify(lol) itself....
One more question: What happens to the variable values in the parent procedure and the child procedure?
Heysus
03-06-2011, 11:28 PM
In my opinion it's completely unnecessary and just makes things really confusing. I suppose it's possible but I would highly discourage it.
Harry
03-06-2011, 11:55 PM
I don't suggest it, but it's possible. Make sure you always include an Exit; after it calls itself or at least have some method of breaking out, so you won't infinite loop.
Nava2
03-07-2011, 12:20 AM
For the record, recursion can actually be very elegant. In fact, its actually a better option in some cases.
For example:
Recursive:
public static void recursiveQuicksort(int[] a) {
// shuffle(a); // to guard against worst-case
recursiveQuicksort(a, 0, a.length - 1);
}
// quicksort a[left] to a[right]
public static void recursiveQuicksort(int[] a, int left, int right) {
if (right <= left) return;
int i = partition(a, left, right);
recursiveQuicksort(a, left, i-1);
recursiveQuicksort(a, i+1, right);
}
// partition a[left] to a[right], assumes left < right
private static int partition(int[] a, int left, int right) {
// DK: added check if (left == right):
if (left == right) return left;
int i = left - 1;
int j = right;
while (true) {
while (a[++i] < a[right]) // find item on left to swap
; // a[right] acts as sentinel
while (a[right] < a[--j]) // find item on right to swap
if (j == left) break; // don't go out-of-bounds
if (i >= j) break; // check if pointers cross
swap(a, i, j); // swap two elements into place
}
swap(a, i, right); // swap with partition element
return i;
}
Iterative:
public static void iterativeQuicksort6(int[] a) {
int[] range = new int[a.length+1]; // if (range[i]<0) then skip[i] = |range[i]|
range[0] = a.length-1;
int i, j, sortedCount = 0;
while (sortedCount < a.length) {
for (i=0; i<a.length; i++)
if (range[i] >= i) {
j = range[i];
if (j-i < 7) {
// selectionsort the elements from a[i] to a[j] inclusive
// and set all their ranges to -((j+1)-k)
for (int m=i; m<=j; m++) {
for (int n=m; n>i && a[n-1]>a[n]; n--)
swap(a, n, n-1);
range[m] = -((j+1)-m);
sortedCount++;
}
i = j;
}
else {
for ( ; i<=j; i++) {
int p = partition(a,i,j);
sortedCount++;
if (p > i) range[i] = p-1;
if (p < j) range[p+1] = j;
range[i = p] = -1; // sorted
}
}
}
else {
// skip[i] += skip[i + skip[i]];
while ((j = range[i-range[i]]) < 0) range[i] += j;
i += -range[i]-1;
}
}
}
... Looks hard. Ill look in to it.
What happens to the variable values in the parent procedure and the child procedure?
Frement
03-07-2011, 12:43 AM
... Looks hard. Ill look in to it.
What happens to the variable values in the parent procedure and the child procedure?
Well, I guess each child has their own local variables, but globals are globals.
Flight
03-07-2011, 12:56 AM
Ironic anyone?
OK. Next question. Is there a function/procedure that allows you to hover over a menu option but not click it?
Floor66
03-07-2011, 06:54 AM
I don't think so but why don't you just take SRL's ChooseOption and remove the part where it clicks ? :)
Ok. Thanks cause banking is becoming a problem for me. I thought there was a specific function for it.
Richard
03-07-2011, 09:32 PM
Recursion can be useful. I made a factorial function in Java that relies on recursion:
int calcFactorial(int integer)
{
if( integer == 1)
return 1;
else
{
return(integer * (calcFactorial(integer - 1);
}
}
Genuinely save quite a fair amount of code, and it makes you look clever ;)
Nava2
03-07-2011, 09:41 PM
Ok. Thanks cause banking is becoming a problem for me. I thought there was a specific function for it.
(*
ChooseOptionMultiEx
~~~~~~~~~~~~~~~~~~~
.. code-block:: pascal
function ChooseOptionMultiEx(Texts: TStringArray; TextType: String; Action: fnct_ActionOptions): Boolean;
Finds Popup menu, then clicks on it.
Will look for the first string first and so on.
It will search for the Text Type you input valid arguments are
'action', 'player': The white text
'npc': The yellow text
'object': The cyan text
'all': Searches for all colors of text.
Will default to 'all'.
.. note::
by Wizzup? & Nava2 & N1ke!
Example:
.. code-block:: pascal
*)
function ChooseOptionMultiEx(Texts: TStringArray; TextType: String; Action: fnct_ActionOptions): Boolean;
var
B,OptionBox: TBox;
TPA, TPA1, TPA2, TextTPA: TPointArray;
aTPA: T2DPointArray;
I, H, HH, ii, L: Integer;
Colors,SearchCols: TIntegerArray;
begin
Result := False;
GetClientDimensions(B.X2, B.Y2);
B.X1 := 0;
B.Y1 := 0;
Dec(B.X2);
Dec(B.Y2);
FindColorsTolerance(TPA1, 4343893, B.X1, B.Y1, B.X2, B.Y2, 0);
FindColorsTolerance(TPA2, 3950929, B.X1, B.Y1, B.X2, B.Y2, 0);
TPA := CombineTPA(TPA1, TPA2);
If Length(TPA) < 10 Then
Exit;
B.X2 := 0;
B.Y2 := 0;
aTPA := SplitTPAEx(TPA, 20, 20);
SortATPASize(aTPA, True);
B := GetTPABounds(aTPA[0]);
Colors := [13034990, 4231423, 2070783, 65535, 16776960, 9812166, 16777215];
TextType := LowerCase(TextType);
case TextType of
'action', 'player': SearchCols := [0,5,6];
'item' : SearchCols := [1,2];
'npc' : SearchCols := [3];
'object': SearchCols := [4];
else
SearchCols := [0,1,2,3,4,5,6];
end;
L := High(SearchCols);
SetLength(aTPA,l+1);
for i := 0 to l do
FindColorsTolerance(aTPA[I], Colors[SearchCols[I]], B.X1, B.Y1, B.X2, B.Y2, 3);
TPA := MergeATPA(aTPA);
aTPA := SplitTPAEx(TPA, 15, 1);
L := High(aTPA);
H := High(Texts);
SortATPAFromFirstPoint(ATPA, Point(OptionBox.X1, optionbox.y1));
for I :=0 To H do
begin
TextTPA := LoadTextTPA(Texts[i], UpChars, HH);
for ii := 0 to L do
If FindTextTPAInTPA(HH, TextTPA, aTPA[ii], TPA) Then
begin
Result := True;
case Action of
ClickLeft: MouseBoxEx(B.x1 + 5, TPA[0].Y, B.x2 - 5, TPA[0].Y + 5,5, 1);
Move: MouseBoxEx(B.x1 + 5, TPA[0].Y, B.x2 - 5, TPA[0].Y + 5,5, 3);
Nothing: begin end;
else
srl_warn('ChooseOptionMultiEx', 'ClickRight not a valid click for RS menus!', warn_AllVersions);
end;
Exit;
end;
end;
if Action <> Nothing then
begin
MMouse(B.X1 - 50, B.Y1 - 50, 40, B.Y2 - B.Y1);
Wait(200 + Random(100));
end;
end;
Pass `Nothing` to action. :)
Powered by vBulletin® Version 4.2.1 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.