I've been learning Python by doing random projects here and there. My newest project is a simple text roguelike RPG. The player starts with base stats and just has to survive
Players can attack, heal or run. Which for the most part does work, however, I'm trying to display a kill count beside the player name and visible stats(exp and HP). I'm pretty sure my count variable is just misplaced as it resets to 0 after every enemy death. I want this because it SHOULD mimic b_count for boss appearance. My code is as follows:
import random
import math
import time
# Define base character class amd attributes
class Base:
def __init__(self, name, lvl, max_hp, hp, strength, defense, wpn):
self.name = name
self.lvl = lvl
self.max_hp = max_hp
self.hp = hp
self.wpn = wpn
self.strength = strength
self.defense = defense
# Set Player class as subclass of base, add exp and lvlUp attributes.
class Player(Base):
def __init__(self, exp, lvlUp, **kwargs):
super().__init__(**kwargs)
self.exp = exp
self.lvlUp = lvlUp
# Define LevelUp
def LevelUp(self):
while self.exp >= self.lvlUp:
self.lvl = 1
self.exp -= self.exp
self.lvlUp *= 1.125
hp_gain = round(self.max_hp * 0.125)
str_gain = round(self.strength * 0.25)
dfn_gain = round(self.defense * 0.25)
self.max_hp *= 1.125
self.hp == self.max_hp
self.strength = str_gain
self.defense = dfn_gain
print("You leveled up and gained {} Hp, {} Strength, and {} Defense. \n You feel rejuvenated".format(hp_gain, str_gain, dfn_gain))
else:
pass
# Define heal
def heal(self):
gain = random.randrange(4 , math.ceil(self.max_hp * 0.75), 2)
if self.hp gain >= self.max_hp:
max_gain = self.max_hp - self.hp
self.hp = self.max_hp
return max_gain
else:
self.hp = gain
return gain
# Define attack
def attack(self, other):
# Define damage based on strength and wpn
dmg = math.floor(random.uniform(self.strength * self.wpn, (self.strength * self.wpn) * 2) - other.defense)
time.sleep(0.2)
print("You dealt {} damage".format(dmg))
other.hp -= dmg
if other.hp > 0:
print("{} has {} health remaining".format(other.name, other.hp))
# Define exp gain and player heal upon enemy death
else:
new_exp = random.randrange(2, 16, 2)
heal = self.heal()
print(f"You killed {other.name}. You healed {heal} HP and gained {new_exp} Exp")
self.exp = new_exp
self.LevelUp()
print("Level {}: [{}/{}]".format(self.lvl 1, self.exp, self.lvlUp))
# Set Mob class
class Mob(Base):
def __init__(self, *args):
super().__init__(*args)
# Define Mob attack
def attack(self, other):
dmg = math.floor(random.uniform(self.strength * self.wpn, (self.strength * self.wpn) * 2) - other.defense)
if dmg <= 0:
dmg = 0
print("{} dealt {} damage".format(self.name, dmg))
elif dmg >= other.hp:
print("{} dealt {} damage and killed you.".format(self.name, dmg))
other.hp -= dmg
else:
other.hp -= dmg
print("{} dealt {} damage".format(self.name, dmg))
print("You have {} health remaining".format(other.hp))
#Set Boss class
#NOT DONE
class Boss(Base):
def __init__(self, *args):
super().__init__(*args)
# Set Player Name
hero_name = input("Enter your name...")
# Define base hero stats
hero = Player(exp=0, lvlUp=32, name=hero_name, lvl=1, max_hp=64, hp=64, strength=8, defense=4, wpn=1.125)
cmdlist = [
["a", "attack"],
["h", "heal"],
["r", "run"]]
# Set mob list
mobs = [
Mob("Goblin", 1, 16, 16, 4, 2, 1),
Mob("Wolf", 1, 24, 24, 6, 2, 1),
Mob("Imp", 1, 16, 16, 4, 2, 1.125),
Mob("Minotaur", 1, 32, 32, 4, 4, 1.25),
Mob("Bandit", 1, 24, 24, 8, 4, 1.125),
Mob("Succubus", 1, 24, 24, 4, 4, 1.25),
Mob("Gargoyle", 1, 32, 32, 6, 2, 1.25),
Mob("Bear", 1, 48, 48, 6, 4, 1.375),
Mob("Chimera", 1, 48, 48, 6, 4, 1.375),
Mob("Necromancer", 1, 32, 32, 6, 4, 1.5)]
# Set boss list
bosses = [
Boss("Minotaur", 1, 32, 32, 4, 4, 1.25),
Boss("Bandit", 1, 24, 24, 8, 4, 1.125),
Boss("Bear", 1, 48, 48, 6, 4, 1.375),
Boss("Chimera", 1, 48, 48, 6, 4, 1.375),
Boss("Necromancer", 1, 32, 32, 6, 4, 1.5)]
# Define battle sequence and count
def battle(player, enemy):
count = 0
print("A {} charges towards you!".format(enemy.name))
# Allows for attack/run each turn
while player.hp > 0 and enemy.hp > 0:
count = 0
print("[{}] Kills: {}".format(player.name, count))
print("[HP: {}] [Next Level {}: [{}/{}]".format(player.hp, player.lvl 1, player.exp, player.lvlUp))
command = input("(A)ttack, (H)eal or (R)un? \n")
if command.lower() in cmdlist[0]:
player.attack(enemy)
print("---------------------")
time.sleep(.5)
if enemy.hp <= 0:
count = 1
return count
enemy.attack(player)
print("---------------------")
time.sleep(.2)
elif command.lower() in cmdlist[1]:
heal = player.heal()
print("You heal for {} HP".format(heal))
continue
elif command.lower() in cmdlist[2]:
chance = random.randint(1, 20)
if chance in range(11, 21):
print("You got away without a scratch")
break
elif chance in range(1, 10):
dmg = round(random.uniform((enemy.strength * enemy.wpn / 4), (enemy.strength * enemy.wpn) / 2))
player.hp -= dmg
print("You got away, but with minor injuries.[-{} HP] \nYou have {} HP remaining".format(dmg, hero.hp))
time.sleep(0.5)
break
if __name__ == "__main__":
b_count = 0
if b_count < 5:
while hero.hp > 0:
b_count =1
battle(hero, random.choice(mobs))
elif b_count > 5 and b_count % 3 == 0:
if b_count % 3 == 0:
while hero.hp > 0:
b_count =1
print("That one looks bigger")
battle(hero, random.choice(bosses))
else:
while hero.hp > 0:
b_count =1
battle(hero, random.choice(mobs))
CodePudding user response:
Inside the battle
function, you're setting the count
variable at the beginning of the function, but also resetting it in a loop before it gets displayed.
def battle(player, enemy):
count = 0
...
# Allows for attack/run each turn
while player.hp > 0 and enemy.hp > 0:
count = 0 # remove this line
print("[{}] Kills: {}".format(player.name, count))
Removing the marked line will display the kills for that battle (the duration of the loop in the battle
function). If you want to keep track of the payers kills for the entire game, I'd make the count
variable an attribute of the Player
class.
One last note, count
is not the best variable name here. You're keeping track of several different counts in your game, so each one should have a distinct name that tells you at a glance what it refers to. In this case kill_count
would be better.