Difference between revisions of "Prog Section 3"

From Immwiki
Jump to: navigation, search
m
 
Line 275: Line 275:
 
   of if checks.
 
   of if checks.
  
----
+
[[category:Leviticus]]
[[Prog Section 2]] | [[Prog Section 4]] | [http://www.ender.com/~jolinn/avendarbible/wiki.pl?Leviticus Leviticus -- Builder Resources Page]
+

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.