calling defined functions in another function in Python3 - python-3.x

I am just starting to code. Got a job as a junior developer thanks to other skills. And right now I am self studying to learn Python 3, Django and React. I am 3 weeks in, and i like it thus far.
While learning to code i found some exercises to do and gave my own swing at it. So I am trying to make kind of a lite rpg, where the player and comp chooses an attack and it gets executed in random order.
But i am having trouble making the attacks and everything else to be in callable functions. I could write out the whole code to the length of times, but i want to make it easier to code and expand on. This is what i have at the moment. I think the mistake is in the parameters in the functions? Which make some local instead of global values.
anyways, thank you in advance.
So i tried a lot of different parameters in different places. cant figure it out. also tried to call the move functions inside the player_move function.
import random
def tackle():
dmg = random.randint(150, 280)
return dmg
def bite():
dmg = random.randint(110, 350)
return dmg
def heal():
dmg = random.randint(130, 260)
return dmg
player_health = 1000
comp_health = 1000
alive = True
def player_move():
move = input("Use one of the following moves: \n"
"1. Tackle\n"
"2. Bite\n"
"3. Heal\n"
"Choose the Move: ")
if move == 1 or move == "Tackle" or move == "tackle":
comp_health -= tackle()
elif move == 2 or move == "Bite" or move == "bite":
comp_health -= bite()
elif move == 3 or move == "Heal" or move == "heal":
comp_health -= heal()
return comp_health
player_move()
print(comp_health)

So i figured a few things out. Most of it was in the scope of the functions. Had to call the functions before using them. I ended up rewriting most of it, but got it to work. (edit) The question still stands though. How can I call a function out of scope??

Related

How do I get data from one function to another

I read about "random" and it got me thinking about helping my kid in reading and writing by making a program where a word is shown and she needs to type it. Because it's a small program I could do it quite easliy with procedural programming, but to make it more 'attractive' to her I decided to fool around with tkinter.
Tkinter forces to create functions which can be called through 'command' and now I have a problem.. If I run the check() function, it doesn't get the variables from the dictee() function. I found several answer from nesting a function in a function (undefined variable problems), or passing arguments with return (ended up in recursion), using global (the list of words wouldn't empty) etc etc.. I couldn't get any of them working... I've been looking for answers, but I can't find the correct solution.. Anyone care to shed their light?
Thanks!
"""import nescessary."""
import sys
import random
def main():
"""Setting up the game"""
print("Aliyahs reading game.'\n")
begin = input("do you want to start? yes or no.\n\n")
if begin == "yes":
dictee()
def dictee():
"""Show random words and ask for input."""
words_correct = 0
words_wrong = 0
vocabulary = ['kip', 'hok', 'bal', 'muis', 'gat'
]
words_passed = []
while True:
if vocabulary == []:
print("\n\nThose were all the words.")
print("Words correct: %d" % words_correct)
print("words wrong: %d" % words_wrong)
one_more_time = input("Do you want to go again? yes or no")
if one_more_time == "no":
print("See you next time.")
input("\nPush enter to close.")
sys.exit()
else:
main()
word = random.choice(vocabulary)
print('\x1b[2J')
print("{}".format(word))
print("\n\n")
words_passed.append("{}".format(word))
vocabulary.remove("{}".format(word))
answer = input("Write the word you saw:\n\n")
check()
def check():
'''Cross check word shown with answer given'''
if answer == word:
print("Nice")
words_correct += 1
else:
print("2bad")
words_wrong += 1
try_again = input("\n\nContinue? yes or no\n ")
if try_again.lower() == "no":
exit_game()
else:
dictee()
def exit_game():
'''summarize results and exit after pushing enter'''
print("Words correct: %d" % words_correct)
print("Words wrong: %d" % words_wrong)
input("\nPress Enter to exit.")
sys.exit()
if __name__ == "__main__":
main()
Ive just made few changes here, and run it and got no errors because I dont know what to type in order to get the right results. Anyways all the changes are related to global and redefinition of values.
# say these outside all the functions, in the main block
words_correct = 0
words_wrong = 0
vocabulary = ['kip', 'hok', 'bal', 'muis', 'gat']
words_passed = []
def dictee():
global word, answer
..... #same bunch of codes
def check():
global answer, words_correct, words_wrong
.... #same bunch of codes
Why do we have to say global? Basically because when we define variables they either get defined on local scope or global scope, variables defined on main block(outside of all function) are on global scope, while inside functions are on local scope. Variables defined on global scope can be accessed anywhere and that on local can only be accessed from within where its defined.
Where do we have to use global? We say global where we define the variable or we redefine, or at least this is what I know of. We need to say global where we declare the variable, like, a = 'good', we also need to say global if we are changing it, a = 'bad' or a += 'day' because we are assigning a new value to it. Using global outside of all functions, on the main block, is useless.
Why are we declaring words_correct and words_wrong outside all functions? It is simply because if you declare and set its value to 0 inside dictee(), each time the function is run the value of those variables will change to 0, which means score will always be 0 or 1, so we define it once only, in the main block. Same logic applies to the two lists(vocabulary and words_passed), each time function runs they reset the list to the full list of words, so to get rid of that, just define it once in the main block.
I also think using parameters here might need re-structuring of your code as your calling both function from each other.
Note that we only say global on functions, out side functions all defined variables are open to global scope and can be accessed from anywhere in the code.
PS: This is just my understanding of global over the span of 4 months, do correct me if im wrong anywhere, thanks :D

I am having trouble understanding the flow of programming

I am new to programming and one of the problems I have run across is structuring. I am learning Python (3) and am practicing by making a few practical programs. An issue I am running in to is how to get the right flow to the program. I find that as I write a function, I realize that I need it to lead to another function, so I end up calling the next function at the end of the function I'm writing. Then I realize that Python will read the code line-by-line, so I have to have the function I will be calling above the one I am actively writing. The effect is that I end up writing the program in reverse. For example:
#Replaces letters in chosen word with X's
def display_word():
selected_word = list(selected_word)
for x in selected_word:
x = "X"
print (x)
#Function that will display the welcome message when program launches
def start_screen():
user_input = input("Hello and welcome to Hang Man! If you would like to
start a game, please enter 'YES' now!")
user_input = user_input.upper()
if user_input == "YES":
display_word()
else:
print ("You're no fun!")
start_screen()
This is a little tid-bit that I have written in a hang-man program I am practicing with. I started out writing the start_screen function, then realized that I will need to call the display_word function within the start_screen function, but to do that, I will have to define the function before it is called, so I have to write the display_word function above the start_screen function, which effectively has me moving in reverse. My question is whether this is the way things go or if there is a better way to do things. It seems like writing the code in reverse is inefficient, but I am unsure if that is just my inexperience talking.
All functions in Python must be defined before they are used. That does not mean that the function has to be listed above the one it is called from.
The functions can be defined in any order. You just have to make sure the executable portions that start your program, like start_screen(), are called below where the function is defined.
In the case of your hangman program, you are perfectly safe to switch the order of the two functions.
In general, if you have all of your executable code following all of your function definitions, you are good to go to keep them in any order you choose!
Example:
This is perfectly ok. You can even switch them!
def fn1():
print('I am function 1')
fn2()
def fn2():
print ('I am function 2')
fn1()
This is bad!
fn1() #not defined yet!
def fn1():
print('I am function 1')
def fn2():
print ('I am function 2')
This is also bad!
def fn1():
print('I am function 1')
fn2() #not defined yet!
fn1()
def fn2():
print ('I am function 2')

Instance variable resets after modification

I'm having difficulty with one small part of my code. I'm modifying a player's HP while they're in combat, but when exiting combat the HP resets to 100. This is odd because the enemy's HP is preserved. By using print(id(player.hp)) I can see that a new instance of player.hp is being created, I just don't know why. I've tried googling the issue but I can't find an example that fits my problem. I'll try to only include the pertinent parts of the code below (there's a lot of superfluous writing that isn't necessary here), but if I need to include everything I will.
class Alleyway(Scene):
room_items = []
room_characters = []
room_enemies = ["hobo"]
def __init__(self):
self.fresh_arrival = True
self.north = False
self.east = True
self.south = True
self.west = False
self.enemy = Hobo()
def fight(self, player, weapon): #Lots of what makes this fun is edited out
while True:
if self.enemy.hp > 0:
print("Do you attack or flee?")
words = input("> ").lower()
if words == "flee":
map_ = Map("alleyway")
game = Engine(map_)
game.play()
if words == "attack":
miss = randint(1,4)
if miss == 1:
print("Too bad, you miss!")
else:
print("You got him!")
self.enemy.hp -= weapon.damage
print("Hobo's HP: {}".format(max(self.enemy.hp, 0)))
if self.enemy.hp > 0:
print("The hobo takes a swing at you.")
hobomiss = randint(1,5)
if hobomiss == 1:
print("He missed!")
else:
print("Ouch, he got you!")
player.hp -= self.enemy.damage
print("Your HP: {}".format(max(player.hp, 0)))
else:
print("No idea what you mean. Attack the man or flee.")
else:
print("You defeat the hobo!")
print()
print("Dirty shoes and shank added to inventory.")
print()
shoes = DirtyShoes()
shank = Shank()
player.inventory.append(shoes)
player.inventory.append(shank)
self.room_enemies.remove("hobo")
map_ = Map("alleyway")
game = Engine(map_)
game.play()
When fight() is called, an instance of Player() is sent in as an argument, which has an instance variable of self.hp = 100.
This is still a work in progress so please gloss over the fact that it doesn't exit when the player dies and other silly things like that (:
Now, when the player flees in the middle of the fight, my goal is for the enemy's HP to be preserved, the player's HP to be preserved, and the items to be added to the player's inventory. So far, the enemy's HP is accurately preserved and everything else in my code regarding the enemy's HP and his alive/dead status work great when combat is exited. My issue is with player.hp -= enemy.damage, player.inventory.append(shoes), and player.inventory.append(shank). None of them work. The player.hp displays correctly during the fight and decreases as expected, however once the player exits combat the HP is reset to 100 and there is nothing added to the inventory. I've tried player.hp = player.hp - enemy.damage for the HP issue and it still creates a new variable. I'm just not sure what's going on since the enemy portions are working fine.
If more information is needed please let me know. And if there are any obvious ways my code can be improved I'm totally open to suggestions.
Got it! I was defining player = Player() inside of a method, so it only created the instance for that method (I think). So I defined it outside of the method and now the modified values stick!

How to create a Button Listener in TKinter

I am trying to make a simon says game and am having trouble collecting the users choice to compare against the computer's pattern. I am using four buttons to select the colors that flash on the screen. The problem I am having is my program continues to chug along even if my user hasn't selected a color yet, despite my best efforts to stop it, what can I do to stop the program? Here is my code...
Sequence[]
PosColors = ["Yellow","Red","Blue","Green"]
PlayerChoice[]
Score = 0
def Game(Sequence, PlayerChoice,Score):
Score += 1
PlayerChoice = []
Number = randint(0,3)
Sequence.append(PosColors[Number])
for i in Sequence:
RunTime = Score * 1000
Gui.after(1000, blink, rect, SquareCanvas , i)
RunTime = (Score + 1) * 1000
Gui.after(2000, blink, rect, SquareCanvas , White)
X = len(Sequence)
Index = 0
Color = " "
while Color != " ":
BlueButton.config(command = partial(setSelection,NeonBlue))
RedButton.config(command = partial(setSelection,NeonRed))
YellowButton.config(command = partial(setSelection,NeonYellow))
GreenButton.config(command = partial(setSelection,NeonGreen))
Color = getSelection()
print(Color)
while Color != " ":
PlayerTurn(Sequence,PlayerChoice,Score,Index)
X -= 1
Index +=1
def setSelection(Color):
if Color == NeonBlue:
return "NeonBlue"
elif Color == NeonRed:
return "NeonRed"
elif Color == NeonGreen:
return "NeonGreen"
elif Color == NeonYellow:
return "NeonYellow"
def getSelection():
return TheColor
def PlayerTurn(Sequence, PlayerChoice,Score,Index):
PlayerChoice.append(Color)
print(PlayerChoice)
Label1.config(text = 'Well done! \nYou advance to the next round!')
I am planning on passing this through a checker and to loop it until there is an error but I need to get past this front loop first... I know my logic works as I created it using just lists and the command line before moving on the the graphical portion I just need to know how to get the program to stop to collect the user guess, especially as the length of the pattern gets larger. Originally I had the command function included later where I build my Buttons but this placement seems to get as close as possible to what I am looking for. Any help is appreciated thank you
You're going to need to rethink your main program logic. Tkinter is designed such that you should never have your own infinite loop. Tkinter already has an infinite loop -- the mainloop() method of the root window. You can't write logic that waits for input from the user. You have to think of the GUI as in a perpetual state of waiting, and you need set up handlers (button callbacks or event bindings) to react to events.
You also need to understand that a button command can't "return" anything. "Can't" is a bit strong since it obviously can, but there's nothing waiting for the result -- no place to return it to. You need to design your button function such that it sets a global or instance variable.

Is there a way to bring lists and variables through a file import in python?

So, the title may seem vague, so I'm going to describe it in more detail here. I'm writing a space-themed text-based game as a project, and I've reached various problems. I'm trying to use multiple files to simply everything, and so, say I have these variables in file 1:
player_health = 100
o2 = 100
And that's fine and it works and all, but in the first file I have, I have an ever-growing check() function available (so the player can see game info), so I made another file to handle loops. In the second file, I have this, for example:
while True:
if o2 == 0:
time.sleep(2)
player_health = player_health -1
and for the player,
while True:
if player_health = 0
print(game_over)
Right now, o2 and player_health are set to 100 as variables. Game_over is a string I made, but that doesn't really matter currently. I defined o2 and player_health in file 1, say, and when I import file 2, they don't seem to work any more. Remember the While loops are handled in File 2. I could just put it all in one file, but then It would be harder for me to bugfix. The reason I'm doing this is so that I can handle the start and the loops and the actual story part separately, and add or remove loops as I see fit without having to sift through tons of code, like I would probably have to if it was all in a single file.
There's a lot of source code, So I'll just post snippets from file one and two. If you want to see all of the source code from both files, I could post it somehow, but there would be a lot.
File One Snippets:
(This is at the beginning of file one, which is named VortexA)
o2 = 100
nitrogen = 100
ship_store = []
player_inv = [] #These Lists and variables handle levels of life support and storage.
air = [o2, nitrogen]
ship_weapons = []
currency = 5
power = 0
He_3 = 0
ship_health = 0
player_health = 100
ship = False
(This is at the end of file one. Just adding it here)
print("Type start(game) to begin")
game = 1
def start(variable):
if game == 1: # This starts the game. Don't want everything in one file.
import vortexB
File 2 (vortexB) Snippets
I already posted some of the loops using variables above, but I'll post the errors I get here.
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
start(game)
File "C:\Users\Daniel\Desktop\Python Stuff\Python Game\vortexa.py", line 87, in start
import vortexb
File "C:\Users\Daniel\Desktop\Python Stuff\Python Game\vortexb.py", line 25, in <module>
print(player_health)
NameError: name 'player_health' is not defined
TL;DR:
Basically, I don't know if it's possible to import variables into another python file through the
import file
function. I'm trying to keep my game simple and easy to fix if something goes wrong by having separate files to handle loops and story.. If that's possible. If it's not, I'm going to have one hell of a messy file...
I'm just going to have the first file handle a tutorial-type thing, the second handle loops, and the third handle game-play elements.The way I want it set up is so that the variables are declared during a tutorial, and then the loops are in effect, and then I want the actual game to start. I feel like I'm missing something really simple, or what I'm trying to do is impossible. I strongly feel that it's something to do with o2 and nitrogen being stored in the air list, but that doesn't really explain player_health not being able to work. If it won't work at all, I'll see if there is another way to do it, like putting it all in one file.
Thanks in advance. Any and all help is appreciated.
Honestly, it sounds like you need a separation of concerns.
As for the title of this article goes, yes. You can import variables (lists, strings, objects, etc.) from specific files.
If you have a file constants.py:
class Player:
health = 100
power = 12
# etc
def __init__(self, name, power):
self.name = name
if power:
self.power = power
#property
def is_ded(self):
if self.health < 0:
return True
return False
And then inside of battle.py:
from constants import Player
me = Player('Kris', 500)
mic = Player('A microphone', 0)
def do_battle(player1, player2):
player1.health = player1.health - player2.power
player2.health = player2.health - player1.power
do_battle(me, mic)
mic.is_ded
# >>>True
me.is_ded
# >>>False
This is built into Python. Congratulations for picking the best language.

Resources