This tutorial will guide you through using loops in Scar(pascal). I will provide examples as well as descriptions for the following types of loops: for..to..do, while..do, repeat..until.
You should already know about variables, begin..end nests, as well as basic Scar(pascal) syntax.
for..to..do
In my opinion, the for..do..to loop is the most useful of the three I will be covering in this tutorial. The following is an example of a basic for..to..do loop.
SCAR Code:
program for_to_do;
procedure for_to_do_practice;
var
i: Integer;
begin
for i := 0 to 4 do
Writeln(IntToStr(i));
end;
begin
for_to_do_practice;
end.
This procedure would output:
All a for..to..do loop does is takes the value set to the variable between the "for..to" which, in this case is "i := 0", and repeats the loop, increasing the value of "i" by one each time, until "i" is equal to the value set between the "to..do" which, in this case is "4". So, as you can see, the preceding example looped through 5 times.
(NOTE: You must set a variable between "for..to" for the loop to count with. It doesn't need to equal "0", but you must change the value between "to..do" accordingly.)
Now, if I wanted to execute more that one line during my for..to..do loop, I would have to add a begin..end nest(which you should already know about, if not please resort to a more basic tutorial for now).
Example:
SCAR Code:
program for_to_do;
procedure for_to_do_practice;
var
i: Integer;
begin
for i := 0 to 4 do
begin
if i <= 2 then // if "i" is less than or equal to 2 then
Writeln(IntToStr(i)) // do this
else //otherwise
Writeln('i is greater than 2.'); // do this.
end;
end;
begin
for_to_do_practice;
end.
In this case the procedure would output:
SCAR Code:
0
1
2
i is greater than 2.
i is greater than 2.
While on this topic I will also talk briefly about for..downto..do loops. They are basically the same thing as a for..to..do loop, just counting down, instead of up.
Example:
SCAR Code:
program for_to_do;
procedure for_to_do_practice;
var
i: Integer;
begin
for i := 4 downto 0 do
Writeln(IntToStr(i));
end;
begin
for_to_do_practice;
end.
This procedure would output:
Simple, yet effective.
If you work with arrays at all you will find these loops to be extremely useful.
while..do
The syntax for a while..do loop is:
SCAR Code:
while Statement = True do
WhateverYouWantTheLoopToDo;
So, with a while..do loop, as long as the statement between while..do remains true, the loop will continue to repeat.
Example:
SCAR Code:
program while_do_loops;
procedure while_do_practice;
var
i: Integer;
begin
i := 0; //set the value of "i" equal to "0"
while i <= 4 do //while "i" is less than or equal to 4 do the following..
begin
Writeln(IntToStr(i));
Inc(i); //Increases the value of "i" by 1
end;
Writeln('The loop is over because i = '+IntToStr(i)+';');
end;
begin
while_do_practice;
end.
The preceding procedure would output:
SCAR Code:
0
1
2
3
4
The loop is over because i = 5;
As you can see, a while..do loop checks the statement before it executes the actual loop. Therefor, if the statement returns false, it will skip over the loop to the next part of the procedure.
Example:
SCAR Code:
program while_do_loops;
procedure while_do_practice;
var
i: Integer;
begin
i := 5; //set the value of "i" equal to "5"
while i <= 4 do //while "i" is less than or equal to 4 do the following..
begin
Writeln(IntToStr(i));
Inc(i); //Increases the value of "i" by 1
end;
Writeln('The loop is over because i = '+IntToStr(i)+';');
end;
begin
while_do_practice;
end.
In this case, because "i" is greater than 4, the compiler will skip over the loop it self, and so the output would be:
SCAR Code:
The loop is over because i = 5;
repeat..until
The repeat..until loop is pretty self-explanatory. The syntax goes as follows:
SCAR Code:
repeat
Loop;
until(Statement = True);
As you can see, unlike the while..do loop, the repeat..until loop checks the statement after the loop, therefor, the loop is guaranteed to run through at least once.
Example:
SCAR Code:
program repeat_until_loops;
procedure repeat_until_practice;
var
i: Integer;
begin
i := 0;
repeat
Writeln(IntToStr(i));
Inc(i);
until(i >= 5);
Writeln('The loop is over because i = '+IntToStr(i)+';');
end;
begin
repeat_until_practice;
end.
This procedure would output:
SCAR Code:
0
1
2
3
4
The loop is over because i = 5;
Now, keep in mind that the loop will execute at least once because it checks the statement at the end.
Example:
SCAR Code:
program repeat_until_loops;
procedure repeat_until_practice;
var
i: Integer;
begin
i := 5;
repeat
Writeln(IntToStr(i));
Inc(i);
until(i >= 5);
Writeln('The loop is over because i = '+IntToStr(i)+';');
end;
begin
repeat_until_practice;
end.
Would output:
SCAR Code:
5
The loop is over because i = 6;
As you can see, even though "i" was already equal to 5, the compiler still executed the loop once because it didn't check the statement until after the loop.
BEWARE OF INFINITE LOOPS!
An "Infinite Loop" is a loop that has a possibility of never ending.
Example:
SCAR Code:
procedure Infinite_Loop_Practice;
begin
repeat
Writeln('This loop may never end!');
until(ThisFunction);
end;
The above repeat..until loop would continue to repeat until "ThisFunction" returned true. Therefor, if something went wrong and "ThisFunction" never returned true, the loop would just continue to repeat until it was stopped manually. This can become incredibly dangerous especially if you're planning to script for RuneScape, as an Infinite loop may lead to a ban :/. So be careful!
BREAKING LOOPS
You may be wondering how you can prevent an Infinite loop.Your looking for a what is known as a "failsafe". for..to..do loop's are good for avoiding infinite loops because they have a sort of "built in" failsafe. Since, as you should know by this point, they have a set amount of times they can loop through before ending.
However, if you would prefer not to use a for..to..do loop there are a couple ways to implement your own failsafes into your loops.
Counting FailSafe
One method you could use would be counting. By "counting" I meen to increase the value of a variable to keep track of loop number. (Count each loop). This method basically just sets a limit to the containing loop.
Your going to need to know before hand a maximum amount of times you want the program to loop through before it is "too many" and you want it to stop. (or have it set to a variable and have a value passed to it during run time.) The reason I recommend a for..to..do loop is because it just saves the script writer (you) from having to increment the "counting variable" your self.
Also, make sure you understand this simple procedure:
SCAR Code:
procedure Inc(x: Integer);
All it does is increase "x" by 1.
Example of a Counting failsafe:
SCAR Code:
procedure Counting_failsafe_practice;
var
Counter: Integer; //It doesn't have to be named "counter" I just chose that for readability.
begin
Counter := 0; // Be sure to set the starting value of your "counting variable" BEFORE the loop, so it doesn't reset every time your loop goes through.
while(not (ThisFunction)) do //while ThisFunction = false do..
begin
Inc(Counter); // Increase the value of "Counter" by 1.
if Counter >= 4 then // if the value of "Counter" is greater than or equal to 4 then...
Break; //By calling this the program will now quit this loop.
end;
end;
As you can see, the above procedure will continue looping through until either ThisFunction returns true, or the value of "Counter" is 5 or greater. Which we then exit the loop by calling "Break;".
Timing FailSafe
Another type of custom failsafe you could add to your loop would be a "Timer". You can find a lot of other functions to go along with this type of failsafe in Timing.Scar. Once you get the hang of using timers you will be able to experiment with using them different ways, but for now I will just show you a basic way to do it.
First, I suggest looking over/familiarizing yourself with these two functions from Timing.Scar:
SCAR Code:
{*******************************************************************************
procedure MarkTime(var TimeMarker: Integer);
By: Stupid3ooo
Description: Sets TimeMarker to current system time
*******************************************************************************}
procedure MarkTime(var TimeMarker: Integer);
begin
TimeMarker := GetSystemTime;
end;
{*******************************************************************************
function TimeFromMark(TimeMarker: Integer): Integer;
By: Stupid3ooo
Description: returns Milliseconds since MarkTime was set
*******************************************************************************}
function TimeFromMark(TimeMarker: Integer): Integer;
begin
Result := GetSystemTime - TimeMarker;
end;
Example of a "Timing" failsafe:
SCAR Code:
procedure Timing_Failsafe_Practice;
var
Timer: Integer; // Declare our variable to track time with.
begin
MarkTime(Timer); // Sets a marker for the current time and stores it in "Timer".
repeat
Wait(100);
until((ThisFunction) or (TimeFromMark(Timer) >= 5000));
end;
Hopefully, from reading the above code you can figure out that the loop will keep going until either "ThisFunction" returns true, or our "Timer" has been going for greater than or equal to 5 seconds. Remember that the timing is measured in milliseconds so 1000 = 1 second etc.
Labels
Labels are used to skip from one part of code to another during runtime.
One thing you NEED to know is: Labels can NOT be used to break out of a loop! You will get an error.
There are three steps to using Labels that will be shown in the example below.
Example of using Labels:
SCAR Code:
procedure LabelDemo;
label Marker; //Step 1: Declare our "Marker" (to mark our "jump to" point in code)
begin
DoThis;
if ThisIsTrue then
goto Marker; //Step 2: the "goto" command tells the compiler to skip to where it finds the "Marker".
ThisFunction;
Marker: //Step 3: Set "Marker" (this is where the script will skip to. Notice the ':' When setting a "marker" for a label you will need to follow it with a colon ( : ) instead of a semicolon ( ; )
end;
In this case if the function "ThisIsTrue" returns true, it will skip over "ThisFunction" and continue to run after "Marker".
USEFUL FUNCTIONS WITH LOOPS
Continue;
'Continue;' can be a very useful little function when working with loops. By calling 'Continue;' the script will then skip to the end of the current loop. Many people seem to think it skips to the beginning, but that is false.
For example:
Simba Code:
var
i: Integer;
begin
i := 0;
repeat
Inc(i);
Writeln(IntToStr(i));
if i = 1 then
Continue;
Writeln('i must not be 1');
until(i = 1);
end.
Would output:
Progress Report:
Compiled succesfully in 593 ms.
1
Successfully executed.
Another example would be:
Simba Code:
for i := 0 to High(Objects) do
begin
if FindObject(Objects[i], ...) then //Just for an example
Continue
else begin
WalkHere;
DoThis;
end;
Wait(3000);
Writeln('not found');
end;
In the above example if 'Continue;' is called, it will skip:
Simba Code:
else begin
WalkHere;
DoThis;
end;
Wait(3000);
Writeln('not found');
And that concludes my tutorial on loops. For now, anyways.
If anyone feels I left anything out or would like me to add something please don't hesitate to say so.
Thanks for reading, hope you learned something