I'm trying to make a super-simple, text-based boxing game as a practice exercise. I want each pass through the loop to throw a punch and inflict a random amount of damage. Each punch will hit a random part of the opponent.
However, the damage never gets subtracted from the original amount.
Where did I go wrong?
Here is my code and output for a couple of rounds.
#starting stats
nose = 100
jaw = 100
face = 100
head = 100
hp = nose + jaw + face + head
moral = 200
import random
#fight
for fight in range(10):
if hp <= 0:
print("DING DING DING\nKNOCK OUT\nYOU ARE THE WINNER!!!!!!")
if hp <= 25:
moral - 25
print("He's losing moral!")
if moral <=0:
hp - 75
print("He's about to KO!!!")
if hp> 0:
print("=========\nMORAL:{0}\nHP:{1}\nNOSE:{2}\nJAW:{3}\nFACE:{4}\nHEAD:{5}\n=========".format(moral, hp, nose, jaw, face, head))
move = input('TYPE "P" TO THOW A PUNCH!!!')
if move == "p" or "P" or "PUNCH":
part = int(random.randint(1,4))
damage = int(random.randint(1, 100))
if part == 1:
print("PUNCH TO THE NOSE!!!")
nose - damage
elif part == 2:
print("PUNCH TO THE JAW!!!")
jaw - damage
elif part == 3:
print("PUNCH TO THE FACE!!!")
face - damage
elif part == 4:
print("PUNCH TO THE HEAD!!!")
head - damage
Output:
=========
MORAL:200
HP:400
NOSE:100
JAW:100
FACE:100
HEAD:100
=========
TYPE "P" TO THOW A PUNCH!!!P
PUNCH TO THE HEAD!!!
=========
MORAL:200
HP:400
NOSE:100
JAW:100
FACE:100
HEAD:100
=========
TYPE "P" TO THOW A PUNCH!!!P
PUNCH TO THE HEAD!!!
=========
MORAL:200
HP:400
NOSE:100
JAW:100
FACE:100
HEAD:100
=========
TYPE "P" TO THOW A PUNCH!!!
Statements like moral - 25 don't do anything at all; they subtract one value from another but then discard the result. You actually need to assign the result back to your variable:
moral = moral - 25
which can be shortened to
moral -= 25
You neglect to save the result. Try this:
hp = hp - 75
Better yet, use the short-hand:
hp -= 75
hp - 75 never resets the variable. With this in mind, hp will always be the global value of 400. Use the -= syntax to accomplish this:
hp -= 75
Related
import time
health = 100
kidsHP = 10
def kidsenemyattack():
global health
print('The enemy deals damage!')
health -= 4
print(health)
print('==========')
time.sleep(3)
kidsenemyattack()
def kidfight():
global kidsHP
ready = input('You can attack!')
if ready in ['1','one','One']:
kidsHP -= 1
time.sleep(2.5)
while health > 0:
kidsenemyattack() and kidfight()
if kidsHP <= 0:
print('You've defeated the evil kids")
Instead of both of the definitions doing what I want (Which is draining my health over time and informing me that I can attack) kidsenemyattack() just overrides kidfight() and vice versa.
I want both of them to be able to be do their functions without one overriding the other.
You're executing kidsenemyattack recursively in the function definition. Remove it from there and logically the code will make sense. There were some formatting issues I had to fix too before the code ran. Here's a working example:
import time
health = 100
kidsHP = 10
def kidsenemyattack():
global health
print('The enemy deals damage!')
health -= 4
print(health)
print('==========')
time.sleep(3)
# kidsenemyattack() <- this is causing your repeating issue
def kidfight():
global kidsHP
ready = input('You can attack!')
if ready in ['1','one','One']:
kidsHP -= 1
time.sleep(2.5)
while health > 0:
kidsenemyattack()
kidfight()
if kidsHP <= 0:
print("Youve defeated the evil kids")
exit(0)
print("Youre defeated")
Running it resulted in a working scenario:
$ python kidsf.py
The enemy deals damage!
96
==========
You can attack!1
The enemy deals damage!
92
==========
You can attack!3
The enemy deals damage!
88
==========
You can attack!12
The enemy deals damage!
84
==========
You can attack!
# this goes on
When running the following code in my application using the terminal and Python 3.8.8 (Anaconda and VSC):
def test():
print(round(random.uniform(7, 10), 2))
test()
...I'm returning multiple decimals places rather than the two decimal places defined in round(), and the length is always different:
7.1234567890 # for example
8.1234 # for example
9.012345 # for example
When I run the same code block in Idle 3.8.8, the function returns exactly what is expected, a return value with exactly two decimal places - every time.
Does anyone know why this would be and more importantly, how I can force two decimal places as a return value in the terminal?
---ADDED ORIGINAL CODE---
# ____NPC Damage____
if npc_race == npc_races[0]: # Troll
npc_race_atk_pwr = round(random.uniform(7, 10), 2)
# NPC Weapons Class
npc_1h_wpns = ["Hammer"]#, "Polearm", "Sword", "Spell"
npc_1h_wpn = random.choice(npc_1h_wpns)
npc_2h_wpns = ["Polearm"]#, "Shield", "Sword"
npc_2h_wpn = random.choice(npc_2h_wpns)
npc_cls_wpns = [npc_1h_wpn, npc_2h_wpn]
npc_cls_wpn = random.choice(npc_cls_wpns)
# NPC Weapon Damage
if npc_race == npc_races[0]: # Troll
if npc_cls_wpn == npc_1h_wpns[0]: # One-Handed Hammer
npc_cls_wpn_dmg = round(random.uniform(0.1, 0.5), 2)
elif npc_cls_wpn == npc_2h_wpns[0]: # Polearm
npc_cls_wpn_dmg = round(random.uniform(0.1, 0.6), 2)
# NPC Critical Weapon Damage
npc_cls_wpn_crt = random.randint(1, 5) # creates the chance for a critical hit
if npc_cls_wpn_crt == 3:
npc_cls_wpn_crt_dmg = round(random.uniform(0.1, 0.3), 2)
if npc_race == npc_races[0]: # Troll
print(f"A {npc_race} was selected for battle. The {str.lower(npc_race)} is using a {str.lower(npc_cls_wpn)} as its weapon and has {npc_hlth}% health. Do you want to fight? ")
fight_confirmation = input("Enter Y/N: ")
if fight_confirmation == "Y" or fight_confirmation == "y":
if npc_race == npc_races[0]: # Troll
total_wpn_dmg = npc_race_atk_pwr * npc_cls_wpn_dmg
total_wpn_dmg += npc_race_atk_pwr
plyr_cur_hlth = plyr_hlth - total_wpn_dmg
print(f"\n\nThe {npc_race} has attacked you with {total_wpn_dmg} weapon damage.")
if npc_cls_wpn_crt == 3:
total_wpn_crt_dmg = npc_cls_wpn_crt_dmg * total_wpn_dmg
total_wpn_dmg += total_wpn_crt_dmg
print(f"You've been critically hit for an additional {total_wpn_crt_dmg} damage resulting in {total_wpn_dmg} total damage!")
plyr_cur_hlth = plyr_cur_hlth - total_wpn_crt_dmg
print(f"\n\nYour health has decreased to {plyr_cur_hlth}%.\n\n\n")
No other number-related variables other than what is defined here are stored, other than plyr_hlth = 100.
---EXAMPLE OF THE OUTPUT---
A Troll was selected for battle. The troll is using a hammer as its weapon and has 62% health. Do you want to fight?
Enter Y/N: y
The Troll has attacked you with 8.2038 weapon damage.
You've been critically hit for an additional 1.886874 damage resulting in 10.090674 total damage!
Your health has decreased to 89.909326%.
# printed out values of variables for verification
npc_cls_wpn_dmg 0.13
npc_race_atk_pwr 7.26
npc_cls_wpn_crt_dmg 0.23
I am currently working through the book Learn Python 3 The Hard Way.
I have reached exercise 43 where a small text adventure game is written to practice Object Oriented programming.
I completed typing in the code for the program and got it working without any errors. Then in the additional study section, the author asked for a simple combat system to be added to the script.
The full script can be seen at this link, I did not want to paste the whole script for ex43 into this question.
https://github.com/ubarredo/LearnPythonTheHardWay/blob/master/ex43.py
I created the following script as a combat system:
import random
import time
class Player:
def __init__(self, hit_points, sides):
self.hit_points = hit_points
self.sides = sides
def take_hit(self):
self.hit_points -= 2
def roll(self):
return random.randint(1, self.sides)
class Combat(Player):
def combat_start():
p = Player(hit_points = 10, sides = 6)
e = Player(hit_points = 8, sides = 6)
battle = 1
while battle != 0:
human = p.roll() + 6
print("Your hit score: ", human)
monster = e.roll() + 6
print("Enemy hit score: ", monster)
if human > monster:
e.take_hit()
print("Your hit points remaining: ", p.hit_points)
print("Enemy hit points remaining:", e.hit_points)
if e.hit_points == 0:
battle = 0
print("The Enemy is Dead!!!")
time.sleep(2)
elif human < monster:
p.take_hit()
print("Your hit points remaining: ", p.hit_points)
print("Enemy points remaining: ", e.hit_points)
if p.hit_points == 0:
battle = 0
print("You died in Battle!!!")
time.sleep(2)
Combat.combat_start()
This works fine on its own and I wanted to use it in the script from the book.
I attempted to call it from the CentralCorridor class. After the player types in "shoot" I called the script I had written by adding:
Combat.combat_start()
What I hoped would happen is the Combat class I had written would start, then when the player won it would continue to the next scene, and if the player lost it would return the Death class.
After much trying and failing, I changed the Combat class to:
class Combat(Scene, Player):
With this added the script ran then breaks out of the loop.
Your hit score: 12
Enemy hit score: 12
Your hit score: 10
Enemy hit score: 11
Your hit points remaining: 8
Enemy points remaining: 4
Your hit score: 10
Enemy hit score: 10
Your hit score: 12
Enemy hit score: 7
Your hit points remaining: 8
Enemy hit points remaining: 2
Your hit score: 7
Enemy hit score: 9
Your hit points remaining: 6
Enemy points remaining: 2
Your hit score: 7
Enemy hit score: 8
Your hit points remaining: 4
Enemy points remaining: 2
Your hit score: 9
Enemy hit score: 10
Your hit points remaining: 2
Enemy points remaining: 2
Your hit score: 10
Enemy hit score: 9
Your hit points remaining: 2
Enemy hit points remaining: 0
The Enemy is Dead!!!
Traceback (most recent call last):
File "ex43.py", line 220, in <module>
a_game.play()
File "ex43.py", line 24, in play
next_scene_name = current_scene.enter()
AttributeError: 'NoneType' object has no attribute 'enter'
If the enemy players score is higher the loop break after one or two rounds.
I'm struggling to find a solution to this and would really appreciate some pointers of where I'm going wrong.
Looking through other answers, I have seen some comment that this is not an ideal way of writing OOP in Python.
In the book it shows:
class Scene(object):
And from what I have read this is the Python 2 style of OOP. I have seen that the Author is more of a Python 2 fan than Python 3.
I do enjoy the exercises he has put into the book and want to continue onto his next one.
Any help as always will be very much appreciated.
----UPDATE----
this is the Play method as requested:
def play(self):
current_scene = self.scene_map.opening_scene()
last_scene = self.scene_map.next_scene('finished')
while current_scene != last_scene:
next_scene_name = current_scene.enter()
current_scene = self.scene_map.next_scene(next_scene_name)
# be sure to print out the last scene
current_scene.enter()
I fixed the issue. After writing,
Combat.combat_start()
I needed to enter:
return 'laser_weapon_armory'
without that the program was crashing as it had no-where to go next.
Also fixed the logic in the Combat class.
Thanks for the help with this.
I have had problems with the shell saying local variable referenced before assignment and don't feel any previous answers have helped. Can I have some specific advice to this code:
import random
marginalCheck = random.randint(0,1)
print("This is the political campaign simulator")
global popularity
popularity = 50
def unpopularT():
if popularity <= 30 and popularity < 0:
print("You are decreasing in popularity.")
popularityRecover = input("Do you wish to carry on or resign. If this carries on, you are likely to lose to a landslide by your Labour opposition")
if popularityRecover == "resign":
print("You have become an infamous, unpopular politician. You are remembered as a horrible, unkind person")
else:
print("You are hanging by a thread")
elif popularity > 70:
print("You are seriously doing well among your supporters and gaining new ones every day")
else:
print("You are doing fine so far in the campaign")
def campaignT():
leadershipT = input("You are chosen as a candidate by your colleagues in the Tory leadership contest. Do you wish to take an A - Far Right, B - Right, C - Centre, D - Left or E - Far Left stance on the political spectrum")
if leadershipT == "A" or leadershipT == "B":
print("You have been elected as leader of the Tories and leader of the opposition. Now the election campaign starts")
ClassicToryAusterity = input("What do you wish to do about the poor funding in the NHS by the Labour government. A - Do you wish to keep the current program, B - Do you wish to increase funding dramatically and increase taxes, C - Do you propose minor increases with small raises on tax, D - Do you support austere implementations on the Health Service")
if ClassicToryAusterity == "A":
popularity += -5
elif ClassicToryAusterity == "B":
popularity += 5
elif ClassicToryAusterity == "C":
popularity += 2
elif ClassicToryAusterity == "D":
popularity += -10
BedroomTax = input("What do you propose to do about the bedroom tax. A - increase it, B - freeze it, C - Decrease it, D - Scrap it")
if BedroomTax == "A":
popularity += -10
elif BedroomTax == "B":
popularity += -5
elif BedroomTax == "C":
popularity += -1
else:
popularity += 10
unpopularT()
else:
print("The Tory whip dislikes your stance and you have not been voted as leader")
chosenParty = input("Choose a party. A - LibDem, B - Labour, C- Tory")
if chosenParty == "C":
print("You have been elected as a councillor by your fellow peers.")
marginality = input("They want you to stand as a MP in a seat. Do you want to stand in a safe or marginal seat")
if marginality == "marginal":
if marginalCheck == 0:
print("You have failed to be elected to parliament")
else:
print("You are duly elected the MP for your constituency!")
campaignT()
else:
campaignT()
What I don't understand is that I have referenced popularity as a global variable, but according to the shell, it is local.
If you want to use access global variables inside functions you don't need to declare anything, but if you need to re-assign the variable by any means, you need to declare it inside the function. For example:
test = 'hello'
def print_test():
print test
def set_test():
global test
test = 'new value'
in your case, you didn't declare the global variable popularity inside your function and you were trying to re-assign it.
So in your case:
def unpopularT():
global popularity
# your code
def campaignT():
global popularity
# your code
This is my very first post on this website, and hopefully I can get some valuable insight and hints in regards to my problem as I'm a relative noob when it comes to programming. I am using Python mode in the Processing environment.
I was given a lecture problem (that the teacher will eventually go over) but I wanted to be able to solve it beforehand. Unfortunately I am not sure how to. I'm supposed to create a program that displays the amount of buns, franks and hotdogs that can be made from the amount of buns and franks, and I have keyboard inputs to increase the amount that is displayed for buns and franks.
Currently, I can't figure out how to get my text to update when I enter keyboard inputs nor can I figure out how to automatically update the number of hotdogs based on the amount of buns and franks I have.
I have attached two pictures of the question that will clear up any confusion if my explanation was not clear. I have also attached the current code I have.
picture 1
picture 2
Code:
#Variables/Model
meat = ""
buns = ""
dogs = min(12 * meat, 8 * buns)
def setup():
size(400,400)
def draw():
global meat, buns, dogs
background(255)
meat = 0
buns = 0
dogs = min(12 * meat, 8 * buns)
fill(0)
text("Packages of meat:" + str(meat), 50, 100)
text("Packages of buns:" + str(buns), 250, 100)
text("Dogs possibly made:" + str(dogs), 150, 200)
def make_hotdogs(totalMeat, totalBuns):
global meat, buns, dogs
if keyPressed == "f":
meat += 1
elif keyPressed == "g":
meat -= 1
elif keyPressed == "b":
buns += 1
elif keyPressed == "n":
buns -= 1
else:
print("Type b, n, f or g")
You're never calling your make_hotdogs() function, so you're never hitting the if statements that check which key is pressed.
You might want to look into the keyPressed() function. You can find more info in the reference.
But honestly, if you're confused, maybe you should just wait for the teacher to explain everything in the lecture.
It's been a week so let's assume that lecture has taken place and let's solve this problem. The issues I see with the OP's code is a lack of understanding of basic Python and the Processing environment. And a failure to take advantange of the problem terminology that's been provided.
Reworking the code to address the above issues and generate a viable picnic planner that runs in the Processing environment:
# Variables/Model
FRANKS_PER_PACKAGE = 12
BUNS_PER_PACKAGE = 8
frank_packages = 0
bun_packages = 0
def setup():
size(400, 400)
fill(0) # black text on a
background(255) # white background
def draw():
hotdogs = make_hotdogs(frank_packages, bun_packages)
text("Packages of franks: " + str(frank_packages), 50, 100)
text("Packages of buns: " + str(bun_packages), 250, 100)
text("Hotdogs possibly made: " + str(hotdogs), 150, 200)
def keyPressed():
global frank_packages, bun_packages
if key == "f":
frank_packages += 1
elif key == "g":
if frank_packages > 0:
frank_packages -= 1
elif key == "b":
bun_packages += 1
elif key == "n":
if bun_packages > 0:
bun_packages -= 1
background(255) # white out old calculations
def make_hotdogs(p_franks, p_buns):
return min(p_franks * FRANKS_PER_PACKAGE, p_buns * BUNS_PER_PACKAGE)
With the exception of make_hotdocs(), the Processing environment calls these functions for us. It calls setup() once at the start of the program; it calls draw() continuously over and over again; it calls keyPressed() whenever the user types on the keyboard, leaving the letter pressed in the key variable.
In Python, we only need to declare global variables where we plan to change their values, not where we simply intend to use their values.