But what happens if the cat is in a bad mood? It wouldn't purr, instead it might scratch the person or something. To do this we have the 'if ... endif' construction in MOO. We need to give the code something to test whether it is true or not, this looks like:
... code to do when the test is true ...
... code to do when the test is false ...
First we need to know what is considered 'true' and what is 'false'. We'll run through each type of value in turn.
The easiest test is whether something is the same as something else. For example 1 is the same as 1, but not the same as 2. Trivial. To do this we have the '==' operator. This checks whether the thing on the left hand side of it is the same as the thing on the right of it. If it's the same, it resolves as 1 (thus true). If it's not then it resolves as 0 (thus false).
3 == 3 resolves as 1 while
"a string" == "a different string" resolves to 0 as the strings are different.
A trap exists here however. == doesn't care about upper and lower case in strings. so
"A" == "a" would be true - resolving to 1.
More traps for the unwary - you can't compare two different types of value.
"A" == 1 wouldn't return 1 or 0, it'd be
E_TYPE - the error saying that you're mixing up different types.
Another similar operator to '==' (equal to) is the inequality tester - '!=' (not equal to). This returns 1 if the two values that it is comparing are different. So
1 != 2 is true because 1 is not equal to 2.
To make the cat occasionally in a bad mood then, we can create a random number using the 'random()' built in function, and compare it to another number. If it's the same, then we can do one thing, if not we can do something else.
The last line of the stroke code, then could be replaced with the following:
rand = random(5);
if (rand == 1)
player.location:announce_all(this:titlec(), " hisses and scratches at ", player:title(), ".");
player.location:announce_all(this:titlec(), " purrs happily.");
The first line uses the random() function to generate a random number between 1 and 5, and assigns that to the variable 'rand'. Then in the second line, we compare the value in rand with 1 to see if they are the same. If they are the third line is executed and the cat hisses and scratches. Otherwise (the else on line 4) the fifth line is used and the cat purrs normally. To say that we've finished the code after the 'else', line 6 is 'endif' to end the if block of code.
You'll note that if, else and endif don't have semicolons at the end of the lines, but it still compiles. Not all lines need a semicolon at the end, particularly those that start or end a block of code, such as 'if', 'else' and 'endif' in this case. Giving a semicolon after them won't make it break however, so if you're not sure, put one in.
'elseif' is another part of this construction. It is extremely useful if there is more than two different possibilities that you want to test for. You can read
elseif as 'otherwise if it is true that'.
... test1 code ...
... test2 code ...
... all other cases code ...
So, if we wanted to have another random reaction on a 2, we could add before the 'else' line:
elseif (rand == 2)
player.location:announce_all(this:titlec(), " looks unimpressed at the stroking and stalks away.");
So, if rand is equal to 1, do the hiss message, otherwise if rand is equal to 2, do the stalk message, otherwise do the purr message.
While we're talking about if, there's another useful construction that's very similar. It does the same thing as if and else - test something for true or false, and then do or return something depending on this result - but can be written into the middle of a line, rather than taking up 3 lines just for the if, else and endif.
The syntax is:
test ? code if true | code if false;
Using it for something like our little cat's messages would be clumsy. But it is useful in cases such as setting a property with a different value depending on the test's outcome for example. Consider:
if (rand == 1)
this.description = "first description";
this.description = "second description";
Compare this to the much neater:
this.description = (rand == 1) ? "first description" | "second description";
Both these little code snippets accomplish the same thing.
If you can't think of anytime you'd use this other construction, don't worry about it, so long as the if, else, endif construction makes sense, you're doing fine.