blocks stuck on ground
authorLaurent Mazet <mazet@softndesign.org>
Tue, 23 Jul 2024 19:07:01 +0000 (21:07 +0200)
committerLaurent Mazet <mazet@softndesign.org>
Tue, 23 Jul 2024 19:07:01 +0000 (21:07 +0200)
display.c
function.c
function.h
tetris.c

index 12fd83b1c1879cffa77a8037fa1289436e3fae91..b1c047074f9a3f26a5cd7b479382c44a9fddad19 100644 (file)
--- a/display.c
+++ b/display.c
@@ -224,7 +224,7 @@ void displayblock (board_t *board, block_t *block, int x, int y)
     for (i = 0; i < block->width; i++) {
         for (j = 0; j < block->height; j++) {
             if (*getcell (block, i, j) != ' ') {
-                _element (board, x + i, y + j, '0' + block->color);
+                _element (board, x - block->width / 2 + i, y + j, '0' + block->color);
             }
         }
     }
index 7e9c16052455ddd8082dd96ce016fccb600f322a..2e6429dabfc815c6c5d37750c8025873a682a4b0 100644 (file)
@@ -87,7 +87,7 @@ int _makecomments (char *buffer, board_t *board)
     for (j = 0; j < board->height; j++) {
         l += sprintf (buffer + l, "rem: \"");
         for (i = 0; i < board->width; i++) {
-            l += sprintf (buffer + l, "%c", getvalue (board, i, j));
+            l += sprintf (buffer + l, "%c", *getcell (board, i, j));
         }
         l += sprintf (buffer + l, "\"\n");
     }
@@ -308,4 +308,37 @@ block_t *rotateblock (block_t *block, int rot)
     return block;
 }
 
+int testvalidpos (board_t *board, block_t *block, int x, int y)
+{
+    int ret = 1;
+    if ((x - block->width / 2 < 0) || (x - block->width / 2 + block->width > board->width) ||
+        (y + block->height > board->height)) {
+       ret = 0;
+    } else {
+        int i, j;
+        for (i = 0; i < block->width; i++) {
+            for (j = 0; j < block->height; j++) {
+                if (*getcell (block, i, j) == '.') {
+                    if (*getcell (board, x - block->width / 2 + i, y + j) != ' ') {
+                        ret = 0;
+                    }
+                }
+            }
+        }
+    }
+    return ret;
+}
+
+void settleblock (board_t *board, block_t *block, int x, int y)
+{
+    int i, j;
+    for (i = 0; i < block->width; i++) {
+        for (j = 0; j < block->height; j++) {
+            if (*getcell (block, i, j) == '.') {
+                *getcell (board, x - block->width / 2 + i, y + j) = '0' + block->color;
+            }
+        }
+    }
+}
+
 /* vim: set ts=4 sw=4 et: */
index e7a5340ea74b57ded8b5e8219a0ec33f9d49be09..2cd7c8c8aefdcdc9c2797f718be1d3c77fbbd1bf 100644 (file)
@@ -39,8 +39,6 @@ board_t *loadboard (char *str);
 
 #define getcell(b, x, y) ({ __typeof__ (b) _b = (b); int _x = (x), _y = (y);_b->tab + _x + _b->width * _y; })
 
-#define getvalue(b, x, y) ({ __typeof__ (b) _b = (b); int _x = (x), _y = (y); (_x >= 0) && (_x < _b->width) && (_y >= 0) && (_y < _b->height) ? *(getcell (_b, _x, _y)) : 0; })
-
 block_t *initblock (int xsize, int ysize);
 
 block_t *changeblock (block_t *dest, block_t *src);
@@ -51,6 +49,10 @@ void freeblock (block_t *block);
 
 block_t *rotateblock (block_t *block, int rot);
 
+int testvalidpos (board_t *board, block_t *block, int x, int y);
+
+void settleblock (board_t *board, block_t *block, int x, int y);
+
 #endif /* __FUNCTION_H__ */
 
 /* vim: set ts=4 sw=4 et: */
index 37383cc516303ed495627b0d68dbce68c46494e8..4eda0a2bce60f7b2c9c3a6cabbdaf0dcf713d112 100644 (file)
--- a/tetris.c
+++ b/tetris.c
@@ -152,7 +152,7 @@ int main (int argc, char *argv[])
     block_t *blocks = getblocks ("std", &nb_blocks);
     int current = rand () % nb_blocks;
     block_t *cblock = copyblock (blocks + current);
-    int xblock = (board->width - cblock->width) / 2;
+    int xblock = board->width / 2;
     int yblock = 0;
     int next = rand () % nb_blocks;
     VERBOSE (DEBUG, fprintf (stderr, "%d/%d: (%d, %d)\n", current, nb_blocks, xblock, yblock));
@@ -170,8 +170,6 @@ int main (int argc, char *argv[])
     int xboard = board->xoffset = xoffset + 1;
     int yboard = board->yoffset = xoffset + 1;
     int xhelp = xboard + xoffset + 1 + board->xsize;
-    int xcursor = 1;
-    int ycursor = 0;
     int yhelp = yboard - 1;
     int xsave = max (xboard + (board->xsize - savelen) / 2, 1);
     int ysave = yboard + (board->ysize - 1) / 2;
@@ -188,77 +186,113 @@ int main (int argc, char *argv[])
     /* event loop */
     int mode = 0;
     int speed = 5000;
-    int rot = 0;
+    int settle = 0;
     int stop = 0;
     struct timeval tend = {0, 0};
     while (!stop) {
+        char msg[128] = {0};
 
-        boardwindow (board);
-        if (1) { /* not end of game */
-            char msg[128] = {0};
-            switch (mode) {
-            case 0:
-freeblock (cblock);
-current = next;
-cblock = copyblock (blocks + current);
-xblock = (board->width - cblock->width) / 2;
-yblock = 0;
-next = rand () % nb_blocks;
-sprintf (msg, "%d/%d: (%d, %d)\n", current, nb_blocks, xblock, yblock);
-                halfdelay (0);
-                //sprintf (msg, "Get ready player One");
-                break;
-            case 1:
-                halfdelay (10);
-                rotateblock (cblock, rot);
-                if (isovertime (&tend)) {
+        switch (mode) {
+        case 0:
+            halfdelay (0);
+            sprintf (msg, "Get ready player One");
+            break;
+        case 1:
+            halfdelay (1);
+            if (tend.tv_sec && isovertime (&tend)) {
+                if (testvalidpos (board, cblock, xblock, yblock + 1)) {
                     yblock++;
-                    if (yblock + cblock->height >= board->height) {
-                        freeblock (cblock);
-                        current = next;
-                        cblock = copyblock (blocks + current);
-                        xblock = (board->width - cblock->width) / 2;
-                        yblock = 0;
-                        next = rand () % nb_blocks;
-                    }
-                    setendtime (&tend, speed);
+                } else {
+                    settle = 1;
                 }
-                displayblock (board, cblock, xblock, yblock);
-                rot = 0;
-sprintf (msg, "%ld/%06ld\n", tend.tv_sec, tend.tv_usec);
-                break;
+                setendtime (&tend, 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, "End of game");
             }
-            msgwindow (msg, xmsg, ymsg, lmsg);
-        } else {
-            msgwindow ("End of game", xmsg, ymsg, lmsg);
+            break;
+        case 2:
+            freeblock (cblock);
+            cblock = NULL;
+            sprintf (msg, "Press q to quit");
+        }
+
+        msgwindow (msg, xmsg, ymsg, lmsg);
+        boardwindow (board);
+        if (mode == 1) {
+            displayblock (board, cblock, xblock, yblock);
         }
 
         int ch = getch ();
-        switch (ch) {
-        case KEY_ENTER:
-        case '\n':
-        case '\r':
-        case 'c':
-            yblock = board->height - cblock->height;
-            break;
-        case KEY_LEFT:
-        case 'j':
-            xblock--;
+        switch (mode) {
+        case 0:
             break;
-        case KEY_DOWN:
-        case 'k':
-            yblock++;
-            break;
-        case KEY_RIGHT:
-        case 'l':
-            xblock++;
+        case 1:
+            switch (ch) {
+            case KEY_ENTER:
+            case '\n':
+            case '\r':
+            case 'c':
+                while (testvalidpos (board, cblock, xblock, yblock + 1)) {
+                    yblock++;
+                }
+                settle = 1;
+                break;
+            case KEY_LEFT:
+            case 'j':
+                if (testvalidpos (board, cblock, xblock - 1, yblock)) {
+                    xblock--;
+                }
+                break;
+            case KEY_DOWN:
+            case 'k':
+                if (testvalidpos (board, cblock, xblock, yblock + 1)) {
+                    yblock++;
+                } else {
+                    settle = 1;
+                }
+                break;
+            case KEY_RIGHT:
+            case 'l':
+                if (testvalidpos (board, cblock, xblock + 1, yblock)) {
+                    xblock++;
+                }
+                break;
+            case KEY_UP:
+            case ' ':
+            case 'i':
+            case 'o':
+                if (!testvalidpos (board, rotateblock (cblock, 1), xblock, yblock)) {
+                    rotateblock (cblock, -1);
+                }
+                break;
+            case KEY_BACKSPACE:
+            case KEY_DELETE:
+            case 127:
+            case '\b':
+            case 'u':
+                if (!testvalidpos (board, rotateblock (cblock, -1), xblock, yblock)) {
+                    rotateblock (cblock, 1);
+                }
+                break;
+            }
             break;
-        case KEY_UP:
-        case ' ':
-        case 'i':
-        case 'o':
-            rot = 1;
+        case 2:
             break;
+        }
+        switch (ch) {
         case 'p':
             mode = (mode == 0) ? 1 : 0; 
             if (mode == 1) {
@@ -280,13 +314,6 @@ sprintf (msg, "%ld/%06ld\n", tend.tv_sec, tend.tv_usec);
                 free (savename);
             }
             break;
-        case KEY_BACKSPACE:
-        case KEY_DELETE:
-        case 127:
-        case '\b':
-        case 'u':
-            rot = -1;
-            break;
         //case ERR:
         //default:
         }