Prog Section 3
From Immwiki
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.