Game¶
Simple fighting game.
Players¶
First we need player in order for our game to work. Each player is just a set of stats, we group and represent them using dictionaries with the attribute names being strings and their values being their respective type ( integers here).
{'health': 50, 'damage': 5}
We create dicts by wrapping key: value
pairs in {}
.
Variables¶
In order to store data somewhere so we can reference and use later we use variables. In this case, we will name our two players in recognisable ways.
Usage¶
player1 = {'health': 50, 'damage': 5}
player2 = {'health': 50, 'damage': 5}
Our players are identical to begin with.
Damage¶
Now we need to make the first operation of our game, dealing damage.
Modules¶
To introduce some level of “randomness”, we use the built-in random module.
Modules are chunks of code that other people have written for our use.
Importing modules can be done with import. In this case, we need its randint function.
from random import randint
Python offers a variety of other built-in modules, we will take look at more of them as we go.
Usage¶
But for now, let’s deal some damage.
minimum = 1
maximum = player1['damage']
damage_dealt = randint(minimum, maximum)
We assign our minimum and maximum (from our player with
the item access []
notation) damage to variables and then pass
those in the randint
function, creating a random integer and then
storing it in the incoming
variable.
To avoid redundancy and be a little bit quicker in our code:
damage_dealt = randint(1, player1['damage'])
Instead of storing our min and max in variables, we pass them directly to the function.
Now, all we have to do is deduce this damage from the other player’s health.
old_health = player2['health']
new_health = old_health - damage_dealt
player2['health'] = new_health
Or, we little bit faster:
player2['health'] = player2['health'] - damage_dealt
EVEN FASTER:
player2['health'] -= damage_dealt
All three ways are equivalent with the only significant difference being less lines of code, making the whole thing more compact. Use whichever you are more comfortable with.
Printing¶
Now we need to show how much damage was dealt and how much health is left.
new_health = player2['health']
message = f'Player 2 took {damage_dealt} damage: {new_health} health left'
print(message)
Aside from normal strings starting and ending with the same type of quotes (single or double), python offers f-strings for quickly formatting/injecting/interpolating data.
In this example, we simply pass our variables in an f-string, storing them in
the message
variable, which we then print to the console using the
built-in print
function.
Repeating¶
All that’s left now is to repeat the exact same process for player2
attacking player1
.
damage_dealt = randint(1, player2['damage'])
player1['health'] -= damage_dealt
print(f'Player 1 took {damage_dealt} damage: {player1["health"]} health left')
We don’t need to re-import the randint
function, this is done once at
the very beginning of our code.
The only notable difference between what we did before and now is printing. Not
only did we pass our string directly in print
, without using a
message
variable, we also messaged player1’s health directly.
In order to differentiate between the start-end string quotes and the
health
string, different quotes had to be used.
Loops¶
So far, our code looks exactly like this:
from random import randint
player1 = {'health': 50, 'damage': 5}
player2 = {'health': 50, 'damage': 5}
damage_dealt = randint(1, player1['damage'])
player2['health'] -= damage_dealt
print(f'Player 2 took {damage_dealt} damage: {player2["health"]} health left')
damage_dealt = randint(1, player2['damage'])
player1['health'] -= damage_dealt
print(f'Player 1 took {damage_dealt} damage: {player1["health"]} health left')
player1 attacks player2, and vice versa and our program exits. Obviously, we
need this to happen multiple times until either of the players falls
to-or-bellow 0
health. Or, in other words, we need our program to loop
back to the beginning while both players are above 0
health.
Conveniently, this can be done with a while loop.
while player1['health'] > 0 and player2['health'] > 0:
damage_dealt = ...
Comparisons¶
Let’s take a look at what’s going on.
player1['health'] > 0
This statement will, unsurprisingly, return
True if player1’s
health is above 0
health, and
False otherwise.
player1['health'] > 0 and player2['health'] > 0
Here we get True
if both players’ health is above 0
, and
False
otherwise.
While¶
Our while loop needs a statement that returns True
or False
next to it. That statement is executed on every iteration, stopping the loop
the moment it evaluates to False
.
while player1['health'] > 0 and player2['health'] > 0:
damage_dealt = randint(1, player1['damage'])
player2['health'] -= damage_dealt
print(f'Player 2 took {damage_dealt} damage: {player2["health"]} health left')
damage_dealt = randint(1, player2['damage'])
player1['health'] -= damage_dealt
print(f'Player 1 took {damage_dealt} damage: {player1["health"]} health left')
Anything that is part of the loop’s execution should be indented inward.
Each player’s health will get decreased on each iteration, until at least one is
not above 0
. The main caveat of this approach the possibility that both
players’ health gets reduced bellow 0
, resulting in a trade-kill.
Break¶
To prevent this from happening, we take a slightly different approach.
while True:
damage_dealt = randint(1, player1['damage'])
player2['health'] -= damage_dealt
print(f'Player 2 took {damage_dealt} damage: {player2["health"]} health left')
if player2['health'] <= 0:
print('Player 1 wins')
break
damage_dealt = randint(1, player2['damage'])
player1['health'] -= damage_dealt
print(f'Player 1 took {damage_dealt} damage: {player1["health"]} health left')
if player1['health'] <= 0:
print('Player 2 wins')
break
We create an infinite loop by giving while
something that always
evaluates to True
. That could be 1 > 0
, 'hg' == 'hg'
, or
simply True
itself.
This allows us sequentially check whether each player’s health is at-or-bellow
0
:
if player2['health'] <= 0:
print('Player 1 wins')
break
If player2['health'] <= 0
returns True
, everything in our
if
clause (indented code) gets executed; printing who won and then
breaking
out of the loop.
Recap¶
And behold our final result.
from random import randint
player1 = {'health': 50, 'damage': 5}
player2 = {'health': 50, 'damage': 5}
while True:
damage_dealt = randint(1, player1['damage'])
player2['health'] -= damage_dealt
print(f'Player 2 took {damage_dealt} damage: {player2["health"]} health left')
if player2['health'] <= 0:
print('Player 1 wins')
break
damage_dealt = randint(1, player2['damage'])
player1['health'] -= damage_dealt
print(f'Player 1 took {damage_dealt} damage: {player1["health"]} health left')
if player1['health'] <= 0:
print('Player 2 wins')
break
Something to consider is that this game is skewed toward player1 since they always strike first ;)