Now that you know how to write conditional statements using if/elif/else
with booleans (see Conditional Statements in Ren’Py) and several basic variable types (see Simple Variable Types in Ren’Py), let’s look into the different things you can compare so that you can write complex branching paths in your game.
There is also a quiz to test your knowledge of comparisons, with additional questions combining the information in this tutorial and the earlier parts on conditionals and simple variables to check your understanding of these concepts.
As this tutorial builds off of information in the previous ones, it’s recommended you take a look at those before tackling this one. This guide also assumes you have a basic idea of how to write choice menus. If you need a quick refresher, you can check out the section on Menus, Labels, and Jumps in the Ren’Py quickstart.
Comparisons
What are Comparisons?
A comparison  is a way of comparing two or more values in a game. Typically at least one of the values you’re comparing is a variable, so you can use the result of this comparison to do things like change dialogue or branch off in an entirely new direction.
Informally, in your program you might want to do things like:
- If the player has at least 8 affection points with Xia, she’ll ask them on a date
- If the player has 10 or more bad end points, they get the bad end. If they have less than 10 bad end points but more than 0, they get the normal end. Otherwise, they get the good end.
- If the player bought Ashwin a digital camera and they’re on a date in the park, show a line of dialogue where they take a picture of the fountain.
- If the player is carrying a life jacket or they made it to the top of the ship in time to get in a life boat, they survive.
- If the player gave Zoran the book Pride & Prejudice and has at least 5 trust points with Zoran, Zoran will share a story from his childhood.
- If the player has enough money, they can buy a flower.
You can see the if/else
-style structure to these sorts of statements like we covered in Conditional Statements in Ren’Py, but the comparisons have more things to check than just one value which is True/False (for example, needing to check more than one value in 3, 4, and 5, or comparing numbers in 1, 2, and 6).
Checking if two values are the same
Sometimes, you might want to check something like “if the player bought Ashwin a digital camera”. If you recall from the last tutorial on simple variables, we had a section of code that looked like:
default gift = None
label start():
"At the mall, you decided you wanted to buy Ashwin something."
menu:
"Buy them a bath bomb.":
$ gift = "bath bomb"
"Buy them a self-help book.":
$ gift = "self-help book"
"Buy them a digital camera.":
$ gift = "digital camera"
"Later that day, you were able to give them the [gift] you bought earlier."
"They liked it a lot."
In this case, gift
is equal to one of “bath bomb”, “self-help book”, or “digital camera”. This isn’t a boolean, so if we want to know specifically if the player bought Ashwin the digital camera, we can’t do if gift:
because that just checks if gift
has some not-false value (this is explained further in the section on Truthy/Falsey values).
So, informally, we want to know: is the value of gift
equal to "digital camera"
?
In Ren’Py (and in most programming languages), the way to check this is with two equals signs like ==
:
if gift == "digital camera":
"Ashwin took out the camera you gave them earlier to take a picture of the fountain."
It’s very important to note that it’s two ==
and not just one =
for comparison. A single =
is only for setting a variable, like with $ gift = "digital camera"
where you are giving the variable gift
a value of “digital camera”. Two ==
let you compare variables, like checking if gift
currently has the value “digital camera”. Comparison does not change the current value of the variable.
As you might recall from the guide to simple variables, you generally should NOT do this kind of exact comparison for floats  aka numbers with decimal points. So while the following code won’t cause an error, it may not perform as you expect:
$ money = 10.00
if money == 10.00: # Bad; floats aren't exact
jump go_to_market
Instead, you’ll use numerical comparisons for floats, described in Numerical Comparisons and Combinations in Ren’Py.
However, it’s fine to use ==
to compare between values like integers and strings, such as:
default num_cookies = 1
label start:
menu:
"Give Zoran a cookie.":
$ num_cookies -= 1
"Don't give Zoran a cookie.":
"You declined to give Zoran a cookie."
if num_cookies == 1:
"You decided to eat a cookie yourself."
else:
"You wished you had something to eat."
or as seen above, if gift == "digital camera":
.
Note that comparing strings is case-sensitive, that is, "digital camera"
is NOT the same as "Digital Camera"
which is NOT the same as "DIGITAL CAMERA"
. Spacing also matters – if you have a stray space at the end of a string, for example, it won’t match a string without that space e.g. "Xia "
is NOT the same as "Xia"
without the extra space. There are string utility functions to help with this, such as strip()
and lower()
, so you can make more accurate comparisons. We’ll talk about those in a later tutorial on strings. For now, just keep in mind that capital letters in your strings are important, as two strings with different capitalizations are not the same.
You typically should not use ==
when comparing with booleans like True
or False
e.g. if ate_apple == True
. For more on that, see the section on “Truthy” versus “Falsey”.
Places where you should use ==
- When comparing against an integer e.g.
if num_game_wins == 2
- When comparing against a string e.g.
if xia_job == "book store"
Places where you shouldn’t use ==
- When comparing against a float e.g.
if grade == 0.9
(Bad! Don’t use exact comparisons with floats, since decimal numbers may have slight rounding errors) - When comparing against a boolean value e.g.
if went_home == True
orif owns_cat == False
(poor style and may not be what you want; see Truthy vs Falsey) - If you’re trying to set a variable (setting uses one
=
e.g.$ xia_job = "doctor"
ordefault ash_gift = "bath bomb"
)
Checking if two values are different
Besides ==
, you might also want to know if two values are not equal. There are two primary ways of checking for this, depending on what kind of value you’re comparing against.
The first way is with !=
, which stands for “not equal”. In many programming languages, !
means “not”, so in this case, !
(not) =
(equal) -> !=
As with ==
, this is a good comparison to use for strings and integers, but not for floats or booleans. So, you could do something like:
default mood = "neutral"
label start():
"Now, at the end of a long day, you were feeling..."
menu:
"Happy":
$ mood = "happy"
"Exhausted":
$ mood = "tired"
"Sad":
$ mood = "sad"
"Just okay":
$ mood = "neutral"
if mood != "happy":
"Ash" "Hey, are you feeling all right?"
"Ash" "I know it was a pretty long day."
If the player isn’t feeling good at the end of the day, Ashwin should check up on them. But there are multiple different “negative” feelings they might have – they might be sad, or maybe just tired or even neutral. Instead of having a check for each possible feeling that leads to this dialogue, we can just check if the player isn’t happy with if mood != "happy"
.
You can use this comparison for integers as well, such as:
default mistakes = 0
default xia_job = "doctor"
label start():
"Xia" "So what's my favourite colour, then?"
menu:
"Yellow.":
pass
"Blue.":
$ mistakes += 1
"Xia" "And my job?"
menu:
"Doctor.":
if xia_job != "doctor":
$ mistakes += 1
"Librarian":
if xia_job != "librarian":
$ mistakes += 1
if mistakes != 0:
"Xia" "Looks like you don't know me as well as you think you do!"
else:
"Xia" "Hmm, probably made the questions too easy..."
We have a few instances of comparisons here. In the choice menu about Xia’s job, we check to see what her job actually is before adding points to the mistakes
variable. If the player says “Doctor” when xia_job
is not "doctor"
, then they answered wrong so the number of mistakes increases, and the same goes for Xia being a librarian.
Then, at the end, if the player made a mistake (so mistakes
is not equal to 0
), Xia tells them they don’t know her as well as they think. Otherwise, she wonders if her questions were too easy.
Another way to write this last conditional statement is:
if mistakes == 0:
"Xia" "Hmm, probably made the questions too easy..."
else:
"Xia" "Looks like you don't know me as well as you think you do!"
As with ==
, the use cases for !=
are very similar:
Places where you should use !=
- When comparing against an integer e.g.
if remaining_cookies != 1
- When comparing against a string e.g.
if ash_gift != "digital camera"
Places where you shouldn’t use !=
- When comparing against a float e.g.
if grade != 1.0
(Bad! Don’t use exact comparisons with floats) - When comparing against a boolean value e.g.
if went_home != True
orif owns_cat != False
(poor style and may not be what you want; see Truthy vs Falsey)
Not
You might remember that when we’ve been using booleans (True/False), to check if they’re True we just do
if thai_restaurant_open:
What if you want to check if it’s False
instead (as in, the restaurant is NOT open)? Luckily, there’s a very special key word called not
which can be used like:
if not thai_restaurant_open:
In more plain language, you can read it like “if the Thai restaurant is not open” or “if the expression “the Thai restaurant is open” is not true”. The expression if not thai_restaurant_open
will evaluate to True if thai_restaurant_open
is False – it’s kind of like a double-negative. If something is not False, then it must be True.
So, you could do something like:
default thai_restaurant_open = False
default pizza_place_open = False
label start:
if thai_restaurant_open:
"You ate some Thai food for dinner."
elif pizza_place_open:
"You ate some pizza for dinner."
else:
"You ate some grilled cheese for dinner."
if not thai_restaurant_open:
"It was too bad the Thai restaurant was closed, though."
"You had definitely been hungry for Thai food."
"Now that you were full, it was time for bed."
The player will see the extra lines of dialogue under if not thai_restaurant_open
only if the Thai restaurant was not open (so, $ thai_restaurant_open = False
somewhere in the script earlier).
Truthy versus Falsey
So this whole time I’ve been saying that it’s better to just write if pizza_place_open
and if not pizza_place_open
when checking boolean values. But a boolean isn’t inexact like a float is, so why is it better not to use ==
, as in, if thai_restaurant_open == True
?
The most important reason is that if went_to_park
and if went_to_park == True
are not the same thing! Explaining why involves two concepts called “Truthy” and “Falsey”.
Hopefully you’re feeling more comfortable now with the idea of True and False, and how to check for them with conditional statements like if not pizza_place_open
and if player_ate_apple
. You’ve also seen several variable types now, like integers, strings, and floats, besides just booleans.
Every variable type has a particular value which is considered “False” if you use it in a conditional statement as if it were a boolean. This is called a “Falsey” value, since it may not be exactly equal to the specific value False
, but it still isn’t “True”. Anything that isn’t “Falsey” is “Truthy” instead, and will evaluate to True in a conditional statement.
- For booleans,
False
is Falsey, andTrue
is Truthy (as you would expect) - For integers, the number
0
is Falsey. Negative numbers like-1
are Truthy, not Falsey.0
is the only number which is Falsey, and everything else is Truthy. - For floats, same thing:
0.0
(or 0 with arbitrary decimal points e.g.0.000000000
) is Falsey. Any other number, no matter how large, small, or negative, is Truthy. - For strings, the empty string (a string with nothing in it, not even a space i.e.
""
or''
) is Falsey. A string with anything in it, one character or many, is Truthy, even if it’s something like"False"
or"0"
because it’s a string which has a word in it so it isn’t empty. - The special value
None
is Falsey.
So what does it even mean if something is “Falsey” or “Truthy”? Well, it explains how those values will be evaluated in a conditional statement like if not x
or if x
.
So, let’s look at the following example:
# Example 1
default gift = ""
label start:
if gift:
"You gave Zoran a [gift]."
else:
"You hadn't bought anything, so you just waved at Zoran."
Here, gift
starts with a default value of ""
, which is the empty string because it doesn’t have anything in it (inside the quotes). We can then check it as if it was a boolean, with if gift:
. This checks if gift
is a “Truthy” value, and in this case because gift
is a string, it checks if the string is empty or not.
The behaviour of the conditional would also be the same if we had done:
# Example 1b (Not as good)
default gift = False
label start:
if gift:
"You gave Zoran a [gift]."
else:
"You hadn't bought anything, so you just waved at Zoran."
However, it’s better practice to do something like default gift = ""
if gift
will later be set to a string like "camera"
. This is because there are many places in coding where the type of the variable matters, particularly if you’re doing any kind of comparisons or calculations with them, and you could get an error or an unexpected result if you tried to compare between, say, a boolean and a string. In fact, in many coding languages other than Python, it’s impossible to mix-and-match variable types – if you declare a variable is a string, you can’t later set it to False
.
Note, however, that the following is NOT the same as Example 1:
# Incorrect 1
default gift = ""
label start:
if gift == True:
"You gave Zoran a [gift]."
else:
"You hadn't bought anything, so you just waved at Zoran."
if gift == True
is specifically checking if gift
is equal to the programming value True
. Similarly, if gift != False
is specifically checking if gift
is not equal to the programming value False
. if gift == True
won’t be true for any string value of gift, not "cake"
or ""
or "True"
(as a string), only True
. We can see this if we substitute the actual value of gift
into the statement – "cake" == True
is False, "True" == True
is False, "" == True
is False, True == True
is True.
If there was a menu earlier to decide on a gift, we can follow the flow of the conditional statement:
default gift = ""
label start:
"You decided to buy Zoran..."
menu:
"A bouquet of daffodils.":
$ gift = "bouquet of daffodils"
"A hand-made apron.":
$ gift = "hand-made apron"
"Nothing.":
$ gift = ""
"Zoran spied you across the marketplace and jogged over."
if gift:
"You gave Zoran a [gift]."
else:
"You hadn't bought anything, so you just waved at Zoran."
Here, if the player buys Zoran a bouquet of daffodils or a hand-made apron, they will see the line where they give Zoran a gift. It doesn’t matter specifically what the gift was in order to show the line – a player who bought a bouquet of daffodils will see “You gave Zoran a bouquet of daffodils” and a player who bought a hand-made apron will see “You gave Zoran a hand-made apron”. Later, because we have the gift’s name stored inside gift
, we can change the dialogue or story based on what specific gift he was given. Meanwhile, a player who didn’t buy a gift will see the line “You hadn’t bought anything, so you just waved at Zoran.”, because gift
is the empty string ""
, which is Falsey, so they see the line under the else
clause.
It’s also very important to remember that == True
and == False
aren’t the same as if x
and if not x
when it comes to checking things like persistent variables, which begin with the default value None
. None
is a “falsey” value, but it is not the exact value False
, which leads to many common errors.
In summary, each variable type can be evaluated as if it were a boolean via if x
or if not x
-style conditional statements. If the variable would evaluate as if it was True, it is “Truthy”. If it would evaluate as if it was False, it is “Falsey”. Comparisons like if x == True
are only correct/True if x
is the exact boolean value True
, but if x
covers a wider range of situations and can be used to both shorten your code and make it more readable. It is considered good coding practice to use if x
and if not x
instead of == True
or == False
, even when working with booleans, and can help prevent unintentional errors.
Summary
Before the quiz, let’s go over the new comparison types we learned and how they’re used in-game:
Comparing if two values are the same
if x == y:
- Note the two
==
(one=
is only for setting a variable; two for comparing) - This is
True
only ifx
andy
have the exact same value - Good for comparing integers and strings
- Not good for comparing floats and booleans
Comparing if two values are different
if x != y:
!
means “not” as in “not equal”!=
- This is
True
for every case unlessx
andy
are the exact same value - Good for comparing integers and strings
- Not good for comparing floats and booleans
not
if not x:
- If
x
is a “truthy” value,if not x
isFalse
- e.g. if x is one of
"hello"
,-45
, orTrue
, thennot x
isFalse
- e.g. if x is one of
- If
x
is a “falsey” value,if not x
isTrue
- e.g. if x is one of
""
,0
, orFalse
, thennot x
isTrue
- e.g. if x is one of
- Can be used for all variable types, but should especially be used for booleans
Next Steps
As usual, there is a quiz to test your knowledge of the topics covered in this tutorial: Equality Comparison Quiz. If you’d like a bit of bonus information on booleans and strings, you can take a look at Booleans vs Strings before moving on to Numerical Comparisons and Combinations in Ren’Py.