Categories
Geek / Technical

User Poetry: But Not Me

While cleaning and rearranging my office, I found an old tech support email from a job I had many years ago. I printed it because I was amused with how the author spaced out the lines and capitalized the first letter of each line. It almost looked like poetry.

By the end, I think it starts to feel like it would fit into a techy version of “Where the Sidewalk Ends.”

So I labeled it “User Poetry” and titled it “But not me”. I’ll change the author’s name and other identifying info to protect the innocent.

Attn. Unix Guys,

I can log into Unix session by telnet to dvap8 with my userid (jsmith) and my password.

However, I can not get to it by Hummingbird Exceed session. I go to Hummingbird Exceed session

In my Computer and put my userid and password successively and Hummingbird session takes it but clocking

And clocking with its welcome window screen. When others login with their userid and password in Exceed

In my computer, they get everything but not me.

Categories
Game Design Game Development Games Marketing/Business

Making Your Game Accessible to People Who Are Color Blind

I’ve written in the past about designing games for color blind players because I believe accessibility is important. It doesn’t take too much effort, and a significant number of players will appreciate it.

Alan Zucconi wrote a multiple-page, interactive tutorial on making your game accessible to color blind players.

He provides a shader that simulates different types of blindness, such as Protanopia (red-green color blindness), in order to help a developer test a game to see how accessible it is.

While the download and tutorial itself is Unity-specific, he provides a good amount of background on the different types of color blindness. That information could be applied no matter what game development tools you use.

Even if you didn’t want to use the shader in question, the tutorial explains the theory behind it so you could always implement your own tool.

For example, I used SDL and a custom engine to create my casual strategy game Stop That Hero!, so adding shader support just to test colors seemed like a lot of work.

Instead, I took a screenshot and the RGB values Zucconi provided, then manually plugged those values into the Channel Mixer tool in GIMP to generate the following image:

Stop That Hero! with Protanopia

If you don’t have Protanopia, you can see the difference. The image on the right looks darker, and some of the colors aren’t discernible. I am pleased to see that my use of contrasting colors mostly worked, as the mountains and trees are easy to see compared to the ground.

On the other hand, key visual indicators are lost. My use of red to represent a depleted health bar is almost indistinguishable from the green part if you have red-green color blindness. Whoops. B-(

The images in Zucconi’s tutorial have a slider that lets you see how different kinds of color blindness may change how your game’s visual will be received. It’s amazing to see a gorgeous, colorful game like The Witness become washed out and almost monochromatic.

And for some people, it’s a permanent filter they can’t opt-out of, so if your game depends on color in order to play, you’ll want to make sure it doesn’t inadvertently leave these people out.

Categories
Game Design

Improving a Game’s Design in Mere Minutes

Recently I volunteered at an event in which I facilitated a simple math game for 10 minute sessions with a rotating group of children ranging in age from 4 to 7 years old.

The event I volunteered at was a celebration for refugee children who had just finished taking one of their last math tests in an educational program. There were math-themed games and a potluck after.

We had about eight game stations, each of which consisted of a simple math game at a table with a few chairs and at least one facilitator. Some of the games were made up by the educators volunteering, and others were given or found online.

An Incomplete Game

I was assigned a game called Double It.

Double It Game

It consisted of a die, transparent markers in two colors, and a sheet of paper with a 4×6 grid of even numbers between 2 and 12, with each number repeated four times and placed in some arbitrary order.

I took some time to look at it before the event started. As a game developer, I immediately noticed a problem with the game: the rules weren’t comprehensive.

“Roll the die. Double the number. Cover the answer below.”

So, what’s the victory condition? I felt like maybe it was implied, but there were a number of variations I found that could work in this format.

If it was a square grid, then it could be math-based bingo card, but it wasn’t a square grid. Maybe whoever gets the most markers on the board wins?

But then I realized that with only four copies of any one number, there was going to be a situation in which a player will roll a number, double it, and find that the answer is already covered. What then?

I hesitantly asked the obviously very busy organizer of the event, who said, “Well, just let them roll again.”

Ok. Seems satisfactory.

And immediately after she left to continue her work, I realized that the game would then always end in a tie.

I had mere minutes before the event started, but I was not happy with this game.

On the one hand, I get it. It’s less about the game and more about teaching math skills. It doesn’t have to be an award-winning game. It just has to be a framework to let them practice within it.

On the other hand, the point of it being in game form is to be a compelling experience. As it stood, maybe the children wouldn’t recognize that it was a foregone conclusion that it was going to end in a tie, and maybe they wouldn’t see there was no challenge or conflict involved, but it seemed like chocolate-covered broccoli, and I wanted to do better for them.

Game Design in Five Minutes

So I gave myself the constraint that the original rules had to be the base of the game, but I set to work to make it a real game.

Given that Double It was supposed to be for 1st graders, I made sure not to get carried away with complexity. There’s no sense in turning this game into something like Vlaada Chvatil’s Mage Knight. In fact, with mere minutes to do this work, I only had time to do some simple tweaks.

Luckily, I got a chance to playtest with one of the other facilitators, and it really helped to talk about the rules changes aloud.

So here are the new rules I added:

  • If a player has all four answers covered, then he/she has a monopoly on that answer.
  • When trying to cover an answer, if there is no uncovered answer, and if the opposing player does not have a monopoly, then the player must remove the opponent’s marker from an answer and can place his/her own marker on that answer.
  • The winner is the player with the most markers on the board once the entire board is filled or time has run out.

The second new rule adds conflict and actually allows for the victory condition described in the third new rule to be met. The first new rule came about as a way to reward the player for getting all four answers, as it seemed like there should be a way to prevent the opposing player from taking your markers off the board.

Playtesting

So how was this game? Well, luckily I had a rotating group of playtesters to let me know!

When each game session started, I found that the children were relatively quiet. Some of them were able to double numbers effortlessly, and it was fascinating watching them quietly roll the die, place a token, and pass the die to the other player. Some had more difficulty and needed help, so I held up my hands and tried to let them visualize what it meant to take a number and double it. In general, this early game was somewhat compelling on its own due to the math and it being a novel set of rules.

But once the board started getting filled up, my new rules came into effect, and I was pleased to see eyes lighting up and smiles breaking out. Some of the children got really animated, and you can tell the engagement level changed. Now they had a reason to pay attention to their opponent’s die rolls, and there was this sense of protection over the board.

I was worried that someone would get upset that he/she had a marker “stolen” by the other player, but instead I saw sheepish grins, which surprised me. Even losing felt fun, apparently.

End Results

Given the very little time I had, I think I did fairly well. With some more design iterations, I might have been able to add some skill and decision-making into the game.

The end result is determined by die rolls, much like how the card game War is determined by the order of cards distributed. There was no skill involved, and so my game still lacked something to make it truly a game.

On the other hand, it still seemed more compelling to add conflict to the game. There was a sense of risk, which gave the players a sense of ownership. That they had no control over what happened may not matter as much for a game for children.

The Future

If I wanted to continue to iterate on this game design, I would start with allowing players to choose between covering an uncovered answer and taking an opponent’s covered answer. Now randomness isn’t the sole arbiter of the game. The players would have some agency, and it could make monopolies feel like a real accomplishment, but I feel like there should be a risk involved in not taking an uncovered answer.

Also, I found the grid layout seemed to bias people to expect it to be a bingo-like game, and so I would change the layout to remove that expectation.

Of course, designing a game for children means that the game doesn’t need to be more complicated than it originally was. Maybe. Perhaps if it got too lopsided, one player would stop wanting to play. This is why playtesting with real players is important.

The original focus was on doubling numbers, and I wonder if educational games work better when the educational aspect is presented as a prerequisite for playing in a subtle way.

That is, now doubling numbers was something you had to know how to do in order to play, and it was not presented as the entire focus of the game. Children who struggle with math seemed to be nervous about the early part of the game, but once the new rules kicked in, I noticed they were more quickly getting through the math part so they could see what happens next. It was as if they had found a higher level reason for bothering to do math rather than just doing math for its own sake.

It’s like learning how to read in order to better play The Oregon Trail or learning how to count to play Candyland. These games weren’t ostensibly about learning how to read or count, but as you played, you HAD to get good at those things in order to play the game better.

Another bit of evidence for this kind of education is also anecdotal. On my Apple II C+, I had Stickybear Typing, which was supposed to teach me how to type. I didn’t like it much. Yet, when I learned how to program and started trying to get the computer to do things for me, I found myself practicing key presses to the point that one day I didn’t have to look at the keyboard. Typing was a skill I picked up because I had a context in which to do the typing. When typing on its own was the goal, I struggled.

As I’m not an educator, anyone know if there is already a name for this kind of learning/teaching?

Credits?

Thinking about exploring this game’s design made me wonder where the original game came from.

A quick search online shows that Double It seems to be Doubles Aren’t Trouble, which is a freely available exercise from Jennifer White’s First Grade Blue Skies. The name and design of the paper is different, but the layout of the numbers and the initial rules are exactly the same. White has a number of free and for-sale resources for the classroom, including games and craft exercises for a variety of grade levels.

Categories
Game Design Game Development Geek / Technical Personal Development Post-mortem

LD33: Free Me, You Idiots! Post-mortem #LDJam

Ludum Dare #33 is months old, and the next Ludum Dare is about to begin. It’s about time I wrote a post-mortem about the game I submitted.

The theme was “You Are the Monster”, which, as usual, caused a lot of panic among the participants who worried that it was impossible to make a game based on that theme in two days. And once again, despite such worries, there were almost 2,000 entries submitted, so people found a way to do it.

I ended up making a fairly compelling, somewhat humorous, non-violent strategy game about being an imprisoned evil using its influence to escape. I called it Free Me, You Idiots!

What Went Right

  1. Quantity Over Quality: Fleshing Out Concepts and Designs Early

    It’s easy to want to get started right away. You only have 48 hours, and every second counts. But I also knew from experience that it helps to spit out as many concepts as possible early on, then pick the one that seems most promising. You are more likely to have a good idea picking the best of a thousand ideas versus the best of ten ideas.

    So I spent the first couple of hours thinking, doodling, and discussing with people on IRC.

    The theme had a lot of obvious and not-so-obvious applications. The obvious choice is to harvest ideas from classic movie monsters, such as vampires, werewolves, and ghosts. It’s direct, and you could have monsters who are genuinely scary or you could have them be misunderstood by the populace.

    The next-most-obvious choice is to think about metaphorical monsters, such as people who have the most evil and disturbing thoughts. It could be a psychological thriller in game form.

    I thought about characters, origin stories, and settings, and I had a lot of fun thinking up ideas as varied as space aliens and beings frozen in the Arctic for centuries.

    I went with the idea of the incarnation of evil imprisoned in a tree for centuries. With no previous story, I was free to write my own with no preconceptions.

    I fell in love with the idea, which really helped me drive the development of the game. If I hadn’t spent time upfront thinking, I might have settled for a merely OK idea, and I might not have found myself as passionate to work on it.

    I spent quite a bit of time thinking about this concept. I threw out a lot of ideas early on and managed to find the core of the game. I had originally thought about having a bunch of stones surrounding the tree that you were imprisoned in that had to be removed by the nearby villagers under your influence. I mocked them up and played with the idea for awhile.

    Concept: An imprisoned evil

    Imprisoned Evil prototype

    Imprisoned Mock Up

    The idea was that rock-gathering was an activity for the villagers, and the villagers would grab these forbidden rocks.

    I’m glad I threw it out because I ended up having entities that did hardly anything but explore and pray. I would have run out of time without a way to remove those rocks and finish the game.

    I think if I had more than two days that those rocks would still be in the game and the entities would be mining, chopping down trees, and more, but because I had a wealth of ideas to choose from, discarding some didn’t feel like I was gutting the game of its essence.

  2. Iterate Like You Mean It

    In the previous Ludum Dare, I spent a lot of my time on animations and art, but not much at all on game play. By the end of that compo, which had a theme of “An Unconventional Weapon”, I had a monster that could chase around the player when you got his attention either by shouting at him or by crossing his line of sight. I wanted the monster’s head to turn separately from the body, and there was going to be this idea that the monster can trip over itself when it is moving in the opposite direction that it was looking. I spent a too much time creating the complex animation system when I could probably have gotten away with something simpler, and as a result, what I submitted wasn’t anywhere near a finished game.

    I didn’t want to make that mistake again in Ludum Dare #33. Even so, I didn’t start writing code until the compo was well underway. While I was worried that I wasn’t going to make everything I wanted by the deadline, my approach meant I was always going to have something to submit.

    My first focus was on interactivity. If the player can do something, I can build upon it, even if I have to cut most features or change the direction of the game design completely.

    It meant I was also playing the game frequently. I would make a change and immediately see how it felt. I can identify things that may be buggy or hard to understand, and I can fix them immediately or prioritize them.

    For instance, when clicking on an entity in the game, an arrow appears over them. This was a simple bit of polish that I thought seemed important enough to add early on. With a bunch of entities moving about, this arrow meant it was easy to identify which entity you were looking at.

    But moving around the world was a bit jarring. You click, and the camera centers to that location. I knew I wanted to add interpolation to smooth the camera’s movement, but I also knew that what I had was passable and could be fixed if I had time for polish later. So the working yet jarring camera movement stayed throughout the rest of the game’s development.

    What was exciting was that by making small yet meaningful changes, it allowed me to add a relatively complex economy without much effort.

    LD#33 Game Play

    The game features a few variables that are interdependent and make it feel quite rich to explore. For instance, the player has Evil Energy to use to influence villagers. Evil Energy replenishes one point every second.

    The number of followers influences the amount of maximum Evil Energy a player has. More followers meant more maximum Evil Energy, which opened up options for the player.

    When you have followers, they will pray to you. When the total amount of prayer time exceeds 10 seconds, the player gets an extra point in Prayer Energy, which can be spent on upgrades and ultimately on the ESCAPE option, which ends the game in victory.

    I originally didn’t intend to add so much because I was worried about spending too much time on balancing all these variables, but without all of these different values and their interactions with each other, the game felt very simplistic.

    I’ll admit feeling worried that I might find that the whole thing was unworkable and would result in nothing but wasted time. Learning about and playing with game economies from the book Game Mechanics: Advanced Game Design by Ernest Adams and Joris Dormans gave me some confidence I could pull it off by adding pieces of it throughout development and building upon them iteratively. Each addition was relatively risk free and easy to fiddle with.

    I was very pleased with the results, and so were the people who played the game. I was surprised by how many actually played it all the way to completion!

  3. A Goal for Being Cool

    I realized that back in pre-20 Ludum Dare compos, it was easy for me to play almost everyone’s games because there was less than 100 entries. There would be a burst of game development activity for a weekend, and then maybe a week of playing and rating games, and then going back to regular life. Plus, back then you didn’t need to rate games to get your game rated.

    Today, with thousands of entries, it takes much more of a commitment. Your game won’t show up in the random sampling for entrants to rate if you don’t also rate other games. It’s a fair system.

    After the compo, I was on vacation from the day job and so I spent the next few weeks playing games. I set myself a Coolness goal. I figured that if I played a handful of games a day consistently for the next couple of weeks, I would be able to hit it.

    And when I rate games, I like to give feedback to the developer. I don’t just post “Nice!” or leave no comment at all, so I wasn’t going to allow myself to speed through reviews in order to quickly increase my Coolness. I was going to play games, give them a fair shot, and give an honest review with constructive feedback.

    LD33 Coolness Result

    I only got 63% Coolness, but it was enough to earn me a bronze medal. I don’t understand how that percentage is calculated. I know I didn’t rate anywhere near 63% of the nearly 1,199 games submitted, yet it seems like I could have hit 100% with only a few more handfuls of rated games if my math was correct.

    But I know that if I hadn’t set a Coolness goal, I would have either made the mistake of not rating enough games, resulting in my own game not getting rated by many participants as in past recent compos, or I would have spent a lot of my waking hours doing nothing but playing LD games, ignoring my other responsibilities. I think I had the balance mostly right.

What Went Wrong

  1. No Polish and No Sound Effects Again

    In an effort to speed development along, I did the opposite of what I did in the previous Ludum Dare compo and ignored animation and polish as much as I could. It wouldn’t matter how cool something looked if the player had nothing interesting to do.

    As a result, the game lacks life. The entities move around without turning or animating, and there is no indication when a player successfully influences someone. The grass tiles had markings which were too subtle and resulted in a sea of green that made it difficult to tell if the player was actually moving the camera.

    Now, it wasn’t completely bad. The prayer bubbles added a nice touch, as did the Evil Energy ball in the HUD scaling quickly when it replenishes. The flavor text had some humor and lore.

    But no sounds, no animations, and no special effects left the game feeling like a lot was missing.

  2. Buggy Engine Code

    There were a few problems with the custom engine I was using. One was something I saw in the last Ludum Dare in which tiles would seem to separate as you moved the camera around. It turned out to be a floating point error that resulted in me accidentally scaling the tiles so they would sometimes be one pixel smaller in width and/or height. I must not have pulled in the fix when I was putting the project together, so I easily fixed it, but it still took me some time to figure out what exactly I was missing.

    Early on I noticed that entities seemed to walk over the tree. They should look like they are in front of the tree when standing in front of it and behind the tree when they were behind it.

    So why were they always appearing on top of the tree no matter where they were?

    I recently ported my code from libSDL to libSDL2, and sprite rendering was done differently to accommodate scaling and rotation. Unfortunately, I introduced a Z-ordering bug which, after spending time on figuring out what was going on, I decided to ignore for this compo rather than spend more time trying to fix it.

    The risks of using your own code instead of a ready-to-go engine such as Unity or Game Maker is that infrastructure bugs like this are not only likely but also might be something you feel inclined to fix immediately. If Unity had a bug, I’d work around it because I’d have no other choice. If my own code has a bug, I’d feel like I could fix it while working on my game and might underestimate the effort it would take to do so.

    So while it wasn’t fatal, I had buggy infrastructure code that slowed me down and prevented me from making a better game.

  3. Missing: Some Features and Any Challenge

    One of the upgrades in the game is CAUSE FEAR. Do you know what it does?

    If you guessed it caused the villagers to be afraid, you would be wrong.

    It does nothing. Why?

    Because I never got around to it. I had ideas for what CAUSE FEAR would do, but since so much of the game didn’t get made, such as the mining and wood cutting I mentioned earlier, there was no real reason to cause villagers to be afraid. Maybe it would make them pray harder for a bit, and so CAUSE FEAR was similar to trading Evil Energy for Prayer Energy but in an indirect way.

    I had a few ideas, but none of them got implemented. Unfortunately, I left the option in even though it did nothing. Whoops. B-(

    Similarly, because there was no real conflict in the game, there was no challenge. There is nothing in the game that prevents you from converting every villager, getting all of the energies you need, and winning the game.

    I wanted the good villagers to try to convert back your followers. I wanted different kinds of villagers, such as priests and acolytes, and have their presence force you to change your tactics. Perhaps if your followers got numerous enough, the other villagers would go to war with them.

    Something. Anything.

    But instead, there’s nothing. There’s enough economy and variety that it seems to hide this lack of conflict, but without conflict, I can’t really say I have a complete game.

What I Learned

  1. A Design Document Is Key

    Throughout the compo, I set myself goals. I set an initial goal of settling on a concept within two hours. I set a goal of having interactivity early on instead of waiting until the end. I set a goal for rating games after the compo.

    Each goal gave me some control over the outcome. I was able to focus on what was needed and ignore what wasn’t. While the lack of polish hurt, it wouldn’t have hurt nearly as much as having a fairly incomplete experience.

    What really helped in setting goals was having a design document for the project. Now, I’m not talking about a 300 page document that no one reads. I’m talking about a living document that changed throughout the 48 hours I used it to help guide me.

    Everything I thought of went into that document, which allowed me to assess what was a priority and what was nice to have and what didn’t need to be there at all.

    I could see what was left and compare it to how much time I had left, and I could make intelligent decisions about feature cuts and what had to be there no matter what.

    I credit Hybrid Mind’s Ludum Dare #29 timelapse for In the Black for showing me how effective a design document can be for even a short 48-hour project. Thanks, Dave!

  2. A Game’s Economy Can Have a Big Impact on the Game’s Appeal

    I was glad I decided to risk adding more to the economy of the game. Evil Energy and Prayer Energy play off each other in an intuitive way, which makes the game more compelling.

    I think people kept playing because throughout the game there was always something to aim for. Converting a follower resulted in an upgrade being made available, which required Prayer Energy to attain, which in turn allowed more followers to be converted more easily, all with the aim of using ESCAPE to end the game.

    I could have had a simpler economy. If I eliminated Prayer Energy and made things more directly available, it could have worked, but it might have felt too simplistic.

    What I’m not happy about is that the richer economy hides a lack of challenge. I don’t want to use economic designs to act as a bandage on a fundamentally broken game.

    But I did learn that doing a decent job designing an economy can result in a great return on investment.

  3. Keep Your Nose to the Grindstone

    During the 48 hours of Ludum Dare #33, I slept, I ate, I showered, I talked with my wife, and I blogged.

    But most of my time during the 48 hours was spent on design and implementation.

    According to my records, I did a little over 24 hours of game development between Friday and Sunday. Just over half of the time spent on the compo was spent doing actual game development, and I’m pretty sure that because I lived and breathed this project, I was even making progress while showering or eating.

    Even with the failings I mentioned, I can see that this laser focus was the real reason why I was able to get a decent game finished.

    I’ve done compos in which I was distracted, and they didn’t always end well. Either I was dealing with poor health, in which I couldn’t sit at my desk for long periods of time, or I was going to a party or a soccer match.

    For this Ludum Dare, I made sure that I was 100% focused on the compo with no outside commitments to keep me from doing anything but game development that weekend.

    It was grueling and exhausting, but that concentrated effort made things move along so much more quickly than if I had spread out the development effort with frequent and potentially long breaks.

    I’m not saying breaks are bad. I took breaks.

    I am merely saying that my mind was focused on game development and not on how to interact with other human beings in a social situation or how frustrating it is when your team is losing due to the same blunders they always make.

    I rested when I needed to rest, but I didn’t allow myself to procrastinate or do much of anything other than participate in this compo.

Summary

The results of this compo were very encouraging to me:

LD33 My Results

Out of 1,199 entries, my game was rated in the top 36% overall and top 8% in innovation. My only rating that was in the bottom half of the group was for graphics, and even then it was at the top of the bottom half. B-)

I credit my ability to focus that weekend on game development almost exclusively, and all of the tools that allowed me to leverage that focus, such as my design document and setting milestones.

The main complaint from players is that there was a lack of music and sound, followed by the noticed lack of challenge. For future compos, I’ll want to focus on not only interactivity but also adding real conflict.

I may want to experiment with adding audio iteratively. Normally I add it at the end, and an informal survey indicated that a lot of other game developers add it at the end as well. I wouldn’t want to spend time on something that might get thrown out before the end.

Still, the idea is that if I can have a playable game early on in a compo, I can also have a playable game with audio early on in a compo, too.

Categories
Politics/Government

Syrian Refugees Are NOT Potentially Poisonous Grapes

In the debate, I often saw an argument along the lines of, “If I gave you 10 grapes and told you two were poisonous, would you eat any?”

It sounds clever. There’s a risk. Most intelligent people would say no, and so the idea is that taking in Syrian refugees when potential terrorists could be hiding among them is akin to consuming grapes when you know they could be poisonous.

This argument is old, as this tweet shows:

Back when the Jews were fleeing the Nazis, nations all around the world denied them access because Nazis might be hiding among them. As a result, many more were killed in the Holocaust that could have been saved.

But what bothers me about the argument is how simplistic it is. It makes it sound like the probability is known, and that the only defense against risk is to avoid it entirely. It also makes the issue about the person being posed the hypothetical and not about who the grapes are.

Saving Syrian refugees isn’t the same as benignly eating a bowl of grapes or M&Ms and “knowing” some are poisonous.

It’s like knowing that there are people in a burning building and questioning whether or not to bother trying to get them out on the chance that some of them are arsonists.

“If there were 10 people in a building, and I told you two were arsonists, would you rescue any?” is about how the grape analogy sounds. Now suddenly we KNOW that there are arsonists among them. We even have a specific number, which makes this choice seem like a balance of odds.

And yet, despite knowing we could always find non-poisonous grapes or even some other food, allowing us to pass on this specific bunch of grapes, we still feel like the non-arsonists deserve to be saved from that building, right? I hope?

Syrian refugees are people fleeing a real danger. We have an opportunity to do the right thing and save them from the people we are supposedly afraid they are.

We lock our doors to protect the people inside, but I would question what kind of person you are to leave outside someone who is literally begging for his/her life.

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.