Category Archives: Games

Simple Ultima-Style Dialogue Engine in C#

The Ultima series is one of the most influential RPG series of all time. It is known for open worlds, intricate plots, ethical choices as opposed to “just kill the bad guy”, and… dialogue. The dialogue of the Ultima series went from being simple one-liners to complex dialogue trees with scripted side-effects.

Ultima 4-6, as well as the two Worlds of Ultima games (which used the Ultima 6 engine), used a simple keyword-based dialogue engine.

In these games, conversing with NPCs (people) involved typing in a number of common keywords such as “name” or “job”, and entering new keywords based on their responses in order to develop the conversation. Only the first four characters were taken into consideration, so “batt” and “battle” would yield the same result. “Bye” or an empty input ends the conversation, and any unrecognised keyword results in a fixed default response.

In Ultima 4, conversations were restricted to “name”, “job”, “health”, as well as two other NPC-specific keywords. For each NPC, one keyword would also trigger a question, to which you had to answer “yes” or “no”, and the NPC would respond differently based on your answer. You can view transcripts for or interact with almost all Ultima 4 dialogues on my oldest website, Dino’s Ultima Page, to get an idea how this works.

Later games improved this dialogue engine by highlighting keywords, adding more NPC-specific keywords, allowing multiple keywords to point to the same response, and causing side effects such as the NPC giving you an item.

If we focus on the core aspects of the dialogue engine, it is really simple to build something similar in just about any programming language you like. In C#, we could use a dictionary to hold the input keywords and the matching responses:

            var dialogue = new Dictionary<string, string>()
            {
                ["name"] = "My name is Tom.",
                ["job"] = "I chase Jerry.",
                ["heal"] = "I am hungry!",
                ["jerr"] = "Jerry the mouse!",
                ["hung"] = "I want to eat Jerry!",
                ["bye"] = "Goodbye!",
                ["default"] = "What do you mean?"
            };

We then loop until the conversation is over:

            string input = null;
            bool done = false;

            while (!done)
            {
                // the rest of the code goes here
            }

We accept input, and then process it to make it really easy to just index the dictionary later:

                Console.Write("You say: ");
                input = Console.ReadLine().Trim().ToLowerInvariant();
                if (input.Length > 4)
                    input = input.Substring(0, 4);

Whitespace around the input is trimmed off, and the input is converted to lowercase to match how we are storing the keywords in the dictionary’s keys. If the input is longer than 4 characters, we truncate it to the first four characters.

                if (input == string.Empty)
                    input = "bye";

                if (input == "bye")
                    done = true;

An empty input or “bye” will break out of the loop, ending the conversation.

                if (dialogue.ContainsKey(input))
                    Console.WriteLine(dialogue[input]);
                else
                    Console.WriteLine(dialogue["default"]);

The above code is the heart of the dialogue engine. It simply checks whether the input matches a known keyword. If it does, it returns the corresponding response. If not, it returns the “default” response. Note that this “default” response could not otherwise be obtained by normal means (for example, typing “default” as input) since the input is always being truncated to a maximum of four characters.

As you can see, it takes very little to add a really simple dialogue engine to your game. This might not have all the features that the Ultima games had, but serves as an illustration on how to get started.

The source code for this article is in the UltimaStyleDialogue folder at the Gigi Labs BitBucket repository.

Announcing Ultima 1 Revenge

I am currently working on an engine port of Ultima 1: The First Age of Darkness, called Ultima 1 Revenge. This means I am reverse engineering the game files and building a new game engine for it, using C++ and SDL2.

Ultima 1: The First Age of Darkness was one of the first open-world Computer Role Playing Games (CRPGs). Originally released in 1981 and remade for the PC in 1986, Ultima 1 was followed by a series of games that lasted almost 30 years, generated a cult following, inspired countless other RPGs, and pushed the boundaries of technology.

Ultima 1 is a fairly weird game, featuring an unusual combination of medieval fantasy and space travel. The world of Sosaria is being ravaged by the monsters of the evil wizard Mondain. Before you can face him in battle, you have to complete dungeoneering quests in the service of the lords of the land, become a space ace, free a princess, and travel back in time using a time machine.

The 1986 PC remake, on which the Ultima 1 Revenge project is based, is very old technology, by today’s standards. Still, it provides a vast array of learning areas. The game’s graphics are made up of three tilesets (CGA, EGA, and Tandy 1000), giving a choice for the differently powered machines of the time. The game world is stored in a small map file, where each four bits is an index into the tileset you’re using. Space travel is a combination of top-down 2D and first-person views. The dungeons are simple 3D-like line drawings, randomly generated based on a seed stored in the savegame file (so they remain consistent for each playthrough, but change if you start a new game). The different parts of the game run in different executables, and a special savegame file is used to pipe the player state from one to the other. Savegames mostly use 16-bit numbers, with the least significant byte stored first. Decoding the game files is an ongoing effort that powers tools such as the online map viewer I built in 2015, and the engine itself.

Today, I have released a demo of the engine. So if you own a copy of Ultima 1 (if you don’t, you can grab a copy from GOG), grab it from the downloads page, set the path to your original Ultima 1 folder in the settings file, and take a tour of Sosaria!

Ultima 1 Reverse Engineering: Decoding Savegame Files

This article was originally posted at Programmer’s Ranch on 29th August 2013. The version migrated here is mostly the same except for minor updates and a brand new screenshot of the latest GOG installer for Ultima 1.

It’s no secret that I’m a long-time fan of the Ultima series of games. My most significant contribution to the Ultima fan community was running Dino’s Ultima Page, a news and information hub for the community, for over a decade.

Ultima insipired such a great following that hundreds of fan-made remakes, tools and other projects appeared over the years. Many remakes were intended to be mods of games such as Dungeon Siege or Neverwinter Nights. Among other things, talented developers found ways to understand the data files of the games (including the graphics, savegames, maps, etc). This resulted in several useful tools (savegame editors, map viewers, etc), but more importantly, it allowed people to create new game engines using the original data files, with the intention of allowing the games to be played on modern operating systems. The first of these was Exult (an Ultima 7 engine), but over the years, projects appeared for most Ultimas – such as Pentagram for Ultima 8, or Nuvie for Ultima 6.

This article describes the process of reverse engineering, i.e. how to try to make sense of data files given the data files and nothing else. We will be looking at the savegame format of Ultima 1. Although Ultima 1 is not free, you can get the entire first Ultima trilogy from Good Old Games for a few bucks. Ultima 1 is a great choice to start reverse engineering because it’s relatively simple – the savegame file is only 820 bytes long and is uncompressed. This made sense for me as when I started this project I was still a budding programmer, and it also made sense because there was very little knowledge about the U1 formats around, whereas the later games had been studied in depth. Reverse engineering is a bit of an advanced topic so feel free to skip it if you feel lost, but it’s also a very interesting topic.

So first thing you need to do is install Ultima 1. If you got it off Good Old Games, it conveniently comes with DOSBox, allowing you to play it under modern operating systems:

u1revenge-install-u1-gog

After launching the game, you will find yourself in the main menu.

u1revenge-mainmenu

Press ‘a’ to go through the character creation process.

u1revenge-chargen-6

Once you have selected your attributes and saved your character, you find yourself back in the main menu. In the Ultima 1 folder, you should notice a new file called PLAYER1.U1:

u1revenge-mainmenu-savefile

That’s the savegame file we’ll be messing around with. You can use a hex editor to take a glimpse of its contents. Personally I like XVI32 because it’s pretty lightweight and even allows you to edit hex entries.

u1revenge-xvi32

This might look like gibberish, but you can already notice a few things. The first 14 bytes in the savegame file are reserved for the player’s name. Knowing the stats you chose during character creation (strength 32, agility 32, stamina 15, charisma 12, wisdom 11 and intelligence 13), you can also spot them in hex on the second line (20, 20, 0F, 0C, 0B, 0D). Windows Calculator has a Programmer mode that is quite useful for switching between decimal and hex:

u1revenge-wincalc

A good way of decoding more parts of the savegame file is interacting with the game itself. Start the game. The world view looks like this:

u1revenge-startworld

Keep a copy of your savegame file at this point. If you move around a bit and save the game, you should at the very least observe changes in your character’s X- and Y-coordinates:

u1revenge-u1moved

You can manually check which bytes in the savegame file changed. I found it more useful to write a hex diff tool that actually highlights the bytes that changed:

u1revenge-hexcompare

As you can see, it’s not so simple: there are many things that might change, including food. However, you can choose your moves carefully (e.g. 2 steps west, 3 steps north) so that you can then spot which bytes have changed that much and determine which are the world coordinates.

Another way of learning more about the savegame file is by actually tampering with it. Using XVI32, I changed the byte after ’96’ from 00 to 13:

u1revenge-tampering

After running the game, note how the Hits shot up from 150 to 5014:

u1revenge-tampering-result

That makes a bit of sense: the 96 (hex) we saw earlier corresponds to 150 in decimal – the original value of Hits. But why did it become 5014 when we tweaked the byte after it?

It’s because DOS games like this stored values as 16-bit integers in little endian format (i.e. the bigger byte is the second one). So if we have the value we tweaked, i.e. 96 13, that’s actually (13 * 100) + 96 (all hex), which results in 5014 (decimal).

Isn’t that neat? Reverse engineering requires a lot of time and patience, but it’s a bit like fitting together the pieces of a jigsaw puzzle. After a while you might end up understanding a good chunk of the data files:

u1revenge-savegame-file-format

Once you understand the data files (which also includes map and graphics files), you can then proceed to write all sorts of tools and stuff. I had called this project U1Revenge (Ultima 1 Reverse Engineering Effort) and wrote a map viewer and was working on an engine for it. Although I stopped working on it, I did release a couple of demos, the latest of which you can grab from the project page.

u1revenge-engine

Reverse engineering is certainly not a new art. The book Masters of Doom describes how fans of DOOM would hack the game’s map files to create their own level editors. Many games have similarly been studied, and a wealth of knowledge is available today. Reverse engineering is not just an achievement; it is a glimpse of history, and helps to understand how games were created even before we were born. The following links provide further reading:

Rediscovering Sensible World of Soccer

Back in the days when I actually had time to play computer games, I was a fan of three main genres: RPG, strategy, and FPS. The sports genre never really captured my interest, with maybe a couple of notable exceptions. One of these was Sensible World of Soccer.

swos-goal

This week I treated myself to playing Sensible World of Soccer ’96/97, which I had bought off GOG.com. Although this is not the classic I grew up playing (which was Sensible World of Soccer ’95/’96 European Championship Edition), it’s practically identical to it: the only noticeable difference is that some players have moved between teams.

Sensible World of Soccer (SWOS) is a game where you can both manage a football team and play football. It offers a great deal of flexibility. If you just want to play football, you can choose all sorts of friendly matches or tournaments to play. On the other hand, if you just want to manage your team, you can do that, and see only the game results. You can both manage the team and control it while playing football games. And you can even do neither: watch a game played by computer-controlled teams.

 

swos-menu

The management aspect is menu-driven. When you start a career (which lasts a maximum of four seasons), you are given control of every aspect of your team, including organising and training your team, buying and selling players, keeping track of the match schedule, watching the club’s profit/loss, goal statistics, and even watching the progress of various tournaments in the world.

swos-team

Managing your team alone is complex enough to give the game a great deal of replayability. Each player has a position in which he’s comfortable (e.g. defence, attack, etc). Each player also has a financial value and a set of top skills (e.g. speed, shot power, ball control, etc) denoted by the yellow letters in the screenshot above. It’s not all as easy as it looks, however. A player may thrive or stagnate depending on his position, and his value may change accordingly. Financial value also does not always accurately reflect a player’s skill. So trying out different players in different position is key to forming a functional team.

swos-strategy

Other than that, before and during each match, you can refine your team’s formation, allowing you to try different strategies to adapt to demanding situations.

swos-goal3

The gameplay itself is incredible fun. You control one player at a time while all the rest move automatically. This is where the player skills pose a challenge: depending on whether your player is good at speed, ball control, passing, or whatever, you may opt to pass the ball, dribble past your opponents, or shoot the ball into the goal. Controlling the ball when shooting is a skill in itself; you usually use the arrows to indicate a direction (e.g. top-right), but you can actually use different key combinations after shooting to give the ball a curved effect or elevation, allowing you to score some pretty spectacular goals.

swos-goal2

Once you go beyond the basic skills, you can get creative and have loads of fun, scoring in incredible ways and posing different challenges. For example, instead of just shooting into the goal, you can cross to another player and score with a tackle or header. You can score from a distance, or pass your way around the goalkeeper, and just run in with the ball. Or my personal favourite: get the goalkeeper and defenders to follow you, run the train around for a bit, and then just deposit the ball at the back of the net.

swos-beating

You might want to start with a pretty good team, such as Manchester United or Bayern Munich. But as you get more familiar with the game, it’s a fun challenge to start with a crappy team and buy better players. That allows you to pretty much dominate a league, and give your opponents a beating. For example, the above 12-0 in a typical 3-minute (real time) career game is a pretty nice feat, and a challenge to achieve.

SWOS is a simple game but gives you a world of opportunities to try out. Career games last 3 minutes of real time, but friendlies may be 3, 5, 7 or 10 minutes (you choose the setting). This means you can play the game for just a few minutes, or spend several hours at a time.

If you’re not put off by the dated graphics, and love some genuinely fantastic gameplay, give this game a go.

Running Games Requiring a CD in DOSBox

Back in 2009, I had written DOSBox for Dummies, a short and simple article explaining how to get old games running in DOSBox, and how to write a batch file so you don’t have to do this every time. A typical batch file might look something like this:

dosbox -c "mount c C:\prophet" -c "C:" -c "prophet"

That will often be good enough. But if your game needs to access resources on CD, such as Ravenloft: Stone Prophet in this case, then that’s not quite going to work:

dosbox-no-cd

To allow the game to access the CD, you’ll need an extra command to mount the CD drive:

-c "mount d D:\ -t cdrom"

The whole thing looks something like this:

dosbox -c "mount c C:\prophet" -c "mount d D:\ -t cdrom" -c "C:" -c "prophet"

That’s much better:

dosbox-ravenloft-stone-prophet

If you don’t want to pop in your CD every time you want to play, just copy the CD onto your hard disk, and mount that folder instead:

dosbox -c "mount c C:\prophet" -c "mount d C:\STONE_V1.0 -t cdrom" -c "C:" -c "prophet"

That works just as well.

Fast spellcasting in Ravenloft: Strahd’s Possession

code_174When you cast a spell in Ravenloft: Strahd’s Possession, the spells get greyed out for a brief cooldown period. That’s pretty normal.

However, there seems to be a bug allowing you to bypass the cooldown completely. If you cast a spell, then close the spellbook or holy symbol, and then reopen it, the spells are immediately available, regardless of the cooldown.

This bug is specific only to Ravenloft: Strahd’s Possession; the other two games using the Ravenloft engine (Menzoberranzan and Ravenloft: Stone Prophet) have different spellcasting interfaces.

Ravenloft: Stone Prophet actually appears to have the opposite behaviour: if you cast a spell, then quickly close and reopen the spellbook or holy symbol, spells are indefinitely in cooldown until you close the spellbook or holy symbol again. My guess is that this is by design: the game stops keeping track of time when spell selection is active, just like in the inventory.

Coast of Bones

screen002

Coast of Bones is the 8th scenario of the human campaign in the Warcraft 2 expansion set, Beyond The Dark Portal. Your objectives are, as is often the case, to destroy all your enemies.

screen003

You start off with a small force on a barren piece of land, and you have a few ships that will help you move to another place where resources are hopefully present.

screen004

In the screenshot above, you can see the entire map, enabled thanks to the on screen cheat. Your enemies are the white orcs to the west, purple to the southwest, and yellow to the south. The white ones are not very well-defended, allowing you to take over their base, and there is also a spare gold mine on the same piece of land. The purple orcs are better defended, and the yellow orcs are tough and have a strong naval presence.

screen005

You have two dwarven demolition squads. You can put them on a transport and use them to take down a couple of cannon towers. The first place to land is shown above.

screen006

This will allow you to take down the yellow cannon tower on the island, which is in a strategic location and monitors sea traffic in the area.

screen007

Land the second demolition squad on the northwestern landmass.

screen008

Then, use it to destroy the white cannon tower that guards the entrance to the white base.

screen009

With the cannon tower out of the way, you can now ferry your troops to the white base, and engage the enemy.

screen010

After killing the defenders, take down any towers, and then finish off the white orcs by destroying their buildings.

screen011

Establish your own base, building a town hall, farms and a lumber mill.

screen012

Establish your economy by having peasants mine gold and harvest lumber, and keep building farms to sustain your base’s growth.

screen013

Invest in your defences, by manning each entry point to the base and setting up towers to assist them. Continue to grow by building a barracks and upgrading your town hall to a keep.

screen015

Build stables to be able to train knights, and build a gnomish inventor to prepare for a naval presence (you will need gnomish flying machines to sniff out enemy giant turtles).

screen016

There’s an oil patch to the southwest. It’s pretty close to purple’s base, but is also quite convenient. It’s a good place to start setting up oil operations.

screen017

Build a shipyard there, but be prepared to face some heavy resistance from purple and yellow orc ships. One or two well-placed ballistas should keep them at bay (pun not intended).

screen018

At this point you will also see more activity from the yellow orcs, who will frequently make landings at the east side of the base. Make sure you are always well-defended.

screen019

My first shipyard couldn’t withstand the strength of the enemy naval forces, so I had to build another. I also reinforced my defences with a second ballista, seen on the right in the above screenshot. The ballista is out of range of enemy ships, and they conveniently get stuck trying to attack it.

screen020

When the main gold mine runs out of gold, you can build a town hall and start using the second one.

screen021

Continue investing in your naval operations by building a second shipyard, a refinery, and a foundry. Make sure you have a steady supply of oil.

screen022

Once you have a few battleships, you can begin to attack coastal buildings. Weakening purple’s naval presence is a good start.

screen023

When the oil platform runs out of oil, there’s another oil patch to the southeast you can use.

screen024

Be careful though – it’s an easy target for purple and yellow orc ships, and also for yellow orc troops.

screen025

Continue attacking purple’s coastal area…

screen026

…but keep your own operations safe. The central oil platform is an easy target for ships, land troops, and death knights’ whirlwinds.

screen027

As the tide of the battle permits, destroy the last remnants of purple’s naval presence.

screen028

Continue the attack towards the yellow orcs’ island coast, but be careful – it’s easy for your ships to get trapped in the narrow canals, in which they are easy prey for catapults and whirlwinds.

screen029

Make a landing into purple orc territory.

screen030

They may be grounded, but they can still put up a fight.

screen031

Bring in additional troops if you need.

screen032

Put an end to any death knights, because they weaken your forces pretty quickly.

screen033

Then work on paralysing their production by destroying strategic buildings, such as the fortress.

screen034

In this scenario, orcs usually don’t use air units; but they may do that when they get desperate. Having a couple of archers handy is a good idea.

screen035

With most of the purple forces neutralised, send fresh ships into the heart of the yellow orcs’ gulf.

screen036

Destroy the naval defences there.

screen037

Once the ships are destroyed, focus on destroying coastal buildings to completely annihilate yellow’s naval presence.

screen038

You will also find that many other buildings and forces are within reach of your battleships from the gulf, so you can easily bring the yellow orcs to their knees.

screen039

Complete the last preparations for an invasion by destroying orc units and buildings along the rest of the coast.

screen040

With that done, you can now make a landing on the yellow orcs’ island.

screen041

Bring in additional forces as needed.

screen042

Destroy strategic buildings first…

screen043

…and then finish off the remaining farms.

screen044

Enjoy your victory.

screen045