Squished tetris

Geschrieben von am .

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.