A Mind for Madness

Musings on art, philosophy, mathematics, and physics


Leave a comment

Should Roguelikes be Winnable?

A topic that I’ve been thinking about recently has to do with balancing roguelikes. If you haven’t heard the term balance before, it basically refers to making a game fair through adjusting values: enemy health, enemy strength, items you find, your health, your strength, and so on.

For a normal RPG, you balance a game so that a skilled player can win and so nothing feels unfair. An example of something an RPG fan might find unfair is an “out of depth” enemy that instantly and unavoidably kills you (this happens in many roguelikes).

Many developers and players think this is bad game design because the player couldn’t do anything about it. Why bother getting good at a game if you will just lose to unpredictable circumstances? The game cheated you somehow, and many players quit various roguelikes before getting better for exactly this reason.

This post isn’t so much on actual balance as it is on two distinct philosophies on the winnability of a roguelike. This is a design choice that must be thought about carefully in roguelike design, and it doesn’t even come up for other types of games.

The question: Should a skilled player be able to win?

Most modern game designers would laugh at this question. Their games are designed so that you don’t even need skill to win. Winning is the default position. Your hand will be held through the process. Checkpoints are made every step of the way so you can try something again if you mess it up.

This might be surprising to people not immersed in the genre, but many classic roguelike games have a steep enough skill hurdle that probably less than 10% who ever play will get a win (maybe even as low as 1%). Sometimes it can take years of playing a game to get good enough at it to win. But the game is balanced such that a really skilled player can win almost every time.

Think about that for a second. This is quite a feat. Here’s an analogy which isn’t perfect: think about running a 5 minute mile. Almost no runner (even ones that train very, very hard) achieves this. But once they do, they can reproduce it many times. This is what makes roguelikes great. The focus is on player skill and progression not on character progression. You get a sense of real accomplishment.

After I wrote this post, I did a search for the topic and found it discussed at the Brogue forums. It seems there isn’t an easy way to even define “winnable.” I’ll give you my definition in a bit, but I want to dispel the obvious one as not being a good one.

We already have to distinguish between the game being winnable and the winnability of a given seed (industry term for a particular playthrough). This is only weird for roguelikes, because the game is different every time you play.

One might try to define a game as winnable if approximately 100% of the seeds can be won with “perfect play.” But using perfect play is problematic in a roguelike because of the randomness. Perfect play means you play in a way that perfectly maximizes your chance of winning.

It isn’t hard to think of situations in which sub-optimal play will randomly luck into a win and optimal play loses the seed (e.g. you need magic reflection, so you check Sokoban, but encounter an enemy with a wand of death that kills you, but the unskilled player doesn’t check Sokoban and goes on to win).

This is kind of funny, because now we have a problem with defining winnable even for a seed. Should it mean: someone somewhere won the seed? This, too, seems problematic. I’ll try to explain why from the commentary at the Brogue forum discussion. One person claimed that at least 80% of Brogue seeds are winnable based on the fact that people got wins on around 80 of the last 100 weekend challenge competitions (not the same person).

Let’s digress to make the problem with the above analysis clear. Suppose we make a game. Flip a coin. If it is heads you win and tails you lose. Under the perfect play definition, the game is not winnable. In other words, perfect play does not guarantee a win. Under the definition that some person somewhere was able to win, it is winnable.

Here’s where things get interesting. If we think about what percentage of seeds can be won, we better find out that the answer is 50%, because this is our expected percentage of games a player that plays perfectly would win. But in the above Brogue analysis, the commenter takes a pool of players and asks if any of them has won. This should greatly inflate the win percentage, because it is like taking 5 coins and flipping them all at the same time and seeing if any were wins.

To get around this subtlety, I’ll call a game winnable if a single skilled player can get a win streak of say 10 or so. A good example of this is NetHack. The vast majority of people who play will never get a win ever. But Adeon has a win streak of 29, and many people have streaks of 10. This proves that it is a game that can be won basically every time (and many consider it so easy they self-impose crazy challenges and still win).

Other famous roguelikes that have this same philosophy are Tales of Maj’Eyal (on normal/adventure at least) or from the “roguelite” genre The Binding of Isaac (where people have 150+ win streaks).

At this point you’re probably thinking, what other philosophy could there be? No one could possibly want to play a game for which you work really hard for 1,000 hours learning to make all the best moves, and yet the design will still have you lose to random impossible scenarios. It wouldn’t be fun. It would be pure frustration.

But people do this all the time in other types of games. The best example I can think of is poker. It takes a huge number of hours of training to become good enough to make roughly the best plays. You can be the best in the world and still lose due to the inherent randomness. You can only see how good someone is through long-term averages.

One way to think of this philosophy is: losing is fun, winning is more fun, winning every time is too easy and boring. Traditional roguelikes are fun, because you get in seemingly impossible situations but with enough skill you can think your way out. You can have a lot of confidence that you will basically never be randomly put in an impossible situation. Losing is your own fault, and you can get better from it.

If you take this alternate philosophy, the fun comes from the fact that you don’t know if a given situation is impossible. Maybe you just weren’t good enough. Balancing so that there are impossible situations makes it so that the top of the skill curve can still feel challenged.

I think the biggest difficulty with balancing in this manner is that a highly skilled player may never reach a 10 streak, but they should probably still be able to win something like 6 or 7 of those 10 games. This would be a very difficult balance to achieve. It is much easier to make it winnable.

Roguelikes already have a very small market. Part of what keeps people interested is that when they lose, it is their own fault. They don’t feel cheated. A game that was upfront about containing a large number of impossible seeds would probably narrow the market even more. One way to mitigate the pain would be for the game to keep track of your monthly win percent. That way you can track your progress.

I haven’t heard of this before. I’d be curious if anyone knows of any roguelikes that fit this design philosophy. The two that come to mind are Sword of the Stars: The Pit and Brogue. Both feel like you can just not find the items necessary to get a run off the ground. But I’m not very good at either, so it could be player error. There are people with about 2500 hours of play in The Pit, so I’d be curious to see if they could get a 5 streak on Normal mode (most refuse to play that difficulty since they’ve won on much harder).


1 Comment

On Politically Correct Art Criticism

WARNING: This post will contain spoilers for many, many things.

I know this is a controversial topic, and I periodically keep coming back to it. But I can only read so many reviews that make these types of arguments before needing to say something myself. The main thesis of this post is that it is never a valid form of art criticism to say: this work is bad, because people with trait X ought not be portrayed doing Y.

Before going any further, I’d like to make the argument to show I understand the point of view I’m criticizing. Suppose Group X (women, blacks, gays, mentally ill, etc) has a negative stigma attached to it that manifests in real world discrimination. The claim is that making media that reinforces this incorrect stereotype causes measurable harm to society by perpetuating this discrimination indirectly. It also harms people in this group (particularly children) by not giving good role models to show the stereotype is not true.

I’ll even grant most of this argument by giving an anecdote from my own life. When I was growing up, I experienced a lot of frustration trying to find a positive portrayal of gay people in media. They either ended up dead from AIDS (Philadelphia, Longtime Companion, Love! Valour! Compassion!, Jeffrey), dead from gay bashing or suicide from bullying (Boys Don’t Cry, The Laramie Project, Brokeback Mountain, Defying Gravity, Bent), were pedophiles or molested as children (Mysterious Skin, L.I.E., Bad Education). It seemed the only option to live a life where something terrible wasn’t happening to you was to live a lie (Maurice, Far From Heaven, De-Lovely).

So believe me when I say I get that this style of criticism is coming from a good place. Here’s some examples of articles that use this argument from the recent past (I’ve read more, but didn’t save them anywhere). Avengers: Age of Ultron is bad because instead of having Black Widow killing men all the time, she also has a subplot of flirtation and romantic interests and concerns over her infertility. This pegs the whole movie into problematic territory, since group X (women) ought not be portrayed as caring about thing Y (men or having babies? more on this confusion later).

A recent, highly creative and interesting game Her Story was recently criticized for, can you guess? You’re wrong, because it has nothing to do with women! The game dared to allude to the main character having dissociative identity disorder (though many people believe she does not). The main character also committed a murder. Thus, it is clearly flawed because we ought not portray group X (mental disorder) doing thing Y (committing crimes).

And on it goes. Do you see the pattern? Let’s start with my opinion on the matter before breaking it down and giving better ways to go about this sort of thing. There is a divide between mass media and art. In the age of the internet, this divide is almost impossible to find. I think the argument for this type of criticism almost works for mass media. It fails miserably for art.

Art is art. No matter how good your motives, it is never, ever valid criticism to deride art because the artistic content has material you disagree with. To make that criticism is to say that certain topics are off limits for artists: a character with trait X can’t do thing Y. What if the character must do that thing in order for the art to be the best it can be?

It is hard to articulate exactly why this is not a valid form of criticism. The best way to invalidate it is to try to come up with any sort of plot where this type of criticism cannot be leveled against it. You can’t do it. You almost can by trying to make it have absolutely no conflict or drama. But as soon as any reasonably fleshed out character has any sort of conflict, you will be able to find a criticism of the above form. We’ll come back to this double standard with the Avengers example later.

Many people have embarrassed themselves by trying this exercise. The most prominent being Anita Sarkeesian who makes her living off criticizing video games from a feminist perspective. She sketched a game idea that she thought would be free from sexist tropes, but as soon as it appeared, people were able to throw her own tropes right back at her. It is easy to criticize, but to create something free from this form of criticism is impossible. That is why it is not valid. If it applies to everything, it applies to nothing.

The other reason is that these criticisms are nothing more than saying the work is not politically correct. When phrased this way I think everyone can agree it is poor criticism. An artist’s work is bad because it is not politically correct? When we see something like this, we should laugh at how lazy and dishonest this type of criticism is.

So where does this leave us? I think there is a valid way to raise these same issues. A valid form of criticism is to point out cliche and lazy uses of tropes. Doing this requires effort and justification. For example, in Her Story, if you try to phrase the criticism in these terms, it falls away as baseless. The use of dissociative identity disorder is done in an original way. In games, it is not a trope that mentally ill people are criminals. Such a subtle use of the disorder to create depth and thought-provoking moments is wholly original in games (and also it isn’t even clear the main character has the disorder!).

The Avengers example is a little more tricky. I alluded to a difference between mass media and art earlier, and something that grosses half a billion dollars enters the public consciousness in a way that an indie game does not. Maybe there is some ethical responsibility there. But I think this becomes much easier when we remind ourselves it is a superhero movie. The new Avengers movie could possibly be the least believable movie I’ve ever seen. It is hard to go a whole minute without thinking, wow, that is fake.

As I’ve pointed out, part of these types of arguments hinge on the idea that people will think the trope is real which will reinforce a harmful stereotype. Forgive me for not being able to put a kid who watches a teenager get beat up and tied to a fence to die because of who he is attracted to and thinks, “That could be me,” on the same footing as world where a human turns into a giant green killing machine and Thor exists. In other words, context matters.

But let’s get back on track. My main objection above is that this style of argument never ends. What could have been done differently? If Black Widow has children and a family, the complaint will be that the male superheros don’t have to split their time (though Hawkeye does!). This reinforces the idea that women can’t have it all but men can (or something? why has taking care of a family taken on such a negative stigma again?). But then if she doesn’t have children this reinforces the negative stereotype that if a woman has a career she won’t be able to have a family even if she wants one. Do you see how once you let this style of argument in, it never ends. It is lose-lose for the artist. The critic can complain no matter what choice is made.

If you want a real critique of Avengers you need only point to the cringeworthy damsel in distress trope that occurs 3/4 of the way through when Black Widow is the one captured and needs to be rescued. But for some reason, people focused on her romantic interests…

Anyway, I’m sick of reading these critiques that take this form. They had a bit more validity in the past when it was harder to find positive portrayals of certain groups of people. With our current technology of Hulu, Youtube, Netflix, Amazon, and on and on, it is just as easy to find the blockbuster as the indie film. Mass media doesn’t drown out diversity in the same way it used to. So let’s move on from this lazy, invalid form of art criticism to something more substantial.


Leave a comment

Basic Game Programming Part 3

Here’s an experiment to try purely in C++ (or the language of your choice). Print any character you want on a blank terminal screen at a specific location (say 10 characters over and on the 4th line). This is a crucial idea in game programming, because even something as simple as using the arrow keys to move something around a screen requires you to do this.

You’ll find it gets tedious quickly. Let me guess what you came up with. You have two auxiliary functions. One of them prints “\n” an appropriate number of times to move you to the correct line. The other prints a bunch of ” ” to move you over. It works.

Now suppose you want more information on the screen like health remaining or an inventory list. You can’t use that method anymore, because it depends on where the cursor ended during the last thing you drew. This, in turn, depends on information that could be changing (Health: 9 vs Health: 10 places the cursor one more space over).

Matters get even worse if you want to draw something on the right edge of the screen, because you have no idea what the player is looking at. One could use a standard terminal size, another could have maximized it to fullscreen. This changes the number of spaces on a line.

Until you actually try to do these things, or at least seriously attempt a thought-experiment doing it, you will never appreciate why adding an external library to handle this stuff is important. There are tons of these in existence, but probably the most common and universal ones are built from SDL (we will definitely not get into that today).

The simplest for C++ is probably ncurses. It stands for “new curses” and has a pretty interesting history (the name implies there was a curses). It effectively emulates a terminal, which sounds ridiculous at first (why not just use the terminal!) until you think through all the problems above. Today, we’ll make an “@” symbol move around the screen using the arrow keys.

For our purposes, the two most useful functions in the library will be clear() and mvaddch(). As we saw last time, clear() was annoying because it was OS and terminal dependent. Since ncurses emulates a terminal, there is one function that clears the screen independent of OS. The function mvaddch takes 3 arguments, the first two are ints and give the y-coordinate and x-coordinate where you want to place a character, and the third argument is a character that gets placed in that location.

Even though I want to think in terms of x and y coordinates, mvaddch actually takes the row then the column number. This means you put in y first and x second and the y-coordinate counts down from the top of the screen which can be confusing to new users of ncurses.

At this point, we understand the structure of the game loop, so you should basically be able to fill in the rest of the program. There are quite a few subtleties, though, so I’ll go slowly through it.

The only variables I need this time are the x-coordinate and y-coordinate, so I’ll make these global. I started it at (5,5) randomly. We get input using getch(). This returns an integer, but we don’t need to worry about what that integer is. Since we are using the arrow keys we can use KEY_UP, KEY_DOWN, etc which are integers corresponding to the correct arrow directions. Also, using integers is nice rather than characters, because in C++ we can more cleanly write a bunch of “else if” statements with a “switch.”

This lets us make the whole Update() function by changing the x and y coordinates depending on which arrow direction was pressed.

void Update() {
	switch(userInput) {
		case KEY_LEFT:
			XPOS = XPOS - 1;
			break;
		case KEY_RIGHT:
			XPOS = XPOS + 1;
			break;
		case KEY_UP:
			YPOS = YPOS - 1;
			break;
		case KEY_DOWN:
			YPOS = YPOS + 1;
			break;
	}
}

As before, our draw function clears the whole screen and then draws everything. Because of how ncurses works, nothing will be drawn to the terminal until refresh() is called. This is basically so you can store a whole bunch information about what is going to be displayed, and then it can work out how to display it separately:

void Draw() {
	clear();
	mvaddch(YPOS, XPOS, PLAYER);
	refresh();
}

The only thing left is to initialize a bunch of stuff, but the content of the program is really that simple. I commented the initialization lines so you can see what they do, but for the most part, you’ll just copy and paste that whole chunk in every use of ncurses.

#include <ncurses.h>

int XPOS = 5;
int YPOS = 5;
char PLAYER = '@';
int userInput;

void Update() {
	switch(userInput) {
		case KEY_LEFT:
			XPOS = XPOS - 1;
			break;
		case KEY_RIGHT:
			XPOS = XPOS + 1;
			break;
		case KEY_UP:
			YPOS = YPOS - 1;
			break;
		case KEY_DOWN:
			YPOS = YPOS + 1;
			break;
	}
}

void Draw() {
	clear();
	mvaddch(YPOS, XPOS, PLAYER);
	refresh();
}

int main() {

	//Initialize ncurses

	initscr(); //Tells it to make a terminal screen.
  	clear();   //Clears the screen.
  	noecho();  //When user types input, it doesn't appear on the screen.
  	cbreak();  //Typed character is immediately available.
  	keypad(stdscr, TRUE);  //Standard screen.
  	curs_set(0);  //Starts the cursor at (0,0).
  	mvaddch(YPOS, XPOS, PLAYER); //Draw '@' in the initial location.
  	refresh();  //Updates the screen to display the '@'.

	while(true) {

		//Input()
		userInput = getch();

		Update();
		Draw();

		if (userInput == 'q') {
			break;
		}
	}

	endwin();  //Closes the terminal screen.

	return 0;
}

This will probably be the last post in this series. I have one more topic I could do (decoupling the draw loop from the game logic loop). For the most part, you should now be in a position to look up tutorials on using fancier stuff like Unity or Monogame.

The problem I found with those tutorials is that they focus solely on how to use their engine and not on what these underlying components of the engine are (and why they exist). Hopefully after these posts, these concepts make more sense allowing you to more easily jump in.

(For the record, these posts keep getting the C# tag even though I type C++. It autocorrects it upon hitting the publish button.)


Leave a comment

Basic Game Programming Part 2

So here’s a video of the finished product for today. If you haven’t read the last post, you should do that and try the exercises. Better yet, watch the finished product and try to create it without reading the excercises:

We’ll go through all the changes I made, but we’ll start with the most important one. Last week I gave the suggestion “Feature 6: Figure out where to clear the screen to not be so cluttered.” This is a crucial concept in drawing the graphics when making a game.

This toy example gives us the fundamental idea, but if you actually try it in C++, you’ll find it somewhat difficult. I used Linux, so I could use system(“clear”) to clear the terminal screen. You’ll need different commands depending on the operating system. Fighting with drawing things in the proper place will give you a huge appreciation for tools that aid in doing this (we’ll talk about one next week called “ncurses”).

If you watch the video, I programmed it to give the illusion that certain things were static on the screen and don’t get redrawn. In reality, on every iteration of the game loop, I cleared the entire screen and redrew the whole screen with the updated information. This makes it look like “Your Health:” stays the same while the number clicks down as you lose health.

You obviously don’t have to do it this way, but experience has taught me you can get some nasty display bugs if you don’t fully clear and redraw. As I said before, this merely amounted to adding a simple system(“clear”) at the beginning of the Draw() function. I also added a few lines of information.

void Draw() {
  system("clear");
  cout << "Your Health: " << PLYRHLTH << "\n";
  cout << "Enemy Health: " << ENMYHLTH << "\n";
  cout << "a. Attack \n";
  cout << "b. Run \n";
  cout << PLYRDMG;
  cout << ENMYDMG;
}

The other major change was to rescope the variables (you might have noticed they changed names and are all caps, my convention for global variables). Since I wanted many of the functions to be able to access and change the PlayerHealth, EnemyHealth, and so on, I made them all global. This also cleaned up having to pass all of them to each function and allowed me to refactor Update() into its own function.

At the top of the program I list them and initialize them. PLYRDMG is the message “You hit for 2 damage” and so on (see Draw() and compare to the video). It is initialized to be blank so everything writes in the same place:

int PLYRHLTH = 10;
int ENMYHLTH = 10;
string PLYRDMG = "\n";
string ENMYDMG = "\n";

The only thing that changed in the Update() function is an added if statement in a few places so that half the time you miss and half the time the enemy misses. I also had to come up with a way tell the game loop whether the player chose to “Run” and exit the game. This was easy before, because we could write if (PlayerInput == “b”) { break; } to break out of the game loop.

Now the function isn’t in the game loop, so calling “break;” doesn’t work. The way around this was something people came up with in Operating Systems programming a long time ago. I made Update() return an integer rather than be a void. This way I could always return 0 if the player wanted it to keep going. Otherwise it returns 1 and I know they want to break out of the game. This why in C and C++ main() is an int rather than a void. Returning 0 tells the OS that everything went well in the execution of the program.

int Update(string playerinput) {
  if (playerinput == "a") {
    if (rand() % 2 == 0) {
      int r1 = rand() % 4;
      ENMYHLTH -= r1;
      stringstream ss;
      ss << "You hit for " << r1 << " damage.\n";
      PLYRDMG = ss.str();
    } else {
      PLYRDMG = "You miss.\n";
    }
  }

  else if (playerinput == "b") {
    return 1;
  }

  else {
    PLYRDMG = "This is not a valid option.\n";
  }

  //Enemy attacks.
  if (rand() %2 == 0) {
    int r2 = rand() % 4;
    PLYRHLTH -= r2;
    stringstream ss;
    ss << "Enemy hits for " << r2 << " damage.\n";
    ENMYDMG = ss.str();
  } else {
    ENMYDMG = "Enemy Misses!\n";
  }

  return 0;
}

Lastly, I added a “Start Screen” to get into the game. I return to this when the game ends and ask if the player wants to play again. This was done simply by putting the whole game in a second while loop. As long as the player keeps entering “y” for “do you want to play” I keep the boolean variable WantToPlay = true. Otherwise I switch it to false and the game ends. This is also something a prebuilt engine will do for you in a much more elegant way.

Here’s the whole thing:

#include <iostream>
#include <sstream>
#include <stdlib.h>

using namespace std;

int PLYRHLTH = 10;
int ENMYHLTH = 10;
string PLYRDMG = "\n";
string ENMYDMG = "\n";

void ResetVariables() {
  PLYRHLTH = 10;
  ENMYHLTH = 10;
  PLYRDMG = "\n";
  ENMYDMG = "\n";
}

void Draw() {
  system("clear");
  cout << "Your Health: " << PLYRHLTH << "\n";
  cout << "Enemy Health: " << ENMYHLTH << "\n";
  cout << "a. Attack \n";
  cout << "b. Run \n";
  cout << PLYRDMG;
  cout << ENMYDMG;
}

string Input() {
  string tmp;
  cin >> tmp;
  return tmp;
}

int Update(string playerinput) {
  if (playerinput == "a") {
    if (rand() % 2 == 0) {
      int r1 = rand() % 4;
      ENMYHLTH -= r1;
      stringstream ss;
      ss << "You hit for " << r1 << " damage.\n";
      PLYRDMG = ss.str();
    } else {
      PLYRDMG = "You miss.\n";
    }
  }

  else if (playerinput == "b") {
    return 1;
  }

  else {
    PLYRDMG = "This is not a valid option.\n";
  }

  //Enemy attacks.
  if (rand() %2 == 0) {
    int r2 = rand() % 4;
    PLYRHLTH -= r2;
    stringstream ss;
    ss << "Enemy hits for " << r2 << " damage.\n";
    ENMYDMG = ss.str();
  } else {
    ENMYDMG = "Enemy Misses!\n";
  }

  return 0;
}

int main() {
  int State;
  string PlayerInput;
  bool WantToPlay = true;

  while(WantToPlay) {

    //Reset the Initial Information
    ResetVariables();
    srand(time(NULL));
    system("clear");
    cout << "An enemy approaches. Do you fight (y/n)?\n";
    PlayerInput = Input();
    if (PlayerInput == "n") {
      WantToPlay = false;
    }
    Draw();

    //Game Loop
    while(true) {

      PlayerInput = Input();
      State = Update(PlayerInput);

      if (State == 1)
        break;

      //Break out of the game looop if won or lost.
      if (ENMYHLTH <= 0) {
        system("clear");
        cout << "You Win.\n";
        break;
      }
      else if (PLYRHLTH <= 0) {
        system("clear");
        cout << "You Lose.\n";
        break;
      }

      Draw();
    }

    cout << "Game Over.\n";
    cout << "Want to play again (y/n)?\n";
    PlayerInput = Input();
    if (PlayerInput == "n") {
      WantToPlay = false;
    }
  }

  return 0;
}

Next time we’ll work on improving the graphics by using outside tools and getting something moving around the screen so it feels more game-like.


1 Comment

Basic Game Programming Part 1

A lot of people think the best way to get young people into programming is through making games. I agree. Unfortunately, it is kind of hard to find the basics, so I want to do a series on it (Pygame is your best bet for a tutorial, but I’ve personally had bad experiences with it). This is definitely not meant to be some comprehensive tutorial. It is only meant to introduce some basic ideas.

There’s a lot of tools out there to make this easy (RPG Maker comes to mind). These tools allow you to make a fairly complicated and polished game without having any idea about how it is coded. Drag and drop images on a screen, and voila, a game is born. This defeats the whole point!

Other tools like game engines (Pygame, Unreal Engine, Unity, Monogame, Cocos, etc) are important to not have to deal with complicated graphics rendering or other hassles. These should be used in real life. For the purpose of this series, we will look at rudimentary simplifications of some of the things going on underneath these engines.

I will not assume you are comfortable with programming, but I also won’t explain the code much. I’ll assume you can look at the code and are able to figure out with some prompting what it does. The most important part of learning to program is learning the ability to look things up.

I’m going to use C++ even though I know most people learn Python or Java these days as their first language. But if you want to write cross-platform games, you’ll want to use C++ (Cocos) or C# (Unity and Monogame) or whatever Unreal uses. If you want a refresher, this game will only use cin, cout, variables, if/else. This should take less than 2 hours to learn from a reasonable tutorial.

If you have a little programming experience, there is a fundamental concept you’ll have to get used to called the game loop. It essentially looks like this:

while(true) {
    //Insert entire game here.
}

The game will infinitely loop through the instructions. For most simple games, this is overkill and uses a ton of unnecessary processing power. Also, without a professional game engine underneath, you don’t have a way to limit the speed at which it loops (30 times per second or 60 times per second). Don’t worry about any of this. Just know that you will eventually want this constant loop, so it is good to get used to it.

Let’s add a touch more detail now. The game loop roughly consists of three parts: Getting input from the player, Updating the game state based on that input, and Drawing to the screen whatever has changed from the update step. This is called the engine, because it keeps churning and puts the game in motion. If you use Unity or some pre-built engine, each of these parts will exist already (and will loop independently in parallel, but that is for another time).

Our game now looks like this:

while(true) {
   GetInput();
   Update();
   Draw();
}

Again, this is needlessly complicated for the game we will make, but it is worth getting used to this flow with something basic so you aren’t learning a whole new framework with something more complicated.

Now let’s describe the game. The game will display your health and the enemy’s health. The player will have 2 choices: Attack or Run. If you attack, you hit the enemy, in which case the enemy’s health decreases by some amount (we’ll make it random between 0 and 3). If you run, you leave the game (effectively a “quit” choice). The enemy always hits you.

If the enemy’s health reaches 0, the player wins. If the player’s health reaches 0, the player loses.

A part of the engine I didn’t describe is the initialization that come before entering the game loop. In this case, we might want to describe the setup and get the initial variables set up and call the Draw() function to get something on the screen.

There will be 2 variables: PlayerHealth and EnemyHealth. Let’s set them both to 10 to start. At this point I think we can write the first form of the Draw() function, which right now will just print out and label these variables and give the two options for action. Eventually, we’ll probably want to say who got hit, too.

void Draw(int playerhealth, int enemyhealth) {
  cout << "Your Health: " << playerhealth << "\n";
  cout << "Enemy Health: " << enemyhealth << "\n";
  cout << "a. Attack \n";
  cout << "b. Run \n";
}

This might look a bit confusing, but “cout” just means “print to the screen.” So each line of that is printing “Your Health: 10″ (and the \n means “new line”).

Now let’s get the input. We’ll do something a little bad, but we’re just trying to get the flow down here. We’ll worry about “good coding practices” some other time. Let’s make the function Input() return the string the user inputs, so we can store it rather than modifying some global variable.

string Input() {
  string tmp;
  cin >> tmp;
  return tmp;
}

Again, “cin” just asks for the player input. The input is stored in the variable “tmp” and then gets returned.

The most complicated part of this is going to be the Update() function, but it isn’t so bad. Update() needs to say: if the player typed “a” we subtract the attack amount from EnemyHealth. If the player typed “b” we exit the loop. If anything else was typed, we don’t do anything and notify them it is not an option.

if (PlayerInput == "a") {
      int r1 = rand() % 4;
      EnemyHealth -= r1;
    }
    else if (PlayerInput == "b") {
      break;
    }
    else {
      cout << "This is not a valid option.\n";
    }

I used here a random number between 0 and 3 (inclusive) for how much damage the attack does. (Look up rand() for how it works. It is part of the standard library.) There isn’t much left, so I’ll give the whole thing now with some comments:

#include <iostream>
#include <stdlib.h>

using namespace std;

void Draw(int playerhealth, int enemyhealth) {
  cout << "Your Health: " << playerhealth << "\n";
  cout << "Enemy Health: " << enemyhealth << "\n";
  cout << "a. Attack \n";
  cout << "b. Run \n";
}

string Input() {
  string tmp;
  cin >> tmp;
  return tmp;
}

int main() {
  //Initialize the variables
  int PlayerHealth = 10;
  int EnemyHealth = 10;
  string PlayerInput;

  //Initial Information Drawn
  cout << "An enemy approaches... \n";
  Draw(PlayerHealth, EnemyHealth);

  //Game Loop
  while(true) {
    PlayerInput = Input();

    //Update Information based on input.
    if (PlayerInput == "a") {
      int r1 = rand() % 4;
      EnemyHealth -= r1;
    }
    else if (PlayerInput == "b") {
      break;
    }
    else {
      cout << "This is not a valid option.\n";
    }

    //Enemy attacks.
    int r2 = rand() % 4;
    PlayerHealth -= r2;

    //Break out of the game looop if won or lost.
    if (EnemyHealth <= 0) {
      cout << "You Win.\n";
      break;
    }
    else if (PlayerHealth <= 0) {
      cout << "You Lose.\n";
      break;
    }

    //Print out the Updated Info
    Draw(PlayerHealth, EnemyHealth);
  }

  cout << "Game Over.\n";

  return 0;
}

Here’s some features to add as homework. Now that the core is there, if you think of one thing and add it each day (15 minutes tops?), in 2 weeks you’ll have a pretty interesting and complicated text-based game. They don’t have to be these or even in this order. These are what popped into my head.

Excercise 0: Try cleaning up the current code so that Update() is its own function like Input() and Draw(). Don’t try too hard, because it is more complicated than it’s worth. You will encounter your first struggle with how to scope variables that all your functions want to know about. Also, breaking out of the while loop will become tricky.

Feature 1: Look up how to do random numbers. Make it so that you only hit the enemy 50% (or whatever you want) of the time. Make it so the enemy only hits you sometimes. This might be a 2 day feature if you are totally new to programming in C++.

Feature 2: Tell the Player that they hit the enemy and how much damage they did.

Feature 3: Make a “Title Screen” that tells you the game you are about to play.

Feature 4: Add some backstory to the introductory text.

Feature 5: Add more options for player input (different types of attacks that do different damage amounts).

Feature 6: Figure out where to clear the screen to not be so cluttered.

Feature 7: Ask if the player wants to play again rather than automatically closing the program when it is over.

That’s a whole week’s worth of exercises, and you’ll have a basic working game at the end. Next week, I’ll go through implementing these changes and maybe make a quick video to show that end result can look like a real-life, old-school text game.


Leave a comment

Best Books Halfway Through 2015

It’s halfway through the year, so it’s time to update you on the best stuff I’ve been reading. This year I’m doing the Goodreads reading challenge and trying to read 50 books. I’m on pace so far, but there’s a lot of time to mess it up. As usual, this is not a “best books that came out in 2015″ list (I’ve only read four or so books from this year). This is a list of the best books I’ve read this year.

In no particular order:

Philip Roth’s American Pastoral. You can see some thoughts I had on it back here.

Dan Simmon’s Hyperion and The Fall of Hyperion.

Hyperion cannot easily be described. It pulls together several sci-fi elements that made me skeptical at first. Anything that deals with time manipulation, particularly time moving backwards, usually makes me groan. This cleverly makes it work.

The mystery is brought up early, and the narration is done through a sequence of stories. Each story hints at different pieces, but are wildly different in tone, style, time frame, and reference point. Each story is excellent in its own right. Together they form a beautiful non-traditional narrative.

Simmons is not only a master at suspense and mystery, but proves he can create a timeless work of art that still feels fresh and original 25 years later.

I was a little concerned when The Fall of Hyperion felt so different. Simmons is amazing with non-traditional point-of-view. He seamlessly works in a way to have both first person and third person (the first person character dreams the story of other characters in third person). It is quite a brilliant trick.

The story is just as gripping and page turning as the first. It gets weirder but in a good way. The sci-fi elements still feel fresh, unlike many novels from 1990. This is turning into one of my favorite sci-fi series, though I’m definitely concerned about continuing. This second book has a clear ending.

Ethan Canin’s Carry Me Across the Water.

This novel has exquisite pacing. It is very short, but spans three generations and never feels too quick. Each of the threads builds into a tragic, inevitable ending. The built suspense is perfectly executed.

I had serious doubts at first that this could work, because I spent the first third grappling with who was who and how they were related. It is a lot to take in, but by the half-way point, I wouldn’t have wanted it any other way.

I liked For Kings and Planets, because it asked the big questions. It showed how others dealt with those questions and the consequences of being flawed in answering them. This was the opposite. I liked it because each character had something familiar, but the novel as a whole remained focused on specific, non-universal questions worth pondering. This is a beautifully written and compelling story.

Ann-Marie MacDonald’s Adult Onset.

Adult Onset is a modern return to a novel form that has been relegated to history: the character study. You’ll find reviews that complain about “too much detail” or “nothing happens” or “slow” or other such nonsense.

This is a result of the age we live in. Everyone wants instant gratification. The plot has to move at this pace, in this way, with cliffhangers here and here, with a perfect Freytag pyramid structure, and on and on just so the reader can coast along with minimal effort.

Sorry to disappoint, but this book causes you frustration for a reason. It is an in-depth study of a single character through a few days of her life. Despite the focus, we end up getting a huge backstory masterfully woven into description.

The book stays highly focused on getting to the bottom of a character flaw. We all desperately want neat and tidy explanations for our psychology, yet we rarely get them. It is human nature, and it is explored with touching humanity here.

As outsiders, we want to shout at the character that sometimes life is messy. Stop trying to make it something it isn’t. Yet we can look to our own lives and find ourselves behaving just as the main character. This is the essence of a great character study.

The excessive description people complain about is done for a reason. The main character feels trapped in tedium. The description emulates these emotions by making the reader feel claustrophobic. You can sense every tiny moment of your day fill up with this stuff, and you want to escape to a moment of personal agency.

Welcome to the main character’s life. If you want plot, go read The Da Vinci Code. If you want art, you’ll find it here.

The worst book I’ve read this year has been Nell Zink’s Mislaid. This book is such a strangely overrated novel. We’ve somehow put ourselves in an emperor-has-no-clothes situation. This woman writes novels in a matter of weeks and then goes on to publish without really editing (according to her own interviews).

The effect is bad writing, but it is so different from the excellent, polished writing we are used to that people praise it for its quirkiness. It’s not. It’s just bad, and there aren’t enough people speaking out against this. This has to do with being bad for their careers to go against what many famous people are saying. Or maybe the groupthink is so strong they really believe it is good. Both scenarios represent a failure in the upper echelons of book reviewers.


Leave a comment

Examining Pro’s Prose Part 4

Today we’re going to examine some prose from Nell Zink’s newest novel Mislaid. She came to prominence last year, when her debut novel, The Wallcreeper was championed by the New York Times as a notable book of the year. I wanted to see what all the fuss was about.

Unfortunately, this post is going to be quite harsh. I won’t focus on any single “writing rule,” but instead I’ll go through and point things out that catch my eye. I haven’t finished reading the book yet, but from a prose standpoint, it is pretty terrible. All the examples below occur within the span of a few pages. The examples are far from exhaustive. Almost every sentence breaks a rule.

First, the novel is a collection of sentences that tell you what happened. In my last post, we looked at the various levels of showing a scene, action, or character trait versus telling it. It is difficult to find even one scene in the first half of the book (what I’ve read so far) which shows you anything. Everything is told. Giving examples can’t give you a grasp on how large this problem is, but here’s an attempt.

“Soon the detective, a working-class townsman, sympathized with Peggy.”

First, we’re told he sympathized. Why not show it? Also, “a working-class townsman” adds nothing (and introduces point of view inconsistencies: how does the main character know this?). Extraneous bits like this abound in the novel and are weak attempts to “add detail,” but are without substance.

“Nor would they have found anything anyway. The runaway was keeping a very, very low profile.”

These sentence fragments occur on almost every page. A rule we haven’t talked about yet is: only ignore proper grammar and usage rules if you are going for a special effect. This should be done so sparingly that no one notices (three times over the course of a whole novel maybe?).

The effect is stilted, choppy prose. I can’t find it now, but there is a paragraph where there are more sentence fragments than complete sentences. Another rule is to minimize modifiers. If you have to modify a verb or noun, you probably haven’t put enough work into choosing the right words. Never use the modifier “very.” At least make it interesting if you’re going to break the rule. The use of “very, very” is inexcusable under all circumstances. Also, past progressive tense creeps in here.

I’ll do a whole paragraph now:

Lee looked up and down the street, watching for slight women with brown hair. He watched for women with blond children. He watched for anyone at all. It was a quiet afternoon, paced by the rhythm of traffic lights. He stood up and walked, thinking he might ask after her, if he happened to see her kind of store. He walked the length of town and as far as the railroad tracks. Ice cream, real estate, musical instruments. Porcelain figurines and teacups. He shook his head at his own dumbness, got back in the car, and sat.

He …

First off, avoid repetition. It is hard as heck when writing about one person to not start every sentence with “he,” but with work it can be done. Look at any of the greats we’ve already discussed. They will never have 8 out of 9 sentences start the same way. The sentence fragment thing appears again.

These sentences all tell you what he did but never do we get beyond a superficial level of showing. The longest sentence in the middle breaks the rule of being clear and direct (and is grammatically incorrect). I still don’t get the comma construction in the middle of it. It reads like an appositive, but can’t be, because then the if-clause makes no sense.

To prove it can be done, I’ll “fix” these problems without altering content or breaking with the intended effect of the style. I’ll even remove the “was.”

Lee looked up and down the street, watching for slight women with brown hair. He watched for women with blond children or anyone at all. The rhythm of the traffic lights paced the quiet afternoon. Lee walked the length of town and thought he might ask after her if he happened to see her kind of store. Along the vacant street, ice cream, real estate, musical instruments, and porcelain figurines caught his attention. Lee traveled as far as the railroad tracks before he shook his head at his own dumbness, got back in the car, and sat.

It’s better but not great. I would like for this to expand out into three paragraphs and really pull the reader in. The whole book suffers from this, because I always feel at arms length from the characters. This novel gets praised for making us think about complicated topics like race and sexuality. Since I never get inside the characters’ heads, all I end up thinking about is how unbelievable their actions are.

Another rule we haven’t discussed is point of view (POV). This is more important than most people want to believe. You either write something highly experimental or you stick to one clear POV. If you use third person limited and change POV, it must be clear. The fluid POV in this novel makes many sentences confusing and forces the writer to use even more extraneous phrases.

“Stillwater Lake retreated far from the bamboo grove. It stood in yellowish-gray mud streaked with reddish brown that looked to Lee like diarrhea.”

If it were clear that this is Lee’s POV, the phrase “to Lee” is unnecessary. It is almost always considered a bad writing practice to indicate a simile is a character’s opinion (unless in an open third person omniscient situation, which this isn’t). With clear POV and narrative voice, we understand all sentences to be the character’s opinion. It is redundant to specify. Also, that alliteration (looked to Lee like) is terrible and should be removed. It is interesting that removing “to Lee” fixes both problems at once.

The first sentence has an awkward choice of verb. It isn’t clear to me what exactly happened or what it means without more context (to be fair, more context comes a few paragraphs later). It is true that lakes can “retreat” if there is a drought or something. Is this what happened? Starting the next sentence with “it” is usually seen as a mistake, because the preceding sentence ends with a noun. This makes it unclear whether “it” refers to the subject of the preceding sentence or the ending noun.

Another rule we haven’t discussed is: all dialogue tags should be “said.” Using other words comes across as amateurish, because it is used by people who are not good at writing dialogue to make the dialogue sound more convincing. It is most commonly found in low quality pulp fiction from many decades ago. If you need to use another word, you haven’t voiced the dialogue properly. If you don’t need another word, don’t use one. I’m pretty sure this book must have been professionally edited, so I’m surprised to see the editor let these slide.

“I can spell ‘astronaut,'” Karen volunteered.
“That’s a third-grade word,” the clerk said. “You’re very smart for such a tiny little thing. You sure you don’t want to have her be white?”
“We’re black and proud,” Meg said.
“I’m blond,” Karen objected.
“There’s no blond race,” the clerk corrected her.

As you can see, “the clerk corrected her,” is redundant. Editors often write “RUE” for this type of thing: Resist the Urge to Explain. You don’t have to explain the clerk corrected Karen when we understand from the dialogue this is what she was doing. It isn’t even clear to me that “objected” is the right alternate to “said” in the above. “Said” works much better in that passage. On the next page we get, “Karen repeated solemnly.” Not only do we get an alternate dialogue tag, but it gets modified with an adverb.

I could do this all day, and I truly feel bad about it. I didn’t come to this post with the intention of bashing Zink’s prose. Philip Roth’s American Pastoral is sitting on my desk right now, because I intended to use him. I started Zink’s book and decided the opportunity was too good to pass up. We keep looking at excellent stylists. It is important to see something in comparison.

I know there will be a lot of excuses that sound good. She’s intentionally subverting the oppressive writing rules that stifle creativity to show they aren’t necessary to create a good novel. Or, she used a voice conducive to the satire and wit of the content of her material … or whatever. Let’s face it. She probably thought a lot about the plot, characters, themes, symbols, and so on and never put much thought in to how the prose came across.

This is fine. Some people write excellent prose with no content. We shouldn’t strive for either extreme. I’ll agree that rules are meant to be broken and that focusing too much on them will create mechanical, uninteresting prose. But they exist for a reason and those reasons became apparent when I had trouble reading this novel. Breaking the rules has to be a deliberate choice, and I’m not going to be convinced Zink did this deliberately until I’ve seen that she can follow the rules.

Follow

Get every new post delivered to your Inbox.

Join 255 other followers