From 1146f7be49eb2a5abe4db7ba06f568cc81192111 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Sat, 10 Feb 2018 20:49:27 +0100 Subject: Nintendo Rotation System --- main.c | 77 +++++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/main.c b/main.c index aa4a20e..910b01f 100644 --- a/main.c +++ b/main.c @@ -17,26 +17,16 @@ #define USE_UNICODE -const int stones[7]={ - 0b0000000001110001, - 0b0000000001110100, - 0b0000000000110011, - 0b0000000000110110, - 0b0000000001110010, - 0b0000000001100011, - 0b0000000000001111, +const int stones[7][4]={ + {0b0000010001110000, 0b0000001100100010, 0b0000000001110001, 0b0000001000100110}, + {0b0000000101110000, 0b0000001000100011, 0b0000000001110100, 0b0000011000100010}, + {0b0000001101100000, 0b0000010001100010, 0b0000001101100000, 0b0000010001100010}, + {0b0000001001110000, 0b0000001000110010, 0b0000000001110010, 0b0000001001100010}, + {0b0000011000110000, 0b0000001001100100, 0b0000011000110000, 0b0000001001100100}, + {0b0000111100000000, 0b0100010001000100, 0b0000111100000000, 0b0100010001000100}, + {0b0000011001100000, 0b0000011001100000, 0b0000011001100000, 0b0000011001100000}, }; -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 leveldelay(int level){ int d=700-(level-1)*35; if(d<50)d=50; @@ -46,38 +36,51 @@ static int leveldelay(int level){ struct board { int lines[HEI]; - int stone,stx,sty; + int stone,str,stx,sty; int ncleared,level,delay; }; static bool boardvalid(const struct board *bd){ + int st=stones[bd->stone][bd->str]; for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ - if((bd->stone&(1<<(4*y+x)))){ + int bit=1<<(4*y+x); + if(st&bit){ 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; + if(bd->lines[bd->sty+y]&((!!(st&bit))<<(bd->stx+x)))return false; } } return true; } static void persist(struct board *bd){ + int st=stones[bd->stone][bd->str]; 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); + bd->lines[bd->sty+y]|=(!!(st&(1<<(4*y+x))))<<(bd->stx+x); } } } +// [0,mx) +static int randomrange(unsigned int mx){ + assert(mx<=(unsigned int)RAND_MAX+1); + unsigned int diff=((unsigned int)RAND_MAX+1)%mx; + unsigned int r=random(); + // happens at most 50% of the time + if(r>RAND_MAX-diff)return randomrange(mx); + return r%mx; +} + // returns false iff game over static bool spawn(struct board *bd){ - int idx=random()%7; - bd->stone=stones[idx]; + bd->stone=randomrange(7); + bd->str=random()%4; bd->stx=WID/2-1; - bd->sty=0; + for(bd->sty=0;(stones[bd->stone][bd->str]&((1<<(4+4*-bd->sty))-1))==0;bd->sty--); return boardvalid(bd); } @@ -146,7 +149,7 @@ static void checklines(struct board *bd){ // returns false iff game over static bool advance(struct board *bd){ - if(bd->stone==0){ + if(bd->stone<0){ return spawn(bd); } bd->sty++; @@ -165,9 +168,13 @@ static void move(struct board *bd,int dir){ } static void rotR(struct board *bd){ - int st=bd->stone; - bd->stone=rotateR(bd->stone); - if(!boardvalid(bd))bd->stone=st; + bd->str=(bd->str+1)%4; + if(!boardvalid(bd))bd->str=(bd->str+3)%4; +} + +static void delaytimeout(const struct board *bd,struct timeval *tv){ + tv->tv_sec=bd->delay/1000; + tv->tv_usec=bd->delay%1000*1000; } @@ -186,14 +193,14 @@ int main(void){ struct board bd; memset(&bd,0,sizeof bd); + bd.stone=-1; bd.ncleared=0; bd.level=1; bd.delay=leveldelay(bd.level); - show(&bd); + spawn(&bd); struct timeval timeleft; - timeleft.tv_sec=0; - timeleft.tv_usec=0; + delaytimeout(&bd,&timeleft); while(true){ show(&bd); @@ -223,8 +230,7 @@ int main(void){ if(ret==0){ if(!advance(&bd))break; - timeleft.tv_sec=bd.delay/1000; - timeleft.tv_usec=bd.delay%1000*1000; + delaytimeout(&bd,&timeleft); continue; } end.tv_sec-=start.tv_sec; @@ -250,8 +256,7 @@ int main(void){ if(key=='Q'||key=='q')break; else if(key=='S'||key=='s'||key==KEY_DOWN){ if(!advance(&bd))break; - timeleft.tv_sec=bd.delay/1000; - timeleft.tv_usec=bd.delay%1000*1000; + delaytimeout(&bd,&timeleft); } 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); -- cgit v1.2.3