#include #include #include #include #include #include #include #include #include #include "termio.h" #define WID 10 #define HEI 22 int delay_msec=700; const int stones[7]={ 0b0000000001110001, 0b0000000001110100, 0b0000000000110011, 0b0000000000110110, 0b0000000001110010, 0b0000000001100011, 0b0000000000001111, }; static int rotateR(int bl){ int dest=0; for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ dest|=(!!(bl&(1<<(4*y+x))))<<(4*x+3-y); } } return dest; } static int rotateL(int bl){ return rotateR(rotateR(rotateR(bl))); } struct board { int lines[HEI]; int stone,stx,sty; }; static void persist(struct board *bd){ // fprintf(stderr,"persist: stone=%d\n",bd->stone); // usleep(1000000); for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ bd->lines[bd->sty+y]|=(!!(bd->stone&(1<<(4*y+x))))<<(bd->stx+x); } } } static void spawn(struct board *bd){ int idx=rand()%7; // fprintf(stderr,"%d\n",idx); // usleep(1000000); bd->stone=stones[idx]; bd->stx=WID/2-1; bd->sty=0; } static void show(const struct board *bd){ struct board bd2; memcpy(&bd2,bd,sizeof bd2); persist(&bd2); printf("\x1B[H\x1B[2J"); for(int y=0;ystone&(1<<(4*y+x)))){ if(bd->sty+y>=HEI)return false; if(bd->stx+x<0||bd->stx+x>=WID)return false; } if(bd->lines[bd->sty+y]&((!!(bd->stone&(1<<(4*y+x))))<<(bd->stx+x)))return false; } } return true; } static void advance(struct board *bd){ fprintf(stderr,"advance: stone=%d\n",bd->stone); if(bd->stone==0){ spawn(bd); return; } bd->sty++; if(!boardvalid(bd)){ bd->sty--; persist(bd); spawn(bd); return; } } static void move(struct board *bd,int dir){ bd->stx+=dir; if(!boardvalid(bd)){ bd->stx-=dir; return; } } static void rotR(struct board *bd){ int st=bd->stone; bd->stone=rotateR(bd->stone); if(!boardvalid(bd))bd->stone=st; } int main(void){ srand(time(NULL)); initkeyboard(false); atexit(endkeyboard); struct board bd; memset(&bd,0,sizeof bd); show(&bd); struct timeval timeleft; timeleft.tv_sec=0; timeleft.tv_usec=0; while(true){ show(&bd); struct timeval start; gettimeofday(&start,NULL); fd_set inset; FD_ZERO(&inset); FD_SET(0,&inset); struct timeval timeout; memcpy(&timeout,&timeleft,sizeof timeout); int ret=select(1,&inset,NULL,NULL,&timeout); assert(ret>=0); struct timeval end; gettimeofday(&end,NULL); if(ret==0){ advance(&bd); timeleft.tv_sec=delay_msec/1000; timeleft.tv_usec=delay_msec%1000*1000; continue; } end.tv_sec-=start.tv_sec; end.tv_usec-=start.tv_usec; if(end.tv_usec<0){ end.tv_sec--; end.tv_usec+=1000000; } timeleft.tv_sec-=end.tv_sec; timeleft.tv_usec-=end.tv_usec; if(timeleft.tv_usec<0){ timeleft.tv_sec--; if(timeleft.tv_sec<0){ timeleft.tv_sec=timeleft.tv_usec=0; } else { timeleft.tv_usec+=1000000; } } assert(FD_ISSET(0,&inset)); int key=tgetkey(); if(key=='Q'||key=='q')break; else if(key=='S'||key=='s'||key==KEY_DOWN){ advance(&bd); timeleft.tv_sec=delay_msec/1000; timeleft.tv_usec=delay_msec%1000*1000; } else if(key=='A'||key=='a'||key==KEY_LEFT)move(&bd,-1); else if(key=='D'||key=='d'||key==KEY_RIGHT)move(&bd,1); else if(key=='W'||key=='w'||key==KEY_UP)rotR(&bd); else bel(); } }