MI Python Text Adventure RPG Tutorial 2 |Add Character and Item Objects

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.

Related posts