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.

I’m imagining things like an object that’s an ‘open broken door’. (perhaps this door can’t then be closed and/or locked). I would have to find this symbol (if I do indeed try to represent this with a unique symbol) in the dictionary of ui.chars when I draw it to the screen. Given the code above this isn’t going to happen, as it only searches for individual states, not a combination — how then could I find the right symbol?

First of all it seems like I don’t want to depend on an exact match, as I would have to reorder every combination of words in the string — i.e., ‘broken open door’ and ‘open broken door’. What I really want to do is compare the list of states + name (‘open broken door’) with the ‘list’ of the key (a string, really) into ui.chars (for example, say the key actually is the string ‘broken open door’).

If I convert the string to a list by splitting on the space (string.split(‘ ‘)), then find the difference of the two sets like this:

difference = set.difference(set(a), set(b))

If the two strings in any order are different from each other, difference will be non-empty.

This alone doesn’t solve the problem where a thing has multiple states and only one of them in combination with its name matches a key in ui.chars. For example, if a door has the states ‘open’ and ‘pickled’. If the key is ‘open door’, ‘open pickled door’ won’t match it using a difference of sets. But maybe ‘pickled’ isn’t applicable to the visual symbol for the door at all, and it should match as ‘open door’.

One possible preliminary test is to create a list of states + name, then check if each word of a key’s string is in this list. If so, this should match if the states + name in its entirety doesn’t match any other key. For example:

list = thing.properties['state'] + [name]

for key in player.ui.chars.keys():
    key_list = key.split(' ')
    for item in key_list:
        if item in list:
            print 'match'
....
#etcetera

Perhaps more trouble than its worth. For certain effects/states I’m going to want to just color the character anyway, rather than having a separate symbol for every combination of thing and its state. Still, this could work well for updating a thing’s symbol on a dynamic basis as states change. Have to try it out and see.

Advertisements

No comments yet

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: