I'm making a text-based rpg with python 3.3 and I am wanting a more dynamic inventory system for my game. I am currently using variables assigned to each item but with functions, the variables I am passing as arguments are becoming too many and quite cluttered. If there is a better way out there I would love help creating a better system.
Here is how my inventory call system looks right now:
print('Item1',item1)
print('Item2',item2)
print('Item3',item3)
and so on.
Well, I have an old text game I made and the inventory system I use is just a list named 'inv'. Then all you have to do when you gain an item of whatever type is to append the inventory list with the string.
inv = []
inv.append('Item1')
Then you can create a dictionary with the key as the item name and the value be a list you can reference. Try this:
itemvalues = {'Item1':[0,0,0]
}
And the list can be a bunch of different attributes such as buy sell price, strength or what have you. Hope this helps.
You could try and use a list:
inventory = []
inventory.append(some_item)
And you can implement an inventory cap:
if len(inventory) > inventory_size:
print('Inventory full.')
If you want to 'use' an item in the inventory, say, then it's also easy to remove (this is of course assuming the index exists):
# use the item
del inventory[index]
Obviously most of the functionality you need is accessible through standard list methods, so check the documentation out.
Related
I'm trying to write a text-based adventure in Python, for which I created a class called Room. A Room consists of a description and 4 other Rooms in each direction (north, south, ...).
But when I create, for instance, two rooms next to each other, I have to create one of them first, meaning it can't understand what I pass as the Room next to it because it's a line below.
I was wondering what ways there are to fix such a problem, other than perhaps making and importing a new file for each room. I'll add a small example.
room_north = Room("RoomNorth", room_south)
room_south = Room("RoomSouth", room_north)
Thanks in advance :)
One way is to change your Room class so that it doesn't need the connections at construction. First create the rooms, and then add the connections:
room_north = Room("RoomNorth")
room_south = Room("RoomSouth")
room_north.south = room_south
room_south.north = room_north
Another way is restructure your code to store all rooms in a dictionary, identified by strings:
rooms = {
"room_north": Room("RoomNorth", "room_south"),
"room_south": Room("RoomSouth", "room_north"),
}
A possible drawback is that every lookup of a room will have to go through this dictionary, of course.
I have a problem with my Plone item I cannot solve. 'Car' is supposed to create a list of all instances of 'Colour'.
All 'Colour' instances are in a given container. I cannot make it static because I want to add more 'Colour' instances in the future.
I tried selecting each item in my container and add it to my vocabularylist. I only need the id/title of my object, but I always end up with a giant stacktrace of failures.
In the end I want to choose a colour out of the given instances on creating a new 'Car' instance similar to a dropdown.
I have read the docs but cannot find a solution and this is my best idea.
I am also not a python programmer and this is my first plone project. I can add the complete failure list later if you need it.
I appreciate every bit of help. Thank you.
```colour= schema.Choice(
title=u"Colour",
description=u"Paintjob",
vocabulary=givecolour(),
required=False
)
#provider(IContextSourceBinder)
def givecolour():
colourlist = self.context.portal_catalog(path={"query" : "/madb-entw/it/colourcontainer", "depth" : 1})
list = []
i = 0
for colour in colourlist:
list.append(
SimpleVocabulary.createTerm(
colourlist.[i].getObject().id
)
)
i += 1
return SimpleVocabulary(list)```
Please always add your traces, so that we can help you better.
There is also the official community.plone.org forum, where are more people can help you.
I recommend you to use the plone.api to find your objects, this is a bit easier and well doumented.
something like this:
from plone import api
color_brains = api.content.find(context=api.content.get(path='/madb-entw/it/colourcontainer'), depth=1, portal_type='Color')
# no need to do getOject() here, get the id/title directly from the catalog brain
colors = [(color.id, color.Title) for color in color_brains]
One note to your query:
colourlist = self.context.portal_catalog(path={"query" :
"/madb-entw/it/colourcontainer", "depth" : 1})
Path has to be absolute, which means it includes the Plone site id and this can be different in another Plone site.
So an absolute path is not a good idea here, better get the portal object and traverse your path relative from there.
If madb-entw is your Plone site id:
portal.restrictedTraverse('it/colourcontainer')
or better as above, use plone.api.content.get(path='/it/colourcontainer')
Which is cleaner and easier.
Currently, I have a class which stores a dictionary of Card elements, each of which is unique. The class can also generate these cards and append them to the dictionary or remove a card from a dictionary. However, I am not sure how to best allow for this action through a callback function since the ID for a card doesn't exist until the card is made, and the functionality isn't directly within the Dash framework since a dictionary object acts as an intermediary where the objects are stored.
Basically, I am wondering what the best way to dynamically create and destroy objects with a callback is?
Thank you!
Assuming you want to avoid extra computation for building cards you wont use, I'd suggest create a which creates each card and store those functions in a dictionary. (You can also create a universal function with params that allow specificity)
my_card_functions = {
'id_1': make_id_1,
'id_2': make_id_2,
}
Creating a card could be done as such:
my_id = 'id_1'
f = my_card_functions[my_id] # will break if id isn't registered
my_card = f()
You can store the cards you want to create in a dcc.store object. Here's an example of some code you might consider:
# Pretend these are structured properly
dcc.Store(id='cards_data')
html.Div(id='my_cards',children=[])
#app.callback(
Output('my_cards','children'),
[Input('cards_data','data')],
[State('my_cards','children')]
)
def make_cards(data, children):
"""Makes cards for each id"""
if not data:
raise PreventUpdate
# The following code is not correct but serves as a demonstrative example
# Some data structure manipulation is necessary to access
# the ids from the children elements
children_ids = [x['id'] for x in children]
# Assuming your data looks something like this:
# {'add':['id_1','id_2']}
for x in data['add']:
if x not in children_ids:
f = my_card_functions[my_id]
my_card = f()
# Store values
children.append(my_card)
return children
Note, this approach does not resolve removal of cards. That could easily be done but would probably require a more dynamic use of caching.
Just on the basis of your question, I have some immediate suggestions (since there is no working code that you have posted).
1. Generate all card elements by default. They can be generated, but not 'displayed'
2. Add your callbacks to toggle the display/rendering of the cards dynamically based on the use case. That way you will have card element ids to play around with in the callbacks.
Hope this helps.
To aid in some mental rehabilitation after a nasty hip accident I decided to try and teach myself to program in Python. So I've just started getting my head around defining functions and classes.
I have a basic enemy class that allows me to create an object like this.
enemy01=Enemy("Goblin",10,100,2,5,1,2)
To get the enemy name I can use
foe=enemy01.get_enemyName()
My problem is I want to use a list of enemies which I append as they get killed off and the variable 'foe' to refer to whatever enemy is in play.
So I tried creating a list of the enemy objects, like
currentEnemy=[enemy01, enemy02, enemy03]
and do
foe=currentEnemy.....
But I cant work out how to attach the .get_enemyName()
I was trying things like this to concatenate it
foe=(currentEnemy, ".get_enemyName()")
But nothing I am trying is working when I type 'print(foe)' which is what would be in the main body of code.
I have tried searching online and here but it's really hard as a beginner to put it into words what I am trying to do. Maybe i'm just going about it the wrong way to start with.
I hope I'm making sense and thanks for reading :)
Simon
You seem to conflate the list of all enemies and a variable referring to a particular one.
Here's what you could do:
enemies = [enemy01, enemy02, enemy03]
for currentEnemy in enemies:
eName = currentEnemy.get_enemyName()
print('The current enemy is', eName)
Later on you would probably decide that creating individual enemies is too tedious and use another loop for that:
# create three identical goblins
enemies = [Enemy("Goblin",10,100,2,5,1,2) for _ in range(3)]
If your class :
class Enemy:
def __init__(self,name):
self.name=name
def get_enemyName(self,):
return self.name
and you have initialised currentEnemy as :
enemy01=Enemy('Goblin')
enemy02=Enemy('Rhino')
enemy03=Enemy('DR.Octopus')
currentEnemy=[enemy01, enemy02, enemy03]
And you want to get list of all enemy names into a list foe. Then try :
foe=[x.get_enemyName() for x in currentEnemy]
print foe
i.e. list comprehensions
i= foe.index('Rhino') #find index of Rhino
del[currentEnemy[i]] #let's kill Rhino
print 'current enemies at play {}'.format([x.get_enemyName() for x in currentEnemy])
Sorry - real silly error on my part. I just missed the list index.
I sorted it
enemylist = [enemy01, enemy02, enemy03]
currentEnemy=enemylist[0]
foe=currentEnemy.get_enemyName()
print(foe)
I am teaching myself Python by reinventing the wheel, i.e. writing a simple console adventure game with interconnected rooms. My interest is not so much in finishing a real game, rather in learning about abstraction and data structures.
I have defined a few basic classes such as World, which contains references to Rooms. These Rooms have Actions and Items. The program checks which Actions are available for each Room and displays them in a list. All of this is working pretty well so I'm trying to complexify things a bit.
I have two problems I can't get my head around. I'll try to explain
them with as little detail as possible.
This is how I defined a possible Action for a Room, in this instance it's a Room referenced by the variable called main (for now data is declared in a module, later to be read from a CSV or XML file):
main.actions = [Action(type = 'move',
result = 'west',
desc = 'Go to the West Room.')]
I need to define an action type because some actions are not movements (e.g. pick up, pull a lever). I'll modify this later to uses subclasses of Action, it's not the issue here.
The 'west' string here refers to the Room which will be the result of the action, i.e. it will become the current room when the action is executed.
However, I'd like the result to be the Room object itself, not a
string ID. But I can't do that until all the Rooms have been initialized.
So I've solved this with the following method of the World object, which works:
def connect_rooms(self):
'''
Once all the rooms have been created,
replace all the string reference to other rooms by the Room objects themselves.
'''
for room in self.rooms:
for action in room.actions:
if action.type == 'move':
room_object = fetch_room(self, action.result)
action.result = room_object
The fetch_room() function (global scope) just does this:
def fetch_room(world, shortname):
# Find a room item by its shortname
for room in world.rooms:
if room.shortname == shortname:
return room
return None
I am sure there is a better way to handle this, since creating connections between nodes seems to be a basic abstract idea.
The other (related) problem is that I'm trying to create conditions built into the Actions themselves, so that the program only proposes them to the player if the conditions defined in the Action are met. For the initial building of the data I can't reference anything else because it hasn't been created yet. I thought of adding a condition in string form and run it later with exec(), but it seems very silly and ugly:
main.actions = [Action(type = 'move',
result = 'west',
desc = 'Go to the West Room.',
conditions = ["player.has('smallkey')"])]
If there is a text somewhere about build such data structures without going insane, I'd be happy to read it.
Thank you.