Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I am not that great with OOP but I am stuck right now. First off, I don't think I set the damage correctly and I am trying to figure out how to output the damage to the user. Any help would be appreciated.
#Pokemon Battle
import random
from time import sleep
from array import *
class Pokemon(object):
def __init__(self, xname, xhealth):
self.name = xname
self.health = xhealth
def damage1(self,Charmander):
Squirtle.health - self.damage
def damage2(self,Charmander):
self.health - Squirtle.damage
print ('What is your name?')
name = input()
print ('Hello '+name+'! You are about to enter a pokemon battle.')
sleep(1)
print ('A wild Charmander appeared!')
sleep(1)
print ('You sent out Squirtle!')
sleep(1)
print ('Do you want to fight(1) or run away(2)?')
choice = input()
damage = random.randint(1,50)
damage = str(damage)
if choice == '1':
print ('You dealt '
sleep(1)
print ('Charmander did ')
if choice == '2':
print ('You ran away.')
else:
print ('Not a valid response.')
Right off the bat, you can use String Formatting to insert variables in strings.
#old way
some_string = "the value of 2+2 = %i",4
#new way
some_string = "the value of 2+2 = {}".format(4)
For your code, try:
if choice == '1':
print("You dealt {}".format(damage_goes_here))
However there's deeper issues with your code. Let me look more and I'll edit.
Object Oriented Programming
Okay so the first problem you have is that you never actually MAKE anything. When you write class SomeClassLikePokemonOrWhatever: what you're doing is making a template of something. It's like making a cast or a mold of an item before you make it -- you want all your Pokemon (or whatever) to be alike, so you make a mold of them and cast them all from the same mold. You can decorate and unique-ify them after that, but we want them all to be the same, basically. So instead, you should have something like this:
class Pokemon:
def __init__(self,name,base_hp):
self.name = name
self.base_hp = base_hp
#the __init__ function gets called when you "instantiate" (e.g. actually MAKE)
#whatever object the class is describing. In most cases, all it does it set
#the starting properties of the object based on how you define it (like this)
#you could also say all pokemon are beautiful, and add something like
self.description = "Absolutely GORGEOUS darling!"
#that will be constant for every pokemon you make through this definition.
#you said you wanted damage to be random between 1-50, so we don't need to add
#that statistic to the class.
That covers the definition of the object, but it still doesn't DO anything. In fact, let's let it do something, shall we? We want it to attack. What's a pokemon that doesn't fight? So let's give it a function (in a class, we call functions "methods.")
def attack(self,target):
#in this method we'll teach the pokemon how to fight
damage = random.randint(1,50) #don't forget to import random to do this
target.hp -= damage
Now you need to make some stuff. You defined what a Pokemon is and what it can do, but you haven't made one. Let's make some. Luckily it's easy.
my_awesome_pokemon = Pokemon("Charizard",200) #you give the args in the same order __init__ takes them
your_sucky_pokemon = Pokemon("Magikarp",20) #same deal here.
That makes two pokemon, one for you and one for them. If you wanted a whole belt full, you could define an array all_my_pokemon and fill it with Pokemon objects defined in this way. Just something to think about.
To actually fight, you'd tell your pokemon to attack.
my_awesome_pokemon.attack(your_sucky_pokemon)
#just that easy, now display how much damage it did....WAIT STOP WE HAVE A PROBLEM!
since you want random damage every time, you can't access it with something like my_awesome_pokemon.damage, since it's a local variable it dies when the attack method ends. You can, however, return that value in the method and use that.... Let's change our method.
def attack(self,target):
damage = random.randint(1,50)
target.hp -= damage
return damage #now we have some way to access how much damage was done from our main thread
Now to display it, we can do
damage_done = my_awesome_pokemon.attack(your_sucky_pokemon) #since .attack() returns the damage it deals, this sets damage_done to a sane amount.
print("My pokemon {} dealt {} damage to {}".format(my_awesome_pokemon.name,damage_done,your_sucky_pokemon.name))
Does that make sense?
I really think you should brush up on your OOP and then come back to this problem, because this is definitely a decent problem to practice on.
First of all, you set damage, and then set it again randomly:
self.damage = xdamage
self.damage = random.randint(1,50)
And this function is left open, which is going to cause compile issues, besides for the fact that you're missing any actual data!
print ('You dealt '
sleep(1)
print ('Charmander did ')
You're going to want to call your damage variable and Charmander's damage variable; think about how that is accomplished in OOP.
Related
SOLVED: I read through my code, it was a 'bug'. When I copied the dice roll method from the 'player character', since it uses the same mechanics for the enemies, I set the damage to 0 if it rolls with one die on accident.
Beginner here. (Python crash course halfway of chapter 9)
I am trying to build a simple turn based text game to practice (classes,if statement, modifying dictionaries/lists etc).
I will copy two snippets from my code, so you can understand my problem better.
(I'm really sorry that I can't give a short description, my best try was the title, but that still doesn't make it good enough. If you want an abridged tldr, go to the bottom with the bold texts.)
First, I have two characters, that you can choose from as an if-elif-else statement.
I used the same "player_xy" (xy being like health, damage etc) for the two characters, but assigning different values to them based on the player's choice. (My reasoning being is so I only have to reference the same variable in the code later in the battle system, making my job easier.)
(The variables fighter_max_hp.. etc are defined earlier, but it doesn't matter (tried moving it to before/inside the if statements.)
while select_repeat == True:
print("Type 'f' for fighter , 'm' for mage, or 'q' to quit!")
character = input("TYPE: ")
#player chooses fighter
if character == 'f':
player_max_hp = fighter_max_hp
player_max_mana = fighter_max_mana
#this goes on for a while, setting up all the stats
#player chooses mage
elif character == 'm':
player_max_hp = mage_max_hp
player_max_mana = mage_max_mana
#this goes on for a while, setting up all the stats
#player chooses to quit
elif character == 'q':
select_repeat = False
#invalid input
else:
print("\nPlease choose a valid option!")
Later in the code, I have a part where a randomizer sets up enemies to fight.
I used the same "enemy_xy" (xy being like health, damage etc) for the enemies. (My reasoning was the same here as for the characters.)
(Same, as with the player variables (tried moving it to before/inside the if statements.)
while enemy_select == True:
#game chooses an enemy to fight!
min = 1
max = 3
enemy_chooser = int(random.randint(min, max))
if enemy_chooser == 1:
#choose werewolf
enemy_hp = werewolf_hp
enemy_dice = werewolf_dice
#this goes on for a while, setting up all the stats
if enemy_chooser == 2:
#choose lesser mimic
enemy_hp = int(player_max_hp / 2)
enemy_dice = player_dice
elif enemy_chooser == 3:
#choose zombie
enemy_hp = zombie_hp
enemy_dice = zombie_dice
#this goes on for a while, setting up all the stats
Keep in mind, all of these enemies use the same "enemy_hp", "enemy_dice" etc. variables, within the same battle system, just assigned as "enemy_hp = werewolf_hp" or "enemy_hp = "zombie_hp".
The fight happens, and:
If your enemy is the werewolf:
you deal damage to it
you receive damage from it
you can kill it
you can get killed by it
If your enemy is the lesser mimic:
you deal damage to it
you can ONLY receive damage from it if you are a fighter (mage's hp doesn't decrease)
you can kill it
you can ONLY get killed by it if you are a fighter (obviously, since it doesn't deal damage to mage hp)
If your enemy is the zombie:
you deal damage to it
you CAN NOT receive damage from it (not the fighter, or the mage)
you can kill it
you can not get killed by it (obviously, since no damage)
Otherwise, it prints out the different variable values as assigned (different stats for each monster) as expected, and it uses correct calculations to deal damage.. it just can't in the two cases mentioned above.
Now comes the main part of my question...
If I change the variables like this:
elif enemy_chooser == 2:
#choose zombie
enemy_hp = werewolf_hp ##CHANGE
enemy_dice = werewolf_dice ##CHANGE
#this goes on for a while, setting up all the stats
Then the zombie can finally deal damage to the player (with the werewolf's stats).
It's as if because the lines
enemy_hp = werewolf_hp
enemy_dice = werewolf_dice
#etc
are written earlier than:
enemy_hp = zombie_hp
enemy_dice = zombie_dice
#etc
it somehow effects the variable (regardless or not if the "if" statement is true).
because werewolf_xy was defined earlier than zombie_xy
#enemy werewolf defined first in the code
werewolf_hp = 20
werewolf_dice = 2
#etc
#enemy zombie defined right after
zombie_hp = 35
zombie_dice = 1
#etc
Same happens with the fighter and mage selection.
Somehow the player_hp = xy_hp only works if xy = fighter, because the fighters variables are defined earlier in the code, and thus making the "lesser mimic" deal damage only to the fighter.
My question is "simply".. why?
I tried everything in my power, to no avail.
As you have seen, I could identify what causes the problem (and thus I >could< potentionally work around it), but I still don't know why Python does what it does, and that bothers me.
Any help or input from more experienced users would be greatly appreciated.
Thank you in advance!
Tankerka
You have a bug.
There's not enough details in this (long!) narrative to identify the bug.
Here's how you fix it:
breakpoint()
Put that near the top of your code,
and use n next, plus p print var,
to see what your code is doing.
It is quicker and more flexible than print( ... ).
Read up on that pair of commands here:
https://docs.python.org/3/library/pdb.html
Separate item: refactor your code as you go along.
You're starting to have enough if / elif logic
that it won't all fit in a single screenful
with no scrolling.
That suggests that it's a good time to use def
to break out a helper function.
You might def get_enemy_hp( ... ):, for example,
and also define get_enemy_dice().
Other things you might choose to study:
a class can be a good way to organize the variables you're defining -- embrace the self syntax!
a dict could map from enemy type to hp, or to dice
The nice thing about helper functions is they're
the perfect target for unit tests.
It takes a minute to write a test, but it winds up saving you time.
https://docs.python.org/3/library/unittest.html
When you identify and fix the problem, let us know!
https://stackoverflow.com/help/self-answer
I'm working on a choose-your-own-adventure game in Python to try to learn how to code. I might be doing this entirely wrong, but I thought rather than just nesting if-elif-else statements endlessly, I could write some sort of function that would be a template for all choices in the game.
My ideas was to have every decision in a given scene to generate two lists - choices and outcomes. The "multitemplate" function would then load the choose and outcomes lists, present the options to the player, take in the answer, and call the correct function for the outcome given.
My issue is that the outcome list is a list of functions, which Python doesn't seem to like. It says I've not defined the functions properly, but when I define my outcome functions before calling "multitemplate", it just prints them first.
Here's my code:
#Function to allow the adventurer to make choices
def refusal():
print("You stop at the roadsign you passed on your way into town. There are only two directions - towards Tarroway, or towards Angion, the town from whence you came.")
def guards():
print("The guards stop you.")
def theinn():
print("You follow the joyful chatter down the deserted street. Its source is a squat, one story building. A sign above the door reads \"The Forked Tongue\"")
choose = ["I walk towards the merry sounds.", "I turn on my heels and head back where I came from.","I stay where I am and watch the night quietly."]
outcome = [theinn(), refusal(), guards()]
def multitemplate(choose,outcome):
global mychoice
global carryon
for x in range(len(choose)):
print (f"{x+1}) " + choose[x], end="\n")
mychoice = (input())-1
while True:
if (mychoice) in range(len(choose)):
carryon = True
outcome[mychoice]
carrion()
else:
print("Please enter the number of the choice you wish to make.")
carryon = False
mychoice = int((input()))-1
I'd appreciate any input on how this should work properly, or if I'm going down a completely blind alley here.
Thanks!
I'm trying to make a blackjack game, and I want to have the option to deal additional cards, but what I've run up against is I'm trying to make a function that will deal additional cards, but I'm not sure the best way to do that. I have an idea on how to do it, but I'm not clear on how I would accomplish it.
Idea:
Have a function that will deal addition cards, and will +1 a variable counting how many cards the player already has, starting at 2, the first time the function is run, will give the player card #3. The function would then randomly give a card, and then return the card, (perhaps playerCardThree, playerCardFour) with a limit of 5 cards allowed at a time. Here is an example of what I'd like it to do, but I'm not sure if it'd work.
def deal():
playerCardTotal + 1
if playerCardTotal >= 5:
print("Error detected, returning...")
play()
newPlayerCard = randint(1,10)
print("You are given card ",playerCardTotal,"it is a",newPlayerCard)
newPlayerCard = playerCard(4)
If someone could help me do something similar, or perhaps lead me to a way that would accomplish the goal cleaner, as I'm sure what I've thought up isn't the most efficient way.
How about using a counter within a class, which will automatically increase each time you instantiate it. Then each card will be an instance. You can raise an error when the counter exceeds 5, as you described in your question. A simplified starting point for your game might be something like this (you should elaborate it as you need):
import random
class MyGame():
counter = 0
def __init__(self):
MyGame.counter += 1
def deal_card(self):
self.card = random.randint(1,10)
if self.get_count() > 5:
raise RuntimeError('too many cards have been played')
print("You are given card #", self.get_count())
def get_count(self):
return MyGame.counter
a = MyGame()
a.deal_card()
b = MyGame()
b.deal_card()
my children and I are messing with a random bedtime story generator. And apart from being amazed at how easy python is to use, we want to generate a random name for our protagonist, but for them to keep the same name throughout the story.
import random
names= ["Tim", "Ju Ju", "Legface", "Dusty", "Smudger"]
thing = ["princess", "elf", "fairy", "mermaid", "shoe maker"]
count = 0
while (count < 1):
print "Once upon a time there was a ",
print(random.choice(thing)),
print "whose name was ",
print(random.choice(names)),
so if the random name turns out to be Tim, I would like to continue the story as
print $thevariablethatisTim
print "was a very happy man"
I realise this is a trivial thing, but I can't seem to get it right and we are having such a good laugh at bedtime with this.
Thanks in advance
Neil
Just choose the name of your hero before you enter the while loop.
hero = random.choice(names)
# stuff
while some_condition:
# do stuff
print(hero) # or formatted string
# do other stuff
any time you want to refer to your protagonist, use the variable hero instead of calling random.choice again.
Full disclosure -- this is my first stack overflow question. I searched around for a similar question for awhile but couldn't find one that helped me given my limited scope of knowledge (there were python global variable questions but the answers given were over my head).
I'm new to programming and i'm learning python via python the hard way by Zed Shaw. I'm on exercise36 and my goal is to write my own text based game.
The game starts with the following function
def start():
global Your_HP
Your_HP = 20
global Your_Ammo
Your_Ammo = 20
global HP_Scan
HP_Scan = 2
global your_stats
your_stats = [Your_HP, Your_Ammo, HP_Scan]
print "You enter a room with two doors"
print "Do you choose the Red Door\n...or the Blue door?"
start_choice = raw_input("> ")
if "red" or "Red" in start_choice:
monster_HP = 2
monster_attack = 3
red_one(your_stats, monster_attack, monster_HP)
The red_one function looks like this:
def red_one(your_stats, monster_attack, monster_HP):
print "Immediately you notice a monster in the room"
print "You point your rifle at the monster before you"
shoot(Your_Ammo, monster_HP)
if monster_HP <= 0:
print "You killed it!"
print "You now have %d bullets left" % Your_Ammo
print "You finally look around the room"
print "There is a door going straight"
print "There is a door going left"
room_choose()
elif monster_HP > 0:
print "The monster has %d HP" % monster_HP
print "He stumbles, but not dead!"
print "He shoots back at you with his lil pistol!"
get_shot(monster_attack, Your_HP)
else:
dead('just because')
The script immediately runs the shoot function which looks like:
def shoot(Your_Ammo, monster_HP):
print "---------"
print "You have %d HP left" % Your_HP
print "How many shots do you fire?"
shots_fired = raw_input('> ')
shots_fired = int(shots_fired)
Your_Ammo -= shots_fired
monster_HP -= shots_fired
return Your_Ammo, monster_HP
The problem is that when I run the script and shoot only 1 time, when I return to the start of red_one, the Your_Ammo and monster_HP variables revert to their original values instead of the updated one i'm returning from shoot
I've tried moving where I'm declaring the global variables (initially declaring outside of all functions instead of in start) and I just get an "x variable is local and global" error.
I know global variables in general are not always the best idea, so I'm just hoping someone can break this down for me in an elegant way and provide a helpful solution, regardless of whether or not it includes a global variable.
Ideally, I'd like to update the variables in the your_stats list throughout the course of the game. Essentially, from any function in the game, I want to be able to return any variable within the your_stats list so I can use that variable as an argument for other functions until the player runs out of HP or ammo.
Sorry this post was a bit verbose! Any help is really appreciated!