Archive for the ‘roguelike’ Category
more on messages (a roguelike in Python #17)
Up to now message handling (what gets printed to the message log) was just adding a message string to the log wherever something in the code warranted it. This was simple at first, but required checks to make sure a monster wasn’t initiating a message (like ‘you can’t go that way’ — seemed like a bug until I understood what was going on!).
So I’ve taken the next step to something a little more involved. Here’s what the message class looks like now;
class Log(object):
def __init__(self):
self.history = ["Go!"]
self.cursor = 0
def add(self, message, enactor, *string):
for handler in enactor.handlers:
if isinstance(enactor.handlers[handler], Messages):
script = enactor.handlers[handler].script
if message in script:
if string:
self.history.append(script[message] % string)
else:
self.history.append(script[message])
self.cursor += 1
break
def set_cursor(self, line_number):
self.cursor = line_number
Adding a message now requires the message (which isn’t the message itself as I’ll explain), the enactor who initiated it, and an optional string to pass into the message. Using this method looks like this:
game.log.add("got something", enactor, target.name)
You can see that before anything gets added to the log I check if there’s a handler in the enactor’s handlers that is of type Messages. This class is a parent class that doesn’t really do anything, but allows me to subclass off it with handlers that actually do something — namely, add scripts to the enactor. For example:
class Messages(object):
def __init__(self):
self.script = {}
class PlayerMessages(Messages):
def __init__(self, gid):
self.gid = gid
self.script = {
"move failed" : "You can't go that way.",
"opened something" : "You opened the %s",
"closed something" : "You closed the %s",
"command not found" : "Try again!",
"got something" : "You get the %s",
"used inventory item" : "You used inventory item %s"}
def update(self):
pass
By checking for an instance of Messages I can create many different message subclasses with different scripts, and attach these to actors depending on what messages I want them to have. Once the add method finds a Messages subclass, it checks if the message is in the script, and if so adds it to the log — with another check if the optional string was passed in as an argument or not.
This should get more interesting once I have messages for other actors — I can customize a standard message for each script.
I think I can extend this to be able to attach multiple scripts to the same actor — I’ll have to change the conditional check in the add method to create a list of handlers that are Messages subclasses, and then run through each handler’s script to find if a particular message is in there. There could be a problem though if I attach two subclasses that have the same type of message in their scripts — I’ll probably just have to add the first one that matches if that case arises.
Also I’ve been playing around with the UI some more.

I dropped the idea of the alt key + a number as a secondary use for inventory items — I’ll probably have enough to do just adding single uses for items! I also mocked up a pane selection scheme, where the tab key cycles through each pane and highlights it (the inventory pane is highlighted in that screenshot). When you highlight a pane you’ll get some additional functionality — scrolling through the message log, examining inventory items, examining things in the viewport, and scrolling through the journal pane (the pane to the right).
sometimes I like to go through every line of code and just change something
Usually it’s for a good reason, to fix something I did earlier for no reason, or maybe for a bad reason that I didn’t understand at the time.
Up to now I’ve been passing objects around by referring to the object itself (I guess this is passing by reference? I think this is what Python does by default). However when you save the game state with yaml (and perhaps with the pickle module too, though I haven’t investigated this), it saves every reference as the actual object data. For example, if you had an attribute on every thing that referenced a map object, that whole map object including its map array would be saved once for each thing.
That in itself wasn’t a problem, as you can clear data that you don’t need to save in your saving routine before you exit the game. However my future plans for the game include a lot of cross-referencing between objects, and I do want to be able to save that state without saving the same object data over and over.
So now instead of passing objects around by reference, each object has a unique game id (the gid). This gets created in a thing’s __init__ method like so:
class Thing(object):
def __init__(self, name, x, y, properties, *handlers):
self.gid = id(self)
while self.gid in game.gids:
self.gid = self.gid + 1
game.gids[self.gid] = self
The reason for the while loop is if I create a thing after a game has been saved and reloaded, there is a slim chance that a new gid could match an old gid (as I’m just using Python’s id() function to create the number). If that does happen, I create a new gid until I have a unique one.
Of course this is not as simple as what I was doing before (though saving is actually a little simpler, as I just save a single dictionary of gids and re-use it when I load it back in). Every time I want to look up a thing’s properties I need to look up the thing’s object first in the gids dictionary. Nevertheless I think it’ll pay off in the long run.
more of what you see (a roguelike in Python #16)

Things are getting to the point where this is less of a demo and more of what I want to do in the game itself. I may or may not write a more complete tutorial based on the demo — I think there’s more than enough here for people to get familiar and get started with libtcod in general.
I’ve put in a rudimentary message log in the bottom pane of the display. That skull on the right is from the libtcod package — I’m thinking about using the right-hand pane to display images like character portraits, text of signs, books, conversations maybe? The top pane will contain game information views, like inventory and so on.
The command set right now is very simple — bump to open things (I’ll extend this to mean operate something that isn’t otherwise openable), press x to pick things up. Control + direction closes things (or will turn something ‘off’). Control by itself will act on a thing in the same cell as you. I still mean to work in throwing things, and using things in inventory, but I’m going to keep the command set simple. I’d like to use ‘z’ for taking an action with something in hand, but allow using anything in inventory (which will be limited) by selecting its inventory number (I think this is what Chickhack does if I remember correctly, I liked it at the time). Control + z then could be used as an undo/rewind, but that’s so far off I’m not really thinking about it at the moment.
I’m going back and forth right now about extending this command set and keeping it simple. I’m leaning toward keeping it simple, both as a creative constraint and to keep the project size small. The one thing that bugs me about this is I’d like multiple uses of things (for example, you have a potion you could either drink or throw at something). I may have to accept single-use items if I keep the command set limited. One possibility to open options up a bit is to use inventory-keys for an item’s primary use (so hitting ‘1′ and then ‘enter’ drinks the potion if that’s inventory item #1) and pressing ‘1′ then ‘z’ does an item’s secondary action, which could be throw. In the end I may save multiple-uses for another project…I don’t want things to get too convoluted.
update: don’t want it too convoluted?…where’s the fun in that? I’ve started trying something I think could work — using number keys for primary use of the item, and Alt + number for the secondary use. I may be able then to hijack Alt + x as a drop key if I ever want one.
things (a roguelike in Python #15)
I haven’t really spent much time yet figuring out what a thing from the Thing class is, so far defining it as an object with a name, speed, position, and maybe a handler for field-of-view or dumb AI. Furthermore the character used to represent it on screen simply was based on its name. Since I knew I wanted to better define a Thing and start figuring out how I want to represent it visually, I’ve started hacking on Thing.
First of all Thing’s parameters have changed. The __init__ now looks like this:
class Thing(object):
def __init__(self, name, x, y, properties, *handlers):
self.name = name
self.x = x
self.y = y
self.properties = properties
self.handlers = {}
if not None in handlers:
for string in handlers:
handler = eval(string)
self.handlers[string] = handler(self)
self.things = []
self.stage = None
self.char_type = self.get_char_type()
As you can see I got rid of the speed parameter, which is now included in properties. A thing therefore looks like this in its yaml definition file:
- iron-barred window - 35 - 12 - speed : normal kind : - window state : - none -
That definition gives the thing’s name, x, and y attributes. The next item in the list is a dictionary containing the keys speed, kind, and state. This dictionary is passed into a new instance of a thing as properties. The last blank list item is handlers.
It’s all very provisional right now as I figure out how to define a thing. But here’s a closer look at the last statement in __init__, self.char_type = self.get_char_type().
Here’s that function:
def get_char_type(self):
name = ''
if self.name in player.ui.char_types:
name = self.name
else:
name_tokens = self.name.split(' ')
for token in name_tokens:
if token in player.ui.char_types:
name = token
if not len(name):
for kind in self.properties['kind']:
if kind in player.ui.char_types:
name = kind
for state in self.properties['state']:
state_modifying_name = ' '.join([state, name])
if state_modifying_name in player.ui.chars:
return state_modifying_name
if len(name):
return name
else:
return 'unknown'
What I’m trying to do is find the visual symbol for a thing (its char_type) based on its name, kind, and state (if any). This is of course not very straightforward and I may have to choose a different method. Whenever a thing’s state changes, its symbol may change as well. There is also the possibility, not accounted for in this code yet, that a thing may have a combination of states that modify its name or kind producing a unique visual symbol. I think I can get this to work but it’ll require some experimentation.
In the meantime I’ll explain how this works. The player.ui.char_types list looks like this:
self.char_types = ['player', 'unknown', 'ground', 'wall', 'window', \
'lamp', 'knife', 'door', 'portal']
So the first thing the get_char_type function asks is if the thing’s self.name is in that list; if so, it assigns it to the local variable name, previously set to an empty string allowing it to be referenced later in the function. If the thing’s self.name is not in the list we break up the name into its tokens (parts), and if one of those are in the list, we assign that to name. Keep in mind that name may still be empty at this point.
Next, if name is empty, we see if the thing’s kind is in the list of char_types, and if so, assign that to name.
Finally we combine whatever state the thing might have with its name, and check if that’s in the list. This takes care of things like ‘closed door’. If there’s a match we return it. If not, we see if name is non-empty (there was a successful match earlier) and return that. Lastly if name is still empty, it’s not in the list of char_types and so we call it ‘unknown’, which gets the question mark symbol when drawn to the screen.
Some notes after the cut on how to find symbols for combination of states.
stages (a roguelike in Python # 14)
A few days ago I got to the point where I wanted to add switching levels and a get command. Adding the get command led me to consider how I would represent inventory in the code, and I thought simple, every thing has a list of things it holds.
The new code is after the jump, but first some explanation.
My thought was that a level is simply a thing that holds the things inside it. OK, I was thinking this is good, because I had wanted to have different kinds of levels in the game, like airships, giant woolly mammoths and so forth, and this would potentially make it straightforward to have a giant woolly mammoth walking around that the player could jump on and explore. So I decided a level would be a kind of handler that gets attached to a thing and adds the functionality of a map.
As you can tell I’m not too concerned with representing scale at this point — I don’t think I will be at any point really, this is a game after all. Regardless, I decided to call a level handler a Stage.
You can see in previous postings of the demo that I managed the map in a single World object. So I needed to do some heavy rewriting, and this led me to reconsider the handler/thing structure altogether. As a result I threw out the Brain class and now add handlers directly to a Thing. I think this is simpler overall.
At one point I got sidetracked by the magic of Python’s __getattr__. This is an attribute on every object, that’s executed when the interpreter doesn’t find the attribute it’s looking for as a result of a call on a property or function. So I was doing things like calling thing.foo where foo was actually an attribute on a handler, not the thing itself. However this proved to be more trouble than it was worth (since, as far as I could tell, __getattr__ expects you to return a value when called, and I decided this was too much hassle). The easier solution for me was to rewrite things so that wherever I call an attribute of a handler, I access it through a dictionary of handlers on the thing, like this:
cells = stage.handlers['Stage'].cells_get(self.thing, self.fov_radius)
A little verbose, but easier in the end, and maybe clearer overall.
Saving the game now means saving the stages in a game. I’ll need to revise this in the future to account for stages within stages though. Switching stages means removing the thing from its current stage and adding it to the new stage. By keeping track of the player’s current stage I know what to draw to the screen. Currently I only update things in the player’s stage, so this will need to be changed in the future so time doesn’t freeze on a stage when the player leaves it. And finally, getting and dropping things means removing and adding the thing to the things that are getting it or receiving it.
There’s a crude inventory display in the upper part of the UI at the moment, but there’s only one thing to get.
Things are now kept in a file by stage, which is named like stage_name.things, and the maps are in stage_name.map.
addendum: With all this talk of stages, it may seem as if something is being left out — namely procedural generation of levels! And for the moment this is true, but as I think I’ve mentioned before I’m not going to focus on generating levels until I have a better idea of what I want the game to be. So for now I’m sticking with hardcoded content to give me a base to test on.
main menu screens and UI (a roguelike in Python, #13)
I spent some time getting a main menu and new/load game screens working, and started to get an idea of what I want the UI to do.

After the cut is the current demo code. Note that I’ve now moved the key configuration, the level map, and definitions of things to separate files. The key config file looks like this:
k : north j : south h : west l : east up arrow : north right arrow : east left arrow : west down arrow : south keypad 8 : north keypad 6 : east keypad 4 : west keypad 2 : south p : print history
While the things definition file looks like this, in part:
- 'window' - 35 - 12 --- - 'closed door' - 30 - 15 --- - 'monster' - 20 - 9 - 'AI'
And of course the level file is a hardcoded map.
Next I think I’ll have a go at adding get, drop, and throw commands along with player inventory — this should be a good test of the demo’s structure overall. Initially I added in stubs for get and drop with a key definition for each command, but today I thought about it and now I think I’m going to streamline the interface somehow.
timeless actions (a roguelike in Python, #12)
One last important thing I needed to add to command handling was commands that take no time — certain out-of-game actions or meta commands like switching UI views and things like that. I’m imagining that most commands will take a player’s turn but I wanted to have support for actions that don’t.
At the same time I wanted to centralize command parsing — before commands were enacted by calling the command directly which was OK but made it tedious to add things that would happen when any command was called. So here’s what I came up with — some significant changes to the Command class:
class Command(object):
def __init__(self):
self.playbook = {
'north' : ('takes turn', self.move, 0, -1),
'east' : ('takes turn', self.move, 1, 0),
'south' : ('takes turn', self.move, 0, 1),
'west' : ('takes turn', self.move, -1, 0),
'ctrl north' : ('takes turn', self.ctrl, 0, -1),
'ctrl east' : ('takes turn', self.ctrl, 1, 0),
'ctrl south' : ('takes turn', self.ctrl, 0, 1),
'ctrl west' : ('takes turn', self.ctrl, -1, 0),
'print history' : ('free action', self.print_history, None)}
And now commands are routed through a single function:
def do(self, string, enactor):
command = self.playbook[string]
command_name, args = command[1], command[2:]
command_name(enactor, *args)
self.history.append((string, enactor.name))
return command[0]
Which gets called like this in the player input function:
command_name = self.ctrl + self.keycfg[key]
game.message.text = "Go!"
if game.command.do(command_name, player.thing) == 'free action':
self.gameplay_update()
So the command_name is created, for example ‘ctrl north’, and is sent to command.do. That gets looked up in the playbook, and the command is called with its arguments. The lookup also tells the game if the action takes a turn or not — this information is returned to the original call, and if it’s a free action the player input function is called again without a turn passing.
The ‘history’ is mostly a way to test this out. I have a vague idea of allowing playback of moves, but that’s going to require a lot of other work that’s not a priority right now.
oh no you mean I have to add things? (a roguelike in Python, #12)
Up to now I’ve been motoring along quite happy with my simple arrangement — a player, a monster, some lamps, field-of-view, saving and loading. In theory I’d written the code as a framework that would make it easy to add stuff, but…I hadn’t actually added any stuff yet. I knew this was an important step. Would things totally break down? How easy would it be to add stuff?
So I’ve started to add stuff. Let’s see how easy it is to add something. Trying to keep things simple, I’m starting with windows and doors.
Now I already had windows, but these were a part of the hardcoded map. I’ve decided to make them of the Thing class instead, and so the hardcoded map will strictly represent terrain (at the moment just walls and ground). To make a window a thing this is what I had to do:
- remove the window from game.world.cell_types and the hardcoded map
- add a test to Fov so that if a cell in field-of-view is a window, it’s marked as transparent in the fov map.
- add the window to player.ui.chars
- remove adding the window to the viewport structure in the view.update, as now it’ s just drawn with the other things.
- create the window thing in Game.
Adding doors followed a similar path as above (minus removing code of course as doors are totally new), but I also had to add the functionality of opening doors. So, I went to the Command class. Here is what the rulebook and rules look like now:
class Command(object):
def __init__(self):
self.rulebook = {
'move' : ('cell has monster', 'cell is unwalkable', 'cell has closed door', 'open door implicitly')}
self.rules = {
'cell has monster' : 'game.world.cell_has_monster(thing.x+dx, thing.y+dy)',
'cell is unwalkable' : 'game.world.cell_is_unwalkable(thing.x+dx, thing.y+dy)',
'cell has closed door' : 'game.world.cell_has_closed_door(thing.x+dx, thing.y+dy)',
'open door implicitly' : 'game.world.open_door_implicitly(thing.x+dx, thing.y+dy)'}
So I added ‘cell has closed door’ and ‘open door implicitly’ (bump to open — now that I think of it I might be able to make a general ‘bump to open’ rule). Here are the corresponding methods in World.
def cell_has_closed_door(self, x, y):
for thing in game.world.things:
if (thing.x, thing.y) == (x, y) and thing.name == 'closed door':
return True
def open_door_implicitly(self, x, y):
if self.cell_has_closed_door(x, y):
for thing in game.world.things:
if (thing.x, thing.y) == (x, y) and thing.name == 'closed door':
thing.name = 'open door'
Though I set the name directly here, I think I’ll change this later to call a method on Thing to change its name. I’m trying to keep World as a state object only, changing its state from outside this object.
In player.ui.chars I have this:
self.chars = {
'player' : '@',
'monster' : '?',
'ground' : ' ',
'wall' : '#',
'window' : libtcod.CHAR_DHLINE,
'lamp' : 'Q',
'open door' : '/',
'closed door' : '+'}
So when I change the name to ‘open door’, the symbol changes, and the movement test for a closed door will pass as well.
Overall, not too bad. I think I’m going to have to generalize the field-of-view code a bit, as I can forsee adding a lot of special cases as I add objects if I keep doing what I’m doing. So far I’m happy with how the rulebook and rules works too.
update:
To make a close doors command required a few more changes. This requires either a command then command input (like a ‘c’ key then direction) or a combination key like command + command. I’ve decided to go with the latter, and I’m using CTRL + direction. I think I like the idea of extending this in the future into a context sensitive command as well. As libtcod doesn’t currently have an easy way to test for a combined key press (I think it’s slated for 1.5) I just made a boolean in player.input like so:
class Input(object):
def __init__(self):
self.update_state = self.intro_update
file = open('keys.cfg', 'r')
self.keycfg = yaml.load(file)
self.ctrl = 0
def get_key(self, key):
if key.lctrl:
self.ctrl = 1
else:
self.ctrl = 0
if key.c:
return chr(key.c)
else:
return key.vk
Every time I call get_key() (when a key is pressed) I check if the left control is pressed and then set the self.ctrl value accordingly. Then in Command I can do this:
def north(self, enactor):
if player.input.ctrl:
self.close_door(enactor, 0, -1)
else:
self.move(enactor, 0, -1)
And then add the rules and a command for close_door() like normal.
premature optimization is the root of all…oh wait (a roguelike in python, #11)
Up to now I’ve been running the demo in a rather small window (about 40×20 cells) with a small viewport (19×19). Actually I like the idea of a game this size, but with the demo I’d like to try something bigger. Since I’m scrolling I knew I might run into issues with how fast the screen redraws (as I’m redrawing the whole thing every turn).
So first I put the level in a text file and made it much bigger (it’s now about 80×50), and then I increased the window size, and the viewport size to 40×40. As I found out the game really got sluggish. Reducing the viewport to 30×30 improved things to make it playable, and so I wanted to see exactly where things were slowing down.
To start, I firmly believe in first writing without optimization in mind. Much of what I write is very verbose, using strings insteads of integers for properties and so on. I think that for what I’m doing the bottlenecks are going to come in specific cases, and it’s not really necessary to bitshift when I can just multiply integers, or whatever real programmers do, I’m sure I’m getting the terms wrong here.
As with many things Python makes it really easy to use support modules and tools, at least for basic things. So what follows here is an idiot’s guide to profiling the bottlenecks in your code.
The cProfile module is dead simple to use and in the standard library. I used it in two ways. First, from the command line, you can do this:
python -m cProfile -o nameOfYourOutputFile nameOfYourGameFile
Your output file doesn’t need to exist first. What this will do is start up your game using the cProfile module to time how many seconds are spent in each function call. When you exit your game you’ll find the output file in the game’s directory. Then you can create a simple .py script like so (this is all in the Python documentation for cProfile by the way) — let’s say your output file was called test_profile:
import pstats
p = pstats.Stats('test_profile')
p.sort_stats('time').print_stats(10)
Running this script will give you a breakdown of time spent. You can sort this output in various ways, see the docs for details.
Now what if you want to profile only one function in your code? When I ran the first script I saw that the viewport draw call was taking a significant portion of time, but the output doesn’t break down the draw function itself. All you need to do is something like this, where you call your draw function:
PROFILER.runcall(self.view.update)
PROFILER.dump_stats('test_profile')
Remembering at the top of your game file to import cProfile and set up the profiler like so:
############################################# # imports ############################################# import os import random import yaml import cProfile import libtcod.libtcodpy as libtcod PROFILER = cProfile.Profile()
That’s it. Then you just run the pstats script above in the same way.
These are the calls that take the most time in my draw function:
ncalls tottime percall cumtime percall filename:lineno(function)
202 7.430 0.037 16.854 0.083 diana.py:427(draw)
194171 1.873 0.000 4.267 0.000 C:\Documents and Settings\GO\My Documents\dev\diana\libtcod\libtcodpy.py:58(__mul__)
194171 1.393 0.000 2.036 0.000 C:\Documents and Settings\GO\My Documents\dev\diana\libtcod\libtcodpy.py:74(int_to_col)
182002 1.360 0.000 1.647 0.000 C:\Documents and Settings\GO\My Documents\dev\diana\libtcod\libtcodpy.py:448(console_put_char)
181800 0.926 0.000 0.926 0.000 C:\Documents and Settings\GO\My Documents\dev\diana\libtcod\libtcodpy.py:454(console_set_back)
194171 0.642 0.000 0.642 0.000 C:\Documents and Settings\GO\My Documents\dev\diana\libtcod\libtcodpy.py:50(__init__)
181800 0.496 0.000 0.496 0.000 diana.py:415(viewport_ij_to_world_xy)
181800 0.494 0.000 0.494 0.000 diana.py:117(cell_type_get)
94940 0.390 0.000 0.390 0.000 diana.py:421(xy_in_viewport)
83478 0.380 0.000 0.380 0.000 C:\Documents and Settings\GO\My Documents\dev\diana\libtcod\libtcodpy.py:1050(map_is_in_fov)
194171 0.358 0.000 0.358 0.000 {isinstance}
203134 0.345 0.000 0.345 0.000 {method 'append' of 'list' objects}
182002 0.288 0.000 0.288 0.000 {ord}
So it looks like multiplying colors together takes a significant portion of time. I may have to look into precaching this information somehow. However there is an even easier way to speed things up, though it requires a third-party module — the Psyco module.
All you need to do to get Psyco working (after downloading and installing it) is put in your game file like this:
if __name__ == '__main__':
try:
import psyco
psyco.full()
except ImportError:
pass
game = Game()
player = Awesome()
while not game.exit:
game.update()
player.ui.draw()
You can also have Psyco optimize only specific functions in your code — as it uses more memory in its overhead, this may be important for some people.
I did notice a speed improvement with Psyco, but as it’s an external dependency my first line of attack will be speeding up the routines in the draw code itself. It may be enough to keep the viewport a reasonable size, thus drawing less to the screen. Of course I haven’t added any real gameplay yet…now that can’t take much time to compute, can it?
how I love refactoring (a roguelike in Python, a diversion)
In working on adding player memory to the map (so cells not immediatly in field-of-view but previously seen are drawn) I realized something. My scrolling/camera code looked like this:
def scroll(self):
self.x_offset = min(max(0, player.thing.x - self.width//2), game.world.level_width - self.width)
self.y_offset = min(max(0, player.thing.y - self.height//2), game.world.level_height - self.height)
self.x_left_offset = min(player.thing.x, self.width//2)
self.x_right_offset = max(0, (self.width//2 - (game.world.level_width - player.thing.x) + (self.width % 2)))
self.focus_x = self.x_left_offset + self.x_right_offset
self.y_top_offset = min(player.thing.y, self.height//2)
self.y_bottom_offset = max(0, (self.height//2 - (game.world.level_height - player.thing.y) + (self.height % 2)))
self.focus_y = self.y_top_offset + self.y_bottom_offset
When it really only needs to look like this:
def scroll_update(self):
self.anchor_x = min(max(0, player.thing.x - self.width//2), game.world.level_width - self.width)
self.anchor_y = min(max(0, player.thing.y - self.height//2), game.world.level_height - self.height)
The problem was I had been treating where the player was rendered as a special case — in effect putting the player and the camera focus position in the same basket. This wasn’t necessary at all — all you need to know is where the camera or view is positioned on the screen (I chose to keep track of the top left corner of the view with the variables anchor_x and anchor_y). Then you just need to translate world coordinates to view coordinates when you deal with the viewport.
I knew the previous code was too complicated. It feels good to get it into shape!
Leave a Comment
Leave a Comment
Leave a Comment
Subscribe to Kooneiform



