SRL Archive - OSR Help

How do you break out of a case loop


VastlySuperior

2012-08-09 03:14:26

Hi

I got a case selection with a few procedure within, I want to break out of this loop within the case selection if a certain condition is true. At the moment I use a if statement between each BeginSomething but that is messy. What better way is there to break out of such a scenario?

Thanks for the help guys.

Case Choice Of
0: Begin
BeginSomething1
BeginSomething2
BeginSomething3
BeginSomething4
BeginSomething5
End;
1: Begin
BeginSomething1
BeginSomething2
BeginSomething3
BeginSomething4
BeginSomething5
End;
End;

Le Jingle

2012-08-09 03:22:22

I'd recommend turning your procedures into functions so if the function meets a desired result, let's say BeginSomething1 becomes true, then you can exit thereafter it's true.
For example;

function BeginSomething1: boolean;
begin
result := false;
writeln('BeginSomething1');
// more structural duties can be here..
result := true; // or if using RS, result := loggedin, as well as sooo many other possibilities..
end;

procedure choose(choice:integer);
begin
Case Choice Of
0: Begin
if BeginSomething1 then // if we reach the true result in BeginSomething1 then we will exit this entire function/procedure
exit;
{...more stuff...}
End;
End;
end;

edit:
also, I think another option could be;

procedure choose(choice:integer);
begin
Case Choice Of
0: Begin
if BeginSomething1 then
exit;
action := 1;
End;
1: Begin
if BeginSomething2 then
exit;
action := 2;
2: //etc..
End;
end;
* @ the edit, least I'm pretty sure that carry's you through cases and will break if the functions are met

riwu

2012-08-09 03:23:41

A case statement is NOT a loop.
If you mean to just stop it half way, just use Exit, but it must be structured in such a way that there will be no more code after the case statement that shd have been executed. (i.e. the case statement should be the last thing in the procedure/function)

eska

2012-08-09 03:26:17

nvm I'm wrong.

riwu

2012-08-09 03:29:46

From: eska
I know that
break; 
gets you out of a loop but I think it also gets you out of any "begin end" except the "begin end" of a function/procedure

Break is specifically for getting out of a loop in which case is not a loop.
eg.

procedure A;
begin
repeat
Action1;
if X then
break; //will break out of the loop and execute Action2
if Y then
Exit; //Will exit the procedure A completely
until(Condition);
Action2;
end;

VastlySuperior

2012-08-09 03:36:53

I know a case selection is not a loop, but the procedures that is called in the case selection is a loop, and I want to break out of that loop if a certain criteria is met. At the moment I`m using what Le jingle has suggested

if BeginSomething1 then // if we reach the true result in   BeginSomething1 then we will exit this entire function/procedure
exit;
{...more stuff...}
End;

But this way becomes ugly and messy, I`m certain there must be an easier way to do it than that. I`m testing to see if I`m lost when walking, when lost a variable is made true, then I must break out of this loop in the Case selection to perform a recovery when I`m lost.

    Case Choice of
0: Begin // mine clay and bank it
Disguise('mine clay and bank it');
WriteLn('Clay Loads = ' + IntToStr(TotalLoads));
If (TotalLoads = LoadsToDo) Then
Begin
FindNormalRandoms;
DepositItems;
Proggy;
LogOut;
TerminateScript;
End else
Begin
If LostMyWay then
Begin
Exit;
End else
Begin
FindNormalRandoms;
DepositItems;
End;
If LostMyWay then
Begin
Exit;
End else
Begin
FindNormalRandoms;
WalkToMine;
End;
If LostMyWay then
Begin
Exit;
End else
Begin
FindNormalRandoms;
MineClay;
End;
If LostMyWay then
Begin
Exit;
End else
Begin
FindNormalRandoms;
BankFromMine;
End;
End;
End;

Above is the actual code which is part of a case selection that is performed.

P1ng

2012-08-09 03:41:38

Can we please see a little bit of your code so that we can ascertain how you are actually looping this, because a case statement itself is not a form of loop.

masterBB

2012-08-09 04:18:04

    Case Choice of
0: Begin // mine clay and bank it
Disguise('mine clay and bank it');
WriteLn('Clay Loads = ' + IntToStr(TotalLoads));
If (TotalLoads = LoadsToDo) Then
Begin
FindNormalRandoms;
DepositItems;
Proggy;
LogOut;
TerminateScript;
End else
Begin
If LostMyWay then
Exit
else
DepositItems;
If LostMyWay then
Exit
else
WalkToMine;
If LostMyWay then
Exit
else
MineClay;
If LostMyWay then
Exit
else
BankFromMine;
End;
End;

If you add FindNormalRandoms to your LostMyWay function.

VastlySuperior

2012-08-09 04:27:44

Maybe my Choice of words is bad.:p

Here is the actual code broken down to its simplest form

    Case Choice of
0: Begin
DepositItems;
WalkToMine;
FindNormalRandoms;
MineClay;
BankFromMine;
End;
1: Begin
DepositItems;
WalkToMine;
FindNormalRandoms;
MineClay;
BankFromMine;
End;
2: Begin
DepositItems;
WalkToMine;
FindNormalRandoms;
MineClay;
BankFromMine;
End;
End;

Maybe the picture will tell more than what I can communicate verbally.

If you want to see the code look here

Le Jingle

2012-08-09 04:35:57

You shouldn't need multiple cases to preform the same things. Since cases aren't specifically loops (unless you make them into a loop), it's easier to go about loops, such as:

for to do

while do

repeat
until()

Here are some examples of loops, taken from the Simba source codes' git;

for..to..do's
https://github.com/MerlijnWajer/Simba/blob/master/Examples/%28Loop%29%20For.simba

repeat until
https://github.com/MerlijnWajer/Simba/blob/master/Examples/%28Loop%29%20Repeat.simba

while..do
https://github.com/MerlijnWajer/Simba/blob/master/Examples/%28Loop%29%20While.simba

VastlySuperior

2012-08-09 04:38:33

That was just an example, I din`t want to edit my whole code to show what I mean. Download the script and look at it. There is 8 options that can be performed.

Select case is necessary.

Case Choice of
0: Begin // mine clay and bank it
Disguise('mine clay and bank it');
WriteLn('Clay Loads = ' + IntToStr(TotalLoads));
FindNormalRandoms;
DepositItems;
FindNormalRandoms;
WalkToMine;
FindNormalRandoms;
MineClay;
FindNormalRandoms;
BankFromMine;
End;
1: Begin // mine clay and soften it then bank it
Disguise('mine clay and soften it then bank it');
FindNormalRandoms;
DepositItems;
FindNormalRandoms;
WalkToMine;
FindNormalRandoms;
MineClay;
FindNormalRandoms;
WalkToWater;
FindNormalRandoms;
SoftenClay;
FindNormalRandoms;
WalkToTheBank;
End;
2: Begin // get soft clay from bank and craft it then bank it
DisGuise('Get Soft Clay From Bank And Craft It Then Bank It');
FindNormalRandoms;
DepositItems;
FindNormalRandoms;
WithdrawItems;
FindNormalRandoms;
WalkPottery;
FindNormalRandoms;
MakePottery(ChoosePottery);
FindNormalRandoms;
BankFromPottery;
End;
3: Begin // get soft clay from bank and craft it and drop it
Disguise('get soft clay from bank and craft it and drop it');
FindNormalRandoms;
DepositItems;
FindNormalRandoms;
WithdrawItems;
FindNormalRandoms;
WalkPottery;
FindNormalRandoms;
MakePottery(ChoosePottery);
FindNormalRandoms;
DropItems;
Proggy;
FindNormalRandoms;
BankFromPottery;
End;
4: Begin // mine clay,soften it,craft it,bank it
Disguise('mine clay,soften it,craft it,bank it');

End;
5: Begin // fire softpots,urns,bowls and bank it
Disguise('fire softpots,urns,bowls and bank it');

End;
6: Begin // fire softpots,urns,bowls and drop it
Disguise('fire softpots,urns,bowls and drop it');

End;
7: Begin // get clay from bank,soften it bank it
Disguise('get clay from bank,soften it bank it');

End;
8: Begin // get soft clay from bank and craft it Fire It then bank it
DisGuise('Get Soft Clay From Bank And Craft It Then Bank It');
FindNormalRandoms;
DepositItems;
FindNormalRandoms;
WithdrawItems;
FindNormalRandoms;
WalkPottery;
FindNormalRandoms;
MakePottery(ChoosePottery);
FindNormalRandoms;
FireOven(ChoosePottery);
FindNormalRandoms;
BankFromPottery;
End;
End;

P1ng

2012-08-09 07:41:57

AFAIK there isn't a way to break out of a loop at each step easily without an if..then statement if each step is different.

while do - checks at the beginning of the loop if the statement is true

repeat until - checks at the end of the loop if the statement is true

for to do - automatically increases the variable so it will break out without you changing the variable.

What I would suggest you do is rather than having your case like this
          DisGuise('Get Soft Clay From Bank And Craft It Then Bank It');
FindNormalRandoms;
DepositItems;
FindNormalRandoms;
WithdrawItems;
FindNormalRandoms;
WalkPottery;
FindNormalRandoms;
MakePottery(ChoosePottery);
FindNormalRandoms;
FireOven(ChoosePottery);
FindNormalRandoms;
BankFromPottery;

At the beginning of each procedure put this
if FindNormalRandoms then
NextPlayer(False);
or something similar and then eliminate each of the FindNormalRandoms from your case statement. That way it checks for randoms at every point and will stop the script/player if it finds a random, but you don't have to put nasty if then statements in your case.

Hope this helps :)

VastlySuperior

2012-08-09 11:09:50

Thanks P1ng, for the suggestion. I already have a FindNormalRandom check in the beginning of each procedure and during the loops, but never used it in that way. It seems FindNormalRandoms does not work in any case so I might just as well exit the script when in a random.

So there is no better way to check if a condition is met In a case selection while it is executing other than using a If statement before each call of a procedure to break out of the loop that is currently executing from the case?

Kyle Undefined

2012-08-09 11:22:26

So you have a case statement, that has "choices" that a user selects, right? Why not call the LostMyWay in the actual walking method? That will keep you from having to call it so often.

superuser

2012-08-09 11:28:17

From: P1ng
for to do - automatically increases the variable so it will break out without you changing the variable.


Also, don't forget downto. :)

for i := 9 downto 0 do begin end;

VastlySuperior

2012-08-09 12:10:28

From: Kyle Undefined
So you have a case statement, that has "choices" that a user selects, right? Why not call the LostMyWay in the actual walking method? That will keep you from having to call it so often.


That is what I did right from the beginning and found that it will just move on to the next procedure after I have made the auto recovery from being lost.I do use it in my walking, but the problem is that it will not break out of the loop in the case selection section, it just continues on to the next procedure, because the main loop for the script is called from within the case selection.

Lets say I am walking to the mine, and I get Lost on the way, I try to recover by then switching to SPS_BlindWalk, but then it really gets wayyyyy lost, Don`t have a clue why, so my last resort to recover is I use a lodestone to teleport and begin the script from the start of that Case selection, but we are already in the loop that gets executed in the case selection, so it just moves on to the next procedure, when I recover I use a Exit to get out of the procedure in which I am lost, so it just moves on to the next procedure, because in the case selection it did not reach the end of the procedure yet.

That`s the reason why I have to check before each new procedure if I`m lost so that I can Exit the Case Selection Procedure.

I think Draynor Village SPS walking is quite bad and outdated. SPS just don`t want to work flawlessly in that area, sometimes it walks without a glitch and then suddenly the path that it just walked correctly it will just freeze and stand there doing nothing, that`s why I created a custom map for draynor, so it don`t do that anymore but now sps clicks so much on the map that it sometimes went way past the destination where it is supposed to be or it runs out of the max of 20 clicks that is allowed in sps walking and then it is lost as well. That areas map sucks or I suck. :D:eek:

Kyle Undefined

2012-08-09 14:21:04

Why not change the linear type into a loop? You can create an array of functions/procedures and execute each one. Before you'd execute, you'd check the Lost method, and if it's not lost, then call the next method. If it is lost, exit out of loop.

VastlySuperior

2012-08-09 15:28:50

From: Kyle Undefined
Why not change the linear type into a loop? You can create an array of functions/procedures and execute each one. Before you'd execute, you'd check the Lost method, and if it's not lost, then call the next method. If it is lost, exit out of loop.


Ok, you will have to explain this better to me or give me directions where I can see samples of what you are talking about. I`m a bit new to all of this and don`t always understand the more complex programming language.

If I understand what you are trying to tell me correctly then I can create an array of all the procedures that I want to call in the case selection,for that specific case and then instead of calling them one by one, I can do lets say an For loop to the length of the array that was created and check the lost boolean value before moving onto the next variable in the array and in that way break out of the loop in a more elegant way?

What type of array will I use here? String, or something else?

Then also I will have to make apologies to everyone else for not understanding what they have been trying to tell me, especially Le Jingle. I just never thought of it as an array to use in a for loop. Tunnel vision is nasty. :duh: :redface:

If I understood you correctly Kyle Undefined.

Basically what you are talking about is this post by Brandon. That is precisely how I should do it?

Thanks Kyle Undefined, you have steered me in the right direction. And thanks to all the other who took the time to try and help me.

Kyle Undefined

2012-08-09 16:17:25

From: VastlySuperior
Ok, you will have to explain this better to me or give me directions where I can see samples of what you are talking about. I`m a bit new to all of this and don`t always understand the more complex programming language.

If I understand what you are trying to tell me correctly then I can create an array of all the procedures that I want to call in the case selection,for that specific case and then instead of calling them one by one, I can do lets say an For loop to the length of the array that was created and check the lost boolean value before moving onto the next variable in the array and in that way break out of the loop in a more elegant way?

What type of array will I use here? String, or something else?

Then also I will have to make apologies to everyone else for not understanding what they have been trying to tell me, especially Le Jingle. I just never thought of it as an array to use in a for loop. Tunnel vision is nasty. :duh: :redface:

If I understood you correctly Kyle Undefined.

Basically what you are talking about is this post by Brandon. That is precisely how I should do it?

Thanks Kyle Undefined, you have steered me in the right direction. And thanks to all the other who took the time to try and help me.


Yes, Brandon's example is exactly what I'm talking about :) Would simplify your problem a lot.

Nebula

2012-08-09 18:10:05

I suggest using a try…except statement. You'd have to purposely make a runtime error. This is easy, just throw SetLength(ATPA, 0) at the beginning of the script and MiddleTPAEx(ATPA[1], x, y) in each procedure wherever you want the script to break out of the case statement.

Then you can just do this:


try
BankFromMine;
DespositStuff;
Dont_even_know_because_the_code_is_too_messy_to_find_actual_procedures;
except
LostMyWay;
end;

This is very ghetto but I think it would work nicely.

omgnomorenames

2012-08-10 01:46:07

Case Choice Of
0: Begin
BeginSomething1
BeginSomething2
BeginSomething3
BeginSomething4
BeginSomething5
End;
1: Begin
BeginSomething1
BeginSomething2
BeginSomething3
BeginSomething4
BeginSomething5
End;
End;
I think I see what your trying to do, if any of these fail then you don't want it to go on to the next procedure. Ex, if BS1 doesn't work don't go on to BS2.

Right Now I am currently drunk so forgive my *hiccup* ghetto fix
(someone probable has a better fix)
Make all procedures boolean functions (ie returns True or False)

begin
if ((((BS1)and BS2)and BS3)andBS4) then begin
BS5
end;
end;
Basic math you do whats in the brackets first so if 1 fails it wont do 2 etc etc.