Archive for August, 2009|Monthly archive page

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.

paneselect

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)

dianamessages

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.

the social space of mudders

I don’t write much about muds anymore as I haven’t been playing muds. Nearly all of them are far less suited to casual play that I would like. Nevertheless I still read the various forums, and right now there’s a long thread over at Mudbytes about a new moderation system the admins there are considering implementing. Read on if you’re curious, but fair warning that this may be interesting only to a very few people.

If you don’t follow muds, there are three main sites with forums: The Mud Connector, Top Mud Sites, and Mudbytes. Mudbytes is a relative newcomer, in some sense taking the role that MudMagic used to fill (a site which is now closed), indeed, as is often the case with community sites, it got its start partly due to people leaving MudMagic. All things considered I’d say that Mudbytes is the most vibrant discussion forum currently going. Particularly in the last few months it seems to have gained some new members, and while in my opinion it used to be focused on DIKU-derived codebases, lately it’s seen a more interesting range of discussion from programming to design.

All of this is a long preamble of context to frame why I’m posting this. I would have posted in the thread linked above but I felt it wouldn’t have served much purpose really, and what I’m trying to do here is get some thoughts out there to figure something out. For the record my nick on Mudbytes is Idealiad.

So what the Mudbytes admin are proposing is a system of moderation with a dedicated forum to contain ‘moderation threads’ — basically reference threads created when any disciplinary action takes place. The basic idea is to create a transparent system so that threads aren’t derailed with moderation disputes, and make it easier to reference moderation actions without digging up threads all over the forum. Also new moderators would be put in place to do the actual work of modding. The idea for this is derived from another forum with a similar system.

This is all in response to some recent issues with people getting suspensions and threads getting locked over some troll threads and responses that apparently are against various Mudbytes rules. People were crying foul over what they saw as heavy-handed moderation and wanted more transparency and accountability in how the modding went down.

So the proposal thread has developed in an interesting way. First of all my response was against the idea of a moderation sub-forum, but for the idea of new mods. My main beef with the separate sub-forum is that I think it creates an atmosphere of antagonism rather than cooperation. I’ll try to explain my reasons for thinking that.

I think the ‘community energy’ of a site is relatively fixed. How the community chooses to spend that energy influences the tone and direction of the site, how its members will treat each other and how new members will integrate into the established community. So when the community spends its energy in creating an infrastructure to deal with infractions, it is taking away energy from other things.

I have to admit my main influence on this thinking is the time I spend on TIGSource. TIGS is not without moderation of course. People there have been banned and threads locked. In general though, I get the sense that the atmosphere of TIGS is much, much different than that of Mudbytes (to be fair it’s also a much larger site, and so personal disputes don’t tend to involve the whole community like they do at Mudbytes, so their impact is somewhat diluted in the grand scheme of things). In essence TIGS spends its community energy on, for lack of a better word, ‘positive infrastructure’. An effort is made to keep things moving in a positive direction. When people trend the other way there is an effort by others to steer the ship to its original course.

As a result of this comparison, I got frustrated with Mudbytes. What I’d like to see is a similar focus on positive infrastructure, and less on what is in effect an infrastructure for litigation.

What could be the reasons for this difference? My first thought was that it has to do with the nature of mudding itself. Muds are games that primarily are social spaces. Unlike the majority of games on TIGS, a mud is in itself a social space. You certainly can have a community based around a game on TIGS, but this idea of a social space is quite different. There is a long tradition of large hierarchies running muds, with all the rules, sometimes formal and sometimes informal, you would expect in any community. By their nature then, mudders are used to all sorts of frameworks for maintaining this social space, and these frameworks are going to mirror what we see in society at large — judicial and political systems — and when the time comes to moderate another social space which they are a member of, like Mudbytes, they’re going to turn to these same rules and frameworks as the tools they’re comfortable with.

It’s not surprising then that in that Mudbytes thread people are not really arguing about the need for such a system of moderation (with one or two exceptions), but instead debating what seems to me more and more elaborate systems of moderation and their finer points of implementation. In essence the die already is cast.

The thing here though is that I think people like this. Whether there is a sub-forum for moderation or not it doesn’t really matter — the community at Mudbytes already is oriented toward this way of being. They like going back and forth over who’s trolling who, what should be modded or shouldn’t, and all the finer political points in between, and will continue to do so no matter what kind of system is set up. It’s kind of like people who go for student government or model UN. In that case a system with more transparency is probably better than a system with less, don’t you think?

So in the end I guess I have to accept this community for what it is if I want to participate in it. I don’t know if it’s possible for it to be different, more like TIGS or something like it. In effect its social space already is dictated by the social habits of the mudders themselves, and I don’t see in the near future those habits changing very much at all.