Now that you know how to write conditional statements using if/elif/else
(Conditional Statements in Ren’Py), how to check if strings or integers are the same (Equality Comparisons in Ren’Py), and the concept of truthy/falsey for non-boolean values (Truthy vs Falsey), you’re ready to learn about numerical comparisons and how to check more than one expression at once.
There is also another quiz to test your knowledge of comparisons, with additional questions combining the information in this tutorial and the earlier parts on conditionals to check your understanding of these concepts.
As with the last tutorial, it’s recommended that you first look over Simple Variable Types in Ren’Py. 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.
Numerical Comparison
If you’re dealing with numbers like integers or floats, sometimes you might want to check whether a number is in a particular range, or if it’s over or under a threshold. From the example list in Equality Comparisons in Ren’Py, this includes 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 has enough money, they can buy a flower.
You may already be familiar with symbols like <, >, ≤, ≥. They’re used in math like y > 5
(y is greater than 5) or x ≤ 2
(x is less than or equal to 2), or even 130 ≤ height ≤ 170
(height is between 130 and 170, inclusive of the end points).
Ren’Py uses <
for “less than” and >
for “greater than”, as you’d expect from above. However, in coding, ≤
becomes <=
(less than or equal to) and ≥
becomes >=
(greater than or equal to). Note that the position of the =
is important; =<
and =>
are incorrect and will cause an error. You can think of the order as following how you’d say it – “greater than” (<
) “or equal to” (=
) aka <=
. There’s no need for double ==
here, since it’s accompanied by a >
or <
symbol. You might also remember the “not equal” comparison !=
did something similar – all three additional symbols (!
, <
, >
) come before the =
(i.e. !=
, <=
, >=
).
With this knowledge, you can compare numbers:
default zoran_love_points = 0
label start():
"Zoran shuffles awkwardly, looking down at his feet."
menu:
"Make a joke.":
$ zoran_love_points += 1
"He smiles when you finish telling the joke."
"Tell him to get over himself.":
$ zoran_love_points -= 1
"He looks almost angry at you."
"Then he sighs deeply."
if zoran_love_points >= 1:
"Zoran" "Yeah, maybe I needed that. Thanks."
For this statement, the game checks if the player has 1 or more love points with Zoran through their past choices (if zoran_love_points >= 1
). If they do, then Zoran trusts their opinion enough to not get upset even if the player told him to get over himself.
It’s also fine to use these comparisons for floats, because they’re not checking for exact values but ranges e.g.
# This is 3.0 (float) instead of just 3 (an integer)
# so we can get a float result when we do
# correct_answers/total_answers.
# Ren'Py 8.0+ will do this automatically, but
# Ren'Py 7.x will round the answer down otherwise
define total_answers = 3.0
default correct_answers = 0
default grade = 0.0
label start:
menu:
"What year was Ren'Py first released?"
"2022":
# Wrong! Ren'Py was first released in 2004
pass
"2004":
$ correct_answers += 1
menu:
"Why is it bad to use == to compare floats?"
"Decimals can have rounding errors.":
$ correct_answers += 1
"You shouldn't compare any numbers with ==":
# Wrong! It's fine to compare integers with ==
# but don't use it for floats!
pass
menu:
"Can you put an else clause before an elif?"
"Yes":
# Wrong! The `if` is required, the `elif` clauses are
# optional, and the `else` clause, if included, must go at
# the end as a "catch-all" for the remaining possibilities.
pass
"No":
$ correct_answers += 1
# Divide the # of correct answers by the # of total
# answers to get a number like 0.6666667 for 2/3
$ grade = correct_answers / total_answers
if grade >= 0.7:
"Amazing!"
elif grade > 0.5:
"Not bad!"
elif grade > 0.3:
"Hmm, maybe try again."
else:
"Study up some more next time!"
Here you can see that we have comparisons like if grade >= 0.7
(if grade
is greater than or equal to 0.7) and elif grade > 0.3
(if grade
is strictly greater than 0.3).
Note that this illustrates a very useful feature of if/elif/else
-style conditional statements, which is that only one expression in an if/elif/else
can be True, and the rest will be skipped. You’ve seen this before in some previous examples, but let’s really take a look at this and see how it works now that we’re dealing with number ranges.
More specifically, what this means is that the above conditional statement is the same as:
if grade >= 0.7:
"Amazing!"
elif 0.7 >= grade > 0.5:
"Not bad!"
elif 0.5 > grade > 0.3:
"Hmm, maybe try again."
else:
"Study up some more next time!"
Let’s look at it more closely.
So, first, we check if grade >= 0.7
. If grade
is equal to something like 0.9
, then 0.9 >= 0.7
is True so the player will see the line “Amazing!” and the game will continue with whatever content is after the conditional statement.
However, if grade
is equal to 0.6
, then 0.6 >= 0.7
is False, because 0.6
is not greater than or equal to 0.7
. In this case, we’ll skip the block underneath if grade >= 0.7
and move on to elif grade > 0.5
.
Now we look at this line and compare it – is 0.6 > 0.5
? Yes! 0.6 is greater than 0.5. So this statement is True and the player sees the line “Not bad!”.
This is the same as elif 0.7 >= grade > 0.5
seen above, because we already know that if we’re checking elif grade > 0.5
then the first if
statement, grade >= 0.7
, wasn’t True. If it had been True, then the player would have seen “Amazing!” and the game wouldn’t have bothered to check elif grade > 0.5
. So, since it wasn’t, then the number must be less than 0.7
.
You can also use this to do something like calculate which ending the player should get based on their accumulated good and bad end points:
if bad_end_points > 10:
# The player made more than 10 bad choices
jump super_bad_end
elif good_end_points > 10:
# The player made more than 10 good choices
jump excellent_end
elif bad_end_points > 5:
# The player made 6-10 bad choices
jump bad_end
elif good_end_points > 5:
# The player made 6-10 good choices
jump good_end
else:
# The player didn't get more than 5 good or bad points
jump normal_end
elif bad_end_points > 5
comes after the line if bad_end_points > 10
, so we know that if the game got to the clause elif bad_end_points > 5
, then bad_end_points
is at most 10, because if it was more, then the first expression would have been True and the game wouldn’t be checking this next one. Since elif bad_end_points > 5
is looking for strictly greater than 5, and we know that it can’t be more than 10, then this statement will only be True if bad_end_points
is between 6 and 10, inclusive.
Similarly, the only way the game will get to the else
clause is if the player had 5 or fewer good or bad end points (so, 0-5), since if they had more than 10 one of the first two expressions would have been True, and if they had more than 5 the third or fourth expressions would have been True. Since we got to the else
clause, that means that none of the previous expressions were True, so the player has between 0-5 good end points and 0-5 bad end points.
Note on Strings
Besides just numbers, you can actually use <=
, >
etc with strings! In the case of strings, it compares them alphabetically, with a few notable caveats. This is, however, used very infrequently. You can read more on this in String Comparisons in Ren’Py.
This kind of comparison is very uncommon for most games, and it won’t be included in the quiz on numerical comparisons after this tutorial.
Combining more than one comparison
Now that you can directly compare values with ==
and !=
, and compare numbers with <
, >
, <=
and >=
, let’s look at combining comparisons. Remember earlier we had some statements like:
- 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.
Note the language used to describe these comparisons – “or” and “and” are actually Python concepts you can use directly! We’ll start with using them for booleans (True/False), since that’s the simplest to understand, and in the next part you’ll see how to combine them with all the previous things you’ve learned to create complex conditional statements.
and
Consider the following statement:
If the player went to the park and they own a dog, then we know that they took their dog to the park. The dialogue should reflect this.
So, say you have two booleans, went_to_park = True
and owns_dog = True
.
If you want to check that both of them are True, you can do:
if went_to_park and owns_dog:
"Your dog was sleeping in the corner of the room, tired after your walk in the park earlier that day."
If either or both of went_to_park
or owns_dog
is False, then this statement won’t play. Let’s construct a more elaborate example, with some elif
and else
clauses to see what happens:
if went_to_park and owns_dog:
"Your dog was sleeping in the corner of the room, tired after your walk in the park earlier that day."
elif went_to_park:
"You sat down on the couch, tired after your walk in the park earlier that day."
elif owns_dog:
"Your dog seemed restless after being inside all day while you went to the movies."
else:
"You sat down on the couch, still thinking about the movie you'd seen earlier."
So, let’s break it down.
- Case 1 – the player has gone to the park and owns a dog
- Both
went_to_park
andowns_dog
are True, so the conditionif went_to_park and owns_dog
is also True. - This means that the player sees the line “Your dog was sleeping in the corner of the room, tired after your walk in the park earlier that day.”
- Both
- Case 2 – the player has gone to the park, but doesn’t own a dog
went_to_park
is True, butowns_dog
is False. This means thatif went_to_park and owns_dog
isFalse
, because the player doesn’t own a dog.- The next expression,
elif went_to_park
, is True, because the player did go to the park. So they see the line “You sat down on the couch, tired after your walk in the park earlier that day.”
- Case 3 – the player owns a dog, but didn’t go to the park
owns_dog
is True, butwent_to_park
is False, soif went_to_park and owns_dog
is False because the player didn’t go to the park- Next,
elif went_to_park
is False, because the player didn’t go to the park. - Next,
elif owns_dog
is True – the player does own a dog. So they see the line “Your dog seemed restless after being inside all day while you went to the movies.”
- Case 4 – the player didn’t go to the park, and they don’t own a dog
went_to_park
is False andowns_dog
is False, soif went_to_park and owns_dog
is False, because the player neither went to the park nor owns a dogelif went_to_park
is False, because the player didn’t go to the parkelif owns_dog
is False, because the player doesn’t own a dogelse
then must execute, since everything before it was False. So the player sees the line “You sat down on the couch, still thinking about the movie you’d seen earlier.”
Basically, for and
, both operands on either side of the and
operator  need to be True in order for the whole statement to be True. It’s not enough for the player to have just gone to the park, or just to own a dog – they must both own a dog and have gone to the park for the first if went_to_park and owns_dog
expression to evaluate to True.
operator – special symbols or words that indicate some kind of computation should take place. You’ve seen operators in math before; they include things like +
, -
, and /
. Those math operators exist in programming languages, as well as a few other ones such as and
, as you’ve seen here, and or
, as you’ll see in the next section. Equality comparisons like ==
and !=
that you saw in Equality Comparisons in Ren’Py are also called operators.
operand – what we call the values the operator acts on. For example, in the expression 2 + 4
, 2
and 4
are the operands, which are acted on by the operator +
. The operator, in this case, adds the two operands together and the result is the number 6
(2 + 4 = 6
).
or
or
is similar to and
, but less strict – only one of the operands on either side of the or
operator has to be True (or both). Consider the following:
If the player helped Ashwin with their groceries or mowed their lawn, then they’ll mention how the player helped them out and agree to return the favour.
if helped_ash_groceries or mowed_ash_lawn:
"Ash" "I guess you did help me out earlier today..."
"Ash" "So I can spare some time to help you, too."
jump moving_day_ash
else:
"Ash" "No, sorry, I'm just too busy."
"Ash" "Maybe you can ask Xia or Zoran."
jump no_help
Let’s look at what happens for the different combinations of helped_ash_groceries
and mowed_ash_lawn
:
- Case 1 – the player both mowed Ashwin’s lawn and also helped them with groceries
mowed_ash_lawn
is True andhelped_ash_groceries
is True. We only needed one or the other to be True, but it’s fine that they’re both True – Ashwin will agree to help and the player will jump tomoving_day_ash
- Case 2 – the player mowed Ashwin’s lawn but didn’t help them with groceries
mowed_ash_lawn
is True, buthelped_ash_groceries
is False. However, we only need one of the two to be True, since we’re usingor
. So, Ashwin will agree to help the player and they’ll jump to themoving_day_ash
label
- Case 3 – the player didn’t mow Ashwin’s lawn, but they did help them with groceries
mowed_ash_lawn
is False, buthelped_ash_groceries
is True. Again, we just need one of the two to be True, so Ashwin will agree to help and the player will jump tomoving_day_ash
- Case 4 – the player did not mow Ashwin’s lawn and didn’t help them with their groceries
mowed_ash_lawn
is False andhelped_ash_groceries
is False. Neither of the two operands is True, so the whole thing is False. Ashwin says they are too busy and the player goes to theno_help
label
and
and or
in Practice
Note that you can use as many and
and or
operators in a conditional statement as you like to connect many operands. The outcome of evaluating such an expression will depend on which of and
or or
you’re using, as well as the value (True/False) of each operand.
and
:
if True and True:
# True
if True and False:
# False
if False and True:
# False
if False and False:
# False
if True and True and True and True:
# True only if *all* operands are True
if True and False and False and False:
# False; all operands must be True
or
:
if True or True:
# True
if True or False:
# True
if False or True:
# True
if False or False:
# False
if True or True or True or True:
# True
if True or False or False or False:
# True; at least one True makes the whole condition True
Summary
In this tutorial, you learned about the operators <
, >
, <=
, >=
for numerical comparison, and about the operators and
and or
for combining multiple expressions into a single conditional statement. and
requires that all its operands evaluate to True
, while or
only needs one of its operands to be True
in order for the whole expression to evaluate to True
.
Next Steps
As per usual, there is a quiz on numerical comparisons and combinations that you can use to test your knowledge: Numerical Comparisons and Combinations Quiz. If you’d like some extra information on using operators like >
and <
for strings, check out String Comparisons in Ren’Py, which comes with a very short quiz on the topic. When you’re ready to move on, check out Combining Comparisons in Ren’Py.
Hey, I just found this website and it’s super useful! It makes me want to mess around and have fun with Renpy. Thank you for explaining stuff so clearly.