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).

Advertisements

2 comments so far

  1. Javier on

    I have just reached the end of the series of post you commited on the matter of the roguelike demo in Python.

    Quite illustrating, thank you!
    I’ll keep on following the roguebasin tutorial, and implementing some ideas of my own. BTW, some of the ideas you use in here are really interesting, so I’ll try to make some use of them… for example… the game engine, the separation for UI/Commands/Input, I kind of notice certain similitudes in the way you use Things and the way in Roguebasin Jotaf uses the composition design pattern, also I’m interested in the speed mechanism you implemented.

    So, thanks again!

  2. georgek on

    You’re welcome Javier, and thanks for the feedback. 🙂


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: