Archive for April, 2009|Monthly archive page
I admit I don’t play many muds anymore for lack of time, but there are a couple of new muds in development that I keep my eye on and play when I can. It’s rare to find well-made new muds these days, but here are two:
Avenshar is a solo effort by Sean Lucas’ RuneFire Studios. Rare for the mud genre it’s played solely in a Flash client, with accessible gameplay and a great UI in my opinion. Sean is doing some interesting things here and it’s well worth checking out.
Developed primarily by Wade Gustafson and Matt Adcock of The Binary Forge Ltd, Maiden is a very promising new mud. You can create a character currently and join the forums and so on, but it’s not yet open for regular play.
If I had to pick one mud to play that combines roleplay and goal-oriented play, it would be this one. A few months back I had a go at building for Wade and Matt but unfortunately I flaked out due to an overload of commitments. I’m hoping that once it opens though I’ll be able to drop in for some casual play and perhaps some building if it works out.
Last weekend I participated in Ludum Dare #14. Forty-eight hours later my first game was born. While it was a great time I didn’t really get everything into the game that I wanted to, it was more of a prototype of the concept. I had worked about 16 hours on the game altogether but also got a normal night’s sleep on Saturday, which probably was a good thing.
Too busy to both start playing the other (121!) entries and do a post-compo release, I chose to start playing games, and worked only about an hour on the game during the week. However last night after another eight hours or so I got things to a point where I was ready, and this morning I managed to bundle some executables.
So here it is. I can’t say I’ve cut the umbilical cord or washed off the amniotic fluids. There aren’t really any instructions. I had an idea and I hope I expressed it in the game. The theme of LD #14, by the way, was Advancing Wall of Doom.
the post-compo release
recommended (Windows .exe in tar.gz, about 4MB)
the post-compo release (Windows .exe in .zip, about 9MB)
the post-compo release (.zip, you will need Python and pyglet installed, about 1 MB)
the original compo release (.zip, you will need Python and pyglet installed, about 1MB)
If you look at the code for the scrolling demo, it’s obvious that I didn’t use any of the OO features of Python. Instead I just wrote procedures and used global variables.
This was a quick way to get off the ground — and in fact there’s no reason why I couldn’t write the entire roguelike this way. However, since part of the fun of self-taught programming is blindly running down alleys in parts of town you don’t know anything about, I set about to rewrite the scrolling demo in an object-oriented fashion.
After doing a little reading on how to handle turn-based time in roguelikes I want to summarize what I found here. There is a metric crap-ton of posts about this on RGRD, not to mention a couple of articles at Roguebasin, and probably several giga-reams of source code you could look at…it’s a bit overwhelming at first, so I’ll start with the simplest:
I go, you go
Now every way of doing it is going to be ‘I go, you go’ naturally, but this is how people describe the simplest way of ordering things. I guess you could call this ‘equal-priority order’ or maybe ‘first-in, first out’ time. There is a global, incrementing turn counter, and all entities are in a list which you iterate over. Each entity takes their turn in the order they’re on the list, and actions either take one turn, or no turns (for stuff like looking at stats, saving the game, and so forth).
Similar to the above, but using a speed for each entity. Set each entity’s timer to 100/(speed), then get the entity with the lowest timer. Decrement all timers by that amount, then run actions for any entity with a timer of 0. Afterward reset those zeroed timers to their original value.
Plus player time
This is a simple system where the player takes an action that costs some amount of time. Then that time is given to all the other entities in the game. They can use that time to take their actions, so for example if the player casts a spell with a long execution time, the monsters can get multiple moves in.
I’m calling this phase order after a post made by Jeff Lait (creator of POWDER). I believe a similar system is used in Martin Read’s Martin’s Dungeon Bash. Jeff describes the system on RGRD, and again in a separate post.
The basic idea is of a repeating pattern of phases with a repeating tick running through the pattern, like a musical cross-rhythm. In Jeff’s game the phases are Fast, Normal, Slow, Quick, Normal. The tick occurs on the normal and slow phases. If an entity is marked for a phase it acts in that phase, unless it’s marked slow, in which case it only acts on the slow phase. The tick is the global heartbeat, where you execute all durational effects.
Explained here in the Angband FAQ. Every entity has an energy level; each turn, their energy increases by the amount of their speed. When the energy reaches 100, they act, and the action decrements their energy by some amount. I’m not sure if all actions take the same amount of energy or not; ADOM uses a similar system, but the energy threshold is 1000, and different actions do take different amounts of energy.
In a modified version of this (explained here), you decrement the energy level by 1000, but keep the remainder.
You also can ‘count backward’ in another alternative, explained here as a ‘Time/Speed’ system using segments.
This is a priority queue in the sense that you do the action of the entity at the front of the time queue, not the entity with a high ‘priority value’. I’m just pointing this out as there seems to be a couple of different interpretations of what a priority queue is. A simple method for this is explained well here.
Every entity has a speed, and each action has a cost (to follow the example in the link above, a cost in milliseconds). At ‘turn 0’, every entity’s time is set to 0. Then iterate through that list and select an action for each entity, which gives the time (action cost * (average speed))/(entity speed). Insert the entity in the priority queue, sorted by time, and once that’s all done you pop the entity off the list with the lowest time. The entity does its action, then chooses a new action, the time for that added to its previous time. You then reinsert it into the list and repeat the process.
A variation of this method uses a general priority queue, and in addition individual priority queues attached to entities. It’s described here by Ray Dillinger on RGRD. Each entity gets one entry in the general priority queue, but multiple entries in their individual queues.
If you look at some of the RGRD threads from 2004-2006 you can find some interesting debate between Jeff Lait and others over the relative gameplay value of time systems. If the player can’t accurately predict the order of the events because of the nature of the time system you use, is that a good or bad thing? It’s well worth reading those threads yourself to hear both sides of the debate.
I’m really loving the 7DRLs for how easy it is to get into them.
Domination sets you and AI-controlled team members versus other teams in a capture the flag game. You have two slots from which to cast spells, and spell refills are never in short supply. This one is less of a roguelike in a traditional sense — really a topdown RTT game — but is fun for a quick play. I think it’d be great networked.
The 7DRLs friendliness — like just two spells to keep track of here — is of course partly a limit imposed by the structure of the 7DRL. But I really feel that it’s not only possible but important to think about taking this into the structure of a larger, longer game.
Dungeon Minder is really cute and entertaining. You’re a faery accompanying a hero as he despoils a dungeon in roguelike fashion.
I don’t know if this was planned, but I like how you as the faery get more moves than the hero — you can flit here and there and it really emphasizes the nature of the character.
As a counterpoint to spells in Domination, you get nine spells in Dungeon Minder, and they’re actually not laid out in a simple way (not a complex way either, really). I was a little confused at first why the spell types don’t map more directly to the spell keys (instead of spells of like type grouped together on their keyboard directly, the mapping feels more random, like the dev wanted you to stop and think what spell was on what key).
Unfortunately I was not such a good dungeon minder:
Dungeon Minder uses libtcod, and you can see the BSP partitioning for the map creation in action. I have to admit I don’t like the look of the map — and single cell width corridors seem especially weird looking. It looks like I’d want to rough up the BSP map a little with some post-process filtering of some kind…
So after making a simple @ walking demo with libtcod, I took a look at it again and thought, you know what would make this cooler? If the map scrolled! Yes — scrolling is cool, and I had never written a scrolling viewport, so my plans were set.
Now there are many scrolling tutorials out there (I usually look at Tony Pa’s for inspiration) and the theory is simple. Instead of drawing the entire map and its contents to the window (as I did in the first demo), you create a frame — sometimes called a frame, viewport, or camera — which the map ‘scrolls’ under.
So instead of each coordinate on the map corresponding exactly with the same coordinates in the window, the correspondence between the map coordinates and the window coordinates will change as your viewpoint (for my purposes, the location of the @ character) moves around the map.
In simple terms, the @ is always in the center of the window — it is the map contents which ‘slide’ under the @ as it moves. So it is logical to ask what happens when the @ gets to the edge of the map. You have two basic choices in this situation — one, keep the @ in the center of the viewport window, and make anything ‘off-map’ a frame color or texture (for example, like when you dynamically resize a web page by making the browser window wider or narrower); and two, allow the @ to go to the edge of the window when it comes close to the edge of the map. Of course, the latter option is much better looking, so the choice is clear there. There are no compromises made on this blog.
So on to the code — I won’t post it all, as the imports, utility functions, game state update, and main loop are still the same.