Categories
Game Design Game Development Geek / Technical

Visualize Markov Chains in Action

Sometime back I took the Coursera online course “Model Thinking” offered by Professor Scott Page.

It covered modeling to help make sense of our complex world. Since models are often simplifications about what really happens, having multiple models that you can apply means you are better able to make sense of the world. I would highly recommend taking the class if you want to be a better citizen and a better thinker.

At one point the class covered very familiar ground. John Conway’s Game of Life and Stephen Wolfram’s cellular automota studies made an appearance, which got me much more enthusiastic about learning how to combine simple methods for complex procedural generation. Along the way came Markov Processes.

Wikipedia says, “A Markov process is a stochastic model that has the Markov property.” Let’s break that down into something resembling everyday language.

Stochastic essentially means random. We’re dealing with a probability. So a Markov process is a model that involves a random element.

And the Markov property? All this part says is that in order to determine what state you are going to be in, the only thing that matters is what state you are currently in. How you got to your current state, otherwise known as your history, is irrelevant. Your past does not determine your future except to the extent that it somehow got you to your present circumstances.

So the simpler definition of a Markov process is that it is a state machine in which how you get to the next state is randomly determined with probabilities based on your current state.

Why is this idea valuable to know?

Let’s say you have weather play a role in your strategy game. If it is raining, your players can’t launch aircraft.

The thing about real weather is that it’s hard to predict. Weather reports tell you that it will be partly cloudy with a 15% chance of rain instead of saying that it will definitely not rain. Because sometimes even if they think it isn’t likely, it happens. Sometimes when they think there will be 4 inches of snow, we find that it is more like half an inch and the predicted snowpocalypse will hit some other city instead. People can talk about the weather as if it is completely random and wonder why meteorologists can keep their jobs when they are wrong so often.

If you wanted to model weather in your game, you could probably use a random number generator. Let’s say that for each day represented in the game, you create a weather report by getting a random number to represent the chance of rain:

int chanceOfRain = rand() % 100;

So when it comes to determining if it actually should be raining or not, you can create a random number and see if it falls within the value:

bool didItRainToday()
{
    return (rand() % 100) < chanceOfRain;
}

It would work well enough. Players can make plans based on the forecast, but there are problems.

First, you can’t prevent streaks of certain values from appearing. If you have aircraft in the game, but the weather system prevents you from using them, they become less useful. One day of bad weather might be a minor setback for your war plans, but having weeks of bad weather could be seen by the player as ridiculous. With random number generators, it’s possible to get into this situation, and your players can get frustrated with the bad luck.

Second, you can’t prevent initial values from being “bad” either. The beginning of the game is when you are trying to pull new players into your game’s world. If the game immediately starts with bad luck, it might leave a bad taste in the player’s mouth.

Third, it’s not as realistic to have a day of sunny weather followed by a day of stormy weather followed by a day of sunny weather. As unpredictable as the weather can be, and as possible as the wild swings are, people expect good weather to follow good weather, and bad weather to follow bad weather, and that we’ll have good weather days more often than bad weather days.

You can mitigate the above issues by hardcoding non-rain values for the first few days and also keeping a count of bad weather and forcing good weather if that count goes above a certain threshold, but it’s a clunky solution that still leaves a lot out of your control as a game designer.

Enter Markov chains

Instead of treating each day as completely independent of the next, you can keep track of your current day’s weather state.

Let’s say that a non-rainy day today has a 90% chance of producing another non-rainy day tomorrow, and that a rainy day has a 60% chance of a sunny day following it.

Weather In Markov Chain Form

So almost all of the time a sunny day predicts a sunny day to follow, but every so often it will predict a rainy day. Rainy days might stay rainy for days at a time, but most of the time it will become sunny again the next day. So players can get a feel for how likely rain is to occur and make decisions based on their own mental model of the system, which makes rain an ever present threat without making it an overwhelming or unfair one.

And as a game designer, you can tweak the probabilities of each state until the weather acts how you want it to without having to hardcode everything, create a hacky bandage for it, or give up control to a random number generator completely. You could add more states, such as partly cloudy days and overcast days, which will have different probabilities for moving to other states. Overcast days can result in rainy days more often than sunny days, just like in real life.

You could also put Markov chains to work for you in other areas of games. What if the population of your city simulation has mood swings? That is, if people are content, they are likely to stay content, but sometimes a situation occurs in which enough people get upset that they influence other people to become upset as well. That is, you could have a Markov chain in which content people are likely to be content but sometimes become discontent, and if they are discontent, they are likely to stay discontent but sometimes become content again, mimicking what happens in real life when there is outrage that dies down after the news cycle stops covering the political scandal. In the city simulation, it might drive the player to take actions to address the population’s concerns before real damage occurs.

Or you could create random terrain with roads. Roads tend to want to go straight, but sometimes they turn 90 degrees. Your terrain generator can start creating a road with a particular direction, and each step it adds another tile of road next to the previous one. 90% of the time the next road tile will be placed by continuing in the current direction, 5% of the time it could turn left, and 5% of the time it could turn right.

If you want to play with Markov chains, learn more about them, and see them in action, then see Victor Powell’s visual explanation of Markov chains.

Categories
Politics/Government

You Are Allowing Terrorists to Win by Giving in to Fear

I had two Muslim roommates when I was in college. They were the nicest guys.

One was in computer science and the other decided to go into religious studies. We played computer games together. They threw the best party I ever went to as part of the fraternity they were pledging for during my time living with them.

I remember conducting an experiment with one of them to see if one of us was more likely to get followed in a store after watching a documentary about discrimination for a class we took together. The results were inconclusive that day, which surprised us.

I also remember watching him eat Skittles as if it was the first time, and it turned out that it might as well have been. He had this look of pleasure as he ate each one, and he explained it was because they no longer used animal-based gelatin, which prevented him from eating them before.

Days after 9/11, I remember having a conversation with another Muslim friend about how no one would sit near her on the El that day. I didn’t understand right away what she was saying until I saw the anguish on her face. People were afraid of her because she had dark skin and wore a hijab.

She was great to hang out with, too. Last I heard, she became a paralegal.

I have non-Muslim Indian friends, some of them who are Christian. We’ve played ping-pong or foosball at the day job together, we’ve danced together, we’ve attended weddings together, and we’ve even done real work together.

I am aware that the untrained eye would lump all of these people together under the category “terrorist”.

Each time I see a terrorist attack has been successfully carried out in the world, there are two groups of people I feel for.

I worry about the victims and their families. My heart goes out to them. I can’t imagine the feeling of loss, sadness, and anger they must be feeling in the aftermath.

But I also spend time worrying about my friends getting hurt or killed by idiots who feel the need to “send them back to where they came from” or otherwise treat them as if they were the enemy.

These are real people. They’re Americans. “Where they came from” is just as likely to be a suburb of Chicago as it is the Middle East.

I see a lot of fear-based posts online by friends and family arguing that you can’t tell the difference between a radical Muslim and a peaceful one and so therefore all of them should be banished from the country, or rounded up and killed, or similar rhetoric that sounds like they have no problem with domestic terrorism when they are the ones conducting it. I see similar talk coming from some prominent politicians who seem to feel that the only part of America they need to worry about is the lighter-skinned part, and so they set an example for others to follow.

They worry about our way of life being under threat but have no problem throwing out life, liberty, and the pursuit of happiness when it comes to those who look different. We cherish our tradition of religious liberty, just so long as it’s Christian.

They worry about Da’esh/ISIS/ISIL/IS destroying this country, but then they turn around and ensure the principles that make this country great in the first place are destroyed first. Giving in to fear, they actively participate in handing Da’esh their victory.

And people like my friends are put at risk as a result.

So while I am processing what happened in Paris and Beirut and Baghdad, I am worrying about the safety of my friends.

Please don’t give in to fear. Real people with real families and real lives are put at risk when someone with enough fear, anger, ignorance, and hate gets the wrong message.

Categories
Geek / Technical

Unit Tests Save The Day Again

The other day I was working on creating widgets to make it easier for me to configure the elements of a screen in a game I’m working on.

At one point I realized that my interface class could hold the common data between the different derived classes, such as the widget’s position. There’s no reason that each derived class needs to have code copied to manage it, so I moved it into the base class:

// IWidget.cpp
IWidget::IWidget(const Point & position) : m_position(position)
{
}

// SpriteWidget.h
class SpriteWidget : public IWidget
{
    public:
        SpriteWidget(SpriteImage * sprite, const Point& position);
.
.
.

// SpriteWidget.cpp
SpriteWidget::SpriteWidget(SpriteImage * sprite, const Point & position) :
    IWidget(position),
    m_sprite(sprite),
    m_buttonControl(0)
{
}

It should have been a very basic refactoring exercise, and yet I found a number of unit tests were failing that made no sense to me. It was as if the member variable m_position wasn’t getting correctly initialized when I created my SpriteWidget.

By default, a Point object initializes to (0, 0, 0), but as you can see above, my SpriteWidget passes along the Point position to the IWidget’s constructor, which initializes it’s member variable. And yet my unit tests indicated that SpriteWidget was not initializing IWidget’s Point correctly and was instead getting m_position initialized to the default values.

Reading the code, everything looked right, but clearly something was wrong. Otherwise, the tests would be passing.

So I started printing out logs to let me know the state of the variable. SpriteWidget’s constructor got position just fine as an argument. And it was correct in IWidget’s constructor. And yet when I tried to print out m_position from within SpriteWidget’s constructor, it returned values for a default Point.

And then I found it.

// SpriteWidget.h
.
.
.
private:
   Point m_position;

I forgot to take the member variable out of SpriteWidget’s class definition, so it was shadowing IWidget’s otherwise inherited member variable, and I didn’t realize it.

But my unit tests were there to let me know that all was not well. Without those tests, I might have thought my code was fine. After all, the logic was correct, which I can verify after rereading it multiple times.

So I probably would have seen this unexpected behavior potentially weeks or months later, especially if my first production use of these widgets used the default position value of (0, 0, 0). It would have taken me forever to track it down, which would have been a disaster during a Ludum Dare timed compo.

Thanks for saving me time and preventing stress, unit tests!

Categories
Geek / Technical Personal Development

Global Day of Coderetreat is This Saturday

A couple of years ago I attended my first Global Day of Coderetreat, a day to celebrate software craftsmanship and practice software development with like-minded developers outside of the context of a normal work environment.

I had a great time then, and so when I learned at the last minute that there was one coming up, I signed up for it right away. It’s a free local event, so there’s no excuse not to take advantage of it.

Last time we paired with different people in multiple iterations of developing John Conway’s Game of Life, with each iteration forcing us to throw away our old code and work under different constraints.

For example, one iteration asked us to avoid using primitives. At the time, I struggled to understand what it meant since you can’t create a custom class without using primitives at some point.

But the spirit of the exercise is that your solution shouldn’t expose implementation details. If you are using integer values to represent states, you could use a typedef:

typedef int State;

And then use State instead of int where appropriate. In this way, your code reads better because the way you model it is part of the language of the code.

Note how even with bad single-character variable names that

void update(GridPosition g, State s);

communicates intent a lot better than

void update(int x, int y, int s);

And ever since that coderetreat, I’ve been able to use that experience to write more readable code than I used to.

I’m looking forward to Saturday’s Coderetreat here in Des Moines, IA. It should be fun.

Are you attending a Coderetreat near you? Are you hosting?

Categories
Geek / Technical Personal Development

You Are NOT a Code Monkey, So Stop Acting Like One

I lead a C++ lunch-and-learn group at my day job. Its audience is either non-developers interested in learning some basic programming, or developers who have experience with a different language and are still getting to grips with C++’s basic syntax.

One of the things I try to stress is the need to be conscious when coding. Software development is an intellectual activity. The most important aspect is not coding. It’s thinking.

So I often stop my group and ask them to justify a code change. Too often I see someone copy and paste code in the hopes that it will “work”. It then becomes trial-and-error in getting the magic incantation of semi-colons, curly braces, and keywords in the right order in an attempt to appease the compiler so that the developer can continue.

It’s what I call Hope-and-Pray-based Development, and while a million code monkeys eventually might be able to hack out the equivalent of Shakespeare’s works using this method, it’s not what a software engineer should be doing when trying to create customer value through code.

Now, it’s one thing to leverage the compiler. If you type out some code, and you’re not sure if it is right, the compiler will happily tell you why faster than you can formulate a guess. But you’re not just typing and pasting code in different ways in the hopes that the compiler will shut up.

The key is that you are testing a hypothesis and getting feedback and, most importantly, learning.

But sometimes the lesson is subtle.

Recently we’ve been working on the Prime Factors Kata by Uncle Bob Martin. It’s a short kata in Java that we’ve translated to C++ as we’ve gone through it, but because of my insistence on being conscious developers, it has taken a few sessions to get through the first few tests.

The first unit test says that you get an empty collection when you ask for the prime factors of the number 1. The second unit test asks you to return the number 2 when you ask for the prime factors of 2. So after the second test passes, the code looks something like:

std::vector<int> primeFactors(int number)
{
  std::vector<int> factors;
  if (number == 2)
  {
     factors.push_back(2);
  }
  return factors;
}

The third test is about the prime factors of the number 3. Once it passes, the code looks like:

std::vector<int> primeFactors(int number)
{
  std::vector<int> factors;
  if (number == 2)
  {
     factors.push_back(2);
  }
  if (number == 3)
  {
     factors.push_back(3);
  }
  return factors;
}

The third part of the test-driven development cycle is refactoring, and my group wanted to refactor this code to look like:

std::vector<int> primeFactors(int number)
{
  std::vector<int> factors;
  if (number == 2 || number == 3)
  {
     factors.push_back(number);
  }
  return factors;
}

The tests still passed, but I asked the group to justify their refactoring. I got responses about how it is more readable this way, or that there are fewer lines of code.

I said that those reasons are all well and good, but I fear they’ve lost something in terms of intent. I said that the variable number is the input. We’re asking for the prime factors of number, and giving back number as output happens to work but isn’t really what we’re doing when we’re providing the prime factors of a number. I argued that this change is hiding the intent of the code and that explicitly returning 2 for 2 and 3 for 3, while more lengthy, didn’t assume anything about the input as output.

This discussion/debate went on for the last 10 minutes of the session. Afterwards, they read ahead in the kata’s slides and saw that the refactoring in the slides does, in fact, do the refactoring as they did.

So was I wrong?

The prime factors of a number are directly related to the number, so it makes sense that the code can be written to return values that are defined in terms of that inputted number. So, ultimately, yes, the code will reflect this fact.

But I wasn’t focused on the code’s correctness. I was focused on the correctness of the thinking behind the code.

The developers in my group didn’t argue that the refactoring’s validity is due to the number being its own prime factor. They were focused on removing what they saw as duplication, on making the code shorter.

Effectively, they saw a change they could make and made it without concern about how it will be read later or how it will impact changes later. It was a change made for its own sake, mimicking changes they’ve seen elsewhere. It “worked” in this other context, so it must “work” here.

In other words, I recognized that this otherwise fine code change was happening for the wrong reasons.

Another example is when we passed our second unit test and decided to refactor the tests. We created a fixture, and the code originally looked like:

class PrimeFactorsFixture : Test
{
};

The compiler didn’t like it: error: ‘static void testing::Test::SetUpTestCase()’ is inaccessible
static void SetUpTestCase() {}

After the developers eventually read the error message and tried to figure out why this function was even relevant to their code, someone suggested that sometimes the keyword public is put in front of the base class.

So they tried it, and it “worked”. The compiler built the code and we were able to run the unit tests.

Rather than continue on with the refactoring, I spent the next few minutes (re)explaining how inheritance works in C++, and that there is a difference between private and public inheritance, and that what they saw was a compiler error as our unit test was expecting PrimeFactorsFixture to have functions that Test provides but because we were inheriting from it privately, those functions were not available.

I spent that time because it is important that they understand WHY it worked. I want them to get out of the habit of throwing spaghetti at a wall and seeing if it sticks. I don’t want them to be satisfied with waving a dead chicken to get past a compiler error. I want them to think beyond “I saw this other code that looked like it might work here” and get to “we need this code because of this good reason.”

Trial and error is fine if you are actively learning from your errors, but if you don’t stop to find out why the errors happen, you won’t learn how to avoid them in the future. You’ll just leave behind a trail of horrible half-functioning code that appears to “work” at the time you wrote it without you being able to explain why.

If your development process could be replaced by a script that generates copy and pasted code or shifts values around at random until the compiler works, you aren’t acting like a software developer. You are acting like a code monkey.

Code monkeys bang on the keyboard until things seem to work, even if the code doesn’t in fact work as they think it does. They focus on getting past compiler errors without worrying about why the errors happened or if the code changes they made to “make it work” are even sensible in terms of what they are trying to accomplish.

Software developers think through what code is needed, and once they implement it, they know with some level of confidence that their code actually does in fact work. They learn from their mistakes. It’s not about getting it working. It’s about getting it working correctly.

And since I want my group to be made up of software developers, I often stop my lunch and learn group and force them to justify what they were thinking when they made a change. I won’t tolerate random code changes to appease the compiler. Instead, I want them to think the code through. I want them to be able to predict accurately how the compiler will react to their code when they write it.

I want them to put down the dead chickens and think.

Categories
Geek / Technical Personal Development

Code Katas Shouldn’t Be Called Katas

I’ve told a few people this over the years, but I hate the term “code kata.”

More accurately, I hate that people call code katas what would otherwise just be “programming problems.”

In martial arts, a kata is a choreographed routine that teaches and reinforces form and movement. Here’s a short video that shows a beginner’s kata. You can see that the stance, the punching, and the blocking moves are repeated in different transitions. A practitioner would do that kata the same way each time.

The goal? To internalize the movement so it becomes second-nature, so that outside of a kata there is less need for conscious thought when deciding what move to do. The position of the head, hips, and shoulders, the movement of the feet, and the general stance of the practitioner are all things that might feel unnatural and forced at first. Repeating the katas help make it feel natural.

Code katas, on the other hand, don’t usually look anything like a martial arts kata. There’s a problem statement, and you are left to solve it on your own.

They are great exercises, and the more famous ones are at CodeKata.com. I think they are helpful for a developer to gain experience with the hard work of software development, which is mostly thinking.

But the word “kata” implies a form to repeat.

Uncle Bob Martin’s bowling game kata, to me, is a kata, because it’s purpose is to teach the red-green-refactor cadence of test-driven development.

For people new to TDD, it’s a great way to learn how to test-drive the design of code. One of the subtle lessons is going through the design upfront and then discovering at the end that the code’s implementation is simpler and doesn’t necessarily look like the initial design. But the important part is writing a test first, writing just enough code to make it pass, and then refactoring out any duplication. Over and over.

I’ve done the bowling game kata a few times, and I’ve seen Uncle Bob demonstrate it twice. The TDD form was always the same, but it wasn’t rigid and mindless. It was helpful to have the slides and follow along, especially as the original kata was implemented in Java and I was doing it in C++. I had a guide that gave me the feedback I needed to know if I was on the right track. “I moved on to the next test, but I see the next slide had us refactor. Whoops. I forgot the refactor part of red-green-refactor.”

Contrast this code kata with what usually passes for a code kata: “Here’s an interesting problem statement. Solve it.”

There’s no guide. There’s not usually a right or wrong way to solve it. And when you do it, there’s no feedback that lets you know you did well or where you need more work. It’s just a programming problem or puzzle.

And while they are useful, I wouldn’t call them katas.

Unfortunately, we’ve had code katas for long enough that I don’t see this name going away anytime soon.

What’s your opinion on calling them “code katas”? Am I missing something subtle about them that makes the name appropriate?

Categories
Games Politics/Government

How to Apologize Correctly

When I was a senior in high school, I was editor of the school paper. I wanted to publish more than fluff pieces. I couldn’t count how many times the formulaic headline “[insert school event here] a Success” showed up in that paper.

Some of the articles ended up quite controversial, and I got us in trouble quite a few times. I was the reason why future issues of the paper had to be approved by the principal.

And while I can be proud that, after years of people complaining, my paper resulted in actual changes to the cafeteria food quality and pricing, I did have one article that poked fun at past administrators that got me pulled into the principal’s office. I was told that I needed to write an apology for the next issue.

I remember writing the words, “We regret any offense we may have caused.” It sounded good and official, as if it was something in a real newspaper.

And I remember being told that my statement wasn’t good enough. It’s not an apology to “regret” that someone was offended. It’s basically saying that we’d do it again and that any offense is the responsibility of the offended.

So I had to rewrite it: “We apologize for the offense we caused.” It’s a lot more direct and lot less weaselly.

An apology isn’t something you say to make bad feelings go away. “I’m sorry” isn’t a magic phrase to get people who are upset with you to disappear. And you don’t apologize with a non-apology such as “I’m sorry if you were offended” because you’re basically saying that you’re not sorry you did someone something wrong because you don’t think you actually did.

According to Ars Technica, slave-Tetris mode was removed from Playing History 2: Slade Trade by Serious Games Interactive after a public outcry when the game became more well known due to a Steam sale.

Ugh. I did just type those words, didn’t I? Slave Tetris? Really? Someone thought it was a good idea?

I have no problem with a game being used to educate players about history. And no one else who understands how games aren’t just for kids has a problem with the concept either.

But Slave Tetris isn’t the most respectful way to teach how horrible the conditions of the slave ships were. This isn’t navigating the Dalles in The Oregon Trail. You can’t reduce the real experiences of millions of people to a mini-game and not expect people to feel that those lives themselves have been minimized.

Simon Egenfeldt-Nielsen of Serious Games Interactive had this non-apology:

The phrase “as it was perceived to be extremely insensitive by some people” is very similar to “we regret any offense we may have caused.”

This phrase makes it sound like the Slave Tetris minigame is actually quite sensitive and perfectly fine, but because some people took offense, SGI decided to take it out to make the bad publicity and bad feelings magically go away.

I think Egenfeldt-Nielsen honestly believes that this is a good educational game that brings the horrors of the trans-Atlantic slave trade to life much better than any history book could do. And he may be right about the game as a whole, although having someone in the game talk like Mr. T seems to contradict his claims that “We are definitely not making it into a joke.”

Playing History 2: Slave Trade - Pity the Fool?

Furthermore, I have a feeling that many of the negative reactions in here are knee-jerk reactions and she eps following what other says. Please take time to look at the game before forming your opinion.

The problem with Egenfeldt-Nielsen’s commentary is that he says, “we are listening” but then in the same breath says, “I really don’t think that all the comments here are warranted.”

Oh.

People are offended, and it isn’t the Race Card or Political Correctness or people who are just looking to get offended professionally.

He made a mini-game about earning points by stacking human slaves efficiently in a slave ship. It’s offensive.

If there was a mini-game about slamming planes into the Twin Towers and scoring points for the number of people you force to jump to their deaths, people would be offended because it is offensive to take such a serious situation and try to pretend there’s a fun game out of it. There would be real lives being represented in a terrible way. The seriousness of that day would be missed, no matter how accurate or true it technically might be.

I agree with Egenfeldt-Nielsen that games have a lot of potential beyond being fun. In fact, there are plenty of serious games out there on a wide variety of topics that the casual game player might get surprised about. There are games about dealing with cancer, depression, and many other health issues. There are games about current events, war, and logistics for aid organizations, all of which treat the topic seriously and can bring awareness without making light of the situation.

But as I’m sure he has discovered, it’s not easy to work with serious subjects. You can’t separate the game from the people and events it is portraying. A game about slavery can’t just be game mechanics with a slavery backstory. To think otherwise is to betray the mindset that this serious issue is serious in the abstract but not serious enough to consider other people’s reactions to it as important.

Slavery is horrific. A game about slavery need not be, but Playing History: Slave Trade‘s Slave Tetris isn’t driving home the point that slave ships were actually like a Tetris board. In a subtle way, it’s minimizing the horror.

But I worry the lesson he learned isn’t to treat serious subjects with more respect and awareness. I worry the lesson he learned was that he needs to walk on eggshells to avoid having seemingly unreasonable people offended. His regret is that others were offended, not that he participated in the offending.

Categories
Game Design Games Geek / Technical

The Neat Little Experiments of Ludum Dare Entries #LDJam

Since I’m on vacation, I’ve had more time dedicated to playing and rating the entries from Ludum Dare #33, and it occurs to me that I’ve never played so many games from a compo before.

And apparently I’ve been missing out.

When over 1,200 people submit games within 48 hours for a single theme, you’re bound to see some really amazing, innovative, and bizarre takes on it. While many might be mediocre, even the poorer entries might have a glimmer of brilliance hidden in them. It’s like having hundreds of people doing research and development all at once.

Monster Mash by Budda allows you to create and customize your own monster. Using the bones of the adventurers you defeat, you can upgrade your body parts and weapons to get more powerful and deal with the stronger and deadlier adventurers.

LD33 Monster Mash by BuddaT

The battle screen features your monster on the left and your enemy adventurer on the right. What I liked about it was how the interface was simple and abstract: click on the various body parts to attack and heal. When your enemy hurts you enough, you might lose the ability to use one of your body parts. It’s bizarre to see your head turn red to indicate it is disabled when the rest of your body is fine, but I bet it is terrifying to the adventurers as well.

I can see this experiment result in a genre of simple yet tactical mobile games.

Goloumo by HippGame is a quick platformer. While you can move about and jump, the way to make it through the game is to use your ability to manipulate other objects in space. Click and dragging a table or an elevator when you’re on it, and you can get to areas that would otherwise be impassable.

LD33 Goloumo by HippGame

It’s a rough experiment, but I can see this mechanic being used to great effect in a Nintendo DS game.

Sirens by miotatsu has you sing to lure ships towards your rocks. It’s art is a bit crude and the audio shows how little polish was expected, but it works well.

LD33 Sirens by miotatsu

It’s essentially a tower defense game in which the stationary rocks are both your weapons and your defense. Still, combined with the singing ability to lure ships in on purpose, I think Sirens has a bit more to it than might be expected.

Hydra Confusion by concalf has you controlling a hydra’s many heads, ensuring each one is fed and happy. If you mess up, a new head appears, which makes it more difficult for you to manage.

LD33 Hydra Confusion by concalf

Hydras were always cool, and I’ve never seen a game that featured one you could play! Moving about and controlling the individual heads isn’t terribly challenging, but managing them all at once is.

Fear Me by joe has you in the role of a monster trying to scare someone who is trying to sleep. You need to be just visible enough to scare without being too visible and caught.

LD33 Fear Me by joe

It’s kind of like playing a character in Monsters, Inc. You can hide under the bed or in a box, but it takes up precious time. While I suppose Metal Gear did similar stealth mechanics, this is the first time I’ve seen you in the role of a scary monster.

What’s funny is how each Ludum Dare starts with the announcement of a theme that many people will vocally hate. When “Roads” was announced for Ludum Dare #13, I remember people complaining that everyone was going to make a racing game and it was going to be a boring theme. But like most LDs, there was quite a bit of variety present.

Similarly, people whined about “You Are the Monster” for LD #33, citing how hard it was to come up with an idea, and yet in just a handful of games I found that no two are alike, and they sometimes bear little resemblance to professionally-created games, but in a good way. It’s mind-boggling how much creativity Ludum Dare unleashed.

Years ago, I was given a jazz album to listen to while I worked, but it was so bizarre and jarring that I couldn’t concentrate. I looked up the artists, and it turns out that they combine “modern avant-garde jazz with rock and pop influences.” Ok, sounds great, but it sounded like random noise to me.

The thing is, I figured that it must sound good to a more practiced ear, and so I wondered what I was missing. When I asked a friend who is more of a music expert, he explained that avant-garde music is meant to be experimental. Often what someone discovers with avant-garde finds its way into the mainstream eventually.

Now, there is a lot more to avant-garde art. It’s not about being a proving grounds for new work but is instead meant to push boundaries and challenge traditional social values. It’s more political than commercial.

But the experiments do get leveraged to create commercial works.

And playing Ludum Dare entries, I’m reminded of this idea. The game mechanics might be rough and unbalanced, but there’s often a spark of cleverness.

Have you seen any interesting Ludum Dare entries worth noting?

Categories
Game Design Game Development Geek / Technical Personal Development

Development Strategies for Game Jams #LDJam

As I play and rate Ludum Dare games, I see that games fall into a few groups:

  • Highly polished games that feel complete
  • Highly polished games that feel incomplete
  • Unpolished games that feel complete
  • Unpolished games that feel incomplete

By complete, I mean they have all the elements of a game: an objective, conflict, rules, unpredictable outcomes, endings, etc.

By polish, I am referring to the production quality. There’s few bugs, the aesthetics are cohesive, and everything feels balanced when you play it.

So how do you make a highly polished and complete game in 48 hours? What tips and tricks are developers using?

Make It Playable as Fast as Possible

Games are complex systems in action. You can’t design a game well unless you playtest it because it isn’t always obvious how the rules of a game interact. Making something playable early means you have more time to test it as you add, remove, or change mechanics. You also have time to make decisions, such as whether to kill planned features or spend time on making the controls feel better.

I’ve found that when I fail to submit a game to a Ludum Dare, it usually coincides with a game that either has no game play or gets the bare minimum of game play added at the very end. I have no time to play and see how the game feels, which means that even if I get it done on time, it’s more likely to be an unpolished and incomplete tech demo.

On the other hand, when I focus on getting something playable early, such as during Ludum Dare #24, it’s a game from the beginning. It might start out unpolished and incomplete, but by the deadline, even if I don’t get all the features I wanted in there and I can identify glaring problems, I have something to submit. For my entry for the theme Evolution, I didn’t get to add the features that take advantage of the theme, but I recall how sluggish the tank felt to move and I spent a little time tweaking it until it felt better to play. When you killed the enemies, I had points float up above their heads. I’m not saying it was a beautiful game, but it was more polished than most of my entries have been. And it didn’t have everything I wanted in it, but what was in it felt complete.

Ideally, your work in progress will be easy to deploy to other people so they can play test it and give you feedback. You might think the game is fine, but you’ve been immersed in it for hours and might miss how difficult it is for someone who hasn’t seen it before. Your game is ultimately for other people to play, so their feedback is very important.

Know Your Tools

If someone gave you a complex tool you’ve never seen before, you’d probably muddle through how to use it, but it would be slow and painful.

On the other hand, if you were given a tool you’re familiar with, you no longer need to worry about how to use it as it is almost second-nature. You can focus on the task in front of you instead of focusing on how to use the tool.

Years ago, I struggled with making programmer art in GIMP. I wrote code. I didn’t art.

Partly from learning during previous Ludum Dare compos, partly from talking with artists about their workflow, and partly from practicing outside of compos for my own projects, I learned how to do things I normally need to do during a game jam. For instance, I use layers, preferably named ones, to make it easier to create a complex image. I know how to scale images and layers with fewer artifacts. I know how to use an alpha selection to get an online of an image, and I can grow and shrink selections so I can create a silhouette or a border. I even learned common shortcut keys so I can quickly switch from the Pencil tool, the Bucket Fill tool, the Rectangle Selection tool, and the Ellipse Selection Tool, which saves me time.

I remember reading the manual for Applesoft BASIC and learning that instead of typing out:

PRINT “HELLO, WORLD!”

you could type out:

? “HELLO, WORLD!”

And that question mark would automatically get turned into the PRINT command. The manual mentioned that it saved four keystrokes and time. At the time I wondered how much time it could possibly save, but since I was typing PRINT almost all the time, I realized that it added up.

Today, knowing your IDE’s shortcuts similarly helps. As my friend Chris Freeman said in his presentation on refactoring, tools reduce cognitive load. Instead of using the mouse to hunt and click on everything in menus, you ideally should be able to unconsciously move your fingers to the right key combinations to make things happen. It’s like learning how to ride a bike or drive a car. Once you get the hang of it, you no longer focus on where your feet are. When you want to move forward, your feet automatically know what to do.

During a game jam, you don’t want to spend time reading a manual or searching online for help. You want to just DO things that move the game forward.

For my first Ludum Dare, I was learning how to use libSDL, and luckily I kept the scope of the game down because I knew I wasn’t going to be able to do very much. I spent a lot of my time figuring out what SDL provided and how to write code to take advantage of it.

For the latest Ludum Dare, I was often very pleased with how even major code changes compiled on the first try. I was much more familiar with the language and with the interface of my tools such as Vim and Gimp.

Come up with a Plan

You’re two hours into a 48 hour compo. What are you working on now?

With only two days of development, it might feel like you don’t have time to plan. Every moment not working on game development is a lost opportunity.

But planning saves time, and it doesn’t even have to be very complicated to be effective. There’s no need to create a Gantt chart for your project.

Some game developers create entire detailed design documents to keep their thoughts organized, and other developers use nothing more than a list of planned features that they cross off as they get implemented.

But what about time?

You could work on one thing at a time until it is all done, but the risk is that the later items don’t get done at all. What you don’t want is to find yourself with an hour left and realizing that you forgot to implement a way to end the game or that your game is completely silent.

Some people try to get a good chunk of the game done early so that the rest of the compo is spent on balancing and adding polish. Some developers set aside blocks of time, such as a couple of hours, to creating sound effects.

Other people understand that their energy levels are going to be different throughout the day, and when they are too exhausted from programming, they can switch hats to creating graphics or music. Einstein actively relaxed by playing the violin, and you could do worse than emulate him.

No matter how you plan your two days, having that plan gives you more insight into what to do at any given moment so that you have the best chance of submitting a finished game.

Your Tips?

I’m not saying I’m an expert, and I still feel like I’m learning how to pace myself and put together something. But after participating in 10+ Ludum Dare game compos and a handful of other game jams, I think I’ve gotten some worthwhile experience to share.

I should probably invest in The Game Jam Survival Guide by Christer “McFunkypants” Kaitila.

What are your strategies when participating in a game jam? How do you ensure your game is complete and polished before the submission deadline?

Categories
Game Design Game Development Geek / Technical Linux Game Development Personal Development

LD33: Free Me, You Idiots! Ported to Android! #LDJam

Shortly after I ported my Ludum Dare game to Windows, I ported it to Android! You can download and install the .apk now and play on your phone or tablet. I’ve updated my LD#33 compo entry.

Here’s a handy link to explain how to install an app outside of the Google Play store.

LD#33 Game Play

Warning: it’s not really optimized for mobile yet. It pauses when idle, but it doesn’t pay attention to the back button, so you’ll have to long-press the Home button then swipe it away to close it.