Monday, January 28, 2008

Speech bubbles

I'm experimenting with dumping animated GIFs of the game:



Click on the picture to see the movie. The frames are being played back at a steady rate rather than at the rate of play, so it can be hard to make out what's going on. Here's a summary:

The thief starts in his cabin aboard a ship docked outside the city walls. He disembarks and heads towards the city gates. Before reaching them, however, he is spotted by a patrolling member of the city guard, who opens the portcullis and gives chase. Diving into the harbor to escape capture, the thief swims underwater a short distance before climbing back out. Unfortunately he emerges under the light of a street lamp and is spotted again. The guard pursues him back aboard the ship, but the thief is able to hide under a table in the aft cabin. The guard, who did not see him hide under there, eventually gives up and leaves.

Meanwhile, you can see miscellaneous mutterings from other guards inside the city. I haven't implemented any sound attenuation yet, so whenever anyone says anything you see it.

The guards say lines when they spot the player, when they lose sight of the player, when they arrive at the last spot where they saw the player, and when they return to patrolling. They also randomly say lines while patrolling. This last part is clearly the weakest and needs lots of thought and improvement. (And better lines: That's what she said!)

Here's another, larger movie demonstrating the theft of some gold from the Temple of Theron (named after a local weatherman and not the South African actress):



The thief reads the sign while waiting for the outer patrol to pass. The door is locked with a simple three-pin lock that takes only a handful of turns to pick. Once the door is open, he discovers an inner guard passing nearby. By following close behind the guard he is able to circle to the far end of the temple without being spotted. He reads a hymn in passing before nabbing the gold.

There's still a ton left to be done on this game. At the moment I am focusing on getting good guard behavior. A big part of that is using guard speech to communicate what they are sensing and doing.

Speech needs to be presented visually. My inspiration is comic book speech bubbles. There are a couple of problems: positioning them, and ensuring that they don't flash by too quickly to be read.

Positioning speech bubbles is similar to map labeling which has a variety of algorithms available. I'm thinking of trying simulated annealing.

Up until now the game has not had any real-time animation, although I plan to add some for accent effects like screen transitions, blood spatters, water splashes, and gold sparkles. The game updates every time the player presses a key. If a speech bubble is associated with a given turn it can go by very quickly when the player is pressing keys quickly, or holding down a key and using the keyboard auto-repeat.

Many games in the Roguelike tradition require the player to dismiss text messages using the Space bar. I find this somewhat cumbersome so I'm looking for a way to avoid it. Andrew Doull, who is developing Unangband, came up with his own solution to this, which is to accumulate messages for the turn on-screen starting at the top line and working downward. You can press a key to dismiss them without taking a turn, but you can also press any of the keys you would ordinarily use to make a move and it will both take a turn and clear that frame's messages. I've tried out the latest build of Unangband and it has the problem that messages can flash by too quickly to be read. There is a message history window, accessed by pressing Ctrl-P, but if you have to use this on a regular basis it seems like a failure of the user interface to me.

One feature I'd like to add eventually is undo/redo capability. This would serve the purpose of a message history since you could rewind time to see what you missed. Again, though, the interface should not require regular use of this just to see what's going on.

I'm going to try halting the keyboard auto-repeat whenever a popup speech bubble appears. This should fix the problem of a held key making turns go by too quickly. It may also be annoying, though. It also doesn't address the problem of a player pressing keys very quickly, as they might when they are trying to maneuver in a direction other than a straight line.

Other ideas: Deadly Rooms of Death, a charming turn-based puzzle game, plays out speech bubbles in real time. The conversations thus occur in a separate timeline from the gameplay. This works when they aren't integrally linked to gameplay, but in my situation the guards' speech indicates their internal state, so speech needs to be coupled to the game's turns.

I've thought about accumulating messages over multiple turns based on how much real time has elapsed. Each message would have an on-screen duration, and would remain in the visible message queue for that much real time, regardless of how many turns have elapsed.

I'll be trying out various things like this to see what the benefits and drawbacks are. If you've got any other ideas, send 'em in!

Monday, January 21, 2008

Locks and Backups

I got the stupid locks hooked up, by getting up at 3am this morning.

I'm working on a cross between Thief and Rogue. It seemed like it might be fun to try and implement stealth gameplay in a turn-based game.

Stealth gameplay is all about getting into places while avoiding detection. There are several challenges in making it fun.

The biggest challenge is that it has strong positive feedback: the worse you're doing, the harder it gets. Once you're detected, guards summon more guards, alarms go off, and so forth. As a designer you want your games to have softer failure modes, where the player doesn't have to die and reload from the last save.

One way to soften things is to make the player character much faster than the enemies, so they can run away. The guards will give up the chase after a short time and return to their patrols, effectively resetting the game.

In a turn-based game it's hard to give different characters different speeds. Some games have speed ratings for characters that determine their turn order. Faster characters will periodically get to make two moves in between slower characters' moves. This makes the interface more complicated, though; it's hard to know when each enemy will move.

I've opted to give enemies slightly reduced movement abilities, instead. Guards cannot cut diagonally around corners. By running around several corners, you can gain distance from guards, eventually losing them. They move to the last place they saw you, look around a bit, and then return to their patrols.

Locks

Of course, it wouldn't be a stealth game without locked doors. Locks are essentially a way to keep the player standing in a dangerous place for a period of time, hoping that a guard won't come by.

Lockpicking is usually pretty stupid in games. The Thief series' lockpicking boils down to a timer; when it expires, you've got the door open.

I've got a simple minigame for mine that has a small memory element. You are presented with the digits 1-N, where N increases for harder locks. You have to push all N digits in the correct order. As long as you are pushing them correctly, they light up. If you push an incorrect digit, the puzzle resets and you have to start at the beginning again. The ordering is determined for each lock in the game at startup and doesn't change, so if you need to pick a second lock of the same type, you can do it in N turns as long as you remember the order.

Backups

I was doing backups to a USB hard drive, but it was still too manual for me. I had to get the drive out, hook it up, and run the backup. Also, I only have one external hard drive so my backups were not offsite.

I'm trying out JungleDisk now. It's an online backup system that uses Amazon's S3 storage. This means the data storage part is generic and can be accessed independently of the JungleDisk software. JungleDisk is also fairly generic; it maps the Amazon storage to a drive letter, so you can use it just like another drive. I could probably use Windows Backup onto it if I wanted.

The pricing is $20 for the JungleDisk software, and then whatever it costs for the Amazon S3 space. Amazon charges for space and bandwidth, so you only pay for what you use. The rates seem pretty reasonable, especially compared to some of the flat-rate online backup services I looked at, like Mozy ($5/month). Amazon's rates are 15 cents per gigabyte per month for storage, and 10 cents per gigabyte of upload bandwidth. Download bandwidth costs at most 18 cents per gigabyte.

Monday, January 14, 2008

Fun with food

This is a fairly useless post; sorry.

Diet Coke vs. Coke Zero

I finally did a side-by-side taste test of Diet Coke and Coke Zero. Here are the ingredients lists for each:


Diet Coke: carbonated water, caramel color, aspartame, phosphoric acid, potassium benzoate, natural flavors, citric acid, caffeine.




Coke Zero: carbonated water, caramel color, phosphoric acid, aspartame, potassium benzoate, natural flavors, potassium citrate, acesulfame potassium, caffeine.



They're both kind of foul, but if I had to choose one I'd go with Coke Zero. It's got slightly more citrus taste and seems a bit less cloying.

The story I heard is that Diet Coke was rolled out around the same time as New Coke, and was an attempt to be New Coke with no calories. New Coke was canned and Coke Classic returned, but Diet Coke retained the New Coke flavor. Coke Zero is a zero-calorie rendition of Coke Classic.

Of course, like an idiot I didn't think to buy a can of regular Coke to compare against the two. However, it can be difficult to compare corn syrup to aspartame. Aspartame lingers on the tongue for a long time after you swallow.

Egg-Carton Rotational Inertia

For a great demonstration of rotational moment of inertia, use up eight of the eggs in a dozen. Get someone to place the remaining four eggs in the carton without you seeing. Then try to guess where the eggs are without opening the carton.

It's surprising when you go to pull the egg carton out of the fridge and all the eggs are at the far end of the carton. My wife and I amuse ourselves by trying to distribute the remaining eggs evenly throughout the carton. If we wanted to keep the rotational inertia as close as possible to a full carton we would keep the eggs at the ends of the carton, though. I've started doing that instead.

Battle Ponies

This week I watched four episodes of the Legend of Zelda cartoon that aired in 1989. It's not great television but it got me trying to think of a cartoon franchise that would appeal to both little girls and little boys. I think I've got it: Battle Ponies! These are ponies (a la My Little Pony) which have been trained as ninjas to fight the evil Zombie Nazi Dinosaur menace.

Binge/Purge Cocktail

Ah, New Year's Day: when a young woman's thoughts turn to toxins, and the purging thereof.

A coworker of mine is trying out a ten-day toxin-purging regime whereby she does not eat, and subsists entirely on a concoction made of (“Toxins?” my wife said. “Let me guess: lemon juice and cayenne pepper, right?”) mixed with Grade B maple syrup (it has to be Grade B or you don't get all your vitamins and minerals) and water.

This sounds suspiciously like a recipe for a cocktail to me. As a cocktail, it has the benefit that, while you're binging, you're purging too! If I have any vodka around I may give this a whirl to work out the proper proportions.

Actual Coding

I'm back working on my stealth-gameplay Roguelike. Very little progress, though. I need to hook up locks to doors. The problem is that doors are currently a terrain feature, with no state. I handle opening and closing by altering the terrain. Now I need to be able to associate a lock object with the terrain feature. Locks have a type, which contains the order in which you need to push their pins to unlock them (if you don't have a key).

I think I will just write ugly code to start with, until I figure out what kind of generalization is appropriate. When you interact with a terrain feature, if it's a door I will look up the associated lock (if any) in some sort of spatial hash.

Eventually it seems like I might want to have an actual door object, which could keep track of its state. Right now I have several door-like things in the game which have similar code: doors, portcullises (you can see through these), and windows, with differing appearances for horizontal and vertical orientation on some of them.

Monday, January 7, 2008

Turn-based movement

The combination of new baby and two-year-old continue to take most of my time and sleep.

I've been thinking about simultaneous movement versus “I go/you go” systems in turn-based games. I've got a Roguelike game I work on from time to time. It is currently a simple I-go-you-go system. Everyone is in a big list, and each unit moves in turn, without being able to move into any square occupied by another unit.

This comes up short in a couple of ways. If you have a line of units all trying to move through a hallway, the order in which they take their turns will determine how closely packed they can be. Because of this, it is harder for the player to predict how units will behave. Predictability is important for my game.

This kind of sequential movement also means that each unit sees the world at a slightly different point in time. Again, this affects predictability.

There are ways in which you can alter the movement order to try and prevent collisions. For instance, if a unit tries to move and discovers that its desired location is occupied by someone who hasn't moved yet, the moving unit could adjust its position in the turn order so that it waits until the blocking unit has moved. (You'd have to ensure that dependency loops were handled somehow.) This might be good enough.

A really expensive way to solve this would be to do pathfinding for all units simultaneously. The state vector would consist of everyone's positions. There would be a lot of edges in this graph, so it probably isn't an option.

Monday, December 31, 2007

Tunnels vs. Arenas

The core task of many, many games is to move forward through a hazard-filled “tunnel”. (Examples: Half-Life, Sly Cooper 1.) This is economical from a storytelling perspective: you know fairly accurately what players will have seen at any given point, and you can closely control how they encounter each situation.

From a content-production standpoint, though, the tunnel design is fairly wasteful. The reward for making progress is to see what comes next, so you can't afford to have the environment look too repetitive. In addition, players move through each part of the world once and then go on, never to return. If you've played the vehicle levels in Half-Life 2, or the rail-grind sequences in the original Ratchet and Clank, you know that in addition to seeing each part of the level once, players tend to see it only briefly. This is expensive.

As computers get more powerful they are capable of displaying higher-resolution textures, higher-detail models, and so forth. Environments take increasingly more time and money to construct. As a result, game designers are trying to induce the player to spend more time in the same place. I think of this as “arena” game design.

Later Ratchet and Clank games dropped the rail-grind sequences because they weren't cost-effective. (Rail-grind sequences are back in the latest installment. Insomniac must have found ways to bring their costs in line with the rest of the game. You can probably guess some ways from looking at it.) Later Sly Cooper games adopted a hub model, with a large central world that had lots of missions set in the same environment. Games like Grand Theft Auto take this to its logical conclusion. There are no distinct levels, just a single, large world.

Designers also use collectibles to encourage players to spend time looking at all the expensive scenery. Urban Chaos, a game by defunct developer Muckyfoot that came out the year before Grand Theft Auto 3 had similar gameplay to the GTA series. It had powerups tucked away in corners of the worlds which would give your character permanent boosts in speed, strength, and so forth. Not unlike Crackdown, really, to name a more recent example. It would be amusing to make a collectible out of the world's triangles themselves.

Monday, December 24, 2007

Scripting languages

I've been busy this week with the new baby so I haven't done more than a few minutes of programming.

Issue Trackers

I did look at wikipedia's big list of issue trackers again to see if something wonderful has appeared. Sadly, no. I used FogBugz here at home until my server crashed. It turns out the version I've got doesn't work well with Vista, so I haven't gotten it going again. I've used (not administered) various other web-based bug trackers at my various jobs. Web-based is inherently sluggish and icky-interfaced and usually requires a Linux server and/or facility with setting up an ecosystem of database, scripting language, and web server that I don't possess. I keep hoping there will be some open-source tracker that just installs and works and doesn't require a bunch of steps. FogBugz came pretty close, although I think I still had to mess around with my IIS settings. And it is web-based. Sigh.

My life in scripting languages

Over the years I've worked on a variety of games, some of which shipped. Nearly all of them used at least two programming languages.

The first game I worked on was Blade Runner, a modestly successful point-and-click adventure game. The game was coded entirely in C/C++ except for a small amount of assembly language in the renderer. There were three engine programmers and five scripting programmers. The scripting language was C. We used Windows' DLL interface to dynamically load the code for each location in the game. The script DLL's interface to the game was well-defined, consisting of a header file full of functions to do things like play lines of dialog, play animations, and check or set game state flags.

Later, I worked on Loose Cannon, an ill-fated project that was begun by Digital Anvil for Microsoft, sold to Ubisoft and given to Sinister Games (where I was) to finish. After two or three years there it was canceled. I learned a lot from that project, and perhaps the most important lesson was:

Starting over from scratch is the wrong thing to do.

The code may leak memory like a sieve (Loose Cannon), contain its own hacky implementation of vtables, or use Hungarian notation that drains a little bit of your soul every day you have to look at it. You may be filled with loathing for the code; it doesn't matter. All code is loathsome, in its own way. Learn to do mechanical modification of code; you'd be surprised what you can do step by step while preserving a working game.

But I digress. One of the restarts involved trying to write the game in Python, with the idea that we would reimplement functionality in optimized C++ as necessary. That effort didn't get terribly far beyond the point of driving a car over the landscape at two frames a second. I have heard tell of shipped games (the Pirates! remake, for one) that use Python as the top-level language, though, so it's not impossible.

After that I helped finish Psi-Ops, a sleeper hit third-person action game featuring your typical brawny, buzz-cut Caucasian super-soldier, albeit augmented in this case with psychic superpowers. (The big debate was whether to name him Jack or Nick.)

Psi-Ops used C/C++ as its primary language, as does practically every game, with Python for scripting. The C++/Python interface was modeled on Boost.Python. We could do gnarly things like deriving a Python class from a C++ class, then deriving a C++ class from the Python class. There were about a dozen programmers, and I think they were all bilingual with regards to the programming. There were a half dozen designers, but if my memory serves, they did not do much (if any) Python scripting.

Finally, I worked on Sly 3, which used (a variant of) Scheme as its scripting language. The use of Scheme dates back to Sly 1 or 2 so I can't say for certain why it was chosen, but my hunch is that it was a combination of:
  • a programmer with an MIT degree and
  • very little time


Why Have a Scripting Language?

Why would you use more than one language to write a game?

There are certainly some big negatives to overcome for it to be a net gain. You wind up writing and maintaining an interface layer between the two languages. The two languages will compete for control of memory and you will have to work out how they should share it. You also have to decide what each language is for: how to decide which language to use to implement any given piece of functionality. You have to train programmers in both languages and in the ways the game's concepts are represented in each. If one of the languages is home-grown, it probably has terrible or nonexistent editing, compiling, and debugging tools.

Despite all this, game programmers keep including scripting languages in their projects. Here are the reasons I can think of:

To a large degree, the productivity of your day can be measured by the number of edit/build/load/test cycles you are able to perform. If the build/load phase takes five minutes, say, then you've got a maximum of 96 cycles in an eight-hour workday. The link phase, in particular, can get rather long (i.e. minutes) for some of the C++ compilers that game developers have to work with. Programmers look for ways to bypass as much of the link and load phases as possible, and scripting languages are seen as a way to do this.

Another reason often cited is to devolve some of the programming duties onto less-expensive programmers (a.k.a. designers). Scripting languages are expected to be simpler to use (by having no pointers, say, or no explicit type annotation), and thus more suitable for use by inexperienced programmers.

Bolting on a scripting language may be a way to use a more productive programming language for the parts of the game where performance is less critical. Languages that support higher levels of abstraction allow you to do more with less typing. Languages with more advanced type systems can verify more properties of your program before it is run, reducing the number of edit/test cycles needed.

Finally, we can't discount that programmers love to complicate things. If we don't have enough problems to solve we will create them! Let's face it: C++ is not a sexy language. It just happens to be the current language of choice for console development. There are lots of other languages that are more popular or exciting and it's fun to use them.

It is very important when you are responsible for a scripting language in a game not to lose sight of the goals. For instance, a scripting language may reduce the build time, but in my experience we've ended up gaining back a lot of the build time as we strive to make the game more efficient. (There's a conflict between malleability and efficiency.) Scripting languages may be simpler; but if they lack good abstraction capabilities (and people who know how to use them) you can end up with copy/paste code monstrosities. In addition, the use of dynamic languages defers detection of the most common types of errors (typos and signature mismatches) to runtime, which means more edit/test cycles.

Over the years I haven't been able to help thinking that the approach we used on Blade Runner was perhaps one of the best. By using a mainstream language, we ensured that our scripters had an integrated development environment. The compiler gave good error messages, and if they had a problem we could easily debug it. By having a clear, simple interface to the game we ensured that compile times were fast. The DLL mechanism ensured that link times were fast, too. Having a single language meant that there weren't any interface issues regarding memory usage, or object representation, to worry about.

If you do end up using a scripting language, please don't roll your own! It may sound like fun, but you have only to look at Maya's Mel language to see the horrors this can inflict on people. Autodesk (the current owners of Maya) have grafted Python onto Maya so that people won't have to deal with their misbegotten scripting language any more than necessary.

Monday, December 17, 2007

Failed word graph gameplay

I've been thinking about ways to make a game based on the graph of words that differ by one letter. There's the puzzle type that originally got me thinking about this, with two words separated by blanks to fill in. That's not much of a game, though; more of a puzzle.

I had the idea of moving around through the graph, discovering words along the way. My first idea was of a 4X space exploration type of game, where each word would represent a star system, and the adjacencies would represent wormholes (wordholes?) between them.

There are a lot of unknowns about this idea. The main unknown for me is how the graph feels. How do you map it to a plane? Is the connectivity tractable for human brains? There are 2415 connected four-letter words. This seems like rather a lot of stars for a typical space game, and there's not necessarily an easy way to restrict the player to a subset of words, since they've already got all the words in their head.

My second idea was to score the player on the longest chain of adjacent words they can string together without revisiting a word they've already used. This puts an element of Hamiltonian pathfinding into the mix.

To test this gameplay I took my DOS 80x25 text console simulator and threw together a prototype of moving through the graph. Each word you type goes in the center of the screen, and the adjacent words are placed around it. I put question marks for words you haven't typed yet.



“Ware” has the most neighbors (25) so I used it when deciding how to lay out the neighbors.

Words form into groups based on which letter is varying. Four-letter words belong to up to four groups. Since I was dealing with a text grid, I tried splitting the words into the four groups and putting them in clusters next to the current word.

It ought to be possible to represent further graph connections to some extent. I've thought of listing words that are two steps away horizontally, extending out from each of the cyan one-step words in the picture above. I don't think there's space in my 80x25 layout to list all words in every case, though. There is also the issue that two one-step words may both have links to the same two-step word. In this case, would you list the word in both places? In a graphical graph representation you could try to put the words next to each other so they could both point to a single node for the two-step word.

Grouping words like I've done in the picture may give away too much of the graph structure. In particular, listing the words alphabetically as I've done gives away too much. It's not that hard to come up with the missing words.

More problematic, though, is the longest-path gameplay. It turns out to be pretty easy to keep going, and going, and going, so you're likely to succumb to boredom before you complete a scoring run. Also, with me showing only one step ahead in the graph, you don't really see dead-ends coming so there isn't much chance for strategy as you choose words.

Any ideas for gameplay involving the word adjacency graph?