Archive for the ‘python’ Tag

what? am I making

The last few weeks have been one of those odd times where I don’t feel a really strong push in one direction. My usual way of doing things is to focus intensely on one thing for a shortish amount of time, and then move on to something else. Incidentally it’s been a long-term thing to try to stretch that focus out a bit so that I can work more consistently on larger projects. But anyway, I’ve felt becalmed lately, and this doesn’t happen that often, so it’s a strange sensation. Kind of puzzling, like — what’s going to happen next?

It’s an early Spring here. You’d think that would get the creative urge going; however it seems to be doing the opposite. On the other hand, I tend to do things backwards at first. Maybe then this is the natural state of affairs. It’s sort of making room for doing a lot of little things in a leisurely and lazy way.

Transplanted the tomatoes to four inch pots:

Found a cool Python editor — basically a livecoding editor — called Reinteract. Haven’t got it to work with pyglet yet, probably because pyglet’s event loop and the Reinteract GTK loop won’t play together nicely without some hacking. Someone on the Leo list clued me to Reinteract, so maybe someone on the list will run with a Leo to Reinteract bridge. It’s a pretty cool IDE, I recommend checking it out.

Starting to play around with an idea for an IF news service. I think as more and more people are blogging on IF, combined with the various forums and newsgroups, some way of feeding (and possibly filtering based on the recipient?) the flow of community information will become more valuable. I like Planet IF but it’s not really serving this purpose at the moment, and I’m not sure that it could; what I’d like is something that gathers all the disparate sources. And well, since I obsessively read everything anyway, why not put that to some good use. The first iteration was just me collecting links. I have some ideas on where to take that but nothing solid yet. I also have wanted to get more into web stuff so this would be a nice project for that.

Worked some more on mockups for a Python IF IDE in GIMP and Inkscape, and realized that’s harder than I thought it would be! I’d really like to work more on drawing to make this easier. As a result I’ve started to learn the Qt framework for GUIs, which is easier than I thought it would be. So there you have that.

While in the library today to pick up a book (and pay my overdue fines, again; I think I must support several librarian’s wages really) a book on display caught my eye, The Assault by Harry Mulisch. In the first part of the book a 13 year old boy witnesses a German collaborator gunned down by the resistance in front of his house, his brother disappears into the night with the collaborator’s gun, and the Germans arrest his family and destroy his house with grenades and flamethrowers. Then he spends the night in a jail cell with a beautiful wounded Communist terrorist, narrowly escapes death the next morning when an Allied fighter strafes his convoy en route to Amsterdam, and finally reaches safety in the arms of his uncle. Mulisch is a prominent Dutch author (who I had never heard of) and it shows, the writing is masterful even in translation, and shares a lot with two of my favorite writers, Saramago and Murakami, in the way their narrative voice exists on top, through, and under the work itself.

As usual I have a list of ideas a mile long. Something is brewing, I just don’t know what.

Advertisements

towards popular Python interactive fiction (#1)

I’ve sort of touched on this topic in previous posts, but I’m trying to crystallize my thoughts here.

In my opinion there currently are three viable options for creating IF with Python: PAWS, PyF, or a custom system. An alternative form of IF can be made with Ren’Py, a visual novel system. Finally, there are two possibilities in the future: Curveship, and another I learned of recently, Prosemonger.

Two other ‘less possible’ possibilities are PUB, and any one of a number of Python mud engines (particularly those with Twisted, a lib originally built for mud IF).

But let’s talk about making a game, using Python, in prose-based, command-line IF (you know, what most people call, ‘IF”). That rules out Ren’Py, PUB (too old), and Python mud engines (too incomplete, or conversely, too complicated I think).

Curveship and Prosemonger are out too of course, as they’re not yet released. As an aside, while I’m eager to write with Curveship, from what I know I don’t think it will be much like IF as it’s played and written today. I think it will be more akin to an academic, generative narrative system, but only time will tell.

At this point a digression is in order (well, with me digressions always are in order, but I…OK, I won’t go there). When I say ‘towards popular Python IF’, what does that mean anyway? And why would you want to write IF with Python in the first place when there are at least five major IF systems that would fit the task very nicely — TADS 3, Inform 7, Inform 6, Hugo, and Adrift?

Continue reading

Bidden #8

I didn’t get back to Bidden until last Thursday (at least according to the commit log, I might have done a couple of things before then), but between Thursday and today I’ve:

* added levels and level switching
* added a datastore to make it easier to make new things after I’ve loaded everything in from level files
* added a basic animation system (X-com style with turn-based)
* tweaked the level generator a little to make it look nicer (to me)
* added a stairway driller to this generator
* along with the stairway added stair exits

For this level generator (the temple) the stairs work a little differently from a typical RL — there’s one stairway created (so far), and all the stairs are connected. When you walk over a stair you automatically descend/ascend, and are put in the middle of the staircase. At the top and bottom level you can’t go up or down anymore of course. I might change this to use an ascend/descend command, but I’m leaning toward not at the moment.

Ran into obvious but for a while insidious bug (aren’t they all) where the stair exit move event handlers were all firing, because I wasn’t modifying the event data packet properly…

I’m finding it’s very important to have a standard way of handling event data for each event handler. Better yet, I should standardize that somehow in something that takes care of that automatically. I don’t think I’m quite there yet though. With the pieces I have now there’s enough to hammer on to get things tight before I start to add much more.

Bidden 7DRL code review

While things are still fresh in my mind I want to review the somewhat bizarre code design I came up with during the 7DRL, if only to mark a way point to look back on as things change.

Here’s the code (Leo makes exporting this outline easy):

+ Code
	- TODO
	+ @thin bidden.py
		- << docstring >>
		- << import >>
		- << constants >>
		+ class Game
			- __init__
			- load
			- save
			- create_gid
			- register_gid
		+ class Event
			- __init__
			- broadcast
			- register_component
		+ class Control
			- __init__
			- action
			- switch_view
			- quit
		+ Controllers
			+ class Menu
				- __init__
				+ new_game
					- << make player >>
					- << make binding >>
					+ << load from .bid >>
						- << test >>
					- << put things in stage >>
			+ class Intro
				- __init__
			+ class Play
				- __init__
				- move
				- use_boon
				- wait
				- help
			+ class Coda
				- __init__
		+ class Component
			- __init__
			- __lt__
			- __gt__
		+ Components
			+ class Hunter
				- __init__
			+ class Container
				- __init__
			+ class Model
				- __init__
				- on_death
			+ class XY
				- __init__
				- on_move
			+ class Stage
				- __init__
				- create
			+ class Collision
				- __init__
				- on_move
			+ class Bump
				- __init__
				- on_move
			+ class Title
				- __init__
				- create
				- make
			+ class Hunted
				- __init__
				- on_death
			+ class Wounds
				- __init__
			+ Boons
				+ class Boon
					- __init__
				+ class Strike
					- __init__
					- on_boon
			+ AIs
				+ class AI
					- __init__
				+ class Zombie
					- __init__
					- decide
		+ class Prototype
			- __init__
		+ class UI
			- init
			+ class Pane
				- __init__
				- fade_in
			+ class Animation
				- __init__
			- input
			- view
			- menu_draw
			- intro_draw
			- play_draw
			- coda_draw
			- quit_draw
			- play_help_draw
		+ class Keyboard
			- __init__
			- check
		- << run game >>

Let’s look at the concise version:

+ @thin bidden.py
	- << docstring >>
	- << import >>
	- << constants >>
	+ class Game
	+ class Event
	+ class Control
	+ Controllers
	+ class Component
	+ Components
	+ class Prototype
	+ class UI
	+ class Keyboard
	- << run game >>

Going over things from the main loop:

    while not libtcod.console_is_window_closed() and not game.control == 'quit':
        keys.check()

        if game.control == 'play':
            for item in game.gids:
                thing = game.gids[item]
                for k in thing.__dict__:
                    c = thing.__dict__[k]
                    if isinstance(c, AI):
                        c.decide()
        ui.view()

The keys instance of Keyboard waits for a key press. If it gets an ‘x’ or the control key it waits for another key press. This is my somewhat hacked way to get key + direction key combinations. It checks if the key is in the configuration for the game, and sends a message (such as ‘up’ or ‘enter’) to the method UI.input.

That method passes along the input to the current game.control, including it in a dict and adding the enactor game ID (in the case of the player, 0). There’s a control basically for each state of the game (main menu, in-play, etcetera). I tried to make all arguments passed around in the form of a dictionary, using the same key names for like types of data.

Each control inherits an action method from the Control parent. This method checks the input message against an actions dictionary, and if the message is a key, it runs the corresponding value as a method on the control instance (for example, I had the ‘enter’ key mapped to a method to advance the state of the game arbitrarily, so I could restart the game without exiting/restarting the Python file). Individual control instances may map the same message to different methods of course.

This method gets the data in the dict described above. A good example is the move method (in the ‘play’ control instance, mapped to the ‘up/down/right/left’ message which is mapped to the arrow keys in the keys instance):

def move(self, data):
    self.directions = {
                        'up' : {'x':0, 'y':-1},
                        'down' : {'x':0, 'y':1},
                        'right' : {'x':1, 'y':0},
                        'left' : {'x':-1, 'y':0},
                        }

    data['event'] = 'on_move'
    data['outcome'] = 'continue'
    data.update(self.directions[data['input']])


    event.broadcast(data)

So this method basically adds data to the dictionary, and then sends it to the instance of Event.

Event , in the context of the 7DRL, probably was a big mistake…going into the week I had vague thoughts of trying out a message passing/broadcasting scheme for the first time, and this was the result. I spent a lot of time figuring this out.

The Event.broadcast method takes the data and sends it along to anything registered to listen for the event included, in this case ‘on_move’. So, when the player presses the up key, it’s not directly moving the player-character, but telling the game to announce that the player-character has the intention of moving…I know, I know.

To digress for a moment, each thing in the game is an instance of Prototype, which basically is a collection of Components. A component is a narrowly-defined piece of functionality, that registers itself with the event instance upon creation. For example, if the component has a method called on_move, the event instance will tell the component when an on_move event occurs.

There is a component called XY that holds the in-game position of a thing, and its on_move looks like this:

def on_move(self, data):
    if (data['enactor'] == self.gid) and (data['outcome'] == 'continue'):
        self.x += data['x']
        self.y += data['y'] 
    return data

When the player presses the arrow key and the event instance broadcasts ‘on_move’, the XY component of the player-character will take that data — if the ‘outcome’ is ‘continue’ — modify its x and y position, then pass the data along back to the broadcaster.

The reason for ‘outcome’, and passing the data back to the broadcaster, is that other components handle things like collision with walls and bumping into other things. They’ll have an on_move method, and it receives the data broadcast. For example, here is collision:

def on_move(self, data):
    enactor = game.gids[data['enactor']]
    dx = data['x']
    dy = data['y']
    xx = enactor.XY.x + dx
    yy = enactor.XY.y + dy 

    stage = game.gids[game.stage].Stage 

    if not stage.cells[yy][xx]['kind'] == 'floor':
        data['outcome'] = 'failure'
        return data

    return data

Now obviously the question came up — in which order is the event broadcast? In other words, if the XY of the player happened to get the event before collision, the player would move before the collision check even happened.

To make this work I gave each component a priority from 1 to 1000, with a default of 1000. The collision component’s priority is 100, and the XY priority is 1000. Then before event broadcasts, it sorts the list of components registered for the event. This is easy to do with Python by writing a method like so on the Component parent.

def __lt__(self, other):
    if self.priority < other.priority:
        return True
    else:
        return False

If the class defines __lt__, then calling sort() on a list of instances of that class will sort it appropriately.

That’s all there is to the event broadcasting, basically a chain of event filters that modify both the event data and game world data as the event propagates through the listening components. I suppose I’ll find out what problems this causes down the road!

NPC actions are basically the same, the only difference being in how they’re initiated. Going back to the game loop:

        if game.control == 'play':
            for item in game.gids:
                thing = game.gids[item]
                for k in thing.__dict__:
                    c = thing.__dict__[k]
                    if isinstance(c, AI):
                        c.decide()

This runs through each component, and if it’s an AI, it runs the decide method. This is all I have for decide at the moment (in the Zombie component):

def decide(self):
    choice = random.choice(self.actions)

    data = {'enactor' : self.gid, 'input' : choice}
    control = game.controllers[game.control]
    control.action(data)

Where its self.actions is just this list — [‘up’, ‘down’, ‘right’, ‘left’, ‘wait’].

This just gave me an idea for attaching AI components to the player…anyway.

After the player does their thing and the AI runs, the UI instance runs its view method, which looks like this:

def view(self):
    libtcod.console_clear(0)

    for item in self.views:
            func = getattr(self, game.control + item)
            func()

    libtcod.console_flush()

So, clear the console, and go through its list of views and run the function — for example, there’s one called ‘play_draw’, where ‘play’ is the game.control and the item is ‘_draw’.

Other conceivable ones might be ‘_log’ to capture the game state, or perhaps ‘_write’ to turn this into IF ;D. In any case, yet another example of severe over-engineering…

These methods are fairly straightforward…I did one weird thing where certain events could create ‘animations’, components that last for just one game loop and get added to the list of game objects to be drawn. That’s something I need to redo (I want to have multi-frame animations possible between each player turn). My current idea here is to make drawing a series of frames, where normally there’s just one frame as I have now in play_draw, but with the potential for adding frames to make the animations.

So that’s it. If I expand this I can see the component system getting really massive…on the other hand I don’t know that any game wouldn’t have a similar situation once you add a lot of stuff. I can derive children from component classes in some cases (for example with AI) so that might keep things more organized. I like the separation of input/views/logic. Right now the world state is woven into the game logic quite a bit, but I’m of mixed feelings of trying to make a hard separation between the two. In this application it may not be worth it.

Any comments or criticism is particularly welcome at this point, so feel free.

Bidden day #7

total time: 54 hours

Well it’s 10 AM, up all night, and it’s rather shocking given the time spent, but I didn’t finish. The still warm entrails are here:

http://sites.google.com/site/biddenrl

You’ll need Python 2.6 and Windows to play (I use the word play very loosely). Linux shouldn’t be that hard but I’m not sure if I have the correct DLLs in the zip — you’re welcome to check it out though to see (I did include some .so DLLs, so maybe that will work).

I got to the point where the player had a goal, but really no gameplay. I spent a lot of time messing around with programming and obscure code structures, where I should have ruthlessly simplified/hacked things to get the gameplay vision in place, since I had a very clear idea of where I wanted to go. On the other hand I’m definitely pleased to have spent so much focused time this week (more than twice what I’ve ever done for Pyweek or Ludum Dare). A lot of the time went to basic programming tasks, which will speed up with practice I think. In general I feel like I’ve crossed a hurdle of some kind in making stuff.

In any case, I’m still very into the Bidden idea, so I’ll continue working on it until it’s fully realized.

Bidden day #7 in progress

time so far: 44 hours

The RNG smiled on me this afternoon and I finished early at work, so got an extra few hours in this afternoon. About 12 hours left, and I’m still very far from a success I think. But the structure is almost completely there. Right now it’s 9 PM and:

* I have the house to myself
* I have a full can of tea
* soul on the radio
* nothing to do tomorrow

We’ll see what happens!

Bidden day #6

time so far: 38 hours

* the creature is corpse’d when you bump into it (decorpsed? corpsefied? ‘killed’ is a little strong given the state of the creature model at the moment).

* world creation occurs properly at game start.

* beginning of a goal.

* but I did spend 2/3 of the night on message passing and event filtering! I’m sure this will come in handy.

tomorrow:

* add more creatures

* add at least one character boon

* add everything else

Bidden day #5

time so far: 35 hours

For some reason I thought it was Thursday today. What luck!

Still avoiding gameplay by making intro and help screens. I’ve also been messing around too much with stuff like UI and game input structures. However tonight I’ve been getting more messy and loose, and progress is accelerating. The screens above are the basic outline of a single play through. All I have to do now is add everything else!

Bidden day #4

time so far: 30 hours

Yes it’s true…only three more days to go…still no goals, conflict, character advancement or content. But I made a lot of title screens!

Really I couldn’t resist. The above example is a kind of mash-up from messing around with ascii-paint, the wonderful tool by priomsrb. I did get some other things done — I’m on my way to a structure for a menu, state switching and so on. I have a feeling though that I’m avoiding some of the harder things by doing these things that are, really, not totally necessary to making a functional game. I think it’s OK in the end though, it’s kind of like a mid-term break, and it should add to the overall experience (assuming I have something playable to experience!).

Still with the goal of a playable run-through from start to finish — would like to get that done by tomorrow night. Then Friday is work all night to add things and release.

Bidden day #3

time so far: 26 hours

The mockup slowly wrenches its way toward a real game. Believe it or not, up to this point in my programming self-education I had never touched procedural map generation — always working with hardcoded maps while doing other things. Luckily libtcod makes all of this fairly painless. I can’t imagine doing all of this from the ground up as some entrants are doing!

The above is a simple binary-space partition, with the borders of the rooms walled in, and then tunnels dug from room to room (somewhat randomly). I’m quite relieved to have made this milestone actually, as I was worried it was going to be a major stumbling block. I think I’ll be able to produce a rougher ruin map, and a twisting labyrinth map, in similar fashion. Of course it’s an open question if I’ll have any content to fill those maps with!

Basic movement and collision is in of course, and along with that and the level generation a proper code structure for the map as well.

I spent a bit of time with generating a template for title creation — if you look in the header you’ll see a partial example of that. In the story of this world there are many groups and factions, forming in every which way, and I hope with the titles to add some of that flavor.

Wrangled more with the json saving and loading — found since everything is unicode in json I need to convert symbols to str before printing with libtcod. It’s turning into more of a cost than a benefit, but one of my goals with this project was to give json a go, and I’m certainly doing that!

My long weekend is over, and it’s back to the dayjob Tuesday-Friday. Hopefully I’ll have some extra free time during the day this week, otherwise I see some long evenings ahead. My goal now that I have the basic structures is to get a playable run from start to finish, even if this just means the bare minimum of content required.

Almost double the number of entries this year compared to last year by the way — incredible!