Jul 07

Gear Loader Working

I’d like to report another milestone in the development of GearHead in Python: that item on the right is the first bona fide Gear to be loaded from disk and displayed onscreen. It’s a human scale class 5 armor plate. As in previous GearHead games, I’ve written a parser to load mecha and item designs from human readable text files.

Why create my own parser when there are tons of serializers already available for Python? Two reasons. First, so I can maintain a format close to the GearHead1 and GearHead2 mecha description files. Using json or whatnot to design mecha would require too much semantic acrobatics. Second, because it was easy. It’s fully functional and only around 80 lines of code.

My next goal is to get an entire mecha file working.


Jul 02

Random Maps from Dungeon Monkey Eternal

I’ve been ripping out the skeleton from Dungeon Monkey Eternal and genericizing it for GearHead Caramel. Python has made this process far easier than it would have been in (non-Object) Pascal. The random map generator presented a special challenge because of how much game-specific stuff it relies on, such as the terrain list and wandering monster mechanics. To get around this problem I added an Architect class that translates generic map generation requests, such as “draw a floor here” or “add a door there”, into game-specific operations. Plus, because it’s object oriented, I can always subclass the generic Room or SceneGenerator classes to do anything I want. You can check out my progress at GitHub.

The character in the above screenshot was drawn by my son, and presumably won’t be appearing in the final game.

Jun 16

GearHead: Caramel Isometric Map Handler

A short video demonstrating the isometric map routines I’ve written for GearHead: Caramel. The big advantage of this new system is that it allows sub-tile movement of characters and animations; instead of jumping from one tile to the next, things can move smoothly across the map.

Apr 04

New Idea: The Story So Far

After yesterday’s post about GearHead-2, I started thinking about how the game reminds the player of the story so far. Instead of listing the history items as above, I wonder if it would be possible to generate a single paragraph describing the current state of the story? Something like:

The space colonies of the Free Commerce States have been attacked by the Red Mask Raider pirates. Led by Yecemk, they destroyed the Silver Knight garrison in Athera Spinner. Your victory against Yecemk earned her respect. Now, you plan to seek training in Wagner Spinner.

I don’t think I’ll be adding this feature to GH1 or GH2, but it’s something I plan to keep in mind for GHC.

Apr 03

More GearHead2 Thoughts

Sorry for the silence- it’s been a busy couple of months. I’ve been playing through GearHead-2 again. Tonight, my character Hawk finally earned the respect of his criminal space trucker rival.

One of the things that makes GearHead-2 very different from GearHead-1 is the scale. In GH1, you will travel between a small number of cities, most of which consist of a single scene. You will probably get to know a number of NPCs, especially if you join a faction and see the same few faces every time there’s an invasion. In GH2, on the other hand, you get to travel through a large number of cities, each of which contains many sub-scenes. You probably won’t remember any of the NPCs because you’ll be interacting with so many of them that they all become a blur. Also because of this scale, there will usually be plenty of missions available, even if your character hasn’t mastered Conversation.

In those cases where GearHead-2 allows the PC to form a relationship with an NPC (mainly the lancemates and the core story enemy), it works much better than GH1. Unfortunately, the other NPCs melt into a faceless blob.

The last thing I want to do before making a new release is to add graphics for spaceships and fortresses. As several players have noticed, these used to be rendered as meshes in the OpenGL version and I forgot to give them sprites after switching back to SDL. Hopefully I can get that done this week.

Jan 24

Random Story Generation Part 2: GearHead-1’s Core Story

To briefly recap part one, one way to create a random story generator is to write a whole lot of story fragments, arrange a subset of the fragments into a list, and count on your player’s sense of closure to assemble the list into a coherent story. In this part I’m going to look at how GearHead-1 did this.

It isn’t really correct to describe the GearHead-1 Plots as story fragments; instead, each one is a complete (though usually quite short) story. For now I’m going to skip talking about the basic Plots (which comprise most missions and random events) and instead just concentrate on the core story plots.

The core story is the series of Plots leading from the player’s introduction in Hogye to the eventual battle with Typhon. The choice of plots is based on three variables: the identity of the PC’s enemy, the mystery that confounds the PC, and the bad thing that happened to the PC. The possible states are:

PC Enemy

  • Unknown (Or, no enemy yet)
  • Character
  • Faction

PC Mystery

  • Resolved
  • Unknown (Or, no mystery yet)
  • Family Secret
  • PC has Amnesia
  • PC is not Human
  • Searching for Item

PC Misfortune

  • Resolved
  • Unknown (Or, no misfortune yet)
  • PC’s Family Died
  • PC is Incriminated
  • PC is Seeking Revenge
  • PC is Former Member of Enemy Faction
  • PC has a Lost Love

The PC’s starting scenario sets the initial values for these variables. For instance, if the player starts as a defector from Luna, the enemy is set to Faction, the mystery is set to Unknown, and the misfortune is set to Former Member of Enemy Faction. These three variables are collectively referred to as the context.

Only one core story Plot exists at a time. When a new core story Plot is needed, the master list is checked for Plots that match the current context. One of the matches is chosen at random. To continue the example above, from the Lunar defector beginning there are five possible first episodes: the PC could be pursued by a bounty hunter (which requires that the enemy be a faction), a price could be placed on the PC’s head (which has the same requirement), the PC could be sent to rescue a kidnapped professor (which requires that the enemy be a faction and the mystery be unknown), the player could be sent to intercept a secret plan (which requires that the mystery be unknown and the PC an ex-member of the enemy faction), or the PC could be accused of being a member of the enemy faction (which requires that the PC be an ex-member of the enemy faction).

Completion of a core story Plot will result in at least one of the context variables changing. For instance, completing the “Accused!” plot will change the misfortune variable to Resolved. The next Plot will be generated from the new context. This story generation method is similar to a Markov Chain, though I’ve been told that it isn’t exactly one.

There are several problems with the GearHead-1 core story generator. First off, there’s nothing to prevent the story from repeating itself. It can get trapped in a loop, and Plots which don’t alter the context can appear several times in a row. Second, it may be possible to arrive at a dead end- a context which has no available plots. Third, the context variables don’t hold a lot of information- having Aegis Overlord as your enemy is identical to having a local bandit gang or a supposedly law-abiding corporation as your enemy. Next time I’ll talk about how GearHead-2 solved some of these problems… and made one of them much worse.

Jan 16

Random Story Generation Part 1: Nothing More Practical Than A Good Theory

A visual depiction of how a Markov Chain story generator works.

I’ve decided to document my experiments in random story generation, in the hope that these notes will be helpful to other developers and hobbyists. This first post will define some of the terms I’ll be using and introduce some of the theory.

My first idea for a random story generator came during a literary criticism class I took during university. We were learning about reader response criticism, which is a model that focuses on the interaction between reader and text. In RRC it doesn’t make sense to say that a text has an inherent meaning; instead, meaning is something that is actively constructed by the reader through the process of reading. The author of the text, and whatever they intended the text to mean, doesn’t enter into it. If we don’t need to worry about authorial intent, why bother with an author at all?

The next piece of the puzzle came from Scott McCloud’s explanation of closure in Understanding Comics. A comic consists of a sequence of separate images; the reader uses closure to combine these images into a coherent story. I realized that the same would apply to a series of short narrative arcs in a computer game. Even without intentional connections between the arcs, the player’s sense of closure would interpret them as a meaningful story.

Finally, Vladimir Propp’s narrative functions provided a way to arrange these arcs so that the reader/player would be likely to interpret them as a coherent story. Propp analyzed Russian folk tales and discovered that all of their plots could be constructed from a finite list of story events which always appear in the same order.

From all this I got the idea to create a big list of story fragments, then use some kind of algorithm to arrange them into reasonably intelligible sequences. Turns out that’s pretty much how all procedural story generators work, even today.

I named the smallest narrative chunk a Plot, which I will capitalize to differentiate from the regular use of the word. A Plot modifies the game world for as long as it is active; it might alter an NPC’s dialogue options, or add an encounter to the world map. In GearHead-1 the Plots are quite coarse, defining an entire mission or a chapter of the core story. In GearHead-2 the Plots are much smaller; a single combat mission might consist of four linked Plots- one for the NPC offering the mission, a separate Plot defining the mission’s combat encounter, a Plot that is activated if the PC wins the mission, and another that is activated if the PC loses. The Plots in Dungeon Monkey Eternal are even more finely grained.

Using lots of small Plots is much better than using few large Plots. First off, if a quest is composed of multiple Plots, it means that the player won’t know how it ends just because they’ve seen this beginning before. Second, it allows reuse of code, which is a huge advantage for both bug control and refactoring. Instead of every mission having to define its own combat encounter, they can just call for a standard combat encounter Plot. Third, it greatly increases the number of combinations your system can generate, and in general you want your random plot generator to be able to generate a really really big number of combinations.

There are numerous ways to arrange Plots, including Markov Chains and context free grammars. The important bit is to have some way to describe the context of a Plot, so that Plots which belong together get placed together. Next time I’ll describe how the GearHead-1 core story context system works. Let me know in the comments if you have any questions.

Dec 15

Painting Fantasy Portraits

To practice both painting and faces, I’ve started doing fantasy portraits. Once I get enough of them I’ll upload the set to OpenGameArt.org and maybe incorporate them into Dungeon Monkey Eternal.

I wanted to do the pictures in traditional media because in my mind that’s how classic fantasy portraits are supposed to be done. Obviously I am not going to achieve the same kind of look as Larry Elmore or Jeff Easely but I have confidence that with enough practice I can do something that isn’t entirely terrible.

The dwarf at the top of this post was the first one I did. It’s in watercolor, which I think was a mistake, and I won’t be using that again (maybe). The human was second, and the orc was third. These were done in acrylics. Both the dwarf and orc are modeled on my own face. The human is based on a photo from atistatplay.deviantart.com.

Dec 13

There’s a new open source FreePascal scifi roguelike in town…

Well actually, it isn’t exactly new. After receiving a letter from ZeniMax, Kornel has shortened the name of this beloved game and released the source. If you have never played D*** the Roguelike before, now is a great time to give it a try.

Dec 08

Dungeon Monkey Eternal now installable

I’ve made two quick changes to Dungeon Monkey Eternal. First, I’ve cleared most of the source files out of the root directory. Second, I’ve added a working setup.py packaging file. The good news is that it should now be much easier to pack the game for Linux distros, create an executable version for Windows, and otherwise move the game around. The bad news is that this update breaks all previous save files.

I’ve also been making some progress with GearHead2, and hope to make a new release of that game before the new year.


Older posts «

» Newer posts