Python (linux) Text based game input error - python

I have been working on a text-based adventure game. I've revised it a few times and can't seem to get the outcome I want, when I attempt to create EVENTS rather than simply relying on an abundance of PRINT strings. Whenever I choose the option I want (door 1 in this case), then the following options, the input is unresponsive or gives me an error. Below is a portion of the code for door 1. A little clarity would be appreciated!
def main():
import sys
from colorama import init
init()
init(autoreset=True)
from colorama import Fore, Back, Style
def run_event(event):
text, choices = event
text_lines = text.split("\n")
for line in text_lines:
print(Style.BRIGHT + line)
print()
choices = choices.strip()
choices_lines = choices.split("\n")
for num, line in enumerate(choices_lines):
print(Fore.GREEN + Style.BRIGHT + str(num + 1) + ". " + line)
print()
return colored_input()
def colored_input():
return input(Fore.YELLOW + Style.BRIGHT + "> ")
print ("")
print ("")
print (" WELCOME TO THE MAZE ")
print ("")
print ("")
print ("You have found yourself stuck within a dark room, inside this room are 5 doors.. Your only way out..")
print ("")
print ("Do you want to enter door 1,2,3,4, or 5?")
print ("")
EVENT_DOOR1 = ("""
Theres an alien eating what appears to be a human arm, though its so damaged it's hard to be sure. There is a knife next to the alien.
what do you want to do?
""","""
Go for the knife
Attack alien before it notices you
""")
EVENT_ALIEN = ("""
You approach the knife slowly, While the alien is distracted. You finally reach the knife, but as you look up, the alien stares back at you.
You make a move to stab the alien, but he is too quick. With one swift motion, the alien thrusts you into the air.
You land hard, as the alien makes it's way towards you again. What should you do?
""", """
Accept defeat?
Last ditch effort?
""")
EVENT_ALIEN2 = ("""
You catch the alien off-guard. He stumbled and hisses in your direction. You scream in terror before he grabs the knife, and punctures your throat as he rips off your limbs.")
You died.. GAME OVER.. Mistakes can't be made this soon.. OUCH
""")
door = colored_input()
if door == "1":
run_event(EVENT_DOOR1)
alien = colored_input()
if alien == "1":
run_event(EVENT_ALIEN)
elif alien == "2":
run_event(EVENT_ALIEN2)
restart=input("Start over? Yes or No? ").lower()
if restart == "yes":
sys.stderr.write("\x1b[2J\x1b[H")
main()
else:
exit()
main()

You run_event function unnecessarily makes another call to colored_input() when it returns, causing the unresponsiveness as the script waits for another input. Remove the return colored_input() line and your code would work.
Also note that you should add a comma to the single-item tuple assigned to EVENT_ALIEN2; otherwise it would be evaluated as a string:
EVENT_ALIEN2 = ("""
You catch the alien off-guard. He stumbled and hisses in your direction. You scream in terror before he grabs the knife, and punctures your throat as he rips off your limbs.")
You died.. GAME OVER.. Mistakes can't be made this soon.. OUCH
""",)

Related

i need some assistance my text based game

Is there a way to make my code repeat after a "death" in my text based game without a systemexit.exit()?
I have tried to search loops but nothing, I have looked at other games online, and I have searched this website for anything that can help
if option==1:
print('\nyou break the front bericade but as you walk in you see a laser streatching across the door frame a little too late, you died')
thisdict["death"] = True
print('\nyou died')
SystemExit.exit()
I want it to just say you died then start you at the beginning and say so, but a system exit doesn't do that very well.
Use a loop, prepare your games state dictionary and call your game-function.
When you die, return out of it, ask for continue and create a "new" game state dict:
def game(starter):
# do stuff
lr = input(f"Hello {starter['name']} - nothing to see but go Left or Right? [L,R]: ").lower()
if lr == "left":
return # doing anything is futile, you die anyhow
else:
return # doing anything is futile, you die anyhow
def main():
state = {"name": "someone"}
while True:
game(state)
if not input("You are dead - Play again? [y,n]").lower() == "y":
break
# create new games state dict (just altering the name here)
state["name"] += "_again"
print("bye")
main()
Output:
Hello someone - nothing to see but go Left or Right? [L,R]: l
You are dead - Play again? [y,n] y
Hello someone_again - nothing to see but go Left or Right? [L,R]: r
You are dead - Play again? [y,n] y
Hello someone_again_again - nothing to see but go Left or Right? [L,R]: nothing
You are dead - Play again? [y,n] n
bye

Python: My code repeats itself after it should have finished

I am writing a rock, paper, scissors game in Python but my code doesn't work as it should. I'm new to Python so please let me know if my code isn't formatted corectly. The game runs fine, assuming you enter one of the already existing answers. However, if you enter one that is different, the code seems to loop randomly after the 'end()' function is executed.
Here is my code:
# imports needed files
from random import randint
import time
# creates a function that ends the game
def end(cpuScore,playerScore):
time.sleep(1)
cont = input("Would you like to play again? (y or n)\n")
if cont=="y":
time.sleep(1)
start()
else:
print("Well... That's a bit rude.")
# creates a function to play the game
def rps(cpuScore,playerScore,num):
# loops code 3 times (unless 'num' is different)
for x in range(num):
num-=1
# creates options
options = ["rock","paper","scissors"]
# picks a random choice for cpu
cpu = options[randint(0,2)]
# asks the player to choose
player = input("rock, paper or scissors?\n")
# why not gun?
if player=="gun":
result = "w"
elif player==cpu:
result = "d"
elif player=="rock":
if cpu=="paper":
result = "l"
if cpu=="scissors":
result = "w"
elif player=="paper":
if cpu=="scissors":
result = "l"
if cpu=="rock":
result = "w"
elif player=="scissors":
if cpu=="rock":
result = "l"
if cpu=="paper":
result = "w"
# if they choose something other than rock, paper, scissors or gun
else:
print("That's an invalid input!")
# adds one to num so that this round is not counted as one of the 3
num+=1
# plays the game again with the amount of rounds remaining
rps(cpuScore,playerScore,num)
# tells the player how they did
if result=="w":
playerScore+=1
time.sleep(1)
print("Fine! You win! Your silly " + player + " beat my " + cpu + "!!!")
if result=="l":
cpuScore+=1
time.sleep(1)
print("Ha! Sucker!! My epic " + cpu + " smashed your measly " + player + "!!!")
if result=="d":
time.sleep(1)
print("Ah! We drew by both choosing %s! Like they say, great minds think alike!" % cpu)
# announces the scores
print("You are on %s and the computer is on %s!" % (playerScore,cpuScore))
# ends the game after 3 rounds
end(cpuScore,playerScore)
# creates the funtion that sets the variables and starts the game
def start():
result=""
cont=""
cpuScore=0
playerScore=0
rps(cpuScore,playerScore,3)
# begins the game
start()
Thanks
Basically your rps function loops num times, with num = 3 initially. If the user enters an incorrect input, you call back the function, which starts the whole process again, in a new context, for num+1 times.
Thus if you answer wrong the first time you have at least six games to play: four new added and the two initial ones you didn't try to play.
My advice try first to do a program that do one and only one iteration of the rock-paper-scissor game. Adding more iteration is a simple fact of adding a global loop.

python global name not defined after transition to classes

I've found a few versions of this question on the site, but none of the answers quite give me an answer I understand (this question is the closest, but the 'already answered' answer seemed to go off in a different direction).
I'm working my way through the learn python the hard way book and have gotten to the point where I'm trying to build a simple combat system for a game. The good news is that it seems to work when I leave it as a stand alone program. The bad news is that it breaks as soon as I try and add it as a class. I can add the full code if it is helpful, but I think the question is essentially related to code that looks like this:
class Room1(Scene):
def kick():
#things happen here
def start():
move = raw_input("> ")
if move == "kick":
kick()
start()
This worked fine when it was just a standalone set of defs, but now that I've added classes it throws up a global name error when move == kick. What am I missing?
Thanks in advance, sorry if there is an obvious answer that I'm missing.
Thanks to everyone for the quick responses! It looks like it may be helpful for me to add the entire code. Just to be clear, this is part of a larger game modeled on example 43 from Learn Python the Hard Way. I very much appreciate the suggestions on improving the structure, but my sense right now is that I want to figure out why this doesn't work with the structure I almost understand before moving on to change more things. Of course, I'm more than willing to accept an answer of "what you are trying to do does not fit in the structure you are trying to use."
When I run the code below as part of a larger structure (in the interest of space I won't paste the entire thing, but the game engine structure is linked to above) I get the error I described. I tried adding 'self.start()' or 'Room1.start()' I get errors that name 'self' or name 'Room1' is not defined.
class Room1(Scene):
gothon_power = 500
move_points = 10
damage = 0
def kick(self):
global gothon_power
global move_points
global damage
damage = randint(10,201)
gothon_power = gothon_power - damage
move_points = move_points - 2
result()
def punch(self):
global gothon_power
global move_points
global damage
damage = randint(1, 101)
gothon_power = gothon_power - damage
move_points = move_points -1
result()
def result(self):
if gothon_power > 0 and move_points > 1:
print "You did %s damage." % damage
print "The Gothon is down to %s health points." % gothon_power
print "You are down to %s move points." % move_points
print "\n"
print "What's your next move?"
move = raw_input("> ")
if move == "kick":
kick()
elif move == "punch":
punch()
else:
print "This isn't going to go anywhere unless you type 'kick' or 'punch'"
print "\n"
result()
elif gothon_power > 0 and move_points == 1:
print "You did %s damage." % damage
print "The Gothon is down to %s health points." % gothon_power
print "You are down to %s move points." % move_points
print "\n"
print "What's your next move? Remember, you only have 1 move point."
move = raw_input("> ")
if move == "kick":
print "You don't have enough move points for a kick."
print "\n"
result()
elif move == "punch":
punch()
else:
print "This isn't going to go anywhere unless you type 'kick' or 'punch'"
print "\n"
result()
elif gothon_power < 1 and move_points > 0:
print "Congratuations, you killed the Gothon!"
return 'room2'
else:
print "The Gothon still has health but you don't have moves."
print "You know what that means."
print "\n"
print "The Gothon killed you."
return 'death'
def start(self):
print "It is time to fight the Gothon"
print "First, let's pause to explain the fighting rules."
print "\n"
print "The Gothon has 500 health points."
print "You have 10 move points."
print "\n"
print "Kicks cost 2 move points and do between 10 and 200 points of damage."
print "Punches cost 1 move opint and do between 1 and 100 points of damage."
print "\n"
print "If you get rid of all 500 Gothon health points before you run out of"
print "move points you win. If you run out of move points before the Gothon"
print "moves out of health points you lose."
print "\n"
print "What's your first move?"
move = raw_input("> ")
if move == "kick":
kick()
elif move == "punch":
punch()
else:
print "This isn't going to go anywhere unless you type 'kick' or 'punch'"
start()
start()
A proper set of methods on a class will look like:
class Room1(Scene):
def kick(self):
#things happen here
def start(self):
move = raw_input("> ")
if move == "kick":
self.kick()
Room1().start()
But you might want to rethink your design a little bit. It really doesn't make sense for a Scene to query for input. You'll have to replicate that code in every room in your game.
Think about this kind of top-level driver for a minute:
game = Game()
starting_room = FrontPorch()
game.move_to(starting_room)
while not game.is_over():
move = raw_input("> ")
cmd, args = move.split(None, 1)
game.current_room.do_command(cmd, args)
Then let each room process the commands that it does specially. At the base level Room class, you can implement commands that are common to most rooms, like "GOTO", "LOOK", "WHERE", etc. Then rooms that allow kicking would override do_command and include logic like you have now.
Here is a presentation I gave at PyCon '06 on writing a text adventure. Skip over the parsing stuff, and go to the part where the game/room/items design is described. You don't have to follow this design verbatim, but you might get some ideas about how your objects and classes will interact. Think about that before actually diving in to write a lot of code.
You can't execute instance methods of a class, without creating an instance. For example, you could instead write:
class Room1(Scene):
def kick(self):
#things happen here
def start(self):
move = raw_input("> ")
if move == "kick":
self.kick()
room = Room1()
room.start()
However, I don't recommend using a class at all in this case. Classes are meant to give a way to represent your own custom objects with state. For example, you could have a Monster class with attributes damage, name, etc.
For this example that you show, it's probably better to just use a function for Room1.
To call kick() as a method you need to use the self.<method Name> syntax and add self as the first argument to it:
def kick(self):
#things happen here
print('kicking')
#call method
self.kick()
or additionally make kick() a static method by calling simply
A.kick()

changing variables in one function from another function

I'm working on a text based adventure game in python. Nothing super fancy. I want to have a lever in 2 different rooms unlock a gate in a third room. Both levers need to be pulled in order for the gate to be unlocked.
here are the two rooms with the levers.
def SnakeRoom():
choice = raw_input("> ")
elif "snake" in choice:
FirstRoom.SnakeLever = True
print "As you pull the lever... You hear something click down the hall behind you."
SnakeRoom()
elif "back" in choice:
FirstRoom()
else:
dead("Arrows shoot out from the walls. You don't make it.")
def WolfRoom():
choice = raw_input("> ")
elif "wolf" in choice:
FirstRoom.WolfLever = True
print "As you pull the lever... You hear something click down the hall behind you."
WolfRoom()
elif "back" in choice:
FirstRoom()
else:
dead("Arrows shoot out from the walls. You don't make it.")
Here is the room with the gate.
def FirstRoom():
Lever = WolfLever and SnakeLever
choice = raw_input("> ")
if "straight" in choice and Lever != True:
print "You see a large gate in front of you. The gate is locked, there doesn't seem to be any way to open it."
FirstRoom()
elif "straight" in choice and Lever == True:
SecondRoom()
elif "left" in choice:
WolfRoom()
elif "right" in choice:
SnakeRoom()
elif "lever" in choice:
print "WolfLever: %s" % WolfLever
print "SnakeLever: %s" % SnakeLever
print "Lever: %s" % Lever
FirstRoom()
I shortened the code so you don't have to read through all the unnecessary stuff.
My biggest problem is I'm not super familiar with the Python language yet, so I'm not sure how to word everything to find the answers I'm looking for.
edit: Instead of FirstRoom.WolfLever I also tried just using WolfLever, in the body of my code, above Start() I have:
WolfLever
SnakeLever
Lever = WolfLever and SnakeLever
But my functions weren't updating these values. So I tried the FirstRoom. approach.
Credit to #Anthony and the following link: Using global variables in a function other than the one that created them
Globals definitely were the answer (With the exception of using classes). Here's what my WolfRoom() and SnakeRoom() functions look like now:
def WolfRoom():
global WolfLever
choice = raw_input("> ")
elif "wolf" in choice:
WolfLever = True
print "As you pull the lever... You hear something click down the hall behind you."
WolfRoom()
For FirstRoom() I added
global Lever
to the beginning of the function and right before Start() I have
WolfLever = False
SnakeLever = False
this way I have no errors or warnings (Was getting syntax warnings for assigning a value to my levers before declaring them as global) and everything works perfectly.

resetting raw_input within a while loop (python)

So I'm trying to get this engine to work, and I did, but it's broken my program. (from LPTHW)
I am basically trying to access a function where it gets an input from the user 11 times, if the user fails to guess the correct input, they die (in game) but my fix for sending the prompts from the engine to the functions, seemed to break the function where I get an input 11 times and just uses the same guess for all 11 inputs.
Here is the main engine
globvar = ' '
class Game(object):
def __init__(self, start):
self.quips = [
"You died. You kinda suck at this.",
"Your mom would be proud. If she were smarter.",
"Such a luser.",
"I have a small puppy that's better at this."
]
self.start = start
def play(self):
# next_room_name is taken from init argument start
next_room_name = self.start
while True:
global globvar
print "\n--------"
# set variable room to get function from next_room_name
room = getattr(self, next_room_name)
print room.__doc__
if room == self.laser_weapon_armory:
prompt = raw_input("[keypad]> ")
elif room == self.escape_pod:
prompt = raw_input("[pod #]> ")
else:
prompt = raw_input("> ")
globvar = prompt
# unpacks function from next_room_name into room
next_room_name = room()
And here is the function im trying to get to work
def laser_weapon_armory(self):
"""
You do a dive roll into the Weapon Armory, crouch and scan the room
for more Gothons that might be hiding. It's dead quiet, too quiet.
You stand up and run to the far side of the room and find the
neutron bomb in its container. There's a keypad lock on the box
and you need the code to get the bomb out. If you get the code
wrong 10 times then the lock closes forever and you can't
get the bomb. The code is 3 digits.
"""
code = "%d%d%d" % (randint(1,9), randint(1,9), randint(1,9))
guess = globvar
guesses = 0
while guess != code and guesses < 10:
print "BZZZZEDDD!"
guesses += 1
guess = globvar
if guess == code:
print "The container clicks open and the seal breaks, letting gas out."
print "You grab the neutron bomb and run as fast as you can to the"
print "bridge where you must place it in the right spot."
return 'the_bridge'
else:
print "The lock buzzes one last time and then you hear a sickening"
print "melting sound as the mechanism is fused together."
print "You decide to sit there, and finally the Gothons blow up the"
print "ship from their ship and you die."
return 'death'
And here is the output I get
--------
You do a dive roll into the Weapon Armory, crouch and scan the room
for more Gothons that might be hiding. It's dead quiet, too quiet.
You stand up and run to the far side of the room and find the
neutron bomb in its container. There's a keypad lock on the box
and you need the code to get the bomb out. If you get the code
wrong 10 times then the lock closes forever and you can't
get the bomb. The code is 3 digits.
[keypad]> 124
BZZZZEDDD!
BZZZZEDDD!
BZZZZEDDD!
BZZZZEDDD!
BZZZZEDDD!
BZZZZEDDD!
BZZZZEDDD!
BZZZZEDDD!
BZZZZEDDD!
BZZZZEDDD!
The lock buzzes one last time and then you hear a sickening
melting sound as the mechanism is fused together.
You decide to sit there, and finally the Gothons blow up the
ship from their ship and you die.
is this the kinda thing you're looking for? your question doesn't seem to be very clear
while guess != code and guesses < 10:
guess = raw_input("BZZZZEDDD! - try again?")
guesses += 1
guess = ''

Categories

Resources