So I participated in the 48 hour Node.js Knockout competition together with James Halliday and Joshua Holbrook. Our team was called Dark Knights and we created an online chess application called Node Chess.

We didn't quite manage to completely finish the game and it has several bugs, like the turns don't alternate and the king can be captured, but it's crazy awesome anyway. If both players follow the rules, it all works correctly. Castling works, pawn promotion works, capture en-passant also. Try it and if you find it awesome, please vote! Oh, and it works only in Chrome. We were under time pressure and at one point it stopped working under Firefox and we did not get to fixing it.

Here is how the game looks,

A chess game between pkrumins and someone. King's Indian Defence.

Joshua did all the awesome vector graphics work. I did the chess engine work, and James used his amazing dnode node.js module to blend client and server code together. James has actually redefined how web development happens. Instead of writing server code and client code, as we are so used to, with his dnode framework it's now possible to use the same code both server and client side! Much less hustle and purely ingenious!

Here is the same game in perspective view, the highlighted squares are the available moves,

The same game in perspective view.

And the moves are animated, too! The pawns shoot the opponent pieces and the queen stabs them. Try it!

Right, so my reflections on the competition.

It was well organized, and we were sent access to a Joyent deployment server and a Heroku server early on together with instructions. It turned out that Heroku's didn't support Socket.IO or websockets. Win for Joyent. Pretty much everyone went with Joyent as far as I know. We had some technical difficulties at the start with deploying our code, but guys at #node.js helped us and we got our app running pretty quickly.

We used 3 Git repositories to push the code to, our own GitHub repositories (pkrumins, substack, jesusabdullah), then the node knockout's private repository for judges, and deployment repository on Joyent. Joyent was configured so that as you push your code to its Git repo, the hooks in it would restart the node.js service and the you'd be instantly running the latest version of your code.

So I'd make changes push to my GitHub repo, James would pull from me. He'd make changes, I'd pull from him, and same for Joshua. It went pretty flawless. We had like 12 merge errors total, but those were all resolved within a minute or two.

Now some numbers. We're actually amazed by our performance. Check out these numbers:

$ git log | grep Author | wc -l

429 commits! Can you believe that? 429 commits in 2 days! That's 9 commits per hour on average! That is what I call hacking!

My commits:

$ git log | grep Author | grep Peteris | wc -l

I did 3.5 commits per hour on average. And funnily, James and Joshua each had 130 commits:

$ git log | grep Author | grep James | wc -l
$ git log | grep Author | grep Joshua | wc -l

That's 2.7 commits per hour on average! Amazing! But we also slept between the competition days. On the both days we did about 4 hours of clean sleep, shrinking our competition time to 40 hours. Then our average becomes 10.7 commits per hour! Wowsers!

Here is a graph, made with Raphael.js, that shows our git commit activity by hour, starting from 3am UTC Aug 28 to 3am UTC Aug 30:

Team "Dark Knights" git commit activity by hour.

Our peak commit intensity was at 9pm the last night, when we did 23 commits in one hour. Our team was widely spread out but we managed to keep the same schedule and keep hacking together.

Total number of code lines written:

$ wc -l `find . -name '*.js' -o -name '*.html' -o -name '*.css' | \
  egrep -v '(jquery|raphael)'`
3074 total

So we wrote 3074 lines in two days, which according to git break up into added vs. deleted as following:

$ git log --numstat | grep '^[0-9]' | \
  egrep '(\.js|\.css|\.html|jquery|raphael)' | \
  awk '{a+=$1;d+=$2}END{print "Added: " a, "Deleted: " d}'
Added: 5210 Deleted: 2042

Hmm, 5210-2042 doesn't quite add up to 3074 but is close enough. From these 3074 lines of code non-empty were:

$ cat `find . -name '*.js' -o -name '*.html' -o -name '*.css' | \
  egrep -v '(jquery|raphael)'` | perl -nle 'print if /\S/' | \
  wc -l

So 2659 real lines of code in 2 days! Talk about productivity! And that's just code alone. Joshua also did 50 artworks,

$ find . -name '*.svg' -o -name '*.png' | wc -l

Total number of file changes:

$ git log --shortstat | grep 'files changed' | \
  awk '{t+=$1}END{print t}'  

We communicated in IRC, in our #stackvm startup channel. Here are some statistics on how much stuff went on in our IRC channel:

$ (
  grep -v '^0[012]:' '#stackvm.08-28.log';
  cat '#stackvm.08-29.log';
  grep '^0[012]' '#stackvm.08-30.log'
  ) | wc -l

So 5069 events happened during the challenge. That's 105 events per hour on average. We have a special lulbot in it who tells us when we commit, for example:

05:59 < lulzbot-X> Whoa Nelly! New commits to pkrumins/node-chess (master)!
05:59 < lulzbot-X>     * Peteris Krumins: MoveGenerator stub
05:59 < lulzbot-X>     * Peteris Krumins: abstract pieces
05:59 < lulzbot-X> githubs:

Here lulzbot informed us that I committed MoveGenerator stub and abstracted pieces in node-chess repo.

Out of these 5069 events, we talked this much,

$ (
  grep -v '^0[012]:' '#stackvm.08-28.log';
  cat '#stackvm.08-29.log';
  grep '^0[012]' '#stackvm.08-30.log'
  ) | egrep -i '^< pkrumins|substack|jesus' | wc -l

So we spoke 2682 times or 83.8 times per hour. We also asked quite a lot questions:

$ (
  grep -v '^0[012]:' '#stackvm.08-28.log';
  cat '#stackvm.08-29.log';
  grep '^0[012]' '#stackvm.08-30.log';
  ) | grep '?$' | wc -l

246 questions, for example (random selection):

< pkrumins> wait, are we including a version of in dnode?
< jesusabdullah> but: simplified pieces for thumbs--yea or nay?
< pkrumins> is anyone working ont he problem where the opponent cant make moves?
< SubStack> pkrumins did you see how I just dumped the node EventEmitter code into our lib/?
< SubStack> does S create a row?
< jesusabdullah> pkrumins: You fixing the board?
< pkrumins> how does resizing in raphael happen?

My chess code wasn't the easiest to write and to make sure it works correctly, I wrote 52 expresso tests,

$ expresso 

   100% 52 tests

Without tests I would have never got that chess code right.

That's about it. The competition was awesome, A++ would participate again. Hope they organize node.js knockout the next year, too!

I hope you enjoyed my post and don't forget to vote for our project! Your vote is so important to us. Thank you!


August 30, 2010, 19:24

Aww, too bad I don't had time to participate. Node KO was awesome.

August 30, 2010, 20:13

of course what you did works, but you can also do git log --author=Peter. That will probably be slightly faster. Note that git log is quite the chainsaw. I recently used it to show how many commits I had over three weeks vs my coworkers with something like:

git log --author=fREW --after=Aug.1 --before=Aug.21 --oneline
git log --after=Aug.1 --before=Aug.21 --oneline --not --author=fREW

Pretty cool huh? Also I didn't really use --oneline since I wanted to take out the author for my output and I took part of the time off and the commit id. You can use --format for that iirc

August 30, 2010, 21:19

Yeah, this is cool, thanks for sharing! Didn't know about --author and --after --before and --oneline.

August 30, 2010, 21:56

Yea I totally recall playing this with you guys on Saturday night! Pretty cool, huh?

August 30, 2010, 22:45

The awesome power of turning off youtube for 48 hours!

August 31, 2010, 04:30


Seth Permalink
August 31, 2010, 02:39

I think this webkit only attitude stinks.

It's fine you didn't bother to test or support other browsers like Firefox (which is the dominate browser at the moment).

But lose the attitude. I've seen JS1k entries that did chess with a full AI that worked in both browsers, there's no reason a little messaging will complicate this.

Also the webkit way, is not always the HTML5 standard way either. At least I don't see any -webkit- and -mozilla- CSS tags.

What I want to know is why doesn't this work in Firefox?

August 31, 2010, 03:11

@Seth, good coders code, great reuse

August 31, 2010, 04:26

It used to work with Firefox and Chrome but then at one point it stopped working on Firefox and we did not notice at which point exactly. We were in time pressure when we discovered that it doesn't work in FF and we never tracked it down. So I don't really know.

August 31, 2010, 09:45

great application, great performance :)

August 31, 2010, 11:26

Hi Peter,

I wrote an angry response to this blog post of yours as a post on my blog, though it has a greater scope than just this post.

David Permalink
August 31, 2010, 18:58

Browser allegiance and hurt feelings aside, this is an amazing achievement. It was a competition after all! No tears now, Internet Explorer will catch up some day.

September 02, 2010, 01:57

It's a marvelous piece of work for a one-day-and-three-people effort. I tried it and voted for it. You could have also allowed users to hook up other chess engines like GNUChess or Rybka. Another improvement that I can think of is to enable user to extract the moves as a PGN.
But in a one day schedule, you did a lot. Writing a working chess engine within that time is something great. Is there a place where I can get the chess engine code?

September 02, 2010, 06:59

Well the chess engine just reports the valid moves for the user. It does not play chess itself.

It's here:

September 02, 2010, 17:51

Oh.. ok. I played with another friend, but did not try playing with the server - to find out that actually I could not have been able to play with the server itself. When you said you developed chess engine, I made an assumption that it would play chess, and also wondered how you could get that done in a single day.

Thanks for the link to the code.

September 04, 2010, 17:41

Why don't you create a video with gource?

It generates awesome git visualizations!


Leave a new comment

(why do I need your e-mail?)

(Your twitter handle, if you have one.)

Type the word "disk_237": (just to make sure you're a human)

Please preview the comment before submitting to make sure it's OK.