What’s up with me?

17 Nov 2010

Hay Internet,

I put down blogging for a while because it became apparent that I had little to say that is relevant outside my circle of friends. Struggling to fill this space, I found myself turning idle musings into statements of belief with conviction for the sake of sounding interesting. The truth is I have hardly any real opinions for which I could muster some conviction, and there are few things I can speak about with authority. I’m getting old now, and I just want to embrace authenticity and drop the know-it-all teenager act.

But, I like to exercise my imagination and writing muscles. The blog maybe isn’t the ideal format for me, but I’ll keep it around while I figure out something better.

I’ve also been busy. For reasons I don’t fully understand, I am on a quest to become really good at making video games, or more broadly, art. I’ve been at it since I was about twelve (before that I wanted to be a paleontologist or a ninja turtle). I’ve always spent most of my free time working towards my career goals. It has been an escape from social anxiety and depression, but it is also gratifying. I am a pretty good video game engineer these days. I have made some cool game demos and major contributions to games. I have worked with teammates I adore and respect. It has been all-consuming, and it has made me a little tired and atrophied parts of me I miss using.

But! I’m only twenty-seven. Many people my age are just finishing school. I am a couple months away from finishing a game on which I am a lead engineer. I am immensely proud of it and the team. It sounds like rhetoric, but it has really made me a better person. I suddenly feel easy-going and optimistic. I’m not sure what I will do next, but it will be fun!

· · · ◊ ◊ ◊ · · ·

Here is the most useful information I know, condensed and explained.

A computer is…

  • Processors – to move and transform information
  • Memory – to store information to be moved or transformed
  • Devices – to pass information in and out (Display, Keyboard, Network Cards, Storage Devices)

How does a computer store information?

  • Memory is a huge line of “bits”
  • Each bit is a tiny device that can hold a high or low electric charge.
  • A bit can represent two possible numbers: zero (low charge) or one (high charge).
  • Two bits can represent four possible numbers (00, 01, 10, 11), three bits have eight possible values, and so on… for N bits there are 2^N possible values.
  • A number value can be represented using any “base”. Base-2, or binary is useful because each digit corresponds to a bit.
  • Base-16, or hexadecimal, is also common because each digit corresponds to four bits (four bits has sixteen possible values).
  • A computer may interpret numbers as characters (see ASCII), display color values, position coordinates, or anything…
  • For signed numbers a bit is reserved for the sign value. For non-integer numbers, bits are divided into sign, base, and exponent (called “Floating-Point”).
  • Modern computers work in groups of 32 or 64 bits, meaning that each variable has a range of 2^32 or 2^64 possible values.
  • Each “byte” or 8-bit chunk of memory has a number identifier or “address”.

How does the processor process?

  • A processor reads a list of instructions (or program) from memory and performs them in order.
  • Most instructions can only operate on a specific kind of memory called the “registers”.
  • There are typically sixteen-ish registers, where each is 32 or 64 bits.
  • An instruction is represented as:
    • A number, or “op code”, that corresponds to an operation
    • A sequence of numbers which correspond to registers, memory addresses, or whatever – their meaning changes by operation.
  • Instructions are often represented as “Assembly Language”. Some typical assembly might look like:

MOV AX, BX

Move – Copy the value stored in register BX to register AX.

ADD AX, BX

Add  – Add the value stored in register BX to the value stored in register AX, and store the result in register AX.

LOAD AX, DX

Load – Copy a value from memory into register AX, where the memory address is stored in registered DX.

JMP DX

Jump – Rather than continue executing instructions normally, execute the instructions starting at the memory address in register DX.

JE AX, BX, DX

Jump If Equal – If the values in registers AX and BX are equal, “Jump” (see above) to the memory address in register DX.

  • Each processor is continuously running a program called the operating system (like Windows or Unix).
  • The operating system loads other programs into memory (from hard drive) and instructs processors to “jump” between them.

How are programs written?

  • Programmers rarely write raw instructions. Rather, they use a “high level” language (like C++ or Java)
  • The text files that contain high level language are called “source code” or source.
  • A program called a “compiler” (like gcc) translates source files into raw instructions (called “binary”).
  • A program called an “environment” (like Visual Studio, Eclipse) is used to edit source files, feed them to the compiler, and report errors.
  • An environment usually has a “debugger” which allows the programmer to pause the program at any time and inspect or change memory.
  • A source file might contain this:

int max(int a, int b)
{
if(a > b)
return a;
else
return b;
}

  • this defines a “function” named max, which might be “called” somewhere else with this line:

x = max(x, 10);

  • Functions operate by using a “stack” – a sequence of memory reserved for storing values in a certain order.
  • In the line above, x is a “variable” – a name for a chunk of memory where data is stored.
  • Let’s say the “type” of x is “int”, so the compiler will read up to 32 bits and interpret them as an integer value.
  • “x = something” means to determine the value of “something” and copy it to x.
  • The function max is resolved by:
    • Copying inputs to the stack (in this case the value of x is the first, and 10 is the second)
    • …as well as the address of the current instruction
    • and then jumping to the first instruction of the sequence named “max”
  • Here is what the instructions of max do:
    • If the value of the first input on the stack (named a) is less than that of the second (named b), then “return” the value of a, otherwise the value of b.
  • When a function “returns” a value, that value is copied to the stack, and the processor jumps back to the instruction that called the function (also remembered on the stack).
  • Back at the calling line, the “x = …” says to copy the output of max from the stack to the memory location named “x”.

What are pointers and references?

  • Whereas most variables are names that correspond to a memory location where a value is stored…
  • Pointers and references are names that correspond to a memory location that stores the address of _another_ memory location.
  • So a pointer is a variable that stores the location of another variable, or “points” to it.
  • Avoid pointers unless you need them (they can be tricky). You’ll find uses for them as you go.

What are structs? classes? objects? templates? inheritance?

  • These are just ways of grouping variables and functions. You’ll figure ‘em out. Use google.

What tools do I need to learn?

  • An environment with a debugger. Visual Studio and Eclipse are good.
  • Source control. I recommend SVN, Perforce, or Mercurial.
  • A good reference manual for whatever technologies you use.

How to make programs go fast?

  • Not all memory is equal. Most instructions can only operate on registers (see above, How does the processor process?)
  • Register memory is very fast, but very small. Values must be swapped in and out as needed from other memory.
  • Cache memory is much bigger, but also slower. When it fills up, it must also be swapped out (google “cache miss”).
  • Main memory is even bigger, and even slower. But it can also fill up, which leads to swapping with the…
  • Hard drive storage is the biggest and slowest of all.
  • A processor spends the majority of its time waiting for memory or storage devices to read or write data.
  • The trick is to compact the most frequently needed data so it can be loaded into the fastest memory and swapped out as rarely as possible.
  • Another trick is to divide up the work for multiple processors to perform in parallel without too much waiting on each other.
  • Some processors have instructions for special purposes (like 3D graphics) which they can perform much faster than a sequence of general purpose instructions.
  • Use a system timer, or a timing program to record how long each section of a program takes to execute, and target the slowest parts or “bottlenecks”.

How to make programs “clean”?

  • Ask yourself, “Will a stranger understand what I’ve written?”
  • Have a plan before you start! If you’re just experimenting, be ready to throw it away and start over. Experiments make for terrible code.
  • Write comments that explain your intention, but don’t describe exactly what you’re doing (the code should do that).
  • Make variable and function names as self explanatory as possible (longer names are okay).
  • Break the work into small tasks and use separate functions, files, and other grouping systems to separate instructions and variables by their purpose (this is called “cohesion”)..
  • Avoid having one “group” of code reference another unless there is a good reason (this is called “loose coupling”)
  • Try to write less whenever possible, don’t duplicate. Re-use code. (this is called “modularity”)
  • Be consistent. (this is called “code convention”)
  • Clean up and rearrange code when it gets too messy (this is called “refactoring”)
  • Have another programmer critique your code (this is called “peer review”).
  • Test! Never assume something works. Use “breakpoints” (in your debugger) to be sure that every block of code is performed correctly.

How to fix bugs?

  • This will be most of the job.
  • If a bug halts the system, use your debugger to examine the current function and variables. Probably some data is wrong.
  • If the bug is a glitch, some data must be wrong. Try to write code that detects the bad data and halts (google “code assertion”).
  • The bad data must have been written from somewhere.
  • If it is an input to the halted function, check the calling function (look for “callstack” in your debugger).
  • Find the last line of code which may have changed the data which looks suspicious, place a breakpoint, and try to reproduce the error.
  • Another method is to add a “data breakpoint” to the address of the data that is being corrupted. The breakpoint will pause the program for inspection whenever that data is modified.

Further Reading?

· · · ◊ ◊ ◊ · · ·

Chance in Games

10 Feb 2010

There are two boring kinds of questions. Those you answer with total certainty, and those you answer with total uncertainty.

For example, in Persona 4 enemies are either strong, weak, or neutral against elemental attacks. When you first confront a new type of enemy you have no information. As you try each elemental attack the enemy’s response to that attack is revealed and available to view at any time onward. The player begins with the task of trying each possible attack, and ends with the task of using the same attack every time.

Alternatively, in games like Poker, Scotland Yard, and Magic: The Gathering, the player can often combine several pieces of information to make an educated guess about the right answer. The choice is never clearly known or unknowable, but somewhere between. The game is an exercise in judgment, not rote procedure.

· · · ◊ ◊ ◊ · · ·

… or harder when you succeed?

Positive feedback: The game becomes harder when you play worse, easier when you play better.

Negative feedback: The game becomes easier when you play worse, harder when you play better.

Examples:

  • Mario Kart SNES has positive feedback: Gaining a lead separates you from the fray, reducing the threat of attacks, which makes it easier to increase your lead.
  • Mario Kart Wii has negative feedback: Gaining the lead means contending with more attacks designed specifically to target the leader, while falling behind means better random items.

A goal in both cases is to create a suspenseful struggle, and to this end positive feedback wins. The reason for negative feedback is that the person falling behind or running ahead is no longer in the struggle. They need some help or harm to push them back in. But that push counteracts their accomplishment or lack thereof. Their actions become less important, and so the suspense is diminished. Too much chaos, not enough control.

IGN’s said it well:

…the manner in which you advance through the higher difficulty single-player courses — a good deal of skill, but just as much luck. You can be zipping through a 150cc stage without a single error and well ahead of every other competitor when, seemingly out of nowhere, bam! Blue shell. Lightning bolt. One cheesy last-ditch effort after another by unfair AI-controlled components. And suddenly you’ve gone from first place to eighth by no fault of your own. You don’t even have a defense against these items — that is, unless you consider praying that your cheap AI competitors don’t decide to rob you of a victory.

· · · ◊ ◊ ◊ · · ·