Quest, the roguelike game

This is the development diary of the roguelike game Quest: a quite simple game written in Python, mainly for learning purposes.

Sunday, January 22, 2006

Still here...

I haven't posted for a couple of days, because I've been totally unable to work on the game. Real life can be absorbing! I hope that this week will be less frantic, and I'll be able to report some progress soon...

Wednesday, January 18, 2006

Weapons

Ok, I haven't had much time to do anything this week - crazy week at work. Still, a couple of features have gone in these last few days:

  • Melee weapons are in. Now, when you wield one (held in one hand) it adds to the combat value. Watch out for monsters finding them around next version!
  • Module information: when choosing a module, the screen shows information about the highlighted module, so the player can decide better wether to try it or not.
  • Health/Mana regeneration now happens sometimes. Before, they never increased, but now a player can heal and rest with enough time.
If I have time, this week I'd like to also add a new ability - Lockpicking, so it's possible to lock/unlock doors without the key, and also make monsters able to use Minor Healing, Tracking and Lockpicking like players do. This will probably entail heavy rewriting of the AI module.

Sunday, January 15, 2006

Version 0.1.2 released

Well, in the end I did have time to polish it out before the weekend was over. The bugs have been solved, and I'm very happy I made it in time, since next week will be crazy and I doubt I'll be able to work on Quest at all.

The changelog for this version:

Interface:
  • The message window now makes messages dim as they get pushed back.
  • The message window now holds seven messages instead of five.
  • It is now possible to quit during the game by closing the main window (if necesary, the game will be saved).
  • When the user enters a string, it is highlighted yellow and stored in the message buffer after it's entered.
  • Whenever possible (with items/beings), choice lists now show the symbol and color of each element, next to the choice (i.e, "+ ~ a torch" instead of "+ a torch").
  • The information window (which shows long text such as descriptions) now has word-wrapping.
  • The key to save and quit in the main game is now "s", to avoid hitting it by accident when using ESC to get out of menus
Engine:
  • The requisites to load a module are now handled by a special file, modulename.req. This way, to check the requirements only this file has to be loaded instead of the whole module, making startup time much faster.
  • Since getting Field-Of-View (FOV) is processor intensive, now the game uses caching. It will cache the FOVs of the level for later use.
  • Monsters now have a primitive memory: if they remember something very interesting, they will try to reach the place where they saw it last, instead of going for something they can see that is less interesting. This makes them able to chase the player quite well.
  • Each tile now has a "track" reference, to the last being that passed through it, the direction they left, and the "strength" of the track, which fades with time. This track can be checked with a new ability (see Content changes), and will eventually allow monsters to track the player.

Content:

  • There are now two kinds of maps: Underground maps (dark everywhere) and Overground maps (lit everywhere).
  • Modules now have requirements of minimum/maximum fame to join, which are set in the editor.

Bugfixes

  • When the display gets a string, it now accepts backspace to delete characters (duh!).
  • Portals now check that a being is standing on them before they let the being cross the Portal.
  • Light sources now behave properly when doors are open/shut.
  • Walls can now only be seen when you're on the right side of them, if they're lit by a light source.
Unfortunately, there are not many screenshots that could show the changes properly, since they aren't really visible, but here is a main game screenshot:

Saturday, January 14, 2006

Evil bugs

Even though I did finally decide to make a 0.1.2 release this weekend, I doubt it will happen. I have a couple of nasty bugs I can't allow in the release, and trying to fix them has made it impossible to work on the other two necessary things for a release: re-writing the documentation, and making a Mac port.

So, tomorrow I'll try to fix the remaining bugs (which have to do with the AI acting quirky and the caching FOV making light sources not work any more when there's more than one level, if you're wondering), but that still makes it very unlikely I can get it all done. And of course, next week I have a lot of meetings and busy time at work...so 0.1.2 is likely to come out next weekend, with a small chance of happenning before that. I doubt very much it will be later than that though, or I'd be really upset!

Thursday, January 12, 2006

Smarter AI, module requirements

So, besides some more bug-fixing, two little new features put in today:

Monsters are smarter. Not very smart, mind you, but at least they react to more than just what they see. I'll explain with an example. Before, if an ogre saw a yummy player (interest rating: 5) and a torch (interest rating: 1), it would obviously start going for the yummy player. But if the player goes around a corner and disappears - the ogre would look around, see the torch, and go for it. Now, though, the ogre remembers the player. He thinks he was indeed much, much nicer than the crappy torch. And then, the ogre walks up to the last place where he saw the player - and many times, from that position he will be able to see the player running along a corridor...which means he will keep going for his @-snack. On the other hand, if the ogre reaches the place where he saw the player and he can't see anything, he will forget about the player, focus on what he can see, and go back for the torch.

You might make some smartass comment like "Ok, but the ogre forgets about the player once he gets to the last place where he saw him. Not very good at following, is he?". You know, you're right. But I'm adding a system that will make the ogre be able to follow (if you're not very stealthy, and/or the ogre is very good at tracking you). And that system might actually make the Stealth attribute useful too! Yay! You'll be able to "cover your tracks" and also to follow monster's tracks (if one is fleeing from you). Hobbits might be a little beefier then - but still underbalanced. On the other hand, the next step will be to make Stealth lock/unlock doors without the key - which will make hobbitses very hard to catch indeed (they will be able to run, cover their tracks, leave locked doors behind them...)

The second change: modules now have requirements to join. Before, all you needed to play a module is to not have played it before with that character. But now, modules can have minimum/maximum fame requirements. This way, I can make a "tutorial" module that requires that you have fame 0 (that is, you suck), or an "advanced" module that requires that you're a kickass adventurer (say, fame 20). I plan to add more requirements, but not for this version - like having completed specific modules before, being of a specific race, having certain attributes to a certain level, etc.

Even though I've added quite a few things lately, I'm hesitant to make a release. On one hand, I've fixed bugs that made the previous nasty, but on the other I'd like each release to have enough meat that you can notice the difference pretty fast. I'm not sure what to do.

Wednesday, January 11, 2006

LOS (probably) solved

Well, the answer to my problem seems to come from an unexpected place: threading! I'll try to explain briefly:

The profiling seems to show that my bottleneck is Line Of Sight calculation - it's called a lot, specially if there's a lot of monsters/lightsources on the level, and it made the game quite slow.

My first attempt was try other algorithms instead of my custom-made one: but they were either not accurate enough, or slower. I just couldn't get it done! Yesterday, I implemented a variation of Bresenham's algorithm, to have a ray-casting system -- too slow.

Fortunately, the start of a solution came from Guild and PGuild author Antoine, in a rec.games.roguelike.development discussion: when he generates a field of view (FOV) in his game, he caches it. Then, if another FOV has to be generated at the same place (if a monster walks into it, for example) it's retrieved from the dictionary instead of recalculated. If anything that can change FOV happens - like a door opening or closing - he clears the cache of the level. A brilliant idea, methinks!

So, doing just that improved the game slightly - not enough, but nice, specially when (for example) a monster carried a light source around. The first change I made to it was make it so when a door opens/closes it doesn't clear the whole cache - only those tiles that the door can "see". Overall, and very specially on big levels, this made an improvement. But I wanted more caching.

But I still thought - hell, many times you just sit there looking at the screen, and that pause of one or two seconds could be used for so much calculating, instead of doing it all between player turns! So I decided to try threading, and so far it seems like another nice boost to game responsiveness.

Basically, when the player enters a level, a new daemon thread is created, a "cacher". This little thread starts generating FOVs of every single freakin' tile of the level map, and caching them all. I haven't noticed slowdown while it's running, and the effect is quite noticeable, specially in monster-packed levels. I don't know if memory usage might be an issue, but so far - and with reasonably large maps - it hasn't at all.

So, for now, and with a grain of salt, since problems might still arise, I'm happy. The game is still a little slower than I'd like when there's 20+ monsters active at the same time, but it's definitely faster than it was before. I will leave LOS for a while and see how it goes, then come back if it still seems slow or this solution has obvious flaws that I haven't seen yet. Next step - slightly smarter monsters.

Tuesday, January 10, 2006

Slow, steady progress

Some of the improvements I mentioned yesterday are fixed for the next version : portals now behave properly, and light sources don't light up walls when you're on the other side of the wall.

I still am working on faster LOS calculation, and will probably cache as many calculations as I can to speed things up, since I don't think I can make it really fast and accurate at the same time -- we'll see.

And I see no easy fix for Dvorak keyboard issues until I make a proper keyboard-mapping tool that lets the user customize command keys, but I'll keep looking into it.

Next on the list is the LOS, that's very important. After that, probably making monsters a little bit smarter by giving them a memory, and adding some sort of "scent" so that they can find the player (or another monster) if they stumble on their previous path. And combined with that, stealth - which should make hobbits a little less underpowered. There are still more things I have planned before a release - modules with actual fame requirements (both min and max fame), and modules that require a previous module to have been won...and more things, but I'll list them as they get added or at least worked on!

All in all, slow but steady - the only things that still nag at me are LOS and also the constant fear of the game becoming too slow.

Monday, January 09, 2006

Various bugfixes, little improvements

Although I haven't had much time to work on the game for the past few days, I have fixed several ugly things that shouldn't have been there, so the next release is nicer: allowing Backspace to delete characters when entering strings (this was working with curses, but the port to SDL broke it), and more importantly (I'm very glad this works now): light sources now update correctly when a door opens or closes.

Another change done today, when choosing a module, all the modules aren't loaded anymore. Before, to check requirements to join a module, the whole module had to be loaded from disk, which (if there were several big modules) amounted to lots of work. Now, requisites are held in a separate, little file. Much faster startup.

There are a few nifty improvements that take use of pygame's features: the message window now has messages dim until very dark as they get older (the last message is white, the next a little dimmer, etc.), which makes for a nice experience. Also, controlling the font size has let me add more messages to the buffer, so seven can be seen at the same time now. I will add a couple more similar things to the next release.

For other things I want to work on this week -
  • Light sources not lighting a wall when you're on the other side of it (if you don't understand it, it doesn't matter, but right now if a light is lighting a wall and you're on the other side, you see the wall as lit).
  • Dvorak keyboard. Apparently, pygame doesn't handle this very well. I don't know if there will be an easy fix, but I will research it, probably tomorrow.
  • Optimization of the LOS algorithm. I have a custom-made one that is very accurate and nice (shadow-casting calculating arc-tangents and angle intervals), but slow. And the ray-casting one I wrote to be faster isn't as accurate. If I can pre-calculate things for my own one, or cache calculations so they're only done once, maybe it would be acceptably fast. I'm not sure, but have to look into it.
  • Make portals behave properly. They should only be used when standing on them, and there should be a key to use them that's easier than "+". In fact, I might make "return" the default key and pressing it on a portal would use it.
On the good news side, there's been quite a few people who've tried the game, even though it's in a pretty bad state yet - encouraging! The more bug reports and feedback, the more drive to keep working on it and make it playable. Thank you, if you're reading this!

Sunday, January 08, 2006

Version 0.1.1 released

Well, I managed to get the windows binary working, yay! There is absolutely nothing new in this version except the fact that now the game is a graphical window (with ascii graphics, of course), and that there is a separate, binary windows port so windows users don't need python to play the game.

You can get the source here, and the Windows self-contained binary here (the Windows binary has lots of needed .dlls, so it's quite big).

A couple of screenshot goodies! For some reason, they have funny colors when seen on this page, so click on them to see them for real. First, the editor:


The black window in the middle is the stupid screenshot interface, ignore it.Now, the main game:


As you can see, they look pretty much the same they did before - except now the colors are different, since I can choose them (or my wife can *cough*), and the font is nicer. On the next version, I'll try to take more advantage of pygame's features, but I wanted to have this done first to make sure I could make the game run in windows.

Next step, which I'll attempt during the week, will be to port it to Mac OSX so it can be run without any requirements as far as python/pygame/etc, like the windows version.

Saturday, January 07, 2006

Finally, good news

Well, a few pieces of good news this time:

First, I have an almost working version of the game with pygame. There are a couple of minor things to fix, and it will be running fine. It looks even better than it did on the console (I can control where to put things exactly, so a square room now looks square, and I have millions of colors to display text), and it is quite faster, for some reason. Kudos for pygame!

Second, I have been looking into packaging the game as a windows executable using py2exe, as was suggested in r.g.r.d, and it works! Instead of having people get python + pygame, I can package everything and make it run as a stand-alone application in windows. I might be able to have this running before monday, and if so I have to post at r.g.r.d so people can check it out if they want to.

I have to look more closely at py2app, which I think will work similarly so it shouldn't be too hard, so people with osx can play without getting additional packages.

Anyway, most of the setbacks are solved and I should have a really working 0.1.0 in a day or so. Yay!