===EDIT SOLVED! COMPLETED CODE IN COMMENTS BELOW!===
Making a text based role play game. Developing HP system. I've managed to make the HP and damage definitions. I need to make it so it updates the HP variable after every instance of damage that is taken.
I have only been coding for a week and don't know the terminology I'm looking for so I've not been able to search for an answer successfully but I've been trying to find an answer for about two hours now.
import random
hit_points = 20
d4_damage = random.randint(1, 4)
d6_damage = random.randint(1, 6)
d8_damage = random.randint(1, 8)
def hp_loss_small():
for x in range(1):
return hit_points - d4_damage
print (hp_loss_small())
def hp_loss_medium():
for x in range(1):
return hit_points - d6_damage
print (hp_loss_medium())
def hp_loss_large():
for x in range(1):
return hit_points - d8_damage
print (hp_loss_large())
Correct result would be if you ran a damage def and lost 4 hit points, it displays 16. But it doesn't update the hp variable, so if you take another 2 damage you go to 18 hp. I need it so it'd update the variable and go to 14.
for x in range(1):
You can omit this completely, since this only runs the statement once.
When you return a value from a function, you can assign the result to a variable. In your case, you'd do hit_points = hp_loss_small(). Additionally, you should pass the current hit points as a parameter (def hp_loss_small(hit_points)), and call it as hp_loss_small(hit_points).
In case anyone else finds this while searching for a similar problem here is my finished code:
import random
hit_points = 20
d4_damage = random.randint(1, 4)
d6_damage = random.randint(1, 6)
d8_damage = random.randint(1, 8)
def dead():
if hit_points < 1:
return ('dead message ')
else:
return (' ')
def hp_loss_small(hit_points):
return hit_points - d4_damage
print (hp_loss_small(hit_points))
hit_points = hp_loss_small(hit_points)
print (dead())
def hp_loss_medium(hit_points):
return hit_points - d6_damage
print (hp_loss_medium(hit_points))
hit_points = hp_loss_medium(hit_points)
print (dead())
def hp_loss_large(hit_points):
return hit_points - d8_damage
print (hp_loss_large(hit_points))
hit_points = hp_loss_large(hit_points)
print (dead())
Related
outcomeG = "0"
outcomeB = "0"
def roll(outcomeG, outcomeB):
outcomeG = random.randint(1, 6)
outcomeB = random.randint(1, 5)
return outcomeG, outcomeB
def goodDiceRoll():
goodDiceOptions.destroy()
global goodDiceRoll
goodDiceRoll = tkinter.Tk()
goodDiceRoll.title("Green Dice roll")
lbloutcome = tkinter.Label(goodDiceRoll, text="Press roll")
btnRollG = tkinter.Button(goodDiceRoll, text="Roll", command=roll(outcomeG, outcomeB))
if outcomeG == "1":
lbloutcome.config(text="Green 1")
goodDiceRoll.update()
f = open("Logs.txt", "a")
ts = time.time()
sttime = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d_%H:%M:%S - ')
f.write(sttime + "Green 1")
f.close()
elif outcomeG == "2":
lbloutcome.config(text="Green 2")
goodDiceRoll.update()
f = open("Logs.txt", "a")
ts = time.time()
sttime = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d_%H:%M:%S - ')
f.write(sttime + "Green 2")
f.close()
#rest of code
This is some of my code that is suppose to let you roll a green dice or red dice and then put it in a file. However when I press the roll button that i made, it is suppose to randomize a number from 1 to 6 and display it but what really happens is absolutely nothing. How can i fix this? Any help will be much appreciated.
If you do roll(outcomeG, outcomeB) then don't expect those two global variables to change. They will remain 0. This is because the (parameter) variables within roll are local to that function. Any assignment made to those variables will not affect the variables that were passed to the function.
If you then call goodDiceRoll() the if blocks will not be entered since the values of those variables are still 0, and by consequence nothing gets written to the file.
You can solve this by doing:
outcomeG, outcomeB = roll()
... and remove the parameters from the roll definition.
But, as you don't call roll that way, but pass a reference to it via:
btnRollG = tkinter.Button(goodDiceRoll, text="Roll", command=roll)
... you are forced into using global variables. So modify roll like this:
def roll():
global outcomeG, outcomeB
outcomeG = random.randint(1, 6)
outcomeB = random.randint(1, 5)
Make sure to also define them as such in goodDiceRoll.
Secondly, it is a really bad idea to assign to goodDiceRoll, which really destroys the previous value it had, i.e. the function you are in. This will make the function unreachable after the first invocation. Use a different variable name.
If what you have posted is the entirety of your code, then it is unlikely that anything will be written, since you only include cases for the green dice rolling a "1" or a "2". Instead of using if statements to deal with different cases of rolls, you should instead do something like this:
f = open("Logs.txt", "a")
ts = time.time()
sttime = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d_%H:%M:%S - ')
f.write(sttime + "Green " + outcomeG + ",\n")
f.write(sttime + "Blue " + outcomeB + "\n")
f.close()
Also you need to make sure when you call the 'roll' function, you can access that data.
I am working on a project, and I have no idea how to avoid using global variables. I have a list of functions that perform bits and pieces but I am not able to pass variables between them!
Here is my current code:
===================
def player_names_input():
global player_A_name,player_B_name
player_A_name = raw_input("Please enter name for Player A : ")
player_B_name = raw_input("Please enter name for Player B : ")
def coin_flip():
global player_A_name,player_B_name,start_player,end_player,game_state
game_state = "running"
import random
print "\nFlipping a coin to see who starts first..."
random_int = random.randint(0, 1)
if random_int == 0:
coin = 'Heads'
start_player = player_A_name
end_player = player_B_name
else:
coin = 'Tails'
start_player = player_B_name
end_player = player_A_name
print '\nCoin flip --> ',coin
print '\nStarting player --> ',start_player
print '\nStarting player gets "X"'
player_names_input()
coin_flip()
Here is my failed attempt to use return instead of global:
=========================================================
def player_names_input():
player_A_name = raw_input("Please enter name for Player A : ")
player_B_name = raw_input("Please enter name for Player B : ")
return player_A_name,player_B_name
def coin_flip(player_A_name,player_B_name):
game_state = "running"
import random
print "\nFlipping a coin to see who starts first..."
random_int = random.randint(0, 1)
if random_int == 0:
coin = 'Heads'
start_player = player_A_name
end_player = player_B_name
else:
coin = 'Tails'
start_player = player_B_name
end_player = player_A_name
print '\nCoin flip --> ',coin
print '\nStarting player --> ',start_player
print '\nStarting player gets "X"'
player_names_input()
coin_flip(player_A_name,player_B_name)
1- Please help make my second code run, I really wanna avoid global variables as everyone recommends.
2- Please critique my code, I am in the beginning and I am trying to learn writing good code (not just code). How bad is my attempt?
Since you have defined player_names_input() to return a 2-tuple (the two values, player_A_name and player_B_name), you could just assign them like so in the scope you are using that function,
player_A_name, player_B_name = player_names_input()
Now, when this is called:
coin_flip(player_A_name, player_B_name)
The two variables will be available for use.
You may want to consider wrapping the actual main program in a main method like
def main():
player_A_name, player_B_name = player_names_input()
coin_flip(player_A_name, player_B_name)
And call that if that file was directly executed - this is done by checking the magic __name__ variable to equal to the string '__main__', so add this too to the end of your program file.
if __name__ == '__main__':
main()
Here is my code:
# This program makes the robot calculate the average amount of light in a simulated room
from myro import *
init("simulator")
from random import*
def pressC():
""" Wait for "c" to be entered from the keyboard in the Python shell """
entry = " "
while(entry != "c"):
entry = raw_input("Press c to continue. ")
print("Thank you. ")
print
def randomPosition():
""" This gets the robot to drive to a random position """
result = randint(1, 2)
if(result == 1):
forward(random(), random())
if(result == 2):
backward(random(), random())
def scan():
""" This allows the robot to rotate and print the numbers that each light sensors obtains """
leftLightSeries = [0,0,0,0,0,0]
centerLightSeries = [0,0,0,0,0,0]
rightLightSeries = [0,0,0,0,0,0]
for index in range(1,6):
leftLight = getLight("left")
leftLightSeries[index] = leftLightSeries[index] + leftLight
centerLight = getLight("center")
centerLightSeries[index] = centerLightSeries[index] + centerLight
rightLight = getLight("right")
rightLightSeries[index] = rightLightSeries[index] + rightLight
turnRight(.5,2.739)
return leftLightSeries
return centerLightSeries
return rightLightSeries
def printResults():
""" This function prints the results of the dice roll simulation."""
print " Average Light Levels "
print " L C R "
print "========================="
for index in range(1, 6):
print str(index) + " " + str(leftLightSeries[index]) + " " + str(centerLightSeries[index]) + " " + str(rightLightSeries[index])
def main():
senses()
pressC()
randomPosition()
scan()
printResults()
main()
So, I am getting this error when I run my program.
NameError: global name 'leftLightSeries' is not defined
I understand that I must be doing something wrong related to the return statement. I'm not sure if I can only return one variable at the end of a user-defined function. If that were to be true, then I should probably separate the scan(): function. Anyways, I would appreciate any help on how to fix this error. Also, this is the result that I am looking for when I successfully complete my program:
Click Here
I am looking to complete the average values like the picture shows, but I am not worried about them at this point, only the list of values from the light sensors. I do not need to reach those exact numbers, the numbers will vary in the simulator.
If you want to return multiple items from scan(), don't use three separate return statements. Instead, do this:
return leftLightSeries, centerLightSeries, rightLightSeries
Also, when you call the function, you have to assign variable(s) to the returned values; it won't automatically create new local variables with the same names. So in main, call scan() like this:
leftLightSeries, centerLightSeries, rightLightSeries = scan()
I wanted to create a x-y coordinate system even though this is supposed to be a text RPG as to keep track of where everything is. So, I was experimenting on making a function and test for that function that would let the character move on a x-y grid, however, no matter what I try, I cannot make it work. Here is the code:
class Player:
def movement(charactor_movement):
proceed = 0
if charactor_movement == "left":
character.position_x = character.position_x - 1
proceed = 1
elif charactor_movement == "right":
character.position_x = character.position_x + 1
proceed = 1
elif charactor_movement == "forward":
character.position_y = character.position_y + 1
proceed = 1
elif charactor_movement == "backward" or charactor_movement == "back":
character.position_y = character.position_y - 1
proceed = 1
charactor = Player()
charactor.position_x = 0
charactor.position_y = 0
proceed = 0
while proceed == 0:
print "You are at",
print charactor.position_x,
print"x and",
print charactor.position_y,
print"y."
global charactor_movement
charactor_movement = raw_input("Where are you going?")
charactor.movement()
At this point, it does what it is supposed to do up to changing the coordinates, as it prints "You are at 0 x and 0 y" and "Where are you going?" no matter what I type. I have tried adding an else to the function which it defaulted to no matter what I typed and gave me "Sorry, I cannot understand you." Any comments on fixing or generally improving the code would be appreciated.(Note: For the testing I purposely did not add a way to exit. The class is what i need fixed.)
You are getting the same coordinates with each iteration because your values within your while loop are not changing. Incrementing character.position_x within movement will never change the value of character.position_x within your while loop, as it is outside your function's scope. You have to use the global keyword within your movement function for each variable you are changing should you want your current logic to remain the same. Additionally, why not just pass charactor_movement as a parameter to your movement function, as opposed to using global as you currently are doing.
A minimal example:
Consider the following:
def somefunct(x):
mycode = x
mycode = 'no codez'
while True:
print mycode
codez = raw_input('gimme teh codez: ')
somefunct(codez)
which outputs
>>>[evaluate untitled-1.py]
no codez
gimme teh codez: codez!
no codez
Declaring mycode as global in the function places it in the scope of the while loop when assigned, thus
def somefunct(x):
global mycode #make variable global here
mycode = x
mycode = 'no codez'
while True:
print mycode
codez = raw_input('gimme teh codez: ')
somefunct(codez)
results in the output
>>>[evaluate untitled-1.py]
no codez
gimme teh codez: codez!
codez!
I am trying to make a text based game in which the user is a pilot in space. I want to create a movement system but am unsure how to do it. I want the user to be able to put in the desired grid coordinates, and his vehicle will begin to change its grid coords to get closer and closer to the ones he inputted.
Now, to do this I will probably need multithreading and a time element. But I am unsure how I can use a time element. Any advice is greatly appreciate, i'm just trying to learn here. Thanks guys!
from Gundam2 import Mobilesuits
#Main Variable/Object declarations:
Leo1=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,100,100])
Leo2=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[300,100,100])
Leo3=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,150,100])
currentmobilesuit=Leo1
#Main Function declarations
def commands(user_input,currentmobilesuit):
if user_input == "radar":
currentmobilesuit.radar()
elif user_input == "commands":
print("Command list:\nradar")
else:
print("Invalid command\nType 'commands' for a list of valid commands")
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
class Mobilesuits:
#class global variables/methods here
instances = [] #grid cords here
def __init__(self,armor,speed,name,description,cockpit_description,\
radar_range, coordinates):
Mobilesuits.instances.append(self)
self.armor=armor
self.speed=speed
self.name=name
self.description=description
self.cockpit_description=cockpit_description
self.radar_range=radar_range
self.coordinates=coordinates
def can_detect(self, other):
for own_coord, other_coord in zip(self.coordinates, other.coordinates):
if abs(own_coord - other_coord) > self.radar_range:
return False
return True
def radar(self):
for other in Mobilesuits.instances:
if other is not self and self.can_detect(other):
print "%s detected at %s" % (other.description, other.coordinates)
Games typically have a "master loop" of some kind; yours does here:
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
The simplest thing to do is to count in the loop:
#Main execution
turn_count = 0
while True:
commands(raw_input(),currentmobilesuit)
turn_count += 1
If you wanted the real time taken to have some impact on the counter, or be the counter, you can get the current time from the time module calling time.time().
#Main execution
import time
time_start = time.time()
time_elapsed = 0
while True:
commands(raw_input(),currentmobilesuit)
time_elapsed = time.time() - time_start
A couple other thoughts:
Make a Game class, and put the turn counter and game loop in that.
Have the commands function return a number that is the number of time units that took place during the command; for example, entering an invalid command might take 0 turns, while repairing a robot might take 5.
#Main execution
turn_count = 0
while True:
turns_taken = commands(raw_input(),currentmobilesuit)
turn_count += turns_taken
You can use non-blocking I/O. This will help you avoid the complications of threading. Here's your sample code implemented with a non-blocking read of stdin:
#!/usr/bin/python
import sys
import select
call_count = 0
#Main Function declarations
def commands(user_input):
global call_count
if len(user_input) > 0:
print('call count: ' + str(call_count) + ' user entered: ' + user_input)
def raw_input_no_block():
global call_count
call_count = call_count + 1
input_avail = select.select([sys.stdin], [], [], 0.1)[0] #wait for 0.1 seconds
if input_avail:
return sys.stdin.readline()
else:
return ''
#Main execution
while True:
commands(raw_input_no_block())