[screen][code-reading] screen付属のtetris.c

screenのソースを読んでいたらterminfoフォルダに、tetris.cというファイルを発見した。READMEによると

This directory contains various file for termcap/terminfo installation
and testing:

screencap   Termcap entry for screen. Add it to /etc/termcap.
      On NetBSD, you should run /usr/bin/cap_mkdb afterwards.

screeninfo.src    Terminfo entry. Use 'tic screeninfo.src'
      to install (Sun: /usr/5bin/tic).

checktc.c   Termcap/info test program. Checks margin
      handling and other things.

8bits     Some chars from the ISO 8859-1 charset.

test.txt    Test file for alternate charset.

tetris.c    The popular game, by John Tromp. This is one of
      the winners of the 1989 IOCCC contest.

termcap/terminfoのテスト用?とのことである。単体でコンパイルできそうなので、gcc tetris.cなどとうち、コンパイルすると案の定テトリスの画面が出てきた。

wcで行数などを確認すると、20行で構成されていることがわかった

  20   43 1468 tetris.c

ソースはちなみにこんな感じです。

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);}

これはすごいww #includeすらしてないやw たぶんgccコンパイルできるんで、興味ある人はするといいやもしれません

ついでなんで、cflowで流れを見てみると

 cflow --tree --number --cpp --b tetris.c|grep '>$' | sed 's/<.*//'
    1 +-main()
   12   +-g()
   13   +-u()
   16   +-G()

こんな感じの構成になってることがわかります。

これだけじゃよくわからないので、もうすこし詳しく見ると

 cflow --number --cpp --b --tree terminfo/tetris.c
    1 +-main() <main (C,V,a) at terminfo/tetris.c:8>
    2   +-atoi()
    3   +-srand()
    4   +-getpid()
    5   +-system()
    6   +-sigvec()
    7   +-t() <t () at terminfo/tetris.c:1> (R)
    8   | +-setitimer()
    9   | \-t() <t () at terminfo/tetris.c:1> (recursive: see 7) [see 7]
   10   +-puts()
   11   +-rand()
   12   +-g() <g (b) at terminfo/tetris.c:8>
   13   +-u() <u () at terminfo/tetris.c:5>
   14     +-printf()
   15     \-getchar()
   16   +-G() <G (b) at terminfo/tetris.c:7>
   17   +-sigblock()
   18   +-printf()
   19   +-getchar()
   20   +-sigsetmask()
   21   +-popen()
   22   +-fprintf()
   23   +-getlogin()
   24   \-pclose()

とまぁこんな感じ。まぇにjavascriptで似たようなことをしているソースを見たことがありますが、cでは見たことがなかったのでなかなか新鮮でした