From 93a5f1b89f48308bb4287a8d39ecde88e4549613 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Wed, 7 Feb 2018 13:19:00 +0100 Subject: Initial --- .gitignore | 2 + Makefile | 4 ++ main.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a7c9ed4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +termio +tetris diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1899fcf --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +all: tetris + +tetris: $(wildcard *.c *.h) + gcc -Wall -Wextra -std=c11 -O2 -fwrapv -o $@ $(filter %.c,$^) -Itermio termio/libtermio.a diff --git a/main.c b/main.c new file mode 100644 index 0000000..d1c5138 --- /dev/null +++ b/main.c @@ -0,0 +1,203 @@ +#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(); + } +} -- cgit v1.2.3-54-g00ecf