Back

Activity 1.5: Making Decisions

divider

The Idea

Conditionals in Lua read almost like English, and there are only three keywords to remember: if, then, and end. There are no parentheses around the condition and no braces anywhere.

main.lua
local charge = 45
if charge >= 80 then
print("READY")
elseif charge >= 40 then
print("CAUTION")
else
print("GROUNDED")
end
Output
CAUTION

Note the spelling: elseif is one word. Writing else if is not an error, but it opens a second if that needs its own end, and the error you get points at the bottom of your file rather than at the real problem.

Comparing things

The comparisons are the usual ones with one difference: "not equal" is ~=, not !=. There is also only one equals-comparison, == — Lua has no === because it never needed one.

main.lua
print(1 == 1.0, "1" == 1, 3 ~= 4)
Output
true false true

Values of different types are never equal, so "1" == 1 is false with no conversion attempted. That is the strictness JavaScript needs === for, and Lua just does it by default.

The rule that catches everyone

Here is the one to tattoo somewhere. Only false and nil are false. Everything else is true.

main.lua
if 0 then print("0 is true") end
if "" then print("empty string is true") end
if not nil then print("nil is false") end
if not false then print("false is false") end
Output
0 is true
empty string is true
nil is false
false is false

Zero is true. An empty string is true. An empty table is true. If you have written Python or JavaScript, both of those treat zero and empty text as false, and code you carry over from them will take the wrong branch without ever producing an error.

It is worth seeing why this is the better design. if score then in Lua asks exactly one question — does a score exist? A player with zero points still has a score. In a language where zero is false, that same line quietly means two different things at once, and you have to write extra code to tell them apart.

and, or, not

The logical operators are words, not symbols. There is no &&, no ||, and no !.

They also do something more interesting than answering true or false. They hand back one of the actual values you gave them.

main.lua
print(nil or "default")
print(false and "never")
print(5 and 10)
print(nil and 10)
Output
default
false
10
nil

Read them as questions about which value survives. a or b gives you a unless a is false or nil, in which case you get b. That is why name or "stranger" is how Lua does default values, and you will use it constantly from Activity 1.7 onward.

Chain them and you get a stand-in for the ternary operator Lua does not have.

main.lua
local hp = 0
print(hp > 0 and "alive" or "down")
Output
down

One warning about that pattern. Because it relies on truthiness, it breaks if the middle value can itself be false or nil — you would fall through to the third value even when the condition was true. Use it for strings and numbers, and write a real if for anything else.

divider

Build

Start a fresh main.lua. You are writing the check a docking bay would run before letting a ship in.


Task 1: Grade the charge level

  • Store a charge percentage, a crew count, and a hull-breach boolean.
  • Report READY at 80 or above, CAUTION at 40 or above, and GROUNDED otherwise.
  • Pick a charge value that lands in the middle branch.
main.lua
-- main.lua - Skynest docking clearance
local charge = 62
local crew = 4
local hullBreach = false
if charge >= 80 then
print("Charge: READY")
elseif charge >= 40 then
print("Charge: CAUTION")
else
print("Charge: GROUNDED")
end
Output
Charge: CAUTION

Task 2: Combine three conditions

  • Clear the ship for docking only if the charge is at least 40, and there are at least 2 crew, and there is no hull breach.
  • Use not for the breach rather than comparing it to false. It reads better and it is what Lua programmers write.
  • Print CLEARED or DENIED.
main.lua
-- main.lua - Skynest docking clearance
local charge = 62
local crew = 4
local hullBreach = false
if charge >= 80 then
print("Charge: READY")
elseif charge >= 40 then
print("Charge: CAUTION")
else
print("Charge: GROUNDED")
end
if charge >= 40 and crew >= 2 and not hullBreach then
print("Docking: CLEARED")
else
print("Docking: DENIED")
end
Output
Charge: CAUTION
Docking: CLEARED

Task 3: Prove the truthiness rule to yourself

  • Add an assignment variable set to nil and a passengers variable set to 0.
  • Test each one directly with if assignment then — no comparison.
  • Predict both results before you run it. One of the two will surprise you if you came from another language, and that surprise is the whole point of the task.
main.lua
-- main.lua - Skynest docking clearance
local charge = 62
local crew = 4
local hullBreach = false
if charge >= 80 then
print("Charge: READY")
elseif charge >= 40 then
print("Charge: CAUTION")
else
print("Charge: GROUNDED")
end
if charge >= 40 and crew >= 2 and not hullBreach then
print("Docking: CLEARED")
else
print("Docking: DENIED")
end
local assignment = nil
local passengers = 0
if assignment then
print("Orders:", assignment)
else
print("Orders: none on file")
end
if passengers then
print("Passengers recorded:", passengers)
end

Challenge (Optional)

  • Replace the CLEARED / DENIED block with a single line using and and or.
  • Add a rule that a ship with zero passengers is still allowed to dock, but one with no passenger record at all is not. This is only expressible because zero and nil are different things.
divider

Check Your Work

Your finished file should produce this.

Output
Charge: CAUTION
Docking: CLEARED
Orders: none on file
Passengers recorded: 0

That last line is the one worth remembering. The passenger count of zero passed the test. Nothing about it looked conditional, and that is exactly how it will bite you later if you forget.