C and the art of obfustication

One of my coworkers sent me the following C program which can play chess. As you can see, it has been seriously obfusticated.

Amazingly, the code compiles and runs and actually plays a passable game of chess. You can pass in the number of moves you want it to look ahead (defaults to 2) on the command line. You enter moves as a pair of numbers - from and to, separated by a space.

I don't know who wrote this so I apologise in advance if I am breaking copyright. The C file has a header which is presumably meaningful if viewed with the correct font but it's illegible to me. You can view it here.

The source

#include <stdio.h>
#include <stdlib.h>

#define m(x)(x<0?-1:!!x)
#define g tj()-J
#define a(x)(x<0?-x:x)
#define h(x)((x)<=K?x:N-(x))
#define f 9999
#define A return
#define H printf(
#define R double
#define U int
#define V for
#define b else
#define u while
#define B if
U v,w,Y= -1,W,J,p,F,o=f,M,N,K,X,YY,_,P[f],s(); typedef U(*L)(); 
L q[f]; tj(){U S=m(v)+(m(w)<1||w-Y||!q[J]:
(w-Y&&(w-Y*2||q[W+Y*(N+1)]|| (J>>K)-K+(Y-1)/ 2))||q[J];
} z(){ _=5; A v*w||g; } e(){ _= -2;
q[W+1]||q[W+2]||q[W+K]!=z||P[W+K]*Y<0); } R VR(){ int PZ=0x7fff;
A(R)(rand()&PZ)/(R)PZ; } l(){ _=K+1; A(v*w&&a(v)-a(w))||g; } 
R UC(){ R i=0,d; u((i+=d=VR())<1.0); A d; } c(){ _= -11; 
A a(v)-a(w)||g; } I(ur,n,x){ W=ur; J=n; B(P[W]!=Y||P[J]==Y)A 
J+1; v=(J&N)-(W&N); w=(J>>K)-(W>>K); A q[W]()||(x&&QL(W,J,s)); } 
TT(W){ v=w=0; A q[W]()+K; } s(){ U j= -1,i; Y= -Y; 
V(i=0; i=0 &&!I(i,j,0))A Y= -Y; } A!(Y= -Y); } bb(){ _=1; 
A a(v*w)-2; } uv(){ V(v=0; v>K)==0){ U S=h(v&N);
q[v]=!S?z:(S==1?bb:(S==2?c:(v&N>K?l:e))); } b B(h(v>>K)==1)q[v]=k; 
b q[v]=0; P[v]=!!q[v]*(28-v); } } y(){ U G=Y,i; J=0; 
V(i=0; i>K)==0)q[J]=l; B(q[W]==e)B(J-W==2)
O(J+1,J-1); b B(W-J==2)O(W-1,W+1); P[J]=P[W]; q[W]=0; P[W]=0; } 
QL(W,J,D)L D; { U HQ=P[J],YX; L AJ=q[J],XY=q[W]; O(W,J); YX=D(); 
O(J,W); q[J]=AJ; q[W]=XY;
P[J]=HQ; A YX; } C(){ U i,j,BZ=0; V(i=0; i>K)+h(i&N),G=Y, S=Z==z?88:
(Z==k?11 +r+(P[i]<0?N-(i>>K):(i>>K)):
(Z==l?124-((YY<8&&((i&N)!=K|| (i>>K)!=(P[i]>0?0:N)))?M:0):
(Z==c?41+r:(Z==e?f-r-r:36+r+r)))); Y=P[i]; 
V(j=0; j>K+K,i&M-1,1)){ Y= -Y; o= -E; t= -QL(i>>K+K,i&M-1,PX); 
Y= -Y; B(t>E){ ++XP; Q=i; E=t; B(E>=S) A++F,E; } }
B(!XP)E=s()?-f+1:0; p=Q; A++F,E; } RZ(){ U i,j,T=0; 
V(; ; ){ y(); o=f; do{
H"\n%d %d %d %s ",X,T,C(),s()?"!":">"); fflush(stdout); }
u(scanf("%o%o",&i,&j)!=2||I(i,j,1)); O(i,j); y(); X=0; ++YY; 
Y= -Y; T=PX(); i=p>>(K<<1); j=p&(M-1); B(I(i,j,1))
{ H"Rats!\n"); A; } O(i,j); Y= -Y; B(T>M*M)H"\nHar har.\n"); } 
} main(ac,av)char**av; { long time(),j=time(&j);
R i=0; srand((U)j); V(M=0; M<=f; ++M)i+=UC(); M=i/100; 
B(M&3)++M; B(M&1)--M; V(N=1; N*N1?atoi(av[1]):2; uv(); RZ(); }


To keep myself sane or otherwise I used some spare moments to unobfusticate the code. I have finally cracked it and can definitely report that it is seriously and intentionally obfusticated - and not just by reducing everything to a single letter. If you like C programming and puzzles I can recommend it as a fun exercise.

Some hints:

    1. the random number generator doesn't do what you expect
    2. some variables are really constants
    3. be very aware of the precedence of operators
    4. make sure you understand bitwise operations

If you are interested you can download the unobfusticated version unobfusticated_chess.c.gz.

I got interested in the whole project and produced an improved version improved_chess.gz. This runs faster, has a slightly better interface (although still text based), a minimalist config file and plays slightly better. It was an interesting exercise.

If you want to study the source of a full-featured chess program I can recommend gnu chess.



last updated