Vor 20 Jahren gewann das
Ofbuscated tetris
von
John Tromp
den
International Obfuscated C Code Contest
in der Sparte Best Game
. Ein komplettes Spiel (mit
High-Score)
auf einer halben A4-Seite: das hat mich damals sehr beeindruckt.
So sieht das Original aus:
long h[4];t(){h[3]-=h[3]/3000;setitimer(0,h,0);}c,d,l,v[]={(int)t,0,2},w,s,I,K =0,i=276,j,k,q[276],Q[276],*n=q,*m,x=17,f[]={7,-13,-12,1,8,-11,-12,-1,9,-1,1, 12,3,-13,-12,-1,12,-1,11,1,15,-1,13,1,18,-1,1,2,0,-12,-1,11,1,-12,1,13,10,-12, 1,12,11,-12,-1,1,2,-12,-1,12,13,-12,12,13,14,-11,-1,1,4,-13,-12,12,16,-11,-12, 12,17,-13,1,-1,5,-12,12,11,6,-12,12,24};u(){for(i=11;++i<264;)if((k=q[i])-Q[i] ){Q[i]=k;if(i-++I||i%12<1)printf("\\033[%d;%dH",(I=i)/12,i%12*2+28);printf( "\\033[%dm "+(K-k?0:5),k);K=k;}Q[263]=c=getchar();}G(b){for(i=4;i--;)if(q[i?b+ n[i]:b])return 0;return 1;}g(b){for(i=4;i--;q[i?x+n[i]:x]=b);}main(C,V,a)char* *V,*a;{h[3]=1000000/(l=C>1?atoi(V[1]):2);for(a=C>2?V[2]:"jkl pq";i;i--)*n++=i< 25||i%12<2?7:0;srand(getpid());system("stty cbreak -echo stop u");sigvec(14,v, 0);t();puts("\\033[H\\033[J");for(n=f+rand()%7*4;;g(7),u(),g(0)){if(c<0){if(G(x+ 12))x+=12;else{g(7);++w;for(j=0;j<252;j=12*(j/12+1))for(;q[++j];)if(j%12==10){ for(;j%12;q[j--]=0);u();for(;--j;q[j+12]=q[j]);u();}n=f+rand()%7*4;G(x=17)||(c =a[5]);}}if(c==*a)G(--x)||++x;if(c==a[1])n=f+4**(m=n),G(x)||(n=m);if(c==a[2])G (++x)||--x;if(c==a[3])for(;G(x+12);++w)x+=12;if(c==a[4]||c==a[5]){s=sigblock( 8192);printf("\\033[H\\033[J\\033[0m%d\\n",w);if(c==a[5])break;for(j=264;j--;Q[j]= 0);while(getchar()-a[4]);puts("\\033[H\\033[J\\033[7m");sigsetmask(s);}}d=popen( "stty -cbreak echo stop \\023;sort -mnr -o HI - HI;cat HI","w");fprintf(d, "%4d from level %1d by %s\\n",w,l,getlogin());pclose(d);}
Download: ofbuscated_tetris.c (1467 byte)
Übersetzt (deaktivierte Warnungen) und gestartet wird es so:
> cc -w -o tetris ofbuscated_tetris.c > ./tetris
Refurbished tetris:
Zum zwanzigsten Jahrestag habe ich mir das Programm noch einmal angeschaut.
Mindeststandard ist heute die Aktivierung der Warnungen des C-Compilers, doch ein Übersetzungsversuch mit
> cc -Wall -Werror -Wextra -o tetris ofbuscated_tetris.c
scheitert kläglich mit 56 Fehlermeldungen (gcc 4.6.3).
So hab ich mir den Spaß gemacht und das Original überarbeitet.
Die Includes und die struct-Typen lassen sich nicht einfach obfuszieren, der Rest aber sieht hoffentlich eben so grauslich aus wie beim Original. Und obwohl es größer geworden ist, passt es immer hoch auf eine halbe A4-Seite:
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <signal.h> #include <sys/time.h> struct itimerval h;int c,l,w,s,I,K=0,i=276,j,k,q[276],Q[276],*n=q,*m,x=17,f[]={7 ,-13,-12,1,8,-11,-12,-1,9,-1,1,12,3,-13,-12,-1,12,-1,11,1,15,-1,13,1,18,-1,1,2,0 ,-12,-1,11,1,-12,1,13,10,-12,1,12,11,-12,-1,1,2,-12,-1,12,13,-12,12,13,14,-11,-1 ,1,4,-13,-12,12,16,-11,-12,12,17,-13,1,-1,5,-12,12,11,6,-12,12,24};FILE*d;void t (){h.it_value.tv_usec-=h.it_value.tv_usec/3000;setitimer(0,&h,0);}void u(){for(i =11;++i<264;)if((k=q[i])-Q[i]){Q[i]=k;if(i-++I||i%12<1)printf("\\033[%d;%dH",(I=i )/12,i%12*2+28);printf(&"\\033[%dm "[K-k?0:5],k);K=k;}Q[263]=c=getchar();}int G( int b){for(i=4;i--;)if(q[i?b+n[i]:b])return 0;;return 1;}void g(int b){for(i=4;i --;q[i?x+n[i]:x]=b);}int main(int C,char**V){char*a=C>2?V[2]:"jkl pq";h.it_value .tv_usec=1000000/(l=C>1?atoi(V[1]):2);system("stty cbreak -echo stop u");for(;i; i--)*n++=i<25||i%12<2?7:0;srand(getpid());struct sigvec v={t,0,2};sigvec(SIGALRM ,&v,0);puts("\\033[H\\033[J");t();for(n=f+rand()%7*4;;g(7),u(),g(0)){if(c<0){if(G( x+12))x+=12;else{g(7);++w;for(j=0;j<252;j=12*(j/12+1))for(;q[++j];)if(j%12==10){ for(;j%12;q[j--]=0);u();for(;--j;q[j+12]=q[j]);u();}n=f+rand()%7*4;if(!G(x=17))c =a[5];}}if(c==*a&&!G(--x))++x;if(c==a[1])n=f+4**(m=n),(void)(G(x)||(n=m));if(c== a[2]&&!G(++x))--x;if(c==a[3])for(;G(x+12);++w)x+=12;if(c==a[4]||c==a[5]){printf( "\\033[H\\033[J\\033[0m%d\\n",w);if(c==a[5])break;for(j=264;j--;Q[j]=0);while(a[4]!= getchar());puts("\\033[H\\033[J\\033[7m");}}d=popen("touch HI;sort -mnr -o HI - HI" ";head HI","w");fprintf(d,"%4d from level %1d by %s\\n",w,l,getlogin());pclose(d) ;system("stty sane");return 0;}
Download: refurbished_tetris.c (1672 byte)
Übersetzt (mit aktivierten Warnungen) und gestartet wird es so:
> cc -Wall -Werror -Wextra -o tetris refurbished_tetris.c > ./tetris
Außerdem gibt es eine entobfuzierte und ein wenig kommentierte Version.