3D Tanks game. 20th IOCCC. Best non-chess game

In the eighties when I was a kid, I wrote a BASIC program to show a 2D labyrinth and two tanks rotating along eight directions and shooting, it was for two players. Every player pressed furiously over keyboard trying to get first to the right position to shoot the other player. It gave me great hours of fun playing with my friends.
By November 2011 when the 20th International Obfuscated C Code Contest (IOCCC) started, a contest for professional C programmers, I thought this game would be a fancy one for an entry but with a little twist: 3D graphics and dual views, one for each player.
I finished it and sent it on time for contest and it won the Best non-chess game category of the IOCCC, also was my fifth win since the 18th contest.
It is a multiplayer 3D game in only 3510 bytes of C language. Today modern games use a pretty similar core with added graphics and music, little has changed since many years ago.
I consider it as a good ending for my winning streak and I've decided to not participate in further IOCCC competitions.
20th IOCCC Best non-chess game. 3D Tanks running
3D Tanks running

Source code

Here is the source code written in C language:
#include <X11/Xlib.h>
#include <X11/keysym.h>
#define I XDrawLine(W,X,Y,
#define l rand()%
#define R while(
#define n *h++
#define x _ c].
#define S if(
#define _ _[
                            *h ;
                        M=512; i; N=
                    288; e; d; u; p; L[1
                <<28]; float w=11.46; m; a ;
            P; k[9304]; *j=k; c; f; q; r; t; v ;
        * z; K(N,i) { t=u*+cos(N/w)-i*sin(N/w); p=i*
    cos(N/w)+u*sin(N/w); u=t; } Display*W; GC Y;  Pixmap
X; s(o,t,g,w,v) { h=v+k; q=2*n; R u=n, r=12+n, K(t,n), K(o,+
    p+w,u+=g), d=1>p?1:p, u=u*N/d+M/2, d=N/2+r*N/d, u=u>
-M*2    ?u<M*2?u:2*M:-2*M, 1&q?i>0|p>0?I f,e,u,d):0:    (i=p
,e=d,f=u    ), --q); } struct{ int c,o,m,f,u,s,i    ,e,r;  }
_   21  ]  ;    Window O; b(y) { XGCValues g    ;     g    .
foreground=y; g.    line_width  =  2   ;    XChangeGC(W,Y,20
,&g); } G(o) { z=x f    + k; h=(x f=    381+193*c)+k; i=2*(n
=*z++); R--i&1?d=l 9-4,e    =l 9    -4*(8>o):0,n=*z+++d,0<(n
=*z+++e)?h[-1]=0:0,n=*z+++d,    i); } g(o) { u=0; K(x s,o<<9
); x u-=u; x r-=p; } F(m,c )    {  f=5120*c; c=12; R +c--&&m
==+c |abs(x u-_ m].u)>f |x i    <1|x c>2 |abs(x r-_ m].r)>f)
; return c+1; } T(o) { c=11;    S!P){ a=++a%72; S!a){ P=1; R
c--){ x c=x m=0; x i=c>2?2:1    ; R x u=l 978-499<<8, x s= l
71, x r=l 979-501<<8, F(c,2)    ); x f=c>2?l +2*+73:147; x o
=2>c?249<<16-c*8:64987<<8*(c    >2); } } } S P){ c=11; R 4&x
i? ++x m-64&&x m-71? o=1,64>    x m?(d=F(c,1))?x m=64,d<4?j[
x e]++,++_ --d].c:0:g(7):G(x    m -65) :_ x i=0,x e].e-- :0,
20>++c); c=3; R c--) { S 1&x    i) { o++; S x c>2) x m>15? x
i=0:G(x m++); else { S x m )    S x m-->6) g(4); S c<2) {  x
s=(72+x s+L[c?B]-L[c?C])%72;    S d=4*L[c?A]-L[c?D]*4) { g(d
); S F(c,2)) g(-d); } S L[c?    E]&!x m&x e<3) { d=10; R _++
d].i) ; g(-4); _ d]=_ c];  _    d].e=c; x e++; x m=7; c=d; x
f = 122 ; x i=4; g(19); x o=    4092<<12; c=x e; } } } } } P
-=o<2; } v=2; R v--){ m=(108    - _  v].s)%72; b(3^_ v].c?0:
128); Q c=0,0,M,N); S!P) s(+    36,54-a,0,-120,-+-+-+-+147,b
((1<<16)-1)); S P) { b(255);    I 0,N/2,M,N/2); t=-.889*m; h
=k+340; R u=(t+=q=n)*M/32,d=    n*N/48,q?I f,e,u,d):0,f=u,e=
+d,k+378>h); R x i&&c-v?s(m,    x s,x u-_ v].u>>8,x r-_ v].r
>>8,x f,b(x o)):0,20>c++); c    =0; R e=16+32*c,Q v^c?16:8,e
    ,(c^v?68:76)+c[b(x o),j]    , 16), b(0,d=20*x c),  Q
        80-d,4+e,d,8),2>c++)    ; } b(255); I M,0,M,
            N); XCopyArea(W,    X,O,Y,0,0,M,N,v*
                M,0); } }
char*o="{\t} \f{\f}\t\t\f{\f{ }\t;      \t{ }\t;  \t\f{\f;      \t"
"\f{\f;\t { ;\t{ }\t;      \t{ }\t;  \t\f{\f;      \t\f{\f;\t}\t\t"
"; \t { ;\t{ }\t}\t\t; \t { ; \t}\t\t{ }\t;\t { ;\t\f{\f}\t\t; \t "
"{ ;\t} \f\f{\f}\t\t\f{\f{ }\t;      \t{ }\t;  \t\f{\f;      \t\f{"
"\f;  \t}\t\t { }\t\t{ }\t}\t\t\f{\f}\t\t { }\t\t{ }\t}\t\t{ }\t}"
"\t\t { }\t\t\f{\f}\t\t{ }\t}\t\t { }\t\t{\f\f\f\t\t }\t\t{ \f;  "
"   \t  ;   \t\f\t;     \t\t ;\t }\f\f{\f;\t}\t{\t{ }\t;      \t}"
"\t}\t;  \t\f{\f;      \t}\t{\t;\t}  \t{\t{ }\t;      \t{\t}\f;  "
"\t\f{\f;      \t\t{\t;\t}\t\t}\t{\t;\t}  \t{\t{ }\t}\t\t}\t{\t;"
"\t}  \t{\t; \t{\t}\f;\t}\t\t}\t}\t\f{\f}  {\t}\f;\t}\t\t}\t}\t}  "
"}  {\t }\f\f;      \t\t} ;  \t}  ;      \t{\t }\f {\t   } \f;    "
"  \t{\f} ;  \t}\f ;      \t  }  }  {\t }\f {\t   }\f\f}  {\t } \f"
"{\t   }\f\f}  \t} } \f{\t {\f} }  }  \t} }\f {\t {\f} } \t\t {\f "
"; \t{\f{\t}\f\t;\t{\f ; \t{\f{\t;\t  {\f ; \t{\f{\t} \t;\t{\f ; "
"\t{\f{\t;\t\t ;\t}\f\t;     \t  ;   \t} \t;     \t\t ;\t}\t\t}\f"
"\f{\f\f{\t\f\t\f} \f{\f\f{ } { \f\t\f{\f\f{\t\f{\t} }\t\f} \f \f}"
" \f}\f\f\t\f{\f\f{\f\f{\t\f{\f\f} \f{ \f}\f\f{\f\f{\t\f\t\f} \f{"
"\f\f{ } { \f\t\f{\f\f{\t\f{\t} }\t\f";
XEvent e; W=
XMapWindow(W,O); srand(time(0)); Y=
XCreatePixmap(W,O,M,N,DefaultDepth(W,r)),P,r); R*o){ S*o^59)d=64&*o?'{'^*o++:3,
 32^*o?d+=*o^9?2:1:0,*j+=P?d*9-43:d,j+=P,P=!P; else R*j=j[-3],j++,*++o^9); o++;
 } R 7){ T(0);
XFlush(W); usleep(33367); R
XPending(W)) L[
XNextEvent(W,&e)&0)]^=1==e.type/2; } }
For sake of readability on this webpage I've replaced the control characters for tabulator and form feed with their C equivalents to make them visible. The original file is available below to download.


For running this program you'll need a system running some variety of *NIX and X/Window.
Download the source code file toledo_tanks.c
To compile you've to introduce a long command line, it's so long that doesn't appear complete in this webpage so copy it to clipboard. After compilation run it without arguments.
cc toledo_tanks.c -o toledo_tanks -lX11 -lm -DA=XK_Up:XK_w -DB=XK_Left:XK_a -DC=XK_Right:XK_d -DD=XK_Down:XK_s -DE=XK_BackSpace:XK_Tab "-DQ=XFillRectangle(W,X,Y,"
Also I've developed a translation layer that allows to run this program in Wind*ws. Get the complete pack with executable:
The IOCCC judges also have been able to compile it over Mac OS/X platforms, for this you must install X11 and add this to command line for compilation:
-L /usr/X11/lib

User's manual

You will see briefly a tank spinning before each level.
Left half of the window shows the red player view and right half shows the green player view, the background will change to blue when the view goes inactive.
The objective is to chase and destroy the other player's tank, there is also an aqua tank for testing your aim and getting extra points.
When only one tank remains on the field, the level will advance. Don't forget to destroy the aqua tank.
The playground is surrounded by mountains and each level is filled with random obstacles (pyramids and cubes).
The bars show players energy and score, each bar shows energy and indicates current player view (wider on the left), right part grows with every point.
Keys for player 1 (lowercase):
Keys for player 2:
Note: Numeric keys don't work.
If you don't like the keys assignment, you can change it on the makefile.

Parental advisory warning

This game is highly violent, when the tank explodes you can see the little stick man blowing in parts.
Not really, just kidding :D

Platforms tested

Complete feature set

Features that programmers will find appealing

Obfuscation tricks

History of this program

When I started working on this program, I figured that it would be easy to fit on the IOCCC character limit, but I missed three things, the enormous X11 names, the unportable keycodes and my 2 KB of artwork.
Very hard coding did the first thing, in fact I worked out twenty-nine different versions, at one step I had four parallel versions with different characteristics removed (mountains, horizon line, score/status bars and explosions), I've managed to fit it all together!.
The second thing was solved using the makefile, it is under 160 bytes and you get adjustable keyboard. The greatest mistery on the earth is why X11 handles unportable keycodes to the user.
And finally, the third "Thing" was growing and growing, and growing, eating bytes for lunch... after endless rounds of crunching I obtained three-hundred seventy-eight bytes of artwork and guess what?, it doesn't fitted.
So I had to integrate a decompressor, based on the space, tabulators and other non-counted characters.
The final program is composed of eight microfunctions, one is the core and does most of the hard work, other functions help doing the X11 things, explosion effects, 3-D calculations and viewing.
The source code was formatted as a cube using a specially written program, the reality is that the program is smaller and obfuscated of what is needed so the reformatting doesn't exceeded the character limits. The crunched XYZ vectors were generated by another special program.
Have fun!

Useful links:

Last modified: Feb/11/2013