Accessing Class variable via function variable - python

I'm playing with Python 3 and putting together an RPG-style system, but am struggling with OOP as I've not really used it in python before.
I'm specifically struggling with the following function:
def choosestat(statname, max, min):
# Takes the name of the stat
# as mentioned in the Player/Character class and
# a min/max value for the length. Allows the player
# to set their stats for the char.
print("Your stat choices are: " + str(stats))
choice = int(input("Please select a strength score ("+min+":"+max+")\n"))
if type(choice) == int and choice < (max+1) and choice > (min-1):
self.statname = stats[choice-1]
stats.pop(choice-1)
else:
print("Please select a valid option.\n")
This should be pulling from the below, to set playerchar.strength to the selected amount:
class Character(object):
# A Class for ALL characters - player, enemy etc.
def __init__(self, name, hp, armor, damage, strength,
intelligence, wisdom, dexterity, constitution, charisma,
inventory, profession):
self.name = name
self.hp = hp
self.armor = armor
self.damage = damage
self.strength = strength
self.intelligence = intelligence
self.wisdom = wisdom
self.dexterity = dexterity
self.constitution = constitution
self.charisma = charisma
self.inventory = inventory
self.profession = profession
class Player(Character):
# A class for the Player character only.
# We will use a few parameters to set initial variables
def __init__(self):
super().__init__(name="", hp=10, armor=10, damage=10, strength=7,
intelligence=7, wisdom=7, dexterity=7, constitution=7,
charisma=7, inventory=[], profession="")
maxhp = 10
level = 1
exp = 0
However, when I run the code, I simply get:
Traceback (most recent call last):
File "main.py", line 122, in <module>
menu()
File "main.py", line 53, in menu
gameloop()
File "main.py", line 73, in gameloop
statchoice()
File "main.py", line 108, in statchoice
choosestat(strength, 6, 1)
NameError: name 'strength' is not defined
The full code is here:
import os
import random
import time
from utilities import roll
class Character(object):
# A Class for ALL characters - player, enemy etc.
def __init__(self, name, hp, armor, damage, strength,
intelligence, wisdom, dexterity, constitution, charisma,
inventory, profession):
self.name = name
self.hp = hp
self.armor = armor
self.damage = damage
self.strength = strength
self.intelligence = intelligence
self.wisdom = wisdom
self.dexterity = dexterity
self.constitution = constitution
self.charisma = charisma
self.inventory = inventory
self.profession = profession
class Player(Character):
# A class for the Player character only.
# We will use a few parameters to set initial variables
def __init__(self):
super().__init__(name="", hp=10, armor=10, damage=10, strength=7,
intelligence=7, wisdom=7, dexterity=7, constitution=7,
charisma=7, inventory=[], profession="")
maxhp = 10
level = 1
exp = 0
class Enemy(Character):
# a class for any enemy.
def __init__(self):
super().__init__(name=enemyname, hp=10, armor=10, damage=10,
strength=7, intelligence=7, wisdom=7, dexterity=7,
constitution=7, charisma=7, inventory=[],
profession="")
playerchar = Player()
# simply call playerchar rather than calling the Class each time
def menu():
# Running the Main Menu under a single Function.
# This is the simplest method of running the menu
while True:
print("|==================|")
print("Welcome to Py RPG!")
print("Please select an option!")
print("1. Start a Game\n")
print("2. Settings\n")
print("3. Quit")
choice = input("\n>")
if choice == 1 or choice == "start":
gameloop()
elif choice == 2 or choice == "settings":
settings()
elif choice == 3 or choice == "quit":
break
else:
print("Please select an option from the menu.")
def settings():
# Settings page for all amendments
# TODO - create a 'settings' file and have this read/amend it?
print("Nothing exists here at the moment!")
menu()
def gameloop():
# the main game loop, contains all calls to relevant functions
while True:
print("This is the main game")
print("Let's begin. What is your name?")
playerchar.name = input(">")
print("Well then, " + playerchar.name + ", let us begin.")
statchoice()
def choosestat(statname, max, min):
# Takes the name of the stat
# as mentioned in the Player/Character class and
# a min/max value for the length. Allows the player
# to set their stats for the char.
print("Your stat choices are: " + str(stats))
choice = int(input("Please select a strength score ("+min+":"+max+")\n"))
if type(choice) == int and choice < (max+1) and choice > (min-1):
self.statname = stats[choice-1]
stats.pop(choice-1)
else:
print("Please select a valid option.\n")
def displaystats(entity):
# quick function to display all relevant stats in-line.
print("Are you happy with your choices?\n")
print("Strength: " + str(entity.strength))
print("Intelligence: " + str(entity.intelligence))
print("Wisdom: " + str(entity.wisdom))
print("Dexterity: " + str(entity.dexterity))
print("Constitution: " + str(entity.constitution))
print("Charisma: " + str(entity.charisma))
def statchoice():
# Using the roll function, we get 6 ability scores, append them to 'stats',
# and run the choosestat function for each to set stats.
stats = []
stats.append(roll(4, 6))
stats.append(roll(4, 6))
stats.append(roll(4, 6))
stats.append(roll(4, 6))
stats.append(roll(4, 6))
stats.append(roll(4, 6))
choosestat(strength, 6, 1)
choosestat(intelligence, 5, 1)
choosestat(wisdom, 4, 1)
choosestat(dexterity, 3, 1)
choosestat(constitution, 2, 1)
choosestat(charisma, 1, 1)
displaystats(playerchar)
reroll = input("Do you wish to re-roll?")
if reroll == "yes" or reroll == "y":
statchoice()
menu()

You can use setattr().
choosestat('strength', 6, 1)
def choosestat(statname, max, min):
print("Your stat choices are: " + str(stats))
choice = int(input("Please select a strength score ("+min+":"+max+")\n"))
if type(choice) == int and choice < (max+1) and choice > (min-1):
setattr(self, statname, stats[choice-1]
stats.pop(choice-1)
else:
print("Please select a valid option.\n")
It's important to pass a string of the field name you want to change to setattr() or in this case through choosestat().

You want your choosestat function inside your class if you are calling self.*something*. Right now it's not. If you move that inside your Character class and add the self argument to it. Then you can access members of that class. Right now in statchoice, strength is not defined. You could try passing in a string "strength" and having a dict inside of choosestat (a member of Character) that maps the strings to their member counter parts:
{"strength" : self.strength, "intelligence" : self.intelligence} and so forth. Also, I don't think that your stats array is global, so you'll either have to make it global or somehow a member of the class and rework some of your other functions, too.

Related

The python program is giving no result

I am trying to code a card game in python using OOP.
the user should select either red( hearts and diamonds)
or black( clubs and spades)
the user then goes on with the game.
here is the code:
import random
class Card:
def __init__(self, name, suit):
self.name = name
self.suit = suit
def print_card(self):
print(self.name + ' of ' + self.suit)
def show(self):
print('{} of {}'.format(self.suit, self.name))
class Deck:
def __init__(self):
self.cards = []
self.build()
def build(self):
for s in ['Hearts', 'diamonds', 'Clubs', 'Spades']:
for v in range(1, 14):
self.cards.append(Card(s, v))
def shuffle(self):
random.shuffle(self.cards)
def show(self):
for c in self.cards:
c.show()
class Game:
def __init__(self, player, score):
self.player = player
self.score = score
self.cards = []
self.hand = []
def shuffle(self):
random.shuffle(self.cards)
def drawCard(self):
return self.cards.pop()
def draw(self, deck):
self.hand.append(deck.drawCard())
return self
def showHand(self):
for card in self.hand:
card.show()
def reset(self):
pass
print('Welcome message')
user = input("Please enter your name: ")
print('While you start your score is 1000')
team = input((' RED or BLACK \n Your team : '))
while True:
if team == 'red':
print('Great, You have chosen Team Red, hearts and diamonds will fetch you points, clubs and sp')
print("")
playGame = input(('Press ENTER to play'))
print('Game starts')
shuffleCard = input(('Press ENTER to shuffle and Pick your card'))
deck = Deck()
deck.shuffle()
print('That was a good mix')
showCard = input(('Press ENTER to reveal your card'))
user = Game(user, 1000)
user.showHand --> here i am expecting the final card to show up but its not happening
the terminal gives this error:
Traceback (most recent call last):
File "/Users/yoshithkotla/PycharmProjects/pythonFinalProject001/main.py", line 71, in <module>
player = player()
TypeError: 'str' object is not callable
Details of the problem : Using the OOP topics and programs we examined in our Lecture Notes 8 and 9 develop a Python
program to implement a card game.
 You select the card game.
o You can invent your own simple card game; just provide the instructions for your card
game as comments in your Python program.
 In our Lecture Notes 9, we will be developing OOP Python code for the fundamentals of a card
game. Use this code in your implementation of your card game. Add additional OOP code for your
specific card game.
Changes made:-
player=player() -> player=game()
Code:-
class game:
def __init__(self, player, score):
self.player = player
self.score = score
def start_game(self, player, score, team):
self.score = score
self.player = player
self.team = team
print("Welcome")
player = input("Please enter your name: ")
print('While you start your score is 1000')
team = input((' RED or BLACK \n Your team : '))
while team == 'red':
print('Great, You have chosen Team Red, hearts and diamonds will fetch you points, clubs and sp')
print("")
playGame = input(('Press ENTER to play'))
print('game starts')
shuffleCard = input(('Press ENTER to shuffle and Pick your card'))
deck = Deck()
deck.shuffle()
print(' that was a good mix')
showCard = input(('Press ENTER to reveal your card'))
player = game()
player.draw(deck)
player.showHand
break
Output:-
Welcome
Please enter your name: Yash
While you start your score is 1000
RED or BLACK
Your team : red
Great, You have chosen Team Red, hearts and diamonds will fetch you points, clubs and sp
Press ENTER to play
Updated query:-
I think you should go with the process to learn all the conditions for the game than start your code.. for reference you should follow this -> click here to know all the conditions for the game and then try to code..!
In the line player = player() you are trying to call a function named 'player' by adding brackets. Player is not a function but a string variable where you store the entered name of a player, so you cannot call it.
Try to erase the brackets or delete line completely (since you've already assigned the variable in line player = input("Please enter your name: ")).

How to take away health points when using a class?

I'm working on a game in python and I can't figure out how to take away health once attack function has taken place. I can run the program and the attack function works fine, it shows a random integer between 1 and 50 but doesn't actually take away health from castlehealth = 100
Underneath print("You attacked for " + str(self.attack)) I left the next line blank because I don't know what to type in, I tried a lot of different things and just can't get the attack to take away from castlehealth.
Here is my code:
import os
import time
from random import randint
class GameActions:
def __init__(self):
castlehealth = 100
self.castlehealth = castlehealth
def health(self):
print("Castle health is: " + str(self.castlehealth))
print()
def attack(self):
attack = randint(0, 50)
self.attack = attack
print("You attacked for " + str(self.attack))
def game():
while True:
game_actions = GameActions()
print("What do you want to do?")
print()
print("attack, view hp")
ans = input()
if ans == "hp":
game_actions.health()
if ans == "attack":
game_actions.attack()
You want the following:
self.castlehealth -= attack
Try something like self.castlehealth -= attack. I also fixed some potential indentation issues for you.
Your full code sample could look this this:
import os
import time
from random import randint
class GameActions:
def __init__(self):
castlehealth = 100
self.castlehealth = castlehealth
def health(self):
print("Castle health is: " + str(self.castlehealth))
print()
def attack(self):
attack = randint(0, 50)
self.attack = attack
print("You attacked for " + str(self.attack))
self.castlehealth -= attack
def game():
while True:
game_actions = GameActions()
print("What do you want to do?")
print()
print("attack, view hp")
ans = input()
if ans == "hp":
game_actions.health()
if ans == "attack":
game_actions.attack()
Explanation: self.castlehealth is an instance variable of your GameActions class. The function GameActions.attack() creates a new attack variable as a random integer and then subtracts that value from the instance variable self.castlehealth of the GameActions class. Now self.castlehealth will be the updated value. Consider also tracking the various attacks and resulting healths in a data structure, since every time you have a new attack self.castlehealth and self.attack will change values and you will lose the ability to access the previous values.

Updating properties of an object in Python OOP

I am trying to create a simple game in Python using the OOP style.
The parent class is set up and there are two sub-classes, one for the hero and one for the ork.
Basically, when the hero attacks the ork (or vice versa) I want the health to be updated based on the damage done (damage is the amount of power the attacking character has). Currently, every time it loops it resets the health values back to the original of 100.
What is the best way of doing this using OOP? I can figure out how to do it in my own procedural and messy way, but I would like to see how it should be done.
class Character:
'''Blueprint for game characters'''
def __init__(self):
#default values
self.character = ""
self.speed = 0
self.power = 0
self.health = 100
def attack(self, attackObj):
self.attacker = self.character
self.attackerPower = self.power
self.victim = attackObj.character
self.victimHealth = attackObj.health
self.newHealth = self.victimHealth - self.attackerPower
print(self.character, "you have chosen to attack", self.victim)
print(self.victim, "you have suffered", self.attackerPower, "damage and your health is now", self.newHealth)
class Hero(Character):
'''Inherits from character to create hero'''
def __init__(self):
Character.__init__(self)
self.character = "Hero"
self.speed = 8
self.power = 9
print(self.character, "you have",self.speed, "speed,", self.power, "power and", self.health, "health.")
class Ork(Character):
'''Inherits from character to create ork'''
def __init__(self):
Character.__init__(self)
self.character = "Ork"
self.speed = 2
self.power = 8
print(self.character, "you have",self.speed, "speed,", self.power, "power and", self.health, "health.")
def main():
charclass = Character()
hero = Hero()
ork = Ork()
endLoop = False
while endLoop == False:
print("Please choose your character by typing the corresponding key: ")
print("H for hero")
print("O for ork")
charChoice = input()
if charChoice in ("H", "h", "hero", "Hero"):
charChoice = hero
enemy = ork
hero = Hero()
elif charChoice in ("O", "o", "ork", "Ork"):
charChoice = ork
enemy = hero
print("Please choose an action by typing the corresponding key: ")
print("A to attack")
actionChoice = input()
if actionChoice in ("A", "a"):
charChoice.attack(enemy)
else:
print("Nothing chosen!")
finishedYN = input("Have you finished? Y/N ")
if finishedYN in ("Y", "y", "Yes", "yes", "YES"):
print("You have chosen to end the game...")
endloop = True
break
else:
pass
if __name__ == "__main__":
main()
A quick fix to your code. Remove all these unecessary attributes, e.g. self.attacker (that's just self), self.attackPower (that's just self.power). self.victim = attackObj.character just gives your object a new attribute that is the same string as whatever attackObj.character is. Similarly, this:self.newHealth = self.victimHealth - self.attackerPower just creates a new attribute each time the method is called that will always be 100 - self.attack
def attack(self, attackObj):
attackObj.health -= self.power
print(self.character, "you have chosen to attack", attackObj.character)
print(attackObj.character, "you have suffered", self.power, "damage and your health is now", attackObj.health)
Really, an even better way is to add methods that mutate your object, that will be used as an interface with how your object interacts with other objects. So, for example:
class Character:
'''Blueprint for game characters'''
def __init__(self):
#default values
self.character = ""
self.speed = 0
self.power = 0
self.health = 100
def attack(self, victim):
victim.receive_damage(self.power)
def receive_damage(raw_damage):
self.health -= raw_damage
This improves the extensibility of your code. You could more easily implement a "buffs" system, or add an "armor" element, that affects how you recieve damage, without ever having to change the code in attack. You can override these methods in subclasses. So, perhaps you want all orks to have "thickskin", and in Ork:
def receive_damage(raw_damage):
self.health -= raw_damage*self.thickskin_modifier
Where self.thickskin_modifier was set in the Ork class __init__. It could be something like 0.9.

How Do I Fix My Code So It Can print() Out The Results I Want?

Note: I'm not looking for you to remake my code, I'm looking for tips and links to sites that will help me improve this code. If you want to fix the code I will also accept your answer.
I'm trying to understand how class works but, I'm having a really hard time doing so. I made a class called Stat which contains all of the stats for a given user. All of the stats for the user are, name, level, totexp and role. each role has 3 stats (it should have three but, my code is messed up), health, attack, and defense. Here is the main code (not working):
class Stat():
def __init__(self, name, level, totexp, role, health, attack, defense):
self.name = Name
self.level = 1
self.totexp = 0
self.role = Role
self.health = health
self.attack = attack
self.defense = defense
self.exp = 0
def choose_name():
while(True):
Name = input("What is your Dicer's name?:\n").title()
if(any(Bad_Words in Name.lower() for Bad_Words in [])):
print("That's an inappropriate name! Try again")
elif(len(Name) < 3):
print("That name is too short! Try again.")
elif(len(Name) > 16):
print("That name is too long! Try again.")
else:
break
def choose_role():
Roles = {
'mage':lambda:Role(100, 40, 10), #(Health, Attack, Defense)
'warrior':lambda:Role(100, 30, 20),
'gunner':lambda:Role(100, 20, 30),
'archer':lambda:Role(100, 10, 40)
}
while(True):
Role = input("What role do you want to be?\nChoices:\n1. Mage\n"
"2. Warrior\n3. Gunner\n4. Archer\n").title()
if(Role.lower() in (Roles)):
return
else:
print("That's not a role! Try again.")
self = choose_name()
self = choose_role()
After the main code the Results (Like in the title) or the result code should print out the Stats accordingly to the order of the instances. Here is the result code:
print("Here is your Dicer's information:\nDicer's name: {0}\n"
"Level: {1}\nExperience: {2}\nRole: {3}\nRole Stats:\n"
"Health: {4}\nAttack: {5}\nDefense: {6}".format(self.name, self.level,
self.totexp, self.role,
self.health, self.attack,
self.defense))
When I run the code I get an error:
Traceback (most recent call last):
File "python", line 37, in <module>
AttributeError: 'NoneType' object has no attribute 'name'
I think I have ideas to why this is happening but I don't know how to fix it. Can you help me with where I need to start on with my code and ways to fix it. Here is the results I wanted (For this example the Name = Bob and Role = Gunner):
Dicer's name: Bob
Level: 1
Experience: 0
Role: Gunner
Role Stats:
Health: 100
Attack: 20
Defense: 30
I'm a little hesitant to post this because the code is a giant mess. But you said you didn't want a re-write you just wanted to see your code fixed, so here it is fixed. I've commented everything I changed
#renamed stat to player, the point of the object shouldn't be to hold just the stats, should hold all information
#pertaining to the player / dicer
class Dicer():
#levelm, totalexp, health removed from constructor
def __init__(self, name, role, health, attack, defense):
self.name = name #changed Name to name
self.level = 1
self.totexp = 0
self.role = role #changed Role to role
self.health = health
self.attack = attack
self.defense = defense
self.exp = 0
#instance function to print the stats of the dicer
def print_info(self):
print(
"Here is your Dicer's information:\nDicer's name: {0}\nLevel: {1}\nExperience: {2}\nRole:"\
" {3}\nRole Stats:\nHealth: {4}\nAttack: {5}\nDefense: {6}".format(self.name, self.level, self.totexp, self.role, self.health, self.attack, self.defense)
)
def choose_name():
while(True):
Name = input("What is your Dicer's name?:\n").title()
if(any(Bad_Words in Name.lower() for Bad_Words in [])):
print("That's an inappropriate name! Try again")
elif(len(Name) < 3):
print("That name is too short! Try again.")
elif(len(Name) > 16):
print("That name is too long! Try again.")
else:
#you have to return the name so you can use it later
return Name
def choose_role():
#removed all the lambdas here
Roles = {
'mage': (100, 40, 10), #(Health, Attack, Defense)
'warrior': (100, 30, 20),
'gunner': (100, 20, 30),
'archer': (100, 10, 40)
}
while(True):
Role = input("What role do you want to be?\nChoices:\n1. Mage\n2. Warrior\n3. Gunner\n4. Archer\n").title()
if(Role.lower() in (Roles)):
#don't just return None, return the name of the role and it's 3-tuple stats
#returning the role and it's stats from a function is not the best way to do this
return Role, Roles[Role.lower()]
else:
print("That's not a role! Try again.")
dicer_name = choose_name()
dicer_role_name, dicer_role_stats = choose_role()
#create a dicer using the stats returned from chose_role() function
mainDicer = Dicer(dicer_name, dicer_role_name, dicer_role_stats[0], dicer_role_stats[1], dicer_role_stats[2])
mainDicer.print_info()
Here is how I would do it if writing it from scratch
class Dicer():
def __init__(self, name, role, statTuple):
self.name = name
self.level = 1
self.xp = 0
self.health = statTuple[0]
self.attack = statTuple[1]
self.defense = statTuple[2]
def print_stats(self):
print("Name", self.name)
print("Level", self.level)
print("XP", self.xp)
print("Health", self.health)
print("Attack", self.attack)
print("Defense", self.defense)
roles = {
#health, attack defense
"mage" : (100, 40, 10),
"warrior" : (100, 30, 20),
"gunner" : (100, 20, 30),
"archer" : (100, 10, 40)
}
name = input("What is your name ")
dicer_role_choice = None
while dicer_role_choice not in roles.keys():
print("Please select a dicer:")
#prints each role on a new line, showing all the possible choices
print("\n".join(roles.keys()))
dicer_role_choice = input()
mainDicer = Dicer(name, dicer_role_choice, roles[dicer_role_choice])
mainDicer.print_stats()
I revamped my code here it is:
Code provider: Bradley Elko
Update 1 [51 lines]
Update 2 [97 lines]
Update 3 [127 lines]
Update 4 [148 lines]
class Char():
def __init__(self):
self.name = ""
self.role = ""
self.health = 0
self.health_now = 0
self.health_gained = 0
self.attack = 0
self.defense = 0
self.glob()
self.add_name()
self.add_role()
self.print_info()
self.menu()
def glob(self):
global Level, TotXp, Xp, Info, Points
Level = 1
Points = 15
TotXp = 0
Xp = 0
Info = "Not Filled In Yet"
def print_info(self):
print("\nYour Character's Stats:")
print("Your character's name is: {0}".format(self.name))
print("Your character is level: {0}".format(Level))
print("You have {0} Level Points\n".format(Points))
print("Your Role Stats:")
print("Your character's role is: {0}\nYour character's health is: {1}\nYour character's attack is: {2}\nYour character's defense is: {3}".format(self.role, self.health, self.attack, self.defense))
print("\nIntroduction To Game:\n{0}".format(Info))
def add_name(self):
while(True):
Name = input("What's your character's name?\n")
if(len(Name) < 3):
print("That name is too short!")
elif(len(Name) > 20):
print("That name is too long!")
elif(any(bad_word in Name.lower() for bad_word in ['fuck'])):
print("That name is inappropriate!")
else:
self.name += Name
break
def add_role(self):
global Role
Roles = {
"Marksman": (100, 50, 30),
"Melee":(100, 40, 40),
"Mage":(100, 30, 50)
}
while(True):
Role = input("\nWhat's your characters role?\nChoices:\n1. Marksman\n2. Melee\n3. Mage\n").title()
if(Role not in ['Marksman', 'Melee', 'Mage']):
print("That's not a role!")
else:
self.role += Role
self.health += Roles[Role][0]
self.health_now += Roles[Role][0]
self.attack += Roles[Role][1]
self.defense += Roles[Role][2]
break
def menu(self):
global Choice
print("\nMenu\nWelcome to the menu! Here is where you will be staying in between fights, regaining health, and using the shop.\n")
while(True):
Choice = input("Where do you want to go?\n1. Shop\n2. Fight\n3. Sleep\n4. Role Stats\n5. Char Stats\n").lower()
if(Choice == "shop"):
return self.shop()
elif(Choice == "fight"):
print("Needing updating!")
break
elif(Choice == "sleep"):
self.sleeping()
break
elif(Choice == "role stats"):
return self.role_stats()
elif(Choice == "char stats"):
return self.char_stats()
else:
print("That's not an option!")
def menu_two(self):
global Choice
print("\nMenu\nWelcome back to the menu!")
while(True):
Choice = input("Where do you want to go next?\n1. Shop\n2. Fight\n3. Sleep\n4. Role Stats\n5. Char Stats\n").lower()
if(Choice == "shop"):
return self.shop()
elif(Choice == "fight"):
print("Needing updating!")
break
elif(Choice == "sleep"):
self.sleeping()
break
elif(Choice == "role stats"):
return self.role_stats()
elif(Choice == "char stats"):
return self.char_stats()
else:
print("That's not an option!")
def role_stats(self):
global Choice
if(Choice == "role stats"):
print("\nRole Stats:\nRole: {0}\nHealth: {1}\nAttack: {2}\nDefense: {3}\n".format(self.role, self.health, self.attack, self.defense))
return self.menu_two()
def shop(self):
while(True):
Buy = input("\nWelcome to the shop! Here is were you spend your level points. What do you want to purchase?\nChoices:\n1. Abilities\n2. Weapons\n3. Stat Points\n4. Nothing\n").lower()
if(Buy == "abilities"):
print("\nYou selected 'Abilities'.")
break
elif(Buy == "weapon"):
print("\nYou selected 'Weapons'.")
break
elif(Buy == "stat points"):
print("\nYou selected 'Stat Points'.")
break
elif(Buy == "nothing"):
print("\nReturning to menu...")
return self.menu_two()
else:
print("\nThat is not an option!")
def char_stats(self):
global Choice
if(Choice == "char stats"):
print("\nYour Character's Stats:")
print("Username: {0}".format(self.name))
print("Level: {0}".format(Level))
print("Level Points: {0}".format(Points))
return self.menu_two()
def sleeping(self):
global Choice
import time
if(Choice == "sleep" and self.health_now >= self.health):
print("\nYour health is full and so you don't need to sleep. Returning to menu.")
return self.menu_two()
elif(Choice =="sleep" and self.health_now < self.health):
print("\nYou are sleeping to regain health. This doubles your characters health regeneration! Please wait patently as your character sleeps to regain health faster.")
for i in range(1, 1801):
time.sleep(1)
if(i in [60,120,180,240,300,360,420,480,540,600,660,720,780,840,900,960,1020,1080,1140,1200,1260,1320,1380,1440,1500,1560,1620,1680,1740,1800]):
self.health_gained += 10
self.health_now += 10
if(self.health_now < self.health):
print("\nYou're still healing. You've regained %d health!\nCurrent health:\nHealth: %d/%d" % (self.health_gained, self.health_now, self.health))
else:
print("\nYou're done healing! You've regained %d health!\nCurrent health:\nHealth: %d/%d" % (self.health_gained - (self.health_now - self.health), self.health, self.health))
print("\nYou woke up from your healing nap. Returning to menu.")
return self.menu_two()
self.health_gained -= 10
MyChar = Char()
Update 1 Date [6/10/2016]
Update 2 Date [6/10/2016]
Update 3 Date [6/11/2016]
Update 4 Date [6/14/2016]
Link 1: https://repl.it/C0gh/46
Link 2: https://repl.it/C0gh/60
Link 3: https://repl.it/C0gh/79

Adding a combat system to a text adventure game; confused by the structure of the code I'm using

Through some educational materials I've been tasked to use the below structure (the classes) for a text adventure game and am required to add a simple combat system for battle between a hero and an enemy.
Currently I am able to have an enemy created in each room and move between the start room(corridor) to the bathroom and back, but at this point I'm stuck. I can't determine where I should be creating my 'hero' or how I'd communicate the changes I'd need to make to the health attributes etc.
If I could structure the code in another way, I would be able to complete the game, but as it is there is a gap in my understanding of how to enable various sections of code communicate with each other.
Thanks,
Dave
# text based adventure game
import random
import time
from sys import exit
class Game(object):
def __init__(self, room_map):
self.room_map = room_map
def play(self):
current_room = self.room_map.opening_room()
while True:
next_room_name = current_room.enter()
current_room = self.room_map.next_room(next_room_name)
class Character(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
class Hero(Character):
def __init__(self, name):
super(Hero, self).__init__(name, 10, 2)
def __str__(self):
rep = "You, " + self.name + ", have " + str(self.health) + " health and " + \
str(self.attack) + " attack."
return rep
class Enemy(Character):
ENEMIES = ["Troll", "Witch", "Ogre", "Jeremy Corbyn"]
def __init__(self):
super(Enemy, self).__init__(random.choice(self.ENEMIES),
random.randint(4, 6), random.randint(2, 4))
def __str__(self):
rep = "The " + self.name + " has " + str(self.health) + \
" health, and " + str(self.attack) + " attack."
return rep
class Room(object):
def __init__(self):
self.commands = ["yes", "no"]
self.rooms = ["\'corridor\'", "\'bathroom\'", "\'bedroom\'"]
self.enemy = Enemy()
def command_list(self):
print("Commands: ", ", ".join(self.commands))
def enter_room_question(self):
print("Which room would you like to enter?")
print("Rooms:", ", ".join(self.rooms))
def leave_room_question(self):
print("Do you want to leave this room?")
print("Commands:", ", ".join(self.commands))
class Bathroom(Room):
def enter(self):
print("You enter the bathroom. But, wait! There is an", \
self.enemy.name, "!")
print(self.enemy)
print("You are in the bathroom. Need to take a dump? ")
self.command_list()
response = input("> ")
while response not in self.commands:
print("Sorry I didn't recognise that answer")
print("You are in the bathroom. Need to take a dump?")
self.command_list()
response = input("> ")
if response == "yes":
print("Not while I'm here!")
return "death"
elif response == "no":
print("Good.")
self.leave_room_question()
response = input("> ")
if response == "yes":
return "corridor"
else:
return "death"
class Bedroom(Room):
def enter(self):
pass
class Landing(Room):
def enter(self):
pass
class Corridor(Room):
def enter(self):
print("You are standing in the corridor. There are two rooms available to enter.")
self.enter_room_question()
response = input("> ")
if response == "corridor":
print("You're already here silly.")
else:
return response
class Death(Room):
QUIPS = ["Off to the man in sky. You are dead",
"You died, no-one cried.",
"Lolz. You're dead!"]
def enter(self):
time.sleep(1)
print(random.choice(Death.QUIPS))
exit()
class Map(object):
ROOMS = {"corridor": Corridor(),
"bathroom": Bathroom(),
"death": Death(),
"landing": Landing(),
"bedroom": Bedroom()}
def __init__(self, start_room):
self.start_room = start_room
self.hero = hero
def next_room(self, room_name):
return Map.ROOMS.get(room_name)
def opening_room(self):
return self.next_room(self.start_room)
a_hero = Hero("Dave")
a_map = Map("corridor")
a_game = Game(a_map, a_hero)
a_game.play()
If I were you, I would set out a game schema. You could find out asking yourself questions like this:
What are the really important entities?
In your case, as you have done, I would consider Character, Enemy, Room and Map, inheriting when it would be appropiate, like Character-> Hero and Enemy, and several types of room from Room as Bathroom, Corridor, ...
If I were you a consider using a data structure to represent the Map. For example, if you are considering do a text game adventure, you could think in different rooms as different states in your game. If you are in the bathroom, you could be attacked by an enemy and if you are in the bedroom, you can retrieve your hitpoints (life) so these places can be thought as different states.
As an example, you would an array for group all your different rooms (states)
rooms = ["bedroom", "bathroom", "corridor", "kitchen", "living_room"]
and other rooms that you can think about.
(there is probably a better example, more efficient and so on, so this example is to help you about not giving up when you gets stuck about an problem.
According to this example, if you use an array, you can assign a value to each room (equal to each position in the array)
Moreover, you will need to know the hero's position, so you could assign a random value to it using rand(). You can read links below for more information:
random docs python
stackoverflow answer
At last, you also would find useful to compare the hero's position, which would have a random assigned value previously with every position of your array or rooms
In this cases, you could use a if... elif.. elif... to compare those values and do something according to the room where your hero would be.
I hope this answer will be useful for you.
Let me know if you have any doubt about my answer.
Cheers

Categories

Resources