Passing print function within another function - python

I decided I would create a simple text-based game as a learning project for Python as this is my first time using it. I have this function slow_print that simulates human typing which works in it's current form for strings, however is it possible to pass through a function instead. As I would like to break up the game text into sections for tidiness.
def slow_print(t):
for letter in t:
sys.stdout.write(letter)
sys.stdout.flush()
time.sleep(random.random()*10.0/55)
print ('')
def intro():
print("Welcome, this is a text-based adventure game.")
print("This isn't designed for the light hearted so proceed at your own peril.")
...
...
Is this possible in Python? After playing around with the params and passing it through I got the error of "Python object is not iterableable". From my understanding strings would be iterateable. Would there be another easier way to accomplish this?
slow_print(intro())
ERROR:
Traceback (most recent call last):
File "C:\Users\CDN Admin\Python\game.py", line 20, in <module>
slow_print(intro())
File "C:\Users\CDN Admin\Python\game.py", line 9, in slow_print
for letter in t:
TypeError: 'NoneType' object is not iterable

It seems like you should rename the variable str inside the function slow_print.
str is a reserved keyword in python and it should be the cause of your error.
I have tried this solution without issues:
import sys
import time
import random
def slow_print(t):
for letter in t:
sys.stdout.write(letter)
sys.stdout.flush()
time.sleep(random.random() * 10.0 / 55)
print('')
if __name__ == '__main__':
slow_print("Welcome, this is a text-based adventure game.")

slow_print takes text and slowly prints it. For it to work, you have to give it text.
intro does not return text. It prints text directly, then automatically returns None, the default return value for functions that don't explicitly return something else. slow_print then receives None and tries to slowly print it, but None is not text.
You need to restructure your code so the text that needs to be slowly printed is passed to slow_print instead of print. That might involve giving intro a parameter to select how to print things:
def intro(printer=print):
printer("Welcome, this is a text-based adventure game.")
printer("This isn't designed for the light hearted so proceed at your own peril.")
...
...
intro(slow_print)
In this modified code, intro has a printer parameter that it will use to print things. This parameter defaults to the built-in print function, but if you pass slow_print instead, intro will use slow_print to print its messages.

slow_print(intro()) prints what intro() returns, and this function does not return anything. You can rewrite this function.
def intro():
rerurn '''Welcome, this is a text-based adventure game.
This isn't designed for the light hearted so proceed at your own peril.'''
Then your slow_print will print intro message.
P. S. If you use intro() elsewhere, you should replace intro()to print(intro()).

Related

Call functions while ending current function

So, Im coding a game, (just a simple text-based game, no fancy graphics or anything), but since im not good at coding professionally, I have everything done using functions, so that everything can call one another. this means that all functions and threads are always essentially 'loaded', I don't know the proper term.
essentially I want
def function():
print("Hello")
function()
to function as
def function():
print("Hello")
while True:
function()
but in my case, I can't do this, because I have many different functions being called from within each other in seemingly random patterns based on user input, and im worried at some point I'll hit a recursion wall, or stack overflow, or whatever it may be called.
AKA I can't use a loop because the order of the functions within the loop will vary from game to game
im pretty sure the only reason the stack overflow or whatever happens in the first scenario, is because the interpreter is yet to read any code after the function calls itself, as in if I had
def function():
print("Hello")
function()
print("goodbye")
the interpreter has yet to come back and print goodbye, therefore it gets stuck in memory
Call a function while ending the current function, and never return to read anything after
similar to I guess a "Break"
call a function and end the current function at the same time to save memory
As for me better to create some functions, and then create main function where that all will run:
def function1():
pass
def function2():
pass
def main():
print("function1")
function1()
print("function2")
function2()
if __name__ == "__main__":
main()

Slow text printing in a function?

Is there a way in Python3 to slow the text that is inside a function?
I have created a text-based game that uses almost exclusively functions for each section of the game, but want the text within to be typed out.
For example:
def room_1():
Print("You are in a foyer.")
Print("You can see a painting on the wall.")
etc.
I have already imported, sys,time and is.
I have tried putting this inside the function but it doesn't seem to work:
for char in room_1():
Sys.stdout.write(char)
Sys.stdout.flush()
Time.sleep(0.1)
You were close, but you should look up some tutorials on how iterators work with Python. print doesn't return a value and your room_1 definition also doesn't return anything so your code was not entering the for loop.
I would recommend making a function that will print slowly.
import sys
import time
def slow_print(input_str):
for c in input_str:
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\n')
def room_1():
slow_print("You are in a foyer.")
slow_print("You can see a painting on the wall.")
room_1()

Python Function requesting input doesn't execute if statement - no error shown

I thoroughly searched for an answer to my question but couldn't find anything that would explain my results. I truly hope that anyone of you can point me in the right direction.
At the moment I am trying to program a text-based adventure game using Python 3 in order to better understand the language.
While doing so I created a function that should ask the user for input and print a specific statement depending on the users input. In case the users input is invalid the function should then keep asking for input until it is valid.
Unfortunately the function only seems to keep asking for input, without ever executing the if/elif statements within the function. Due to no errors being shown I am currently at a loss as to why this is the case...
print("If You want to start the game, please enter 'start'." + "\n" +
"Otherwise please enter 'quit' in order to quit the game.")
startGame = True
def StartGame_int(answer):
if answer.lower() == "start":
startGame = False
return "Welcome to Vahlderia!"
elif answer.lower() == "quit":
startGame = False
return "Thank You for playing Vahlderia!" + "\n" + "You can now close
the window."
else:
return "Please enter either 'r' to start or 'q' to quit the game."
def StartGame():
answ = input("- ")
StartGame_int(answ)
while startGame == True:
StartGame()
You fell into the scoping trap: you are creating a new variable startGame inside the function that is discarded after you leave it. You would instead need to modify the global one:
def StartGame_int(answer):
global startGame # you need to specify that you want to modify the global var
# not create a same-named var in this scope
# rest of your code
This other SO questions might be of interest:
Python scoping rules
Asking the user for input until they give a valid response
Use of global keyword
and my all time favorite:
How to debug small programs (#1) so you enable yourself to debug your own code.
The last one will help you figure out why your texts that you return are not printed and why the if does not work on 'r' or 'q' and whatever other problems you stumble into. It will also show you that your if are indeed executed ;o)
Other great things to read for your text adventure to avoid other beginner traps:
How to copy or clone a list
How to parse a string to float or int
How to randomly select an item from a list

Running functions from a list issue

I am wondering how to run functions from a list, and calling them using the random module, but I can't seem to get it to work can anyone help? Here is an example below.
import random
def word1():
print "Hello"
def word2():
print "Hello again"
wordFunctList = [word1, word2]
def run():
printWord = random.randint(1, len(wordFunctList))-1
wordFunctList[printWord]
run()
run()
So I wanted to do this in an infinite loop, but all I get for output is
Hello
Hello again
Then the program just doesn't do anything else? Can anyone help me? Btw, I am using the app pythonista. Also I am a programming NOOB. I just recently started with python.
The whole reason I am asking this question is because I am making a text based world generator, and I want to define functions for biomes, then randomly call them from a list while the world is generating.
I'd do it this way:
import random
def word1():
print "Hello"
def word2():
print "Hello again"
wordFunctList = [word1, word2]
def run():
# Infinite loop, instead of recursion
while True:
# Choose the function randomly from the list and call it
random.choice(wordFunctList)()
run()
Read this answer. It explains why you should avoid tail recursion and use infinite loop instead.
Explanation on random.choice(wordFunctList)():
wordFunctList is a list with function objects:
>>> print wordFunctList
[<function word1 at 0x7fcb1f453c08>, <function word2 at 0x7fcb1f453c80>]
random.choice(wordFunctList) chooses the function and returns it:
>>> random.choice(wordFunctList)
<function word2 at 0x7f9ce040dc80>
random.choice(wordFunctList)() calls the returned function:
>>> print random.choice(wordFunctList)()
Hello again # Outputs during the function call
None # Returned value
With extra parentheses (random.choice(wordFunctList)()()), you were calling the returned value of the function, that is None, but None is not callable and that's why you were getting the error.

Can I insert deletable characters in python input buffer?

I want to automatically indent the next line of a console app but the user needs to be able to remove it. sys.stdout.write and print make undeletable characters and I can't write to sys.stdin (as far as I know). I'm essentially trying to get smart indenting but I can only nest deeper and deeper. Any ideas on how to climb back out?
Edit: I should have noted that this is part of a Windows program that uses IronPython. While I could do something much fancier (and might in the future), I am hoping to quickly get a reasonably pleasant experience with very little effort as a starting point.
The cmd module provides a very simple interface for creating a command line interface to your program. It might not be able to put some buffer characters in front of the next line but if you're looking for an obvious way to let your users know that the command has returned, it can provide a shell-like prompt at the beginning of each line. If you already have functions defined for your program, integrating them into a processor would be a matter of writing a handler that access the function:
import cmd
import math
def findHpyot(length, height):
return math.sqrt(length **2 + height **2)
class MathProcessor(cmd.Cmd):
prompt = "Math>"
def do_hypot(self, line):
x = raw_input("Length:")
y = raw_input("Height:")
if x and y:
try:
hypot = findHypot(float(x), float(y))
print "Hypot:: %.2f" %hypot
except ValueError:
print "Length and Height must be numbers"
def do_EOF(self, line):
return True
def do_exit(self, line):
return True
def do_quit(self, line):
return True
if __name__ == "__main__":
cmdProcessor = MathProcessor()
cmdProcessor.cmdloop()
Things to consider when writing an interactive shell using cmd
The name after do_ is the command that your users will use so that in this example, the available commands will be hypot, exit, quit, and help.
Without overriding do_help, calling help will give you a list of available commands
Any call that you want to quit the program should return True
If you want to process entries from the function call, say you wanted to be able to handle a call like "hypot 3 4" you can use the local line variable in the function call

Categories

Resources