add time penalty mode
authorLaurent Mazet <mazet@softndesign.org>
Mon, 29 Jul 2024 19:08:34 +0000 (21:08 +0200)
committerLaurent Mazet <mazet@softndesign.org>
Mon, 29 Jul 2024 19:08:34 +0000 (21:08 +0200)
display.c
function.c
function.h
tetris.c

index 96f44dbd57b948ac8c820ea2597adbd4bffdde72..e6ed047e35a959edd1f74ce30ab80e4b39b2f0a0 100644 (file)
--- a/display.c
+++ b/display.c
@@ -93,6 +93,9 @@ void _put_color_block (int y, int x, char symb)
     case '7':
         mvaddcb (y, x, green);
         break;
+    case '8':
+        mvaddcb (y, x, white);
+        break;
     }
 }
 
index 894f61ffc62a701d6bfabd2ac316157c40d8548e..943dfb218a23aecc432135253555f06f6cb36069 100644 (file)
@@ -415,4 +415,39 @@ void stackboard (board_t *board)
     }
 }
 
+int addline (board_t *board, int nbholes)
+{
+    int i, j;
+
+    /* check empty ligne */
+    int isempty = 1;
+    for (i = 0; i < board->width; i++) {
+        if (*getcell (board, i, 0) != ' ') {
+            isempty = 0;
+            break;
+        }
+    }
+
+    /* move up */
+    for (j = 1; j < board->height; j++) {
+        for (i = 0; i < board->width; i++) {
+            *getcell (board, i, j - 1) = *getcell (board, i, j);
+        }
+    }
+
+    /* random line */
+    for (i = 0; i < board->width; i++) {
+        *getcell (board, i, board->height - 1) = '8';
+    }
+    while (nbholes) {
+        i = rand () % board->width;
+        if (*getcell (board, i, board->height - 1) == '8') {
+            *getcell (board, i, board->height - 1) = ' ';
+            nbholes--;
+        }
+    }
+
+    return isempty;
+}
+
 /* vim: set ts=4 sw=4 et: */
index 86420f9beab1bfd1895e6400fb0ca6b97c815f2f..e9af8131c5df32ce3b231d23df330347f58872aa 100644 (file)
@@ -59,6 +59,8 @@ int checkline (board_t *board, int *score, int *lines);
 
 void stackboard (board_t *board);
 
+int  addline (board_t *board, int nbholes);
+
 #endif /* __FUNCTION_H__ */
 
 /* vim: set ts=4 sw=4 et: */
index 256caf792bcd13756b5f84c445f1059b8a6378c4..bb610fc531df91a10782b618d3acc8946fea3492 100644 (file)
--- a/tetris.c
+++ b/tetris.c
@@ -22,6 +22,7 @@
 char *progname = NULL;
 char *version = "1.1";
 
+int chrono = 0;
 char *filename = NULL;
 int scale = 1;
 
@@ -32,6 +33,7 @@ int maxwidth = 15;
 
 int nbdigit = 5;
 int maxscor = 100000;
+int nbholes = 2;
 
 int savelen = 12;
 int xoffset = 1;
@@ -52,7 +54,8 @@ char *help =
 int usage (int ret)
 {
     FILE *fd = ret ? stderr : stdout;
-    fprintf (fd, "usage: %s [-f file] [-h] [-s int] [-v int] [-w int]\n", progname);
+    fprintf (fd, "usage: %s [-c] [-f file] [-h] [-s int] [-v int] [-w int]\n", progname);
+    fprintf (fd, " -c: time penalty (%s)", (chrono) ? "yes" : "no" );
     fprintf (fd, " -f: file name (%s)\n", (filename) ? filename : "none");
     fprintf (fd, " -s: scale [0..3] (%d)\n", scale);
     fprintf (fd, " -v: verbose level (%d)\n", verbose);
@@ -62,6 +65,30 @@ int usage (int ret)
     return ret;
 }
 
+block_t *drawblock (board_t *board, block_t *blocks, int nb_blocks, block_t *cblock, int *current, int *xblock, int *yblock, int *next)
+{
+    /* clean block and get next */
+    if (cblock) {
+        freeblock (cblock);
+        *current = *next;
+        *next = rand () % nb_blocks;
+    }
+
+    /* init state */
+    if (*current == -1) {
+        *current = rand () % nb_blocks;
+    }
+    if (*next == -1) {
+        *next = rand () % nb_blocks;
+    }
+
+    cblock = copyblock (blocks + *current);
+    *xblock = board->width / 2;
+    *yblock = 0;
+
+    return cblock;
+}
+
 void setendtime (struct timeval *t, int s)
 {
     gettimeofday (t, NULL);
@@ -100,6 +127,9 @@ int main (int argc, char *argv[])
         }
         char c = arg[1];
         switch (c) {
+        case 'c':
+            chrono = 1;
+            break;
         case 'f':
             arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
             if (arg == NULL) {
@@ -188,15 +218,8 @@ int main (int argc, char *argv[])
     srand (time (NULL));
 
     /* get first bloc */
-    if (current == -1) {
-        current = rand () % nb_blocks;
-    }
-    block_t *cblock = copyblock (blocks + current);
-    int xblock = board->width / 2;
-    int yblock = 0;
-    if (next == -1) {
-        next = rand () % nb_blocks;
-    }
+    int xblock, yblock;
+    block_t *cblock = drawblock (board, blocks, nb_blocks, NULL, &current, &xblock, &yblock, &next);
     VERBOSE (DEBUG, fprintf (stderr, "%d/%d: (%d, %d)\n", current, nb_blocks, xblock, yblock));
 
     /* init curses window */
@@ -233,10 +256,13 @@ int main (int argc, char *argv[])
     int mode = -1;
     int settle = 0;
     int speed = 5000;
+    float chronoratio = 5.0;
     int stop = 0;
-    struct timeval tend = {0, 0};
+    struct timeval blockend = {0, 0};
+    struct timeval lineend = {0, 0};
     while (!stop) {
         char msg[128] = {0};
+        msgwindow (msg, xmsg, ymsg, lmsg);
 
         switch (mode) {
         case -1:
@@ -245,38 +271,58 @@ int main (int argc, char *argv[])
             sprintf (msg, "Get ready player One. Press <s> to start");
             break;
         case 0:
-            halfdelay (0);
             boardwindow (nextblock, 1);
             displayblock (nextblock, blocks + current, -1, -1);
             sprintf (msg, "Game in pause. Pause <p> to continue");
             break;
         case 1:
             halfdelay (1);
-            if (tend.tv_sec && isovertime (&tend)) {
+            if (blockend.tv_sec && isovertime (&blockend)) {
                 if (testvalidpos (board, cblock, xblock, yblock + 1)) {
                     yblock++;
                 } else {
                     settle = 1;
                 }
-                setendtime (&tend, speed);
+                setendtime (&blockend, speed);
             }
             if (settle) {
                 settleblock (board, cblock, xblock, yblock);
-                freeblock (cblock);
-                current = next;
-                cblock = copyblock (blocks + current);
-                xblock = board->width / 2;
-                yblock = 0;
-                next = rand () % nb_blocks;
-                settle = 0;
             }
-            if (!testvalidpos (board, cblock, xblock, yblock)) {
-                halfdelay (0);
-                mode = 2;
-                sprintf (msg, "To bad, you loose. Score is %d", score);
+            int nblines = checkline (board, &score, &lines);
+            if (nblines) {
+                while (nblines-- > 0) {
+                    boardwindow (board, 0);
+                    stackboard (board);
+                    usleep ((200 + 2000 / (lines / 10 + 1)) * 100);
+                    refresh ();
+                }
+                if (chrono) {
+                    setendtime (&lineend, chronoratio * speed);
+                }
+            } else if (chrono && lineend.tv_sec && isovertime (&lineend)) {
+                if (!testvalidpos (board, cblock, xblock, yblock + 1)) {
+                    settleblock (board, cblock, xblock, yblock);
+                    settle = 1;
+                }
+                int isempty = addline (board, nbholes);
+                if (!isempty) {
+                    sprintf (msg, "Shame, you loose. Score is %d", score);
+                    mode = 2;
+                    settle = 0;
+                }
+                setendtime (&lineend, chronoratio * speed);
+            }
+            if (settle) {
+                if (!testvalidpos (board, blocks + next , board->width / 2, 0)) {
+                    sprintf (msg, "To bad, you loose. Score is %d", score);
+                    mode = 2;
+                } else {
+                    cblock = drawblock (board, blocks, nb_blocks, cblock, &current, &xblock, &yblock, &next);
+                    boardwindow (nextblock, 1);
+                    displayblock (nextblock, blocks + next, -1, -1);
+                }
+                settle = 0;
             }
-            boardwindow (nextblock, 1);
-            displayblock (nextblock, blocks + next, -1, -1);
             break;
         case 2:
             freeblock (cblock);
@@ -284,20 +330,21 @@ int main (int argc, char *argv[])
             sprintf (msg, "End of game. Press <q> to quit");
         }
 
-        msgwindow (msg, xmsg, ymsg, lmsg);
-        int nblines = checkline (board, &score, &lines);
-        while (nblines-- > 0) {
-            boardwindow (board, 0);
-            stackboard (board);
-            usleep ((200 + 2000 / (lines / 10 + 1)) * 100);
-            refresh ();
+        if (*msg) {
+            halfdelay (0);
+            msgwindow (msg, xmsg, ymsg, lmsg);
+            usleep (800000);
         }
+
         boardwindow (board, 0);
         scorewindow (xscore, yscore, nbdigit, score, (lines / 10) + 1);
         int newspeed = 10 + 4900 / (lines / 10 + 1);
         if (newspeed != speed) {
             speed = newspeed;
-            setendtime (&tend, speed);
+            setendtime (&blockend, speed);
+            if (chrono) {
+                setendtime (&lineend, chronoratio * speed);
+            }
         }
         if (mode == 1) {
             displayblock (board, cblock, xblock, yblock);
@@ -371,7 +418,10 @@ int main (int argc, char *argv[])
             switch (mode) {
             case 0:
                 mode = 1;
-                setendtime (&tend, speed);
+                setendtime (&blockend, speed);
+                if (chrono) {
+                    setendtime (&lineend, chronoratio * speed);
+                }
                 break;
             case 1:
                 mode = 0;
@@ -432,5 +482,7 @@ int main (int argc, char *argv[])
 /* test: { echo -n s; sleep 1; echo lllololo; sleep 1; echo jjjujuju; sleep 1; echo lllololo; sleep 1; echo jjjujuju; sleep 1; echo q; } | tetris.exe -w 9*/
 /* test: { echo -n s; sleep 1; echo ccccccccccccc; sleep 1; echo q; } | tetris.exe */
 /* test: { echo -n s; sleep 1; echo -n jjuuuc; sleep 1; echo -n jjoc; sleep 1; echo q; } | tetris.exe -f lines.ttr */
+/* test: { echo -n s; sleep 1; echo -n jjuuuc; sleep 1; echo -n jjoc; sleep 1; echo q; } | tetris.exe -c -f lines.ttr */
+/* test: { echo -n sccccccc; sleep 50; echo q; } | tetris.exe -c */
 
 /* vim: set ts=4 sw=4 et: */