We are experiencing issues that prevent checkout in Internet Explorer 8.

You can browse and even save your cart, but you'll need to use another browser or a different device to place your order. Sorry for the inconvenience.


Jon Jon - tank (at) thinkgeek (dot) com.

I am most often found in dimly lit areas, and flourish in cold climates. I'm not contagious, but am difficult to remedy when contracted. Sunlight is my enemy, but a bowl of ramen is my friend.


For the first four years, I was the only developer here at ThinkGeek. In early 2004 we brought on another Perl junkie, Buddy. Then, the unthinkable occurred: Buddy managed to convince me to make one of the most drastic religious conversions possible in the Un*x world. In the summer of 2004 I set Emacs aside (after over a decade of use) and started using Vim exclusively. I'm also the proud adoptive parent of a crazy beagle puppy, 5:30. You can see him trying to get Cisco to play, while our other office puppy, Dulcie, watches in the background.

For the curious out there who e-mail every so often asking what we use for our software development, here's the basics:

  • 2 Developers
  • Primary language for development is Perl
  • Vim is used exclusively as our code editor (no stinking graphical IDEs here)
  • Subversion for version control (plus a suite of utilities Buddy wrote called "VCTools")
  • Current DB is MySQL 4.1 (one for development, and a pool in production using replication)
  • Gentoo is our distribution of choice (not for the misguided "ricer" aspect, but because we just really dig Portage)
  • Buddy and I share a room, sitting no more than six feet from each other, but we still communicate primarily over IM (taking off our headphones would require too much effort)
  • Buddy uses Linux exclusively, I use a mix of Linux and Mac OS X

I'll leave you with the following little snippet:

sub ruleset_traverse {
    my ( $r_cond, $T ) = @_;

    unless ( exists $pr_hndl_cond{ $r_cond->{type} } ) {
        if ( $T->{errors} ) {
            $T->{errors}->add( BAD_CONDITION
                => "Unknown condition type." );

    my @children = ruleset_children( $r_cond );
    my $res = $pr_hndl_cond{ $r_cond->{type} }->( $r_cond, $T );

    foreach my $child ( @children ) {
        next unless ruleset_result_match( $res, $child->{result} );

        if ( $child->{TYPE} eq 'cond' ) {
            ruleset_traverse( $child, $T );
        elsif ( $child->{TYPE} eq 'action' ) {
            $pr_hndl_action{ $child->{type} }->( $child, $T, $res )
                if exists $pr_hndl_action{ $child->{type} };

        last if $T->{stop} > 0;

There you have the inner core of our promotions/discount-code system. Sprinkle in some support code, top with a wrapper module, season the two main dispatch tables to taste and viola. Simple decision tree based promotions with unlimited nesting of conditions and chaining of actions. Of course, you'll need to use your imagination when duplicating our triggers code and coming up with the supporting dispatched routines. And for simplicity, the bulk of the exceptions handling was taken out of there as well.