I have just finished working through this tutorial for programming a Roguelike in Python and am now very much on my own in figuring out where to go and what to do next.
My predicament is with the messiness of the code. I would like to store elements somewhere, for example items; creatures; skills; anything where there could be a large number of them with numerous properties for themselves.
At the moment, all this code is in one single file that is getting quite large, and this is at its most basic. The function for placing items on a level looks much like this at the moment: (This function is called when the level is generated)
def place_objects(room):
#Maximum number of items per room
max_items = from_dungeon_level([[1, 1], [2, 4]])
#Chance of each item (by default they have a chance of 0 at level 1, which then goes up)
item_chances = {}
item_chances['heal'] = 35
item_chances['lightning'] = from_dungeon_level([[25, 4]])
item_chances['fireball'] = from_dungeon_level([[25, 6]])
item_chances['confuse'] = from_dungeon_level([[10, 2]])
item_chances['sword'] = from_dungeon_level([[5, 4]])
item_chances['shield'] = from_dungeon_level([[15, 8]])
#Choose a random number of items
num_items = libtcod.random_get_int(0, 0, max_items)
for i in range(num_items):
#Choose random spot for this item
x = libtcod.random_get_int(0, room.x1+1, room.x2-1)
y = libtcod.random_get_int(0, room.y1+1, room.y2-1)
#Only place it if the tile is not blocked
if not is_blocked(x, y):
choice = random_choice(item_chances)
if choice == 'heal':
#Create a healing potion
item_component = Item(use_function=cast_heal)
item = Object(x, y, '~', 'Salve', libtcod.light_azure, item=item_component)
elif choice == 'lightning':
#Create a lightning bolt scroll
item_component = Item(use_function=cast_lightning)
item = Object(x, y, '#', 'Scroll of Lightning bolt', libtcod.light_yellow, item=item_component)
elif choice == 'fireball':
#Create a fireball scroll
item_component = Item(use_function=cast_fireball)
item = Object(x, y, '#', 'Scroll of Fireball', libtcod.light_yellow, item=item_component)
elif choice == 'confuse':
#Create a confuse scroll
item_component = Item(use_function=cast_confuse)
item = Object(x, y, '#', 'Scroll of Confusion', libtcod.light_yellow, item=item_component)
elif choice == 'sword':
#Create a sword
equipment_component = Equipment(slot='right hand', power_bonus=3)
item = Object(x, y, '/', 'Sword', libtcod.sky, equipment=equipment_component)
elif choice == 'shield':
#Create a shield
equipment_component = Equipment(slot='left hand', defense_bonus=1)
item = Object(x, y, '[', 'Shield', libtcod.sky, equipment=equipment_component)
objects.append(item)
item.send_to_back()
As I intend to add more items, this function will get seriously long, as will all the functions that then needed to be created to handle what each item does. I would really like to take this out of main.py and store it somewhere else, to make it easier to work with, but I don't know how to do this at the moment.
Here are my attempts to try and think through the problem:
Could I have a file that contains an item class with a number of properties that each item contains; (name, type, condition, enchantment, icon, weight, color, description, equip_slot, materal). Then store the functions for what the items do in that file? How would the main file know when to call this other file?
Could all the item data be stored in an external file (like an XML or something) and read from there when needed?
This is something that I could apply to more than just items obviously. This would be really useful for not having a really bloated main.py that holds all the creatures, items and other objects in the game ballooning thousands of lines of code, when what I really want is a main loop and a better structure of organization.
If you don't need human-readable files, consider using Python's pickle library; this can serialise objects and functions, which can be written to and read back from files.
In terms of organisation, you could have an objects folder, separating out those classes from your main game loop, e.g.:
game/
main.py
objects/
items.py
equipment.py
creatures.py
For further improvements, use inheritance to do e.g.:
class Equipment(Object):
class Sword(Equipment):
class Item(Object):
class Scroll(Item):
Then all the setup for any e.g. sword can be defined in the initialisation (e.g. which hand it's in) and only the things that vary for a specific sword (e.g. name, power bonus) need to be passed in.
Could all the item data be stored in an external file (like an XML or something) and read from there when needed?
You can do this with the ConfigParser
module.
You could store the properties of the items in a separate file (a normal, text file). Read this file to create your objects automatically.
I'm going to use the examples from the documentation as a guide here:
import ConfigParser
config = ConfigParser.RawConfigParser()
config.add_section('Sword')
config.set('Sword', 'strength', '15')
config.set('Sword', 'weight', '5')
config.set('Sword', 'damage', '10')
# Writing our configuration file to 'example.cfg'
with open('example.cfg', 'wb') as configfile:
config.write(configfile)
Now, to read the file:
import ConfigParser
from gameobjects import SwordClass
config = ConfigParser.RawConfigParser()
config.read('example.cfg')
config_map = {'Sword': SwordClass}
game_items = []
for i in config.sections():
if i in config_map:
# We have a class to generate
temp = config_map[i]()
for option,value in config.items(i):
# get all the options for this sword
# and set them
setattr(temp, option, value)
game_items.append(temp)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With