This is a “Stencyl For Noobs” guide! This is meant to be a good, concise guide for the beginner or a refresher for the more experienced.
Intermediate Boolean (True/False) Logic
What we’re learning: More complicated decision making; the idea of priority and selecting the right path/decision
The “Not” Block
The “Otherwise” Block
The “Otherwise If” Block
The Unison of the Three
* * * * *
So you can build an elementary if-statement… is that enough? Well… you can get away with some simple decision making, but more complex logic becomes a bear without some advanced methods. So when it comes to logic, we have different terms/tools that can be applied to our code to make our programming endeavors a bit easier.
In this edition of SFN, we are going to talk about the workings of the “Not” block, the “Otherwise” block and then “Otherwise-If” block.
The “Not” Block
Notice how this block is a hexagonal shape? That means its going to evaluate, as stated in the basic Boolean guide, to a “True” or “False”. But wait, why is it asking for a Boolean then? The little hexagonal slot means it wants us to give it a Boolean too.
So in short, put in a Boolean, get a Boolean back.
So understanding that, here’s the kicker: it inverts the result of the evaluated Boolean its fed. If you give it something that evaluates to “True”, it shoots out a “False”. If you give it something that evaluates to “False”, it shoots out a “True”. Simple as that, and the “Not” is very important for higher-level decision-making. So:
Not True = False
Not False = True
CAUTION: Particularly pertaining to mathematical computations, be sure you understand what the true opposite and thus the result of your “Not” block will be. For instance “<” and “>” aren’t actually opposites; “X < Y” and “X > Y” don’t produce totally opposite values for every possible X and Y pair (when X = Y, both would be “False” and therefore not opposites). Instead, “<” and “>=” are opposite; likewise, “>” and “<=” are opposite as well. These kind of distinctions are important, because you want to know very precisely what your “Not” statement is really saying, and recall that even one evaluated answer that is outside your intended logic (one “True” that was meant to be a “False”, for example) can cause you huge problems (and be exceptionally hard to track down).
Using the “Not” block, you can then make “If” code run by supplying a “False”, because the “False” becomes a “True” after passing through the “Not” block. You could check to see if a button is NOT being pressed as opposed to being pressed. That is one use, anyway.
The “Otherwise” Block
Next, let’s talk about the “Otherwise” block, another conditional check with code that can be placed inside of it. It doesn’t check conditions like an “If” statement does, however. Instead, it watches another conditional check like the “If” block and executes based on that.
This is why understanding the “Not” block is important: the “Otherwise” block is essentially a glorified “If Not” block. What you do is you can place this directly after an “If” block, and it will run only if the prior “If” block did not run. So concisely:
If A : Do X
Otherwise (i.e. If Not A): Do Y
Maybe now you are asking why we wouldn’t just use two “If” blocks, where one has the “Not” and the other is regular. There are multiple reasons for this: its easier to read and the “If” and “Otherwise” act together. When the “If” evaluates, it lets the “Otherwise” know whether it should run or not. In that way, you only run one conditional check instead of two checks with an “If” and “If Not”, which is better for performance. Also, we are only discussing it in conjunction with an “If” block. Its importance becomes stronger when we add something like the “Otherwise If” block to our arsenal.
The short answer: its cleaner and easier to understand, especially when you come back to your code two weeks later and have to refresh yourself.
The “Otherwise If” Block
The “Otherwise If” block is a combination of the two. It looks at the previous conditional, but unlike our previously discussed block, it does indeed have its own conditional to check (notice the hexagonal slot). For example:
If <Left is Down> : Move Left
Otherwise If <Right is Down> : Move Right
See how this works? It checks Left to see if we should move left, and if Left is not down, check to see if we should move right instead.
Think about if we had used an “Otherwise” block. Remember that the “Otherwise” is kind of like a “If Not” for the conditional before it. Therefore, we would be saying if Left is not down, move right! No! We move right if Right is down, not if Left is not down.
Again, why not just use two if statements then? The reasons are similar in nature to the “Otherwise” block’s reasoning. However, equipped with all three blocks, we now explore why their cooperation altogether becomes important.
The Unison of All Three
The truth is that all three of these blocks can be and often may need to be used together. Therefore, you need to understand how the blocks come together to make distinct, cohesive sections of logic.
First, three concepts about our blocks:
“If” blocks start a decision-making section, but they can stand alone as a single conditional.
- “Otherwise” blocks always end a decision-making section when used, but are not required.
- “Otherwise If” blocks come after “If” blocks but before “Otherwise” blocks; they are not required either, but unlike the previous two they can be used multiple times in the same section as long as they are between an “If” and “Otherwise”.
So what do I mean by decision-making sections? Observe:
The two if-statements above represent two distinct sections of decision-making logic. They are independent from one another: neither needs to know what happened to the other one to figure out what it should do. They each comprise their own logic or decision-making sections. On that note, any time you use the “If” block, you are starting a new, independent section!
So then, as previously mentioned, “Otherwise” and “Otherwise If” blocks rely on previous conditionals to decide how to run. Putting them down by themselves without any other conditionals does not work. So when you stick one of these after an “If” block, they become part of that section. The “If” evaluates its condition, and then tells the “Otherwise” and “Otherwise If” blocks after it whether they are allowed to run. Conversely, one “If” block will never tell another “If” block that it isn’t allowed to check its condition because, again, they act separately from each other. An “If” block will ALWAYS evaluate its conditional when it is reached in normal code flow!
NOTE: There are ways for an “If” block to pseudo-communicate with another “If” block, but I’m not going to get into that right now. The main point is that it cannot force another “If” block to skip evaluating its conditional when reached in normal code flow.
Next, understand that only one conditional’s code will run PER section. Look at the following:
There are a few things I want you to notice here. First, as I just stated, only one of the interior code sections will run. If the “If” block evaluates to “True”, it shuts out the two remaining blocks because they are in the same section. However, if “False”, the section then moves on to the “Otherwise If” and gives it its chance. If that evaluates to “True”, then the “Otherwise” is skipped. Take note of that: “Otherwise If” blocks can also cancel following “Otherwise If” blocks and “Otherwise” blocks, just like “If” blocks do.
NOTE: Its worth highlighting that since “Otherwise” blocks always come at the end of sections, they never cancel anything.
Finally, notice one more conundrum: what if the “If” block and “Otherwise If” block BOTH have True evaluations? The “If” block wins, because its first on the decision-making ladder. In that way, its important to pay attention to priority and its relation to position. Look at this:
See what we have here? The top “If” always evaluates first and gets first say, followed by each “Otherwise If” moving downward. You can have as many “Otherwise If” blocks following an “If” as you want; it will just keep climbing down until it finds a conditional that is True or it reaches the end.
Also notice that we have no “Otherwise” block in this section. The “Otherwise” block is not necessary to finish; decision-making sections can terminate with an “Otherwise”, “Otherwise If”, or even right after the first “If” block as seen before. In this situation, without an “Otherwise” block, it is then possible that all will evaluate to “False” and no action will be taken for this section. The “Otherwise” block, when used, acts like a “final resort” that executes when all else fails. In the above, we might decide to add an “Otherwise” block with “Last Resort Plan” so that we do something, but understand that a terminating “Otherwise” at the end is not always necessary.
Phew! You still with me? So to kind of sum everything up:
- “If” = May or may not activate
- “If” + “Otherwise” = Guaranteed that one or the other will activate, but not both.
- “If” + “Otherwise If” = One or neither may activate, but not both.
- “If” + “If” = One, neither, or both may activate; each “If” starts their own distinct section of logic and therefore do not affect each other. Each checks their own condition and acts accordingly.
- “If” + (One or Many) “Otherwise If” + “Otherwise” = One of the group is guaranteed to activate, but only one. Priority given to higher blocks, defaulting to the “Otherwise” only if nothing else is triggered.
And that’s that… hopefully I didn’t lose you. Boolean logic can definitely be a beast, but its so imperative to the design of your game. That being said, we’re still not done quite yet. Next time, we’re going to cover things like nested conditionals, the “And” block, the “Or” block, and finally some of the “fine print” of crafting well-tuned decision logic. Meanwhile, hope this helps!