2010-02-01

At the end of last year I made a blog post entitled New Year’s Resolution? Be A Better Coder. In that post, I detailed three key areas in which to improve. At the end of each month, I have decided that I will give a little status update.

1. Read More
The Idea: There is so much knowledge in both books an online. It would be a bountiful effort to take in some said knowledge.
The Goal: My goal is to read three books this year (one every four months) and subscribe to ten good blogs.
The Progress: Out of all the resolutions, I think this is the one where I am tearing it up. I am a little more than half-way through a book I picked up after The Pragmatic Programmer (See my post on that.) called Agile Development. On the blog front, I have finally set up my Google Reader and I am following five programming blogs (and XKCD, of course). As an aside, I am always looking for recommendations!

2. Learn a New Language
The Idea: Every language is a tool in the toolbox. Learning more tools and maintaining a repertoire of them would be most beneficial.
The Goal: My goal is to learn and implement a few solutions in Python and in Perl.
The Progress: None. I could give you five great excuses why I am too busy, but great excuses only help me to develop my ability to bullshit.

3. Be an Architect
The Idea: Where a programmer applies some duct tape to stop a leak, an architect replaces the corroded pipes with sturdier ones. This is most essential to career advancement, I’d say.
The Goal: My goal here was a little more extract. It was a promise to leave things in a better state than when I found them.
The Progress: On two projects that I am working on, I have been able to clean up some rather hairy code.

  • Share/Bookmark
2010-01-26

As I mentioned in a previous post, challenging yourself is the key to development as a game programmer. Instead of some sage advice*, I would like to offer you a way. Do you have the will? Here are three sites where you can challenge yourself.

Project Euler

Project Euler is a collection of mathematical problems that will take your computer programming skills (and your math) to the next level. You can sign up for an account and track the problems that you have completed by correctly answering the question at hand. You can do some of these problems by hand, and you could do them through brute force in the language of your choice, but the real challenge is in finding an elegant solution. After you have correctly answered the question, you can jump to a forum to see solutions far more elegant than your own.

Dream.In.Code – 52 Weeks of Code

I have been a member of Dream.In.Code for a little while. I enjoy hopping in every now and then to answer some C, C++, and Game Development questions. I’d been inactive for a little while until recently when I got an email about the 52 Weeks of Code idea. Each week a new challenge will be posted. Week 1 was using jQuery, Week 2 was XNA, 3 was the Twitter API, and now Week 4 is a Python challenge. Learning new languages and technologies will help you improve tenfold, so I really recommend this one. Save for the jQuery challenge, these are things I’ve been meaning to do anyways!

TopCoder

TopCoder is a site where Coders compete. If there was a GDL (Game Developer League), this would be it. You can register at TopCoder to complete in programming contests where your mettle will be put the test. Oh, and you’ll get money. Who doesn’t enjoy a little extra money?

* I am not a sage, nor do I define my advice as such. I am but a man offering his opinion.

  • Share/Bookmark
2010-01-20

“Test this on some non-production assets and get back to me.” This is the beginning of a miscommunication that just whipped me into a panic recently. The end result was something more like, “Please use this Bootleg Build on as many important production assets as possible. Spare no one.”

So it happened. Approximately 358 (Approximately? Okay. Maybe exactly.) data files on the cusp of finalization were rendered broken by a “test” of a batch process. Then they were immediately checked into Perforce. Individually. Over a period of thirty or so minutes. While other people checked items in and out willy nilly. Fantastic. Looks like we’ve got a problem on our hands. Instead of (or after) panicking, it was time for a Coder of Action.

Remember when I talked about Learning the Command Line? Well, this is the approach I took to the problem. If you can think of a better way, PLEASE leave a comment.

The first thing I had to do was to uncover the change lists I needed. I pulled up a command line and first got an idea of the damage done.

p4 changes -u someguy -s submitted -m 100

Okay, so it looks like he made at least 200 changes. Every change in this list took place on the day in question. Extending the -m flag (max entries to show) to 200 reveals the exact amount of change lists I needed.

p4 changes -u someguy -s submitted -m 186 > C:\GuyChanges.txt

Now I have a file containing a list of the 186 changes that were submitted by someguy. This is a good start. I’ve written some small batch files before, but I’m thinking that I need a little more power. I need to extract the number from each line and run a command on it. After a little refresher on batch operations for the command line, I give this a shot.

FOR /F “tokens=1,2,*” %X IN (C:\GuyChanges.txt) DO (p4 describe -s %Y) >> C:\GuyDescriptions.txt

This is good. I’ve now got a better description of each changelist involved. Every file involved is sitting in GuyDescriptions.txt with some chode I don’t need around it.

Change 346355 by (user) on (date) (time)

A comment.

Affected Files …

… //repository/path/here.txt#4 edit

What I need is a command line (or two) to extract the correct lines.

FOR /F “eol=C tokens=1,*” %X IN (C:\GuyDescriptions.txt) DO (echo %Y) >> C:\GuyFilesTemp.txt

This removes the first line (Change (X) by…) and grabs the second token of each other line. Effectively, I’ve removed the first line and now have a few more chode lines and the path to the repository. I process this temp file to narrow it down again. Fortunately for me, I have the luxury of knowing every comment was the same. The next command looks like this:

FOR /F “eol=I tokens=1″ %X IN (C:\GuyFilesTemp.txt) DO (echo %X) >> C:\GuyFilesTemp2.txt

Now, I know this is a bit reserved for me to do it one little command at a time, but I was being extra safe here. This effectively strips off the comments and the command that was chillin’ at the end of the file paths. One more simple command and we’ll have a pure list of files.

FOR /F “eol=f tokens=1″ %X IN (C:\GuyFilesTemp2.txt) DO (echo %X) >> C:\GuyFiles.txt

Perfect. So what do I have now? I have a list of every file affected and the revision number that was submitted. This is the revision where it broke. All I need to do now is to subtract one from that revision number and I’ll be golden. In order to do that and create a file to batch revert I created a small C# program. (I actually tried a command first, but when it faltered, I thought how easy a C# command line application would be. It ended up taking me about three or four minutes to write.)

Perforce is a lovely source version system which does not natively allow you to revert to a revision. Useful, I know. The effective work around is to sync to the head revision of a file, open it for edit, sync to the older version, resolve the file using your version, and then submit. This effectively puts the older version as the new head revision, so your file history is not lost. It does look ugly on the revision graph, though.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ConsoleApplication1
{
   class Program
   {
      static void Main(string[] args)
      {
         StreamReader file = new StreamReader("C:/GuyFiles.txt");
         string contents = file.ReadToEnd();

         // The files look like this: //path/to/file.txt#(broken revision)
         string[] files = contents.Split('#', '\n');
         string[] realFiles = new string[files.Length/2];
         int count = 0;
         foreach (string token in files)
         {
            int revision = 0;
            if (Int32.TryParse(token, out revision))
            {
               // Add (revision-1) to the end of the "p4 sync //path/to/file.txt#" command string.
               revision -= 1;
               realFiles[count] += revision;
               count++;
               continue;
            }
            realFiles[count] = "p4 sync " + token + "#";
         }

         StreamWriter newFile = new StreamWriter("C:/GuyCommands.txt");

         newFile.WriteLine("p4 sync");

         foreach (string command in realFiles)
         {
            // For this command we want "p4 edit //path/to/file.txt
            newFile.WriteLine(command.TrimEnd('#', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0').Replace("p4 sync", "p4 edit"));
         }
         foreach (string command in realFiles)
         {
            // This command will be "p4 sync //path/to/file.txt#(revision-1)
            newFile.WriteLine(command);
         }
         newFile.WriteLine("p4 resolve -ay");
      }
   }
}

Okay. First, I sync to the head revision. A “p4 sync” will do. Then, I need to open all of the files for edit. For every file, I create a “p4 edit //path/to/file.txt” to open the file for edit. Then, we want to do a “p4 sync //path/to/file.txt#(revision-1)”. Then, we add a “p4 resolve -ay” to accept our changes over anyone else’s. This gives me a list of the commands to run and in the proper order. With this, I simply run another little command.

FOR /F “tokens=*” %X IN (C:\GuyCommands.txt) DO (%X) >> C:\GuySyncResults.txt

After this, I manually moved all the files into a changelist and submitted them, because Perforce is pretty great and collating everything into a list with “p4 change”. Finally, we wrap it up with a “p4 submit -c 84784″ and go on our merry way. Way to go, communication!

Update: As an aside, I am genuinely interested in hearing about how you would solve the same problem. The first comment kicked this off with a python solution, but what would you use? Do you see any ways that I could have simplified this? This was a rushed solution because fixing it immediately was the highest / only priority. Smarter solutions are always appreciated. As they say, “Work smarter, not harder.”

  • Share/Bookmark
2010-01-13

“Working out lets you do the things you actually enjoy.”
- Poster at the Gym.

I go to the gym two or three times a week. For about six months now I have been going to the gym to lift free weights, run, or swim (or relax in the hot tub) and I always notice the little inspirational posters they have hung about. I applaud their effort, but I think people hardly ever read them. The other day I saw a simple poster while I was running. It had a person on a track ready to run with the message, “Working out lets you do the things you actually enjoy.”

For some reason, I immediately thought that little nugget deserved some thought.

I like to play Ultimate Frisbee. If you don’t know or happen to be misinformed, Ultimate can be very intense. It is approximately one hour of sprinting with some throwing and catching and sprinkle in some self-destruction as you jump, dive (lay out), or collide to chase that plastic. I have often gone to the gym to improve my game. While I do enjoy going to the gym sometimes, I definitely have my fair share of gym dread when I would rather be doing other things. It is hard to push myself to go to the gym and work on my endurance when I could be playing Demon’s Souls. I can already run long enough, right?

But let’s talk about programming, the obvious direction this metaphor was going.

Sometimes you shirk those tasks you dread. Timmy Terrific will write the low level code to handle our special hardware or Robby Render will implement the occlusion. I will just stick to writing the weapon system. I did it twice before and I know what designers want, how to make it flexible, but also stable. It is all too easy to specialize. There are plenty of systems that go into any game that need a programmer. When you take the same tasks over and over again, you gain specific insight into that system. My question to you, however, is this: Are you actually learning anything new or are you polishing an old technique?

You can polish a turd. After five or six iterations you can create a working, almost bug free implementation of whatever system. Does it take advantage of the latest and greatest technology available? Do you use newer, better fitting design patterns and data structures? Can you extend its functionality to do new and exciting things? Sometimes we can only take our old system so far. Down the road, we may want more than Sound::Play(). We want a thread-safe, cross-fading, dynamic beast of a sound system that we can use to do our innovative new user-controlled sound. We want the ability to pass the sound system our position and rotation and it determines what kind of post-processing to apply to our dynamic sword swinging noises. Have we iterated enough to really let the sound system take flight?

So I say to you this, “Implementing different systems allows you to best implement the ones you actually enjoy.”

Struggle with an entirely new paradigm. Jump headfirst into the server code, far from your comfort zone. Taking on a new challenge forces you to work the gray mass, and hopefully leading to self-improvement. Who knows, maybe that complicated server architecture will make sense to you when you’re through. Perhaps you’ll have an epiphany about how best to reconstruct your newest sound system. No matter what happens, surely you’ll learn a thing or two. You may even find that you enjoy other tasks. Personally, I enjoy anything that gives me a little challenge or allows me to gain some insight. I want to prove that I’m pretty flexible. I want to be a better architect. As games evolve, it is critically important to be flexible. You never know when that middle-ware is going to come out rendering you useless. (Secretly, that’s a pun.)

Don’t stop there, though. Try coding a solution in a different language. I cannot stress how much I have grown as a programmer working on Guess What? in Objective-C and by using C# for tools. I have come back from managed memory land with great insight, and I think that some of those skills apply to C++ as well. Learning tactics for generating less garbage, I can take that and run with it back in our traditional games language. Sometimes you find inspiration in the little things. Sometimes you see a poster about exercise and think code.

Point being: Stimulate your brain. The more interesting, challenging things that you code, the better you get. Always strive to improve and you’ll get better at doing what you love.

  • Share/Bookmark
2009-12-30

2010. Wow. 2009 came and went pretty quickly. I left Multimedia Games and joined Bioware. I’ve had five different bosses. I have actively worked with two new languages and continued to hone my craft with a few others. However, that’s the past. It’s time to look forward, time to set some goals. Hopefully by sharing I can encourage people to do the same.

  1. Read more.
    There is a wealth of information out there. Just try searching Google for programming blogs or Amazon.com for programming books and you will find a ton of information. (Seriously, I weighed it.) Well, this year I want to make some headway into that. I actually own a bookshelf filled with programming books, most of which I’ve only glossed through.
    This year, I will read a programming book every four months. I think three books in a year is quite conservative, but I know if I set goals that are too ambitious than I will become encumbered and fail. I can always up the ante next year!
    I will also try to follow ten good blogs by the end of March. I want to make this deadline a little earlier, otherwise I won’t reap the benefits by the year’s end. The way I see it, this is reading one or two posts a day.
  2. Learn a new language.
    A new language is just another tool in the toolbox. As a game programmer, I have been surprised to be using two new languages (C# and Python). Come January, I know I will see more. In fact, I know two projects I am working on and I might need to be able to hack my way through some Erlang and some Perl. Learning the syntax of a new language will not only help me set a solid foundation in said language, but also in the paradigms and design patterns involved. It couldn’t hurt to know more about Java.
    This year I will try to solidify my Python and learn Perl. I have been hacking through some python scripts at work, but I wouldn’t say I’m confident in writing Python yet. Also, I need to be able to start editing / writing some Perl scripts, so I should probably get some solid knowledge. By the years end I will have read and coded a solution using Python and a solution using Perl.
  3. Be an architect and not just a programmer.
    This is a piece of advice that a former boss gave me. “Be an architect and not just a programmer,” he said. This is solid advice. It differentiates between someone who designs systems and someone who writes them. Thinking like an architect means looking for the healthy, long-term solution to a problem. It means keeping in mind maintainability and creating systems that survive. It means less bugs, less cruft. It’s looking for the root cause of a null pointer instead of a check for NULL or an assert.
    I do not have a solid plan for this one. It is about changing the way you approach a problem. It is spending your time wisely and looking beyond the cheap, top-level bug fix to create a better system overall. Perhaps I can promise to leave things in a better state than when I found them. Can I quantify how many systems? I don’t think so. I don’t want to force improvement where it’s not needed.

So there they are, my programming related New Year’s resolutions. Do you have any good ones? Share with me, I shared with you!

  • Share/Bookmark