updating a global list python - python

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!

Related

Is it possible to make certain parts of a function run before calling it in python?

So right now my code looks like this (haven't added the other two options yet):
def what_do(action):
print "You can eat, move, hunt, or rest."
for number in resources:
print number + str(resources[number])
if action == "eat":
print "You ate. Hunger restored."
resources['hunger'] == 0
if action == "hunt":
print "You went out and hunted. You found 10 food."
resources['food'] += 10
print resources['food']
what_do(raw_input("What will you do?"))
Aside from the other problems this code has, is it possible to print the string I have placed directly after defining the function before calling it?
Functions denote blocks of statements that are run together. Although Python and other languages do define "co-routines" that can pause and resume running, their usage is more advanced than what you seek.
Your pattern for now will be better addressed by splitting your problem into several functions - and one function to coordinate than all - once you have mastered this arrangement and can grow groups of functions at will, you will be able to move on to more sophisticated forms as the need arise. (For example you could also use a class for this, or even orchestrate some co-routines) .
def prompt():
print "You can eat, move, hunt, or rest."
def get_action():
return raw_input("What will you do?")
def what_do(action):
for number in resources:
print number + str(resources[number])
if action == "eat":
print "You ate. Hunger restored."
resources['hunger'] == 0
if action == "hunt":
print "You went out and hunted. You found 10 food."
resources['food'] += 10
print resources['food']
def game():
while True:
prompt()
action = get_action()
what_do(action)
game()

Python beginner, text-based game

I'm fairly new to the programming game; I'm 3/4 of the way through Learn Python the Hard Way and I had a question about a little text-based game I made... So in this game my guy is stranded on a desert island and you have the option(raw input) of going left right or into the jungle. After choosing a direction, you're given the option to choose how many miles to walk. Each direction is supposed to have a different end result (and mile distance).
If you enter a number that is less than the number of miles to the destination, you're prompted with a choice to either "turn around or "keep going". If you enter turn around, you're taken back to the beginning, where you're again asked to choose a direction. If you enter keep going, the program returns to miles(), where you can choose a new amount of miles to walk.
def miles():
print "How many miles do you walk?"
miles_choice = raw_input("> ")
how_much = int(miles_choice)
if how_much >= 10:
right_dest()
elif how_much < 10:
turn()
else:
print "You can't just stand here..."
miles()
Ok so here's two questions:
How would I make it so that if the user originally enters a number of miles less than the destination distance, and the second mile input + the first mile input == the amount of miles to the destination, it will add the inputs and run my destination function, not just repeat miles().
Since all three final destinations will have different distances, should I write three separate mile functions? Is there a way to make it so that depending on the original direction chosen, miles() will run the different endpoints?
I'm sorry if this doesn't make a lick of sense... I'm still learning and I'm not sure how to fully explain what I'm trying to get across.
You could store the amount of miles to walk in each direction in a dict, and then check the dict to see if the user has walked far enough:
distances = {
'right': 7,
'left': 17,
'forward': 4
}
direction_choice = raw_input("> ")
miles_choice = raw_input("> ")
if how_much >= distances['direction_choice']:
right_dest()
elif how_much < distances['direction_choice']:
turn()
else:
print "You can't just stand here..."
miles()
Be sure to properly validate and cast the user input, which I have not addressed. Good luck!
I don't fully understand the requirements (the intended behavior and constraints). However, you might consider passing a parameter to your function (through and argument) to convey the maximum number of miles which the play could go in that direction).
For example:
#!/usr/bin/env python
# ...
def miles(max_miles=10):
print "How many miles do you walk?"
while True:
miles_choice = raw_input("> ")
try:
how_much = int(miles_choice)
except ValueError, e:
print >> sys.stderr, "That wasn't a valid entry: %s" % e
continue
if max_miles > how_much > 0:
break
else:
print "That's either too far or makes no sense"
return how_much
... in this case you pass maximum valid number of miles into the function through the "max_miles" argument and you return a valid integer (between 1 and max_miles) back.
It would be the responsibility of this function's caller to then call right_dest() or turn() as appropriate.
Note that I've removed your recursive call to miles() and replace it with a while True: loop, around a try: ... except ValueError: ... validation loop. That's more appropriate than recursion in this case. The code does a break out of the loop when the value of how_much is valid.
(By the way, if you call miles() with no parameter then the argument will be set to 10 as per the "defaulted argument" feature. That's unusual to Python (and Ruby) ... but basically makes the argument optional for cases where there's a sensible default value).
#Question #1: I used Class intern variables. You will maybe need them for further programming parts and should take it to zero when you are done on one direction, to start with zero for next step/lvl.
#Question #2: Dictionaries are the best way to do so,self.dest. Parameter pos used as key to get the value from the dictionary.
class MyGame:
def __init__(self):
self.current_miles = 0
self.dest = {'Left' : 10, 'Into the jungle' : 7, 'Right' : 22}
def miles(self,pos):
print "How many miles do you walk?"
miles_choice = raw_input("> ")
self.current_miles += int(miles_choice)
if self.current_miles >= self.dest.get(pos):
self.miles("Right")
elif self.current_miles < self.dest.get(pos):
print "you went "+ str(self.current_miles) + " miles"
else:
print "You can't just stand here..."
self.miles(pos)
mg = MyGame()
mg.miles('Into the jungle')

Pokemon Battle in Python [closed]

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.

randint usage in Learn Python the hard way exercise 43

I am having trouble with the randint usage of exercise 43 in Learn python the hard way link to exercise. Assuming I follow Zed Shaw's code perfectly in all other parts of the program, and I have from random import randint, when I run the program and type the 3 digit passcode into the keypad, it returns a "BZZZZEDDD!". Here is that section of code:
class LaserWeaponArmory(Scene):
def enter(self):
print "You do a dive roll into the Weapon Armory, crouch and scan the room"
print "for more Gothons that might be hiding. It's dead quiet, too quiet."
print "You stand up and run to the far side of the room and find the"
print "neutron bomb in its container. There's a keypad lock on the box"
print "and you need the code to get the bomb out. If you get the code"
print "wrong 10 times then the lock closes forever and you can't"
print "get the bomb. The code is 3 digits."
code = "%d%d%d" % (randint(1,9), randint(1,9), randint(1,9))
guess = raw_input("[keypad]> ")
guesses = 0
while guess != code and guesses < 10:
print "BZZZZEDDD!"
guesses += 1
guess = raw_input("[keypad]> ")
if guess == code:
print "The container clicks open and the seal breaks, letting gas out."
print "You grab the neutron bomb and run as fast as you can to the"
print "bridge where you must place it in the right spot."
return 'the_bridge'
else:
print "The lock buzzes one last time and then you hear a sickening"
print "melting sound as the mechanism is fused together."
print "You decide to sit there, and finally the Gothons blow up the"
print "ship from their ship and you die."
return 'death'
Lets say in the guess = raw_input("[keypad]> ") when running the program I type in "368".
Shouldn't that be within the parameters of code = "%d%d%d" % (randint(1,9), randint(1,9), randint(1,9)) and be TRUE for if guess ==code:? Instead it runs it as if guess != code and returns a "BZZZZEDDD!"
Your guess of 368 is within the possible range for the code, but that's not what the while loop is checking. The line
code = "%d%d%d" % (randint(1,9), randint(1,9), randint(1,9))
will generate a string of three random digits. The code could be anything between 111 and 999 (except there can be no zeroes) and you have no way of knowing exactly what it is as the program currently stands. At the bottom of the lesson, under Study Drills, the author says:
Add cheat codes to the game so you can get past the more difficult
rooms. I can do this with two words on one line.
Presumably, this code is one of the rooms he's talking about. Try adding something that will give you a hint of the code.

Creating a while loop for a Game

I am new to Python and I had a quick question about a code I have been working on today. I am creating a game that uses a while loop where the two opponents will have turns to "hit" one another until one of the players have 0 health points.
This is the code I have so far, although it is not working. Can anyone help?
done=False
while not done:
if You.Hit_points>Opponent.Hit_points:
move=raw_input("Would you like to make a move? (y/n) ")
if move=="y":
print "",You.name,"hit ",Opponent.name," by",You.Hit_points," hit points!"
Opponent.Health=You.Hit_points+You.Skill_points+Opponent.Health
print "Due to the hit",Opponent.name,"is left with",Opponent.Health," health points."
print ("The Mighty Beast will make a move.")
print "",Opponent.name,"hits",You.name,"by",Opponent.Hit_points,"points"
You.Health=(Opponent.Hit_points-Opponent.Skill_points)+You.Health
print "Due to the hit",You.name,"loses",Opponent.Hit_points,"points.Leaving",You.name,"with",You.Health,"health points."
print "Now it is",Opponent.name,"'s turn to make a move"
You.Health=You.Health-(Opponent.Hit_points+Opponent.Skill_points)
print "Due to the hit",You.name,"is left with",You.Health,"health points."
else:
You.Hit_points==0
move=="n"
done=True
if You.Hit_points>Opponent.Hit_points:
should probably be
if You.Hit_points > 0 and Opponent.Hit_points > 0
right? Otherwise as soon as You's HP drops below Opponent's--which could be after the first turn--the fight will end.

Categories