REPL HERE:
https://pythontextadventuretutorial2.mandrews85.repl.run
Lets refactor our code a bit here. Before our main.py Python file becomes too cumbersome and convoluted. We are going to split all our classes into separate files or “Modules”. We will have one file for the Player, Character, Room and Item. Then import them into our Game class in the main.py Python file.
While we are at it we will add some more attributes to our objects. Player and Character objects will have hit points, strength, dexterity, damage, items list, armors list, and weapons list attributes. For our Room objects we will add an enemies list, npc list, items list, weapons list and armors list. More about these attributes later on. Now on to our Python RPG text adventure.
Player Module:
Lets create our Player.py Python file
First we import random and the items module for later on. Then we define our Player attributes. For the items, weapons and armor we initialize empty lists. Update the Player status method with the new attribute variables to be printed.
For the Player object we add a create method to name and roll our Player. Then a random die roll method.
The create method in our Player class takes the Player user_input method. If the user input is an “N”. A second Player user input call is prompted. The second user input prompt will be the Players name.
If the create methods input is an “R”. We call the Players roll_die method and pass in 100 as the argument for the max integer for randint().
If the Players user input is a “P” the player may move on to the game. If the player name and hp are not None.
The roll_die method takes an integer for the max value of the “die”. The roll variable uses the Python random.randint() method with the “die” passed in as the max value. Then the result is printed concatenated on to the players name as a string with the Python str() method and returned.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 import random
from items import *
class Player():
def __init__(self):
self.name = None
self.pos_x = 0
self.pos_y = 0
self.max_hp = None
self.hp = self.max_hp
self.xp = 0
self.gp = 0
self.st = None
self.dex = None
self.dmg = None
self.items = []
self.weapons = []
self.armors = []
def status(self):
print(self.name)
print(str(self.name) + " POS X: " + str(self.pos_x))
print(str(self.name) + " POS Y: " + str(self.pos_y))
print("HP: " + str(self.hp))
print("STR: " + str(self.st))
print("DEX: " + str(self.dex))
print("DMG: " + str(self.dmg))
for item in self.items:
print(item.name)
for weapon in self.weapons:
print(weapon.name)
for armor in self.armors:
print(armor.name)
def user_input(self):
user_input = input(">>> ").upper()
return user_input
def create(self):
player.status()
print("CREATE YOUR CHARACTER")
print("(N)AME YOUR CHARACTER")
print("(R)OLL YOUR STATS")
print("(P)LAY GAME")
user_input = self.user_input()
if user_input == "N":
print("WHAT IS YOUR NAME")
user_input = self.user_input()
self.name = user_input
self.create()
elif user_input == "R":
print("ROLLING STATS")
print("ROLLING HP")
roll = self.roll_die(20)
self.hp = roll
print("ROLLING STRENGTH")
roll = self.roll_die(100)
self.st = roll
print("ROLLING DEXTERITY")
roll = self.roll_die(100)
self.dex = roll
self.create()
return
elif user_input == "P":
print("PLAY THE GAME")
if self.name == None or self.hp == None:
print("FINISH MAKING YOUR CHARACTER")
self.create()
else:
print(" INVALID CHOOSE AN OPTION N, R, P")
def roll_die(self,die):
roll = random.randint(0,die)
print(self.name + " ROLLS: " + str(roll))
return roll
player = Player()
player.create()
Run the above Player.py file. Our Player creation method lets the user name and roll the players stats. You should see the Player status method being updated.
Item Module:
Here we are initializing our Item class. We give each item a: name, damage value, armor value, gold piece value and weight. We will then instance a few items below. A short_sword, wizards_staff, leather_armor and a gem. For the “weapon” objects damage. We are passing in the randint() method. Note that if we don’t want an item to do damage or have an armor bonus. We just add a 0 integer to the arguments passed in to the instance. Then update the status method to print the new arguments.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 import random
from Item import *
class Item():
def __init__(self,name,dmg_value,ar_value,gp_value,weight):
self.name = name
self.dmg_value = dmg_value
self.ar_value = ar_value
self.gp_value = gp_value
self.weight = weight
def status(self):
print(self.name)
print("DMG VALUE: " + str(self.dmg_value))
print("AR VALUE: " + str(self.ar_value))
print("GP VALUE: " + str(self.gp_value))
print("WEIGHT " + str(self.weight))
### INSTANCE ITEM name,dmg_value,ar_value,gp_value,weight
### WEAPONS
short_sword = Item("SHORT SWORD",random.randint(1,6),0,50,3)
wizards_staff = Item("WIZARDS STAFF",random.randint(1,40),0,400,4)
### ARMORS
leather_armor = Item("LEATHER ARMOR",0,2,80,12)
cloth_robe = Item("CLOTH ROBE",0,1,5,2)
### ITEMS
gem = Item("GEM",0,0,100,.1)
Character Module:
Lets Create our Character.py Python file. The Character class is similar to the Player class except we are not giving any input. Also instead of a create method for the class we are passing in the attributes upon instantiation. Lets also add a dialog argument, so the characters print a string out to the player. Update the Character status() while we are at it to print the new attributes. Then we make an orc_peon instance of our Character class. Lets also pass in the Item objects we created above to the orc peon’s: items, weapons and armors list. Don’t forget to import our Item.py file. We will make the Characters dmg equal to the random dmg_value of the first item in the weapons list. In this case the orc_peon with the short_sword.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 import random
from Item import *
class Character():
def __init__(self,name,pos_x,pos_y,max_hp,st,dex,gp,xp,items,weapons,armors,dialog):
self.name = name
self.pos_x = pos_x
self.pos_y = pos_y
self.max_hp = max_hp
self.hp = self.max_hp
self.st = st
self.dex = dex
self.gp = gp
self.xp = xp
self.items = items
self.weapons = weapons
self.armors = armors
self.dmg = self.weapons[0].dmg_value
self.ar = self.armors[0].ar_value
self.dialog = dialog
def status(self):
print(self.name)
print(str(self.name) + " POS X: " + str(self.pos_x))
print(str(self.name) + " POS Y: " + str(self.pos_y))
print("HP: " + str(self.hp))
print("STR: " + str(self.st))
print("DEX: " + str(self.dex))
print("DMG: " + str(self.dmg))
print("AR: " + str(self.ar))
print("GP: " + str(self.gp))
print("XP: " + str(self.xp))
for item in self.items:
print("ITEMS: ")
print(item.name)
for weapon in self.weapons:
print("WEAPONS: ")
print(weapon.name)
for armor in self.armors:
print("ARMORS: ")
print(armor.name)
def roll_die(self,die):
roll = random.randint(0,die)
print(self.name + " ROLLS: " + str(roll))
return roll
#name,pos_x,pos_y,max_hp,st,dex,gp,xp,items,weapons,armors
orc_peon = Character("ORC PEON",0,0,6,30,60,50,20,[gem],[short_sword],[leather_armor],"DIE DIE DIE")
friendly_wizard = Character("FRIENDLY WIZARD",0,0,6,30,60,50,20,[],[wizards_staff],[cloth_robe]," HELLO ADVENTURER I AM A FRIENDLY WIZARD. I HAVE BROUGHT YOU TO THIS REALITY")
Room Module:
For our Room class import the Character and Item files. Lets add: enemies, items, weapons and armors arguments to the class. When we instance each room we will pass in a list for each. Then add our Character objects to the correct list. Update the status method. Then we instance our rooms.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 from Character import *
from Item import *
class Room():
def __init__(self,name,desc,pos_x,pos_y,npcs,enemies,items,weapons,armors):
self.name = name
self.desc = desc
self.pos_x = pos_x
self.pos_y = pos_y
self.npcs = npcs
self.enemies = enemies
self.items = items
self.weapons = weapons
self.armors = armors
def status(self):
print(self.name)
print(self.desc)
print("ROOM: X: " + str(self.pos_x))
print("ROOM Y: " + str(self.pos_y))
print("YOU SEE:")
for npc in self.npcs:
print(npc.name)
for enemy in self.enemies:
print(enemy.name)
for item in self.items:
print(item.name)
for weapon in self.weapons:
print(weapon)
for armor in self.armors:
print(armor)
### name,desc,pos_x,pos_y,npcs,enemies,items,weapons,armors
start_room = Room("START ROOM","THIS IS THE STARTING ROOM",0,0,[friendly_wizard],[],[],[],[])
peon_room = Room("ORC PEON ROOM","THIS IS THE ORC PEON ROOM",0,1,[],[orc_peon,orc_peon,orc_peon],[],[],[])
gem_room = Room("GEM ROOM","THIS IS THE GEM ROOM",0,-1,[],[],[gem,gem,gem],[],[])
Game Module:
Now lets import and pass in all our objects to our Game class in the main.py Python file. Don’t forget to add the rooms we created to the Game grid rooms list!!!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 from Character import *
from Item import *
from Room import *
from Player import *
class Game():
def __init__(self):
self.name = "GAME"
def status(self):
print(self.name + " IS INSTANTIATED")
def grid(self,player):
rooms = [start_room,peon_room,gem_room]
for room in rooms:
if player.pos_x == room.pos_x and player.pos_y == room.pos_y:
room.status()
def options(self,player):
#player.status()
print("MOVE: (N), (E), (S), (W)")
### PLAYER USER INPUT
user_input = player.user_input()
if user_input == "N":
player.pos_y += 1
elif user_input == "E":
player.pos_x += 1
elif user_input == "S":
player.pos_y -= 1
elif user_input == "W":
player.pos_x -= 1
else:
print("INVALID CHOICE")
return
def main_loop(self,player):
self.status()
player.create()
while True:
self.grid(player)
player.status()
self.options(player)
game = Game()
game.main_loop(player)
Run the game main loop. We now have player creation with a grid based movement system. Characters have inventories and rooms have characters. The player is able to see the status of each room.
Of course this is no fun if we can’t kill some orc peons and take their gems or talk to the friendly wizard. So, next time we will implement a battle system along with inventory management and a dialog system in our MI Python text adventure RPG.