Difference between revisions of "Prog Section 3"
From Immwiki
(One intermediate revision by one other user not shown) | |||
Line 225: | Line 225: | ||
prog add speech_prog p Loopy | prog add speech_prog p Loopy | ||
loop 1 to 3 | loop 1 to 3 | ||
− | + | say The outermost loop is on number $v1. | |
loop 1 to 2 | loop 1 to 2 | ||
− | + | say The second loop check is on number $v2. | |
loop 7 to 8 | loop 7 to 8 | ||
− | + | say The innermost loop check is on number $v3. | |
endloop | endloop | ||
endloop | endloop | ||
− | |||
endloop | endloop | ||
+ | say The loop now, is ended. | ||
So, if you were to say "Loopy" to the hen, you would see the following: | So, if you were to say "Loopy" to the hen, you would see the following: | ||
Line 244: | Line 244: | ||
The hen says, ‘The innermost loop check is on number 7.’ | The hen says, ‘The innermost loop check is on number 7.’ | ||
The hen says, ‘The innermost loop check is on number 8.’ | The hen says, ‘The innermost loop check is on number 8.’ | ||
− | The hen says, ‘The outermost loop | + | The hen says, ‘The outermost loop is on number 2.’ |
The hen says, ‘The second loop check is on number 1.’ | The hen says, ‘The second loop check is on number 1.’ | ||
The hen says, ‘The innermost loop check is on number 7.’ | The hen says, ‘The innermost loop check is on number 7.’ | ||
Line 251: | Line 251: | ||
The hen says, ‘The innermost loop check is on number 7.’ | The hen says, ‘The innermost loop check is on number 7.’ | ||
The hen says, ‘The innermost loop check is on number 8.’ | The hen says, ‘The innermost loop check is on number 8.’ | ||
− | The hen says, ‘The outermost loop | + | The hen says, ‘The outermost loop is on number 3.’ |
The hen says, ‘The second loop check is on number 1.’ | The hen says, ‘The second loop check is on number 1.’ | ||
The hen says, ‘The innermost loop check is on number 7.’ | The hen says, ‘The innermost loop check is on number 7.’ | ||
Line 275: | Line 275: | ||
of if checks. | of if checks. | ||
− | + | [[category:Leviticus]] | |
− | [[ | + |
Revision as of 23:34, 26 April 2011
= Control Structures = "We offered them ORDER!" -- Khan, Star Trek: Episode 24: Space Seed
As we have seen, control structures allow us to alter the normally linear order in which program commands are executed.
If Checks The most common type of control structure is the if check, which tests to see if a certain aspect of the game world is true or false. An if check alters the flow of the program so that if it is true, a block of commands following the check will be executed. If it is false, these commands will not be executed, and execution of the program will skip past them. Every if statement appears before a block of commands, and must always have a matching endif statement, to mark the end of this block of commands. The syntax of an if check is generally:
if check([<argument1>]) <logical operator> <argument2> [block of commands] endif
The check is the actual if check. The check is really a function, which tests an aspect of something in the game world. This can be something as simple as whether or not a target is a pc, or as complex as a person’s percentage in a particular skill or spell. The argument 1 is the pc, mobile, object, number, or other entity which is being checked. Generally, the target is a variable. It can, however, be a number, or the literal name of the pc or npc in question. A check can also have a blank argument, in the case of checks which do not require a target. The logical operator expresses a logical relationship between the argument1 and the argument2 of the if check. The operator can either be numerical (if either side resolves to a number), or a string operator (if either side resolves to a string.)
The following are numerical operators:
== equality != negation of equality (i.e., "is not equal to") < less than <= less than or equal to > greater than >= greater than or equal to & Bitwise and | Bitwise or
The following are string operators:
== Exact equality != Strings do not match / String contains the given text !/ String does not contain the given text
As can be seen, not every logical operator works for every if check. In general, if the result of a check’s evaluation is not numerical, only the first two operators can be used (as these are the only ones which do not require a number to appear to either side.)
The argument2 is an argument which is compared to the result of the check. Generally speaking, this can be a variable that represents a pc, mobile, object, a number, or some other form of data. So, putting this all together, let’s consider a few examples of some if checks.
greet_prog 100 if ispc($n) say Hello, $N. endif say $N just entered the room.
This is a simple program, that will greet a pc if they enter the room, then let everyone know the name of anything that enters a room, even if it’s not a pc. So, in this prog, we can see that: - The check is ‘ispc’ - The argument1 is ‘$n’ - There is no logical operator. - There is no argument2. - The if block is one line: "say Hello, $N". - The endif comes right after that.
Remember, the only required thing for an if check is the if, the check, and the endif.
Now, let’s suppose Jolinn, and his (Charmed) Ethron Love NPC were to enter a room, and this prog is on a hen. (Yes, a hen.) Someone standing in the room would see:
The hen says, ‘Hello, Jolinn’ The hen says, ‘Jolinn just entered the room.’ The hen says, ‘The hawt ethron love slave has just entered the room.’
As we can see, since the ethron love slave is not a pc, the commands in the if block are not executed.
Now, what have if checks really allowed us to do? Basically, we can now say, "If a condition is TRUE, then execute a specified list of commands." But, what if we want to say, "If a condition is TRUE, then execute a specified set of commands. However, if it’s FALSE, execute a different set of commands"? To help us with this scenario, we have the else command. This command allows you to specify alternate set of commands in a body of an if check, to be executed in the event that the check does not return a true result. To see how else works, let’s return to our example.
greet_prog 100 if ispc($n) say Hello, $N. else say I would say hello, $N, but you’re just a mobile. endif say $N just entered the room.
In this case, if Jolinn and his ethron entered the room, they would see:
The hen says, ‘Hello, Jolinn.’ The hen says, ‘Jolinn just entered the room.’ The hen says, ‘I would say hello, a hawt ethron love slave, but you’re just a mobile.’ The hen says, ‘A hawt ethron love slave just entered the room.’
As we can see, the commands after the else statement are executed for the ethron, since the ethron is NOT a pc, and therefore the else block has its triggered.
Now, suppose that we have an effect which we want to occur under multiple conditions. An example might be: A mob who will speak either to an aelin OR a nefortu when given a sum of a gold. Now, we can easily do this by having two (or more) if check blocks in a row, but this requires us to unnecessarily duplicate commands. To this end, we introduce the or statement, which allows us to have an if-block that executes on any of multiple conditions being satisfied. Consider the following example:
speech_prog p Hello if race($n) == aelin or race($n) == nefortu say Why hello to you too, $N. else say Hmph. Whatever, wingless person! You are dead to me! endif
So, if: An aelin said "Hello", they would see: ‘Why hello to you too, aelin.’ A nefortu said "Hello", they would see ‘Why hello to you too, nefortu.’ An ethron said "Hello", they would see ‘Hmph. Whatever, wingless person! You are dead to me!’
So, the or check allows multiple possible conditions to trigger the same if block.
Now, what if we want to execute a block of commands when two (or more) simultaneous conditions hold true at once. For example, suppose we want a mob that attacks a target if it both a pc AND an ethron. Or, suppose we have a sword that requires you be good AND lawful to wield. We can even imagine situations where we might want three, four, five, or even an arbitrary number of conditions to hold true.
To support this functionality, progs support the "nesting" of if check. "Nesting" means that you can put one if check (including its body, else statement, endif) inside of another if check. So, in essence, we would have:
if check1(var) if check2(var) command command command else (optional) command endif else (optional) endif
Essentially, the if block of check2 is a subset of the if block of check1. The commands in check2’s block are only executed if both check1 and check2 are true. To illustrate how this works, let’s consider a concrete example. Suppose that this prog appeared on a hen:
prog add speech_prog p Hello if ispc($n) if race($n) == ethron say Why hello there, $N, you beautiful green thing, you! else say Why hello there, $N. endif else say You’re nothing more than a drone, $N! endif
Let’s suppose we have Jolinn, who is a human, Aeolis, who is an ethron, and a hot ethron love slave, who is an npc who is an ethron.
If... Jolinn says, "Hello", he would see:
The hen says, "Why hello there, Jolinn."
Aeolis says, "Hello", he would see:
The hen says, "Why hello there, Aeolis, you beautiful green thing, you!"
A hawt ethron love slave says, "Hello", she would see:
The hen says, "You’re nothing more than a drone, hawt ethron love slave!"
As we can see, "nesting" results in a block of commands which is executed only if BOTH checks are true. This is perfectly equivalent to the logical AND, "If A AND B are true, then do C".
Loops
Often times, we may wish to repeat a command a certain number of times in a program. Now, clearly, we could do this just by including that number of copies of the command, but this solution leaves certain things to be desired. Firstly, it is inefficient (what if we want to execute a command a hundred times?). Secondly, and most importantly, it does not allow us to execute a command a variable number of times.
Loop Syntax: Loop <low number> to <high number> command_1 command_2 . . command_n endloop
This will execute the commands in the loop (1-n), a number of times equal to high number - low number. In general, low number and high number are both numbers, or variables whose values resolve to being numbers. Just like if checks, you can "nest" loops, by placing one loop block inside of another one.
In a loop, you can reference the "iteration", or number the loop is on, by the $v variable, adjoined to a number. The number represents the "depth" of the loop you are currently in. So, by default, $v1 references the outermost loop’s current iteration. $v2 references the next innermost loop iteration, and so on, until $vn, where n is the innermost loop iteration.
This can be a little confusing, so let’s give a concrete example. Suppose that our favorite counting hen has a prog that reads:
prog add speech_prog p Loopy loop 1 to 3 say The outermost loop is on number $v1. loop 1 to 2 say The second loop check is on number $v2. loop 7 to 8 say The innermost loop check is on number $v3. endloop endloop endloop say The loop now, is ended.
So, if you were to say "Loopy" to the hen, you would see the following:
The hen says, ‘The outermost loop is on number 1.’ The hen says, ‘The second loop check is on number 1.’ The hen says, ‘The innermost loop check is on number 7.’ The hen says, ‘The innermost loop check is on number 8.’ The hen says, ‘The second loop check is on number 2.’ The hen says, ‘The innermost loop check is on number 7.’ The hen says, ‘The innermost loop check is on number 8.’ The hen says, ‘The outermost loop is on number 2.’ The hen says, ‘The second loop check is on number 1.’ The hen says, ‘The innermost loop check is on number 7.’ The hen says, ‘The innermost loop check is on number 8.’ The hen says, ‘The second loop check is on number 2.’ The hen says, ‘The innermost loop check is on number 7.’ The hen says, ‘The innermost loop check is on number 8.’ The hen says, ‘The outermost loop is on number 3.’ The hen says, ‘The second loop check is on number 1.’ The hen says, ‘The innermost loop check is on number 7.’ The hen says, ‘The innermost loop check is on number 8.’ The hen says, ‘The second loop check is on number 2.’ The hen says, ‘The innermost loop check is on number 7.’ The hen says, ‘The innermost loop check is on number 8.’ The hen says, ‘The loop now, is ended.’
As we can see, loops are interpreted from the "outside in". Begin with the outermost loop, then execute its contents. If those contents contain a loop statement, execute that loop. Continue until the innermost loop is reached.
And, as we can see, $v1, $v2, and $v3 are variables which refer to iteration of the corresponding loop.
Break
Finally, it is sometimes necessary to terminate execution of a prog entirely. In this instance, the break command accomplishes this effect. The moment this command is executed, the prog will stop. This is particularly useful for terminating out of certain branches of if checks.