I'm learning Python using "Learn Python the hard way" and am currently making a simple game
Following the book's guidelines, each "room" is to be it's own function and herein lies my problem, I have some variables that need to be accessed by all functions. e.g. Current_health, armor, strength stat.
I have looked at the previous questions on here (that I actually understood) and the only solution seems to be to declare it as a global variable within the function, but as I'm going to have 20+ rooms (functions) it seems a bit silly to declare them all every time
The other option is to pass the variable when calling the function, but as I need to put through 8 variables each time that also seems impractical. Any help would be greatly appreciated. I'll paste the code below in case it helps (the game is far from finished so some may not make sense)
Right now the start() works because of my global variables but I'll run into the error as soon as it tries to run shadow_figure() because of the wep_dam reference
from sys import exit
str = 0
wep_dam = 0
dam = str + wep_dam
cha = 0
sne = 0
arm = 0
max_life = 10
points_remaining = 0
def shadow_figure():
print "\n\nYou approach the figure, who remains silent."
print "As you get closer you realise he has bag at his feet."
print "Mysterious figure: \"You may choose only one.\""
print "You look into the bag, and see a shiny sword on top of a large steel shield."
ans = raw_input("Do you: \n1. Take the sword \n2. Take the shield \n3. Take the whole bag and run \n4. Walk away without taking anything\n> ")
if ans == "1":
print "The sword gives you an extra 3 damage"
wep_dam += 3
exit_beach()
elif ans == "2":
print "The shield gives you 3 armor, but it's so heavy it reduces your sneak by 1"
arm += 3
sne -= 1
def beach():
print "\n\nYou wake up on a beach with no idea how you got there. \nYou see a shadowy figure close to the water."
ans = raw_input("Do you: \n1. Approach him \n2. Go the other way\n> ")
if ans == "1":
shadow_figure()
elif ans == "2":
exit_beach()
else:
print "Please enter either 1 or 2"
def reset_stats():
str = 0
wep_dam = 0
dam = str + wep_dam
cha = 0
sne = 0
arm = 0
max_life = 10
points_remaining = 10
print "\n\n\n\nGame Reset\n\n\n\n"
def start():
global str
global wep_dam
global dam
global cha
global sne
global arm
str = 0
wep_dam = 0
dam = str + wep_dam
cha = 0
sne = 0
arm = 0
max_life = 10
points_remaining = 0
print "You are an adventurer, your stats are currently:"
print "Strength: %d \nCharisma: %d \n Sneak: %d" % ( str, cha, sne)
print "Strength determines your damage, charisma determines your chance of pursuasion, \nand sneak determines whether or not you can go get past enemies without being detected"
print "you have 10 points available to spend, to spend a point, simply type the number which corresponds\nwith the skill and hit enter"
print "\n\n1. Strength \t2. Charisma \t3. Sneak\n"
points_remaining = 10
while points_remaining > 0:
ans = raw_input("Choose a skill: ")
if ans == "1":
str += 1
points_remaining -= 1
print "Strength is now %d" % ( str)
print "%d points remaining\n" % ( points_remaining)
elif ans == "2":
cha += 1
points_remaining -= 1
print "Charisma is now %d" % ( cha)
print "%d points remaining\n" % ( points_remaining)
elif ans == "3":
sne += 1
points_remaining -= 1
print "Sneak is now %d" % ( sne)
print "%d points remaining\n" % (points_remaining)
else:
print "Error, please enter a number from 1 to 3\n"
print "Your stats are now: "
print "Strength: %d \nCharisma: %d \n Sneak: %d\n\n" % ( str, cha, sne)
print "Is this OK? Or would you like to restart?\n"
ans = raw_input("1. Continue \n2. Restart\n> ")
if ans == "1":
print "Game will now begin...."
beach()
elif ans == "2":
ans = raw_input("Are you sure? Yes/No\n> ")
ans = ans.lower()
if ans == "yes":
reset_stats()
start()
else:
beach()
else:
print "Error, please enter 1 or 2"
start()
You may wrap your globals in class:
class Player:
str = 0
wep_dam = 0
dam = str + wep_dam
cha = 0
sne = 0
arm = 0
max_life = 10
points_remaining = 0
and access its fields in rooms like this: Player.arm += 3
Related
I'm trying to develop a code for the zombie dice game.
My problem is when the first player replies that he doesn't want to continue playing.
The game ends and I can't get the second player to play. Can someone help me?
import random
print("========== ZOMBIE DICE (PROTÓTIPO SEMANA 4) ==========")
print("========= WELCOME TO THE ZOMBIE DICE GAME! ========")
numeroJogadores = 0
while numeroJogadores < 2:
numeroJogadores = int(input("Enter the number of players: "))
print(numeroJogadores)
if numeroJogadores < 2:
print("NOTICE: You must have at least 2 players to continue!")
listaJogadores = []
for i in range(numeroJogadores):
nome = str(input("\nEnter player name: " + str(i+1) + ": "))
listaJogadores.append(nome)
print(listaJogadores)
dadoVerde = ("brain", "steps", "brain", "shot", "steps", "brain")
dadoAmarelo = ("shot", "steps", "brain", "shot", "steps", "brain")
dadoVermelho = ("shot", "steps", "shot", "brain", "steps", "shot")
listaDados = [dadoVerde, dadoVerde, dadoVerde, dadoVerde, dadoVerde, dadoVerde,
dadoAmarelo, dadoAmarelo, dadoAmarelo, dadoAmarelo,
dadoVerde, dadoVermelho, dadoVermelho]
print("\nSTARTING THE GAME...")
jogadorAtual = 0
dadosSorteados = []
tiros = 0
cerebros = 0
passos = 0
while True:
print("PLAYER TURN: ", listaJogadores[jogadorAtual])
for i in range (3):
numeroSorteado = random.randint(0, 12)
dadoSorteado = listaDados[numeroSorteado]
if (dadoSorteado == dadoVerde):
corDado = "Green"
elif (dadoSorteado == dadoAmarelo):
corDado = "Yellow"
else:
corDado = "Red"
print("Dice Drawn: ", corDado)
dadosSorteados.append(dadoSorteado)
print("\nThe faces drawn were: ")
for dadoSorteado in dadosSorteados:
numeroFaceDado = random.randint(0,5)
if dadoSorteado[numeroFaceDado] == "brain":
print("- brain (you ate a brain)")
cerebros = cerebros + 1
elif dadoSorteado[numeroFaceDado] == "tiro":
print("- shot (you got shot)")
tiros = tiros + 1
else:
print("- steps (a victim escaped)")
passos = passos + 1
print("\nCURRENT SCORE: ")
print("brins: ", cerebros)
print("shots: ", tiros)
if cerebros >= 13:
print("Congratulations, you've won the game!")
break
elif tiros >= 3:
print("You lost the game!")
break
else:
continuarTurno = str(input("\nNOTICE: Do you want to continue playing dice? (y=yes / n=no)")).lower()
if continuarTurno == "n":
jogadorAtual = jogadorAtual + 1
dadossorteados = 0
tiros = 0
cerebros = 0
passos = 0
if jogadorAtual > numeroJogadores:
print("Finalizing the game prototype")
else:
print("Starting another round of the current turn")
dadossorteados = []
print("======================================================")
print("===================== END OF THE GAME ====================")
print("======================================================")
Does anyone know what I'm doing wrong?
I'm new as a programmer. If anyone knows how to help me with this problem, I would be grateful.
EDIT: Well now the code just works. I can switch players just fine, but if you go through all the characters it crashes again since jogadorAtual gets too big for listaJogadores. I don't quite understand the game, but assuming you want to start back with the first player, an elegant way you can accomplish that is by doing modulus with the % operator, which divides two numbers but returns the remainder. If you divide the number of players by the size of listaJogadores, you'll always get a number inside listaJogadores's range.
# Change this...
print("PLAYER TURN: ", listaJogadores[jogadorAtual])
# ...to this
print("PLAYER TURN: ", listaJogadores[jogadorAtual % len(listaJogadores)])
If that's not what you need for your game, let me know.
Original answer: Is the game ending or is it crashing? When I run the game, it always crashes with:
File "C:\Users\me\Desktop\Untitled-1.py", line 56, in <module>
diceDrawns.append(diceDrawn)
AttributeError: 'int' object has no attribute 'append'
This is because after looping, you try to do diceDrawns.append(), but you've already replaced the diceDrawns list with an integer on line 87. I'm not sure if you meant to replace diceDrawn instead, but that's definitely the source of the problem.
An unrelated note: You can do += as a shorthand way to increment a variable by a certain amount, so you can replace a lot of instances of things like currentPlayer = currentPlayer + 1 with currentPlayer += 1, and the same can be done with any operator, so you could also do things like -= or *=
I'm in a beginner Python class and my instructor wrote pseudocode for us to follow. I've followed it to a T (I feel) and have been getting bugs no matter how I try changing the program. I'd rather have my mistake quickly pointed out than spend more time mucking about. This is written in Python 2.7.8.
#Anthony Richards
#25 February 2018
#This program is a simple simulation of an order-taking software.
#It demonstrates multiple variables, functions, decisions, and loops.
def main():
declareVariables()
while keepGoing == "y":
resetVariables()
while moreFood == "y":
print "Enter 1 for Yum Yum Burger"
print "Enter 2 for Grease Yum Fries"
print "Enter 3 for Soda Yum"
option = input("Please enter a number: ")
if option == 1:
getBurger()
elif option == 2:
getFries()
elif option == 3:
getSoda()
else:
print "You've made an incorrect entry. Please try again."
moreFood = raw_input("Would you like to order anything else? (y/n): ")
calcTotal(totalBurger, totalFries, totalSoda)
printReceipt(total)
keepGoing = raw_input("Would you like to place another order? (y/n): ")
def declareVariables():
keepGoing = "y"
moreFood = "y"
totalBurger = 0
totalFries = 0
totalSoda = 0
subtotal = 0
tax = 0
total = 0
option = 0
burgerCount = 0
fryCount = 0
sodaCount = 0
def resetVariables():
totalBurger = 0
totalFries = 0
totalSoda = 0
total = 0
tax = 0
def getBurger(totalBurger):
burgerCount = input("Please enter the number of burgers: ")
totalBurger = totalBurger + burgerCount * .99
def getFries(totalFries):
fryCount = input("Please enter the number of fry orders: ")
totalFries = totalFries + fryCount * .79
def getSoda(totalSoda):
sodaCount = input("Please enter the number of drinks: ")
totalSoda = totalSoda + sodaCount * 1.09
def calcTotal(totalBurger, totalFries, totalSoda):
subtotal = totalBurger + totalFries + totalSoda
tax = subtotal * .06
total = subtotal + tax
def printReceipt(total):
print "Your total is $"+str(total)
main()
def func():
x = "this is not global"
func()
# print(x) would throw an error
def func2():
global y
y = "this is global"
func2()
print(y) # This indeed will print it
Although you can use this, this is very, very bad practise.
Scopes. You define the variables, but they only exist in declareVariables. Simply move the references over to inside the function you want (main) so they can exist there. Better yet, merge all the functions into one big one, so you don't have to worry about this (or have them all exist in the global scope [defining them before any functions are defined])
I'm trying to make a text based game, and to make my fighting mechanics I have to repeat an if statement until you or the monster dies.
Here it is --
Ph would stand for Player health, str is player strength, mdam is monster damage, mstr is monster strength, monsterh is monsterhealth, the random.random() is the attack bonus you receive (Adding onto this, is there any way to round the number to one or no decimal places?) Thank you! :D
if fight == "A" and ph > 0:
damage = (str) + (random.random())
monsterh = 6
mstr = 0.9
monsterh = (monsterh) - (damage)
print(damage)
print(damage - str)
print('You attack the monster. You deal %s damage.' % damage )
time.sleep(3)
if monsterh > 0:
mstr = 0.9
mdam = (mstr) + (random.random())
print('The monster attacks you!')
ph = ph - mstr
print("You get hit %s" % mdam )
else:
xpgain = damage + 5
print("You won! You've gained %s XP!" % xpgain)
I would wrap your combat seen in a while loop. For example:
while (ph > 0 or monsterh > 0)
# combat rules
# Check who died and move on from there
if (ph > 0)
# next thing the player does
else
# print "You died"
In regards to rounding, there are multiple options depending on exactly what you want to do: python: getting only 1 decimal place
To round the value you get from
random.random()
you can do
round(random.random(),1)
to round to 1 decimal place, or if you want to get rid of decimals, replace
random.random()
with
int(random.random())
As for repeating the if statement, you can put it into a loop which will break when a condition is met
while true:
if fight == "A" and ph > 0:
damage = (str) + (int(random.random()))
monsterh = 6
mstr = 0.9
monsterh = (monsterh) - (damage)
print(damage)
print(damage - str)
print('You attack the monster. You deal %s damage.' % damage )
time.sleep(3)
elif ph<=0 or fight!="A":
print("You lose!")
break
if monsterh > 0:
mstr = 0.9
mdam = (mstr) + (int(random.random()))
print('The monster attacks you!')
ph = ph - mstr
print("You get hit %s" % mdam )
else:
xpgain = damage + 5
print("You won! You've gained %s XP!" % xpgain)
break
Although you wouldn't need the fight!="A" since I don't think you change the value of fight at all.
Also you don't have to do
mdam = (mstr) + (int(random.random()))
You can just do
mdam = mstr+int(random.random())
This above ^ applies to other places in your code as well. If you have any questions please feel free to ask.
This program is not working right. It seems to be unable to print the cars after "You have the following cars:"
How could I get the variables to change in the def game() section?
Here is a pastebin: http://pastebin.com/pjsuWRYs
import random
car1 = ("car1")
car2 = ("car2")
car3 = ("car3")
car4 = ("car4")
car5= ("car5")
car6 = ("car6")
car7= ("car7")
car8 = ("car8")
car9 = ("car9")
def game():
print ("You have the following cars:")
print (car1)
print (car2)
print (car3)
print (car4)
print (car5)
print (car6)
print (car7)
print (car8)
print (car9)
print ("You selected Grand Thief Auto")
gta = input ("To commit GTA type GTA")
if gta in ("gta", "Gta", "GTA", "a"):
chance = random.randint(0,100)
if chance <= 1:
print ("You stole a Bugatti Veryron")
car1 = ("Bugatti Veryron")
elif chance <= 5:
print ("You stole a Ferrari Spider")
car2 = ("Ferrari Spider")
elif chance <= 10:
print ("You stole a Audi Q7")
car3 = ("Audi Q7")
elif chance <= 15:
print ("You stole a BMW X6")
car4 = ("BMW X6")
elif chance <= 20:
print ("You stole a Jaguar X Type")
car5 = ("Jaguar X Type")
elif chance <= 25:
print ("You stole a Ford Mondeo")
car6 = ("Ford Mondeo")
elif chance <= 30:
print ("You stole a Audi A3")
car7 = ("Audi A3")
elif chance <= 35:
print ("You stole a Ford Fiesta")
car8 = ("Ford Fiesta")
elif chance <= 40:
print ("You stole a Skoda Octavia")
car9 = ("Skoda Octavia")
elif chance <= 100:
print ("You got caught!")
game()
game()
If you want to make the "car"s accessible in the functions, you must set them as global variables.
Try putting
global car1, car2, car3, car4, car5, car6, car7, car8, car9
before the print ("You have the following cars:") and after define game():
I would also suggest using lists or dictionaries instead of defining each variable by itself.
You could have:
cars = ["car1", "car2", "etc"]
# To change a value for "car2" for example, do this:
# List values (indexes) in Python are starting from 0
cars[1] = "Bugatti"
# To print the car name do:
print (cars[0])
print (cars[1])
# Etc.
or:
cars = { "car1" : "Bugatti", "car2" : "Ferarri", "car number" : "car name"}
# To change a value for "car2" for example, do this:
cars["car2"] = "Bugatti"
# And to print the car names:
print (cars["car1"])
print (cars["car2"])
If you chose to use lists or dictionaries, you will have to set the cars variable global as well
To make things look nicer, I would suggest changing input ("To commit GTA type GTA") to (input ("To commit GTA type GTA: ").lower() which will add an extra space for "beauty" and make the input case-insensitive
I would also add newlines (\n) or empty print () statements to make the output prettier and easier to understand. This will just add an empty line wherever you want it to be.
when I use randint() sometimes this error will appear:
ValueError: empty range for randrange() (1,1, 0)
why is this/how do i stop it from happening?
im not doing anything wrong as far as i can tell, this error dosnt apppear on any specific randit() call and only appears every now and then.
the error takes me to the actual random module:
raise ValueError, "empty range for randrange() (%d,%d, %d)" % (istart, istop, width)
Here is my whole program (i call randint() often)
from random import randint
units = 5
food = 20
days_without_food = 0
SP = 4
print '------------------------------------------------------'
print 'welcome! starting a new game'
print '------------------------------------------------------'
location = 'plains'
def search(): #do2 create leadership skill or search skill
global units
global food
global SP
if SP > 0:
SP = SP - 1
found = randint(1,3)
if found == 1 or found == 2:
if units == 0:
units = randint(1,5)
print '------------------------------------------------------'
print 'you recruited %s units!' %units
main()
a = units / 2
ammount = randint(1,a)
units = units + ammount
print '------------------------------------------------------'
print 'you recruted %s units!' %ammount #recruit a random ammount of units not over half ammount of already owned.
main()
else:
print '------------------------------------------------------'
print 'you did not find anything'
main()
else:
print '------------------------------------------------------'
print 'your army is too tired to look for anything'
main()
def battle(): #do1 create villages with a random amount of units between 100-300
global SP
global units
global food
if SP == 0:
print '------------------------------------------------------'
print 'your army is too tired to fight'
main()
else:
SP = SP -1
if units == 0:
print '------------------------------------------------------'
print 'it is madness to go looking for a fight without an army'
main()
a = units / 2
b = units * 2
e_units = randint(a,b)
e_units = int(e_units) #random ammount of enemy units reletave to ammount of player units
if e_units == 0:
e_units = randint(1,3)
guess = randint(e_units-5,e_units+5)
if guess < 0:
guess = randint(1,e_units+10)
print '------------------------------------------------------'
print 'it looks like the enemy has %s units' %guess #unacurate guess of how many enemy units there are
print 'a: attack'
print 'b: leave'
action = raw_input('a or b?')
if action == 'a':
units = units - e_units
if units <0:
units = 0
print '------------------------------------------------------'
print 'you lost the battle and all of your units'
main()
else:
a = e_units * 2
ammount = randint(1,a)
food = food + ammount
print '------------------------------------------------------'
print 'you won the battle and found %s food!' %ammount + ' after the battle you have %s units' %units
main() # battle
else:
chance = randint(1,10)
if chance == 10:
units = units - e_units
if units <0:
units = 0 #attempt to leve
print '------------------------------------------------------'
print 'it is to late, they spotted you!' + ' after the battle you have %s units' %units
main()
else:
print '------------------------------------------------------'
print 'you leave without the enemy spotting you'
main()
def change_location():
global food
global units
global SP
global days_without_food
if food < 0:
days_without_food = days_without_food + 1
if days_without_food > 0 and days_without_food < 3:
chance = randint (1,5)
if not chance == 5:
print '------------------------------------------------------'
print 'you have no food, but your men are stll loyal to you'
food = 0
main()
elif chance == 5:
deserters = randint(1,int(units/4))
units = units - deserters
print '------------------------------------------------------'
print 'without any food, %d men deserted your army' % deserters
food = 0
main()
else:
chance = randint(1,2)
if chance == 1:
men_starved = randint(1,int(units/4))
units = units - men_starved
print '------------------------------------------------------'
print 'without any food, %d units starved to death' % men_starved
food = 0
main()
else:
deserters = randint(1,int(units/4))
units = units - deserters
print '------------------------------------------------------'
print 'without any food, %d men deserted your army' % deserters
food = 0
main()
days_without_food = 0
SP = 3
food = food - int(units / 2)
places = ['plains','beach','river','mountain','sea','desert','hills',
'forest','volcano','jungle','storm','village'] #do3 add more places
location = places[randint(0,len(places)-1)]
main()
def main(): #do1 Create nomadic and settled versions
global units
global location
global food
global SP
print '------------------------------------------------------'
print 'you are at a %s' %location
print 'a:look for a fight'
print 'b:look for supplies'
print 'c:Take stock'
print 'd:Move on'
action = raw_input('a,b,c, or d?')
if action == 'a':
battle()
elif action == 'b':
search()
elif action == 'c':
print '------------------------------------------------------'
print 'food: %s. ' %food + ' units: %s. ' %units + ' Search points %s. ' %SP
main()
elif action == 'd':
change_location()
else:
main()
main()
randint(a, b) should be called with the arguments a and b in which b should be greater than a. Else the randrange() method called by randint() will raise a value error like this:
raise ValueError, "empty range for randrange() (%d,%d, %d)" % (istart, istop, width)
Check this source for random module with randint()(line:237) and randrange() (line:173) methods for better understanding.