How can I Create a quest menu for my Text-RPG - python

i want to create a quest menu for my text rpg, it should be a list of all quests and after completion the finished quest should be removed fromt the menu. I tried it with a class but i get this error:
IndexError: list assignment index out of range
<main.quest_menu object at 0x000001D4F8EC3FD0>
#generate a class for my quest menu
class quest_menu():
def __init__(self, quests):
self.quests = quests
generate functions to remove single quests from the menu
def delete_quest_1(self):
del self.quests[0]
def delete_quest_2(self):
del self.quests[1]
generate quests in a list
quests = quest_menu( ["Quest: Murder: kill Rottger = exp: 100, gold 100",
"\nQuest: Ring of strenght: Find the ring of strenght= : exp 50"])
commands to delete quest from inventory when quest is completed
quests.delete_quest_1()
print(quests)
quests.delete_quest_2()
print(quests)
What am I doing wrong? Does anybody have some tips to improve the code?
Thx in advance!

I think what's wrong is that, You deleted a quest first then the only Quest that remains is the second one, this makes that quest first item in the list so using the function to delete the quest will result in IndexError as the quest is now at Index 0. Try to this instead.
class quest_menu():
def __init__(self, quests):
self.quests = quests
def delete_quest_1(self):
del self.quests[0]
def delete_quest_2(self):
del self.quests[1]
quests = quest_menu( ["Quest: Murder: kill Rottger = exp: 100, gold 100", "\nQuest: Ring of strenght: Find the ring of strenght= : exp 50"])
quests.delete_quest_1()
print(quests.quests)
quests.delete_quest_1()
print(quests.quests)

Related

Finding class via string

import random
class Game():
def __init__(self, username, gameId):
self.users = []
self.users.append(str(username))
self.gameId = gameId
def new_user(self, username):
self.users.append(str(username))
def remove_user(self, username):
try:
self.users.remove(username)
except:
print("[-] User not found!")
def generate_gameId():
gameId = ""
letters = 5
while(letters>0):
gameId += chr(random.randint(65, 90))
letters-=1
return(gameId)
lobby = []
for i in range(2):
lobby.append(generate_gameId())
lobby[i] = Game("Test", lobby[i])
lobby[i].new_user("Test123")
lobby[i].remove_user("Test123")
This is my code for a simple networking game, I will have multiple Game classes at the same time, but I need to find the specific object of a specific gameId. The gameId is randomly generated. Each time a user wants to join the lobby he has to enter the gameId to enter.
How would you achieve something like this? Am I doing it wrong?
There are some things that can be refactored in your code:
In the constructor of your Game class, there's no need for a username parameter, since there's already a new_user method:
class Game():
def __init__(self, gameId):
# Just create the list of users
self.users = []
self.gameId = gameId
# ...
lobby = []
for i in range(2):
lobby.append(generate_gameId())
lobby[i] = Game(lobby[i])
# Use the `new_user` method to create a Test
lobby[i].new_user("Test")
lobby[i].new_user("Test123")
lobby[i].remove_user("Test123")
You're storing the ids in an integer list. You should use a dictionary given that a game will have an unique id:
lobby = {}
for i in range(2):
game_id = generate_gameId()
game = Game(game_id)
# Create a entry in the dictionary
lobby[game_id] = game
game.new_user("Test")
game.new_user("Test123")
game.remove_user("Test123")
Then, you can access the list of games and their ids:
for game_id, game in lobby.items():
print(f'The game {game_id} has the following users:')
for user in game.users:
print(user)
print()
The other guys said everything I was going to say so I deleted most of my post, but here's some other things you could improve on if you want:
You are not looking up a "Class" here. You're looking up an instance of a class, otherwise known as an object. The word "class" in programming always means "The definition of an object". Classes can be instantiated to make objects AKA instances. A good analogy is that a "class" is the blueprints for making a car, while the instance/object would be the car itself that was made using the blueprints(the class).
Don't combine naming conventions. You're combining camel case and snake case which is never a good idea, choose one or the other (python is usually snake case). Specifically, generate_gameId() should be generate_game_id(). This just makes it easier to write code without making spelling mistakes.

chesspiece in list to announce winner

def destroy_piece(self, piece):
""" Removes piece from the canvans and click-handler
automatily called by move_piece
"""
img1=piece.get_img_int(0)
img2=piece.get_img_int(1)
del self._on_clicks[str(img1)]
del self._on_clicks[str(img2)]
self.delete(piece.get_img_int(0))
self.delete(piece.get_img_int(1))
self.destroyed_pieces = []
self.destroyed_pieces.append(piece)
for elem in self.destroyed_pieces:
if ......
messagebox.showinfo("WINNER")
class GUIKing(GUIChessPiece,King):
def __init__(self,board,row,col,color,path="./imagepack/"):
if color==BLACK:
path1=path+"bk.png"
path2=path+"bk_s.png"
else:
path1=path+"wk.png"
path2=path+"wk_s.png"
GUIChessPiece.__init__(self,board,row,col,color,path1,path2)
def on_click(self,event):
GUIChessPiece.on_click(self,event)
I am having trouble with continuing this code to detect win, simply by checking if the king is in the list, pieces are classes represented by pictures on a canvas. Though is it the images or the piece that is getting appended to the list? I am attaching the code for the king class
Because 'King' is a class, then to identify whether a member of that class is in the list self.destroyed_pieces you can do:
for elem in self.destroyed_pieces:
if isintance(elem,King):
messagebox.showinfo("WINNER")

Python Attribute Error in Blackjack game

I am working on am assignment for my programming class in which we have to take a blackjack program and add the option to bet.
This is the original program:
http://courses.ischool.berkeley.edu/i90/f11/resources/chapter09/blackjack.py
This works with no problems.
In the class BJ_Game I have added some code to collect bets
class BJ_Game(object):
def __init__(self, names):
self.players = []
for name in names:
player = BJ_Player(name)
self.players.append(player)
self.dealer = BJ_Dealer("Dealer")
self.deck = BJ_Deck()
self.deck.populate()
self.deck.shuffle()
# betting
def placing_bets (self, names):
self.total_bets=10
for name in names:
yes_no=input("The dealer bets 10.", name, "would you like to bet on this round? (y/n)")
if yes_no=="y":
player_bet=input(int("How much would you like to bet?:"))
else:
break
self.total_bets=player_bet+self.total_bets
return self.total_bets
(Sorry about the formatting, I'm new at this. In real life it's indented just like in the link)
The only other change I made was to add the bottom two lines to print the bets that the winner has won:
def win(self):
print(self.name, "wins.")
# awarding bets
print("You win $", self.total_bets)
When I run this, I get an error:
AttributeError: 'BJ_Game' object has no attribute '_BJ_Game__additional_cards'
I am not understanding how the changes I made caused this issue. Help is greatly appreciated.
Is this line:
def __additional_cards(self, player):
still in your program? If not, you have your answer. If yes, have a closer look at the code directly above this line.

How to re-initialize a class object

I'm making the typical text game program and I'm stuck on the restart function. I want to restart the room instances, but when I try to delete the object I get AttributeError: room1. Here's some pseudo-ish code:
class Room:
inventory = []
__init__(self, itemsInRoom, doors):
#makes a room instance and puts some items and doors into the room
self.roomItems = []
self.roomDoor = []
for item in itemsInRoom:
#puts initial items into the room
self.roomItems.append(item)
for eachDoor in doors:
#tells the instance what doors there are
self.roomDoor.append[doors]
Def functionsBlahBlah():
Pass
class RoomNumber:
room1 = Room(['stool', 'tavern wench', 'bar keep'], ['north', 'east'])
room2 = Room(so on and so forth)
def functionsBlahBlah():
Pass
def restartFunction():
del RoomNumber.room1
del RoomNumber.room2
startGame()
def startGame():
RoomNum()#initializes rooms
main()
startGame()
So anyway, I try to delete RoomNumber.room1 in the restart function so I can turn around and initialize it again with it's original items and stuff. As I said though, I get an error. Any ideas on where I'm going wrong?

Better way to create my lists in classes?

I've been working on making my text based game more realistic, and one design I would like to implement is to make sure the rooms stay 'static' to a point (i.e. a player uses a potion in the room, if they come back to that room that potion should no longer be there.)
This is how my code is basically set up (I have been using "Learn Python The Hard Way" by Zed Shaw so my code is set up much in the same way):
class Scene(object):
def enter(self):
print "This scene is not yet configured. Subclass it and implement enter()."
class Room(Scene):
potions = []
for i in range(3):
potions.append(Potion())
def enter(self):
...
When I run this, I get a NameError: global name 'potions' is not defined. I know I can fix this one of two ways: 1. make potions a global variable, but then I would have to make a new list for each room that contains potions (There are 36 rooms in total, set up as a 6x6 grid) OR
2. Put this line of code in the enter function, but that would cause the list to reset to 3 potions each time the user enters the room.
potions = []
for i in range(3):
potions.append(Potion())
If there's no other way, I suppose declaring a new variable for all the rooms that contain potions (There's only 5). But my question is if there's another way of making this work without making it a global.
Thanks for your help!
First, let's look at your example (I'll simplify it):
class Room(Scene):
potions = [Potion() for x in range(3)]
What you have done there is create a class attribute potions that are shared among all instances of Room. For example, you'll see my potions in each of my rooms are the same instances of potions (the hex number is the same!). If I modify the potions list in one instance, it modifies the same list in all of the Room instances:
>>> room1.potions
[<__main__.Potion instance at 0x7f63552cfb00>, <__main__.Potion instance at 0x7f63552cfb48>, <__main__.Potion instance at 0x7f63552cfb90>]
>>> room2.potions
[<__main__.Potion instance at 0x7f63552cfb00>, <__main__.Potion instance at 0x7f63552cfb48>, <__main__.Potion instance at 0x7f63552cfb90>]
>>>
It sounds like you want potions to be a unique attribute of each instance of a Room.
Somewhere you will be instantiating a room, e.g., room = Room(). You need to write your constructor for your Room in order to customize your instance:
class Room(Scene):
def __init__(self): # your constructor, self refers to the Room instance.
self.potions = [Potion() for x in range(3)]
Now when you create your room instance, it will contain 3 potions.
You now need to think about how you will make your rooms instances persist between entrances by your characters. That will need to be some sort of variable that persists throughout the game.
This idea of object composition will extend through your game. Perhaps you have a Dungeon class that has your 36 rooms:
class Dungeon(object):
def __init__(self):
self.rooms = [[Room() for x in range(6)] for x in range(6)]
Or perhaps your rooms have up to four doors, and you link them up into something potentially less square:
class Room(Scene):
def __init__(self, north_room, east_room, south_room, west_room):
self.north_door = north_room
self.east_door = east_room
[... and so on ...]
# Note: You could pass `None` for doors that don't exist.
Or even more creatively,
class Room(Scene):
def __init__(self, connecting_rooms): # connecting_rooms is a dict
self.connecting_rooms = connecting_rooms
Except both examples will get you a chicken and egg problem for connecting rooms, so it is better to add a method to add each room connection:
class Room(Scene):
def __init__(self):
self.rooms = {}
# ... initialize your potions ...
def connect_room(self, description, room):
self.rooms[description] = room
Then you could do:
room = Room()
room.connect_room("rusty metal door", room1)
room.connect_room("wooden red door", room2)
room.connect_room("large hole in the wall", room3)
Then perhaps your dungeon looks like this:
class Dungeon(Scene):
def __init__(self, initial_room):
self.entrance = initial_room
Now in the end, you just have to hold onto your dungeon instance of Dungeon for the duration of the game.
btw, this construct of "rooms" connected by "paths" is called a Graph.

Categories