split main function
authorLaurent Mazet <mazet@softndesign.org>
Sun, 4 Aug 2024 21:12:26 +0000 (23:12 +0200)
committerLaurent Mazet <mazet@softndesign.org>
Sun, 4 Aug 2024 21:12:26 +0000 (23:12 +0200)
constant.c
constant.h
oneplayer.c [new file with mode: 0644]
oneplayer.h [new file with mode: 0644]
tetris.c
twoplayers.c [new file with mode: 0644]
twoplayers.h [new file with mode: 0644]

index aa9c06344ea8bd8a6462578a45725c0fb7d7be6e..604fd5098ba1ef990540e75529c78077a39d9f9d 100644 (file)
@@ -1,3 +1,5 @@
+#define __CONSTANT_C__
+
 #include <stdio.h>
 #include <string.h>
 
@@ -5,6 +7,23 @@
 
 #include "constant.h"
 
+/* constants */
+
+int height = 20;
+int minwidth = 8;
+int width = 10;
+int maxwidth = 15;
+
+int nbdigit = 5;
+int maxscor = 100000;
+int nbholes = 2;
+
+int savelen = 12;
+int xoffset = 1;
+int yoffset = 1;
+
+/* boards */
+
 #define _nb_blocks_std 7
 
 block_t _blocks_std[_nb_blocks_std] = {
@@ -29,5 +48,4 @@ block_t *getblocks (char *name, int *nb)
     return pt;
 }
 
-
 /* vim: set ts=4 sw=4 et: */
index b31eb6f0249fb0a98ca0c29b1064f8dd0bc352d6..9147046b4b9dc84a96ebd4e7ed3d63a0fd2d45d9 100644 (file)
@@ -3,6 +3,27 @@
 
 #include "type.h"
 
+/* global constants */
+
+#ifndef __CONSTANT_C__
+
+extern int height;
+extern int minwidth;
+extern int width;
+extern int maxwidth;
+
+extern int nbdigit;
+extern int maxscor;
+extern int nbholes;
+
+extern int savelen;
+extern int xoffset;
+extern int yoffset;
+
+#endif /* __CONSTANT_C__ */
+
+/* block definitions */
+
 block_t *getblocks (char *name, int *nb);
 
 #endif /* __CONSTANT_H__ */
diff --git a/oneplayer.c b/oneplayer.c
new file mode 100644 (file)
index 0000000..3270377
--- /dev/null
@@ -0,0 +1,312 @@
+#include <curses.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "constant.h"
+#include "debug.h"
+#include "display.h"
+#include "function.h"
+#include "time.h"
+#include "type.h"
+
+static char *help =
+    "<i> Put down tile\n"
+    "<j> Move left tile\n"
+    "<k> Move down tile\n"
+    "<l> Move right tile\n"
+    "<o> Rotate left tile\n"
+    "<p> Pause\n"
+    "<q> Quit\n"
+    "<u> Rotate right tile\n"
+    "<s> Save file\n"
+    ;
+
+/* main function for one player*/
+int oneplayer (int width, int height, int scale, int chrono, char *filename)
+{
+
+    /* init all variables */
+    board_t *board = NULL;
+    int current = -1;
+    int lines = 0;
+    int next = -1;
+    int score = 0;
+
+    /* read file */
+    if (filename) {
+        char *buffer = readdata (filename);
+        if (buffer == NULL) {
+            VERBOSE (ERROR, fprintf (stderr, "can't read file (%s)\n", filename));
+            return 1;
+        }
+        board = loadboard (buffer);
+        free (buffer);
+        if (board == NULL) {
+            VERBOSE (ERROR, fprintf (stderr, "incorrect file (%s)\n", filename));
+            return 1;
+        }
+        current = board->current;
+        lines = board->lines;
+        next = board->next;
+        score = board->score;
+    } else {
+        board = initboard (width, height);
+    }
+    setscale (board, scale);
+
+    /* get blocks */
+    int nb_blocks = 0;
+    block_t *blocks = getblocks ("std", &nb_blocks);
+    board_t *nextblock = initboard (maxblockwidth (blocks, nb_blocks) + 2,
+                                    maxblockheight (blocks, nb_blocks) + 2);
+    setscale (nextblock, scale);
+
+    /* init seed */
+    newseed ();
+
+    /* get first bloc */
+    int xblock, yblock;
+    block_t *cblock = drawblock (board, blocks, nb_blocks, NULL, &current, &xblock, &yblock, &next);
+
+    /* init curses window */
+    initscr ();
+    noecho ();
+    cbreak ();
+    nonl ();
+    keypad (stdscr, TRUE);
+    curs_set (0);
+    start_color ();
+
+    /* window positions */
+    int xboard = board->xoffset = xoffset + 1;
+    int yboard = board->yoffset = xoffset + 1;
+    int xscore = xboard + xoffset + 2 + board->xsize;
+    int yscore = yboard;
+    nextblock->xoffset = xscore + (9 + nbdigit + 1 - nextblock->xsize) / 2;
+    int ynext = nextblock->yoffset = yscore + 1 + 2 + yoffset;
+    int xhelp = xscore - 1;
+    int yhelp = ynext + nextblock->ysize + yoffset;
+    int xsave = max (xboard + (board->xsize - savelen) / 2, 1);
+    int ysave = yboard + (board->ysize - 1) / 2;
+    char *savename = NULL;
+
+    /* help window */
+    int lhelp = helpwindow (help, xhelp, yhelp);
+
+    /* window positions */
+    int xmsg = xboard;
+    int ymsg = max (yboard + xoffset + 1 + board->ysize, yhelp + lhelp + yoffset);
+    int lmsg = xhelp - xmsg + strmaxlen (help, '\n');
+
+    /* event loop */
+    int mode = -1;
+    int settle = 0;
+    int speed = 5000;
+    float chronoratio = 5.0;
+    int stop = 0;
+    timeval_t blockend = {0, 0};
+    timeval_t lineend = {0, 0};
+    while (!stop) {
+        char msg[128] = {0};
+        msgwindow (msg, xmsg, ymsg, lmsg);
+
+        switch (mode) {
+        case -1:
+            boardwindow (nextblock, 1);
+            displayblock (nextblock, blocks + current, -1, -1);
+            sprintf (msg, "Get ready player One. Press <s> to start");
+            break;
+        case 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 (blockend.tv_sec && isovertime (&blockend)) {
+                if (testvalidpos (board, cblock, xblock, yblock + 1)) {
+                    yblock++;
+                } else {
+                    settle = 1;
+                }
+                setendtime (&blockend, speed);
+            }
+
+            if (settle) {
+                settleblock (board, cblock, xblock, yblock);
+            }
+            int nblines = checkline (board, &score, &lines);
+            if (nblines) {
+                while (nblines-- > 0) {
+                    boardwindow (board, 0);
+                    stackboard (board);
+                    msleep (20 + 200 / (lines / 10 + 1));
+                    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;
+            }
+
+            break;
+        case 2:
+            freeblock (cblock);
+            cblock = NULL;
+            sprintf (msg, "End of game. Press <q> to quit");
+        }
+
+        if (*msg) {
+            halfdelay (0);
+            msgwindow (msg, xmsg, ymsg, lmsg);
+            msleep (800);
+        }
+
+        boardwindow (board, 0);
+        scorewindow (xscore, yscore, nbdigit, score, -1, (lines / 10) + 1);
+        int newspeed = 10 + 4900 / (lines / 10 + 1);
+        if (newspeed != speed) {
+            speed = newspeed;
+            setendtime (&blockend, speed);
+            if (chrono) {
+                setendtime (&lineend, chronoratio * speed);
+            }
+        }
+        if (mode == 1) {
+            displayblock (board, cblock, xblock, yblock);
+        }
+
+        int ch = getch ();
+        switch (mode) {
+        case -1:
+            switch (ch) {
+            case 's':
+                mode = 0;
+                ch = 'p';
+                break;
+            }
+            break;
+        case 1:
+            switch (ch) {
+            case KEY_UP:
+            case 'i':
+                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_ENTER:
+            case '\n':
+            case '\r':
+            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 ' ':
+            case 'u':
+                if (!testvalidpos (board, rotateblock (cblock, -1), xblock, yblock)) {
+                    rotateblock (cblock, 1);
+                }
+                break;
+            }
+            break;
+        case 2:
+            break;
+        }
+        switch (ch) {
+        case 'p':
+            switch (mode) {
+            case 0:
+                mode = 1;
+                setendtime (&blockend, speed);
+                if (chrono) {
+                    setendtime (&lineend, chronoratio * speed);
+                }
+                break;
+            case 1:
+                mode = 0;
+                break;
+            }
+            break;
+        case 'q':
+        case KEY_ESC:
+            stop = 1;
+            break;
+        case 's':
+            savename = savewindow (savelen, xsave, ysave);
+            if (savename != NULL) {
+                board->current = current;
+                board->lines = lines;
+                board->next = next;
+                board->score = score;
+                char *ptr = saveboard (board);
+                if (writedata (savename, ptr)) {
+                    VERBOSE (WARNING, printf ("issue writing Board\n"));
+                }
+                free (ptr);
+                free (savename);
+            }
+            break;
+        //case ERR:
+        //default:
+        }
+    }
+
+    endwin ();
+
+    freeblock (cblock);
+    freeboard (nextblock);
+    freeboard (board);
+
+    return 0;
+}
+
+/* vim: set ts=4 sw=4 et: */
diff --git a/oneplayer.h b/oneplayer.h
new file mode 100644 (file)
index 0000000..cbf130c
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ONEPLAYER_H__
+#define __ONEPLAYER_H__
+
+int oneplayer (int width, int height, int scale, int chrono, char *filename);
+
+#endif /* __ONEPLAYER_H__ */
index 756a73e6c9d1d2108d52cf5e4ad412f1b8ebc770..3dcd3c52a7a9d401c51928fb967c35541ca852f6 100644 (file)
--- a/tetris.c
+++ b/tetris.c
@@ -1,8 +1,8 @@
 /* depend: */
 /* cflags: */
-/* linker: block.o color.c constant.o debug.o display.o function.o time.o -lcurses */
-/* doslnk: block.o color.c constant.o debug.o display.o function.o time.o -lpdc~1 */
-/* winlnk: block.o color.c constant.o debug.o display.o function.o time.o -lpdcurses */
+/* linker: block.o color.c constant.o debug.o display.o function.o oneplayer.o time.o twoplayers.o -lcurses */
+/* doslnk: block.o color.c constant.o debug.o display.o function.o oneplayer.o time.o twoplayers.o -lpdc~1 */
+/* winlnk: block.o color.c constant.o debug.o display.o function.o oneplayer.o time.o twoplayers.o -lpdcurses */
 
 #include <curses.h>
 #include <stdio.h>
 #include "debug.h"
 #include "display.h"
 #include "function.h"
+#include "oneplayer.h"
 #include "time.h"
 #include "type.h"
+#include "twoplayers.h"
 
 /* static variables */
 char *progname = NULL;
@@ -25,42 +27,6 @@ char *filename = NULL;
 int multi = 0;
 int scale = 1;
 
-int height = 20;
-int minwidth = 8;
-int width = 10;
-int maxwidth = 15;
-
-int nbdigit = 5;
-int maxscor = 100000;
-int nbholes = 2;
-
-int savelen = 12;
-int xoffset = 1;
-int yoffset = 1;
-
-char *help =
-    "<i> Put down tile\n"
-    "<j> Move left tile\n"
-    "<k> Move down tile\n"
-    "<l> Move right tile\n"
-    "<o> Rotate left tile\n"
-    "<p> Pause\n"
-    "<q> Quit\n"
-    "<u> Rotate right tile\n"
-    "<s> Save file\n"
-    ;
-
-char *help2 =
-    "<a> or <u> Rotate right tile\n"
-    "<d> or <l> Move right tile\n"
-    "<e> or <o> Rotate left tile\n"
-    "<s> or <k> Move down tile\n"
-    "<p> Pause\n"
-    "<q> or <j> Move left tile\n"
-    "<z> or <i> Put down tile\n"
-    "<escape> Quit\n"
-    ;
-
 int usage (int ret)
 {
     FILE *fd = ret ? stderr : stdout;
@@ -157,408 +123,15 @@ int main (int argc, char *argv[])
         return 1;
     }
 
-    /* init all variables */
-    board_t *board = NULL;
-    board_t *board2 = NULL;
-    int current = -1;
-    int current2 = -1;
-    int lines = 0;
-    int lines2 = 0;
-    int next = -1;
-    int score = 0;
-    int score2 = (multi) ? 0 : -1;
-
-    /* read file */
-    if (filename) {
-        char *buffer = readdata (filename);
-        if (buffer == NULL) {
-            VERBOSE (ERROR, fprintf (stderr, "can't read file (%s)\n", filename));
-            return 1;
-        }
-        board = loadboard (buffer);
-        free (buffer);
-        if (board == NULL) {
-            VERBOSE (ERROR, fprintf (stderr, "incorrect file (%s)\n", filename));
-            return 1;
-        }
-        current = board->current;
-        lines = board->lines;
-        next = board->next;
-        score = board->score;
-    } else {
-        board = initboard (width, height);
-        if (multi) {
-            board2 = initboard (width, height);
-        }
-    }
-    setscale (board, scale);
-    if (multi) {
-        setscale (board2, scale);
-    }
-
-    /* get blocks */
-    int nb_blocks = 0;
-    block_t *blocks = getblocks ("std", &nb_blocks);
-    board_t *nextblock = initboard (maxblockwidth (blocks, nb_blocks) + 2,
-                                    maxblockheight (blocks, nb_blocks) + 2);
-    setscale (nextblock, scale);
-
-    /* init seed */
-    newseed ();
-
-    /* get first bloc */
-    int xblock, yblock;
-    block_t *cblock = drawblock (board, blocks, nb_blocks, NULL, &current, &xblock, &yblock, &next);
-    int xblock2, yblock2;
-    block_t *cblock2 = NULL;
-    if (multi) {
-        cblock2 = drawblock (board2, blocks, nb_blocks, NULL, &current2, &xblock2, &yblock2, &next);
-    }
-
-    /* init curses window */
-    initscr ();
-    noecho ();
-    cbreak ();
-    nonl ();
-    keypad (stdscr, TRUE);
-    curs_set (0);
-    start_color ();
-
-    /* window positions */
-    int xboard = board->xoffset = xoffset + 1;
-    int yboard = board->yoffset = xoffset + 1;
-    int xscore = xboard + xoffset + 2 + board->xsize;
-    int yscore = yboard;
-    nextblock->xoffset = xscore + (9 + nbdigit + 1 - nextblock->xsize) / 2;
-    int ynext = nextblock->yoffset = yscore + 1 + 2 + yoffset;
-    int xhelp = xscore - 1;
-    int yhelp = ynext + nextblock->ysize + yoffset;
-    int xsave = max (xboard + (board->xsize - savelen) / 2, 1);
-    int ysave = yboard + (board->ysize - 1) / 2;
-    char *savename = NULL;
-
-    /* help window */
-    int lhelp = helpwindow ((multi) ? help2 : help, xhelp, yhelp);
-
-    /* window positions */
-    int xmsg = xboard;
-    int ymsg = max (yboard + xoffset + 1 + board->ysize, yhelp + lhelp + yoffset);
-    int lmsg = xhelp - xmsg + strmaxlen (multi ? help2 : help, '\n');
-
-    /* resize windows for multiplayer */
-    if (board2) {
-        board2->xoffset = xhelp + strmaxlen (help2, '\n') + xoffset + 1;
-        board2->yoffset = yboard;
-        nextblock->xoffset = xscore + (strmaxlen (help2, '\n') - nextblock->xsize - 2) / 2;
-        xscore += (strmaxlen (help2, '\n') - 11 - 2 * (nbdigit + 1) - 2) / 2;
-        lmsg += xhelp - xmsg;
-    }
-
-    /* event loop */
-    int mode = -1;
-    int settle = 0;
-    int settle2 = 0;
-    int speed = 5000;
-    float chronoratio = 5.0;
-    int stop = 0;
-    timeval_t blockend = {0, 0};
-    timeval_t blockend2 = {0, 0};
-    timeval_t lineend = {0, 0};
-    while (!stop) {
-        char msg[128] = {0};
-        msgwindow (msg, xmsg, ymsg, lmsg);
-
-        switch (mode) {
-        case -1:
-            boardwindow (nextblock, 1);
-            displayblock (nextblock, blocks + current, -1, -1);
-            sprintf (msg, (multi) ? "Get ready players." : "Get ready player One.");
-            sprintf (msg + strlen (msg), " Press <s> to start");
-            break;
-        case 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 (blockend.tv_sec && isovertime (&blockend)) {
-                if (testvalidpos (board, cblock, xblock, yblock + 1)) {
-                    yblock++;
-                } else {
-                    settle = 1;
-                }
-                setendtime (&blockend, speed);
-            }
-            if (multi && blockend2.tv_sec && isovertime (&blockend2)) {
-                if (testvalidpos (board2, cblock2, xblock2, yblock2 + 1)) {
-                    yblock2++;
-                } else {
-                    settle2 = 1;
-                }
-                setendtime (&blockend2, speed);
-            }
-
-            /* Player one */
-            if (settle) {
-                settleblock (board, cblock, xblock, yblock);
-            }
-            int nblines = checkline (board, &score, &lines);
-            if (nblines) {
-                while (nblines-- > 0) {
-                    boardwindow (board, 0);
-                    stackboard (board);
-                    msleep (20 + 200 / (lines / 10 + 1));
-                    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)) {
-                    if (multi) {
-                        sprintf (msg, "To bad, player One looses. Score is %d / %d", score, score2);
-                    } else {
-                        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;
-            }
-
-            /* Player two */
-            if (multi) {
-                if (settle2) {
-                    settleblock (board2, cblock2, xblock2, yblock2);
-                }
-                int nblines2 = checkline (board2, &score2, &lines2);
-                if (nblines2) {
-                    while (nblines2-- > 0) {
-                        boardwindow (board2, 0);
-                        stackboard (board2);
-                        msleep (20 + 200 / (lines / 10 + 1));
-                        refresh ();
-                    }
-                }
-                if (settle2) {
-                    if (!testvalidpos (board2, blocks + next , board2->width / 2, 0)) {
-                        sprintf (msg, "To bad, player Two looses. Score is %d / %d", score, score2);
-                        mode = 2;
-                    } else {
-                        cblock2 = drawblock (board2, blocks, nb_blocks, cblock2, &current2, &xblock2, &yblock2, &next);
-                    }
-                    settle2 = 0;
-                }
-            }
-            break;
-        case 2:
-            freeblock (cblock);
-            freeblock (cblock2);
-            cblock = NULL;
-            cblock2 = NULL;
-            if (multi) {
-                sprintf (msg, "End of game. Press <escape> to quit");
-            } else {
-                sprintf (msg, "End of game. Press <q> to quit");
-            }
-        }
-
-        if (*msg) {
-            halfdelay (0);
-            msgwindow (msg, xmsg, ymsg, lmsg);
-            msleep (800);
-        }
-
-        boardwindow (board, 0);
-        if (multi) {
-            boardwindow (board2, 0);
-        }
-        scorewindow (xscore, yscore, nbdigit, score, score2, (lines / 10) + 1);
-        int newspeed = 10 + 4900 / (lines / 10 + 1);
-        if (newspeed != speed) {
-            speed = newspeed;
-            setendtime (&blockend, speed);
-            setendtime (&blockend2, speed);
-            if (chrono) {
-                setendtime (&lineend, chronoratio * speed);
-            }
-        }
-        if (mode == 1) {
-            displayblock (board, cblock, xblock, yblock);
-            if (multi) {
-                displayblock (board2, cblock2, xblock2, yblock2);
-            }
-        }
-
-        int ch = getch ();
-        switch (mode) {
-        case -1:
-            switch (ch) {
-            case 's':
-                mode = 0;
-                ch = 'p';
-                break;
-            }
-            break;
-        case 1:
-            switch (ch) {
-            case 'a':
-                if (!testvalidpos (board2, rotateblock (cblock2, -1), xblock2, yblock2)) {
-                    rotateblock (cblock2, 1);
-                }
-                break;
-            case 'e':
-                if (!testvalidpos (board2, rotateblock (cblock2, 1), xblock2, yblock2)) {
-                    rotateblock (cblock2, -1);
-                }
-                break;
-            case KEY_UP:
-            case 'i':
-                while (testvalidpos (board, cblock, xblock, yblock + 1)) {
-                    yblock++;
-                }
-                settle = 1;
-                break;
-            case 'd':
-                if (testvalidpos (board2, cblock2, xblock2 + 1, yblock2)) {
-                    xblock2++;
-                }
-                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_ENTER:
-            case '\n':
-            case '\r':
-            case 'o':
-                if (!testvalidpos (board, rotateblock (cblock, 1), xblock, yblock)) {
-                    rotateblock (cblock, -1);
-                }
-                break;
-            case 'q':
-                if (multi) {
-                    if (testvalidpos (board2, cblock2, xblock2 - 1, yblock2)) {
-                        xblock2--;
-                    }
-                }
-                break;
-            case 's':
-                if (multi) {
-                    if (testvalidpos (board2, cblock2, xblock2, yblock2 + 1)) {
-                        yblock2++;
-                    } else {
-                        settle2 = 1;
-                    }
-                }
-                break;
-            case KEY_BACKSPACE:
-            case KEY_DELETE:
-            case 127:
-            case '\b':
-            case ' ':
-            case 'u':
-                if (!testvalidpos (board, rotateblock (cblock, -1), xblock, yblock)) {
-                    rotateblock (cblock, 1);
-                }
-                break;
-            case 'z':
-                while (testvalidpos (board2, cblock2, xblock2, yblock2 + 1)) {
-                    yblock2++;
-                }
-                settle2 = 1;
-            }
-            break;
-        case 2:
-            break;
-        }
-        switch (ch) {
-        case 'p':
-            switch (mode) {
-            case 0:
-                mode = 1;
-                setendtime (&blockend, speed);
-                if (chrono) {
-                    setendtime (&lineend, chronoratio * speed);
-                }
-                break;
-            case 1:
-                mode = 0;
-                break;
-            }
-            break;
-        case 'q':
-            if (multi) {
-                break;
-            }
-            /* fall through */
-        case KEY_ESC:
-            stop = 1;
-            break;
-        case 's':
-            if (multi) {
-                break;
-            }
-            savename = savewindow (savelen, xsave, ysave);
-            if (savename != NULL) {
-                board->current = current;
-                board->lines = lines;
-                board->next = next;
-                board->score = score;
-                char *ptr = saveboard (board);
-                if (writedata (savename, ptr)) {
-                    VERBOSE (WARNING, printf ("issue writing Board\n"));
-                }
-                free (ptr);
-                free (savename);
-            }
-            break;
-        //case ERR:
-        //default:
-        }
+    switch (multi) {
+    case 0:
+        return oneplayer (width, height, scale, chrono, filename);
+        break;
+    case 1:
+        return twoplayers (width, height, scale);
+        break;
     }
 
-    endwin ();
-
-    freeblock (cblock);
-    freeblock (cblock2);
-    freeboard (nextblock);
-    freeboard (board);
-    freeboard (board2);
-
     return 0;
 }
 
diff --git a/twoplayers.c b/twoplayers.c
new file mode 100644 (file)
index 0000000..c9dadd1
--- /dev/null
@@ -0,0 +1,334 @@
+#include <curses.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "constant.h"
+#include "debug.h"
+#include "display.h"
+#include "function.h"
+#include "time.h"
+#include "type.h"
+
+static char *help =
+    "<a> or <u> Rotate right tile\n"
+    "<d> or <l> Move right tile\n"
+    "<e> or <o> Rotate left tile\n"
+    "<s> or <k> Move down tile\n"
+    "<p> Pause\n"
+    "<q> or <j> Move left tile\n"
+    "<z> or <i> Put down tile\n"
+    "<escape> Quit\n"
+    ;
+
+/* main function for two players */
+int twoplayers (int width, int height, int scale)
+{
+
+    /* init all variables */
+    board_t *board_left = initboard (width, height);
+    board_t *board_right = initboard (width, height);
+    int current_left = -1;
+    int current_right = -1;
+    int lines = 0;
+    int next = -1;
+    int score_left = 0;
+    int score_right = 0;
+
+    setscale (board_left, scale);
+    setscale (board_right, scale);
+
+    /* get blocks */
+    int nb_blocks = 0;
+    block_t *blocks = getblocks ("std", &nb_blocks);
+    board_t *nextblock = initboard (maxblockwidth (blocks, nb_blocks) + 2,
+                                    maxblockheight (blocks, nb_blocks) + 2);
+    setscale (nextblock, scale);
+
+    /* init seed */
+    newseed ();
+
+    /* get first bloc */
+    int xblock_left, yblock_left;
+    block_t *cblock_left = drawblock (board_left, blocks, nb_blocks, NULL, &current_left, &xblock_left, &yblock_left, &next);
+    int xblock_right, yblock_right;
+    block_t *cblock_right = drawblock (board_right, blocks, nb_blocks, NULL, &current_right, &xblock_right, &yblock_right, &next);
+
+    /* init curses window */
+    initscr ();
+    noecho ();
+    cbreak ();
+    nonl ();
+    keypad (stdscr, TRUE);
+    curs_set (0);
+    start_color ();
+
+    /* window positions */
+    board_left->xoffset = xoffset + 1;
+    board_left->yoffset = xoffset + 1;
+    int xscore = board_left->xoffset + xoffset + 2 + board_left->xsize;
+    int yscore = board_left->yoffset;
+    nextblock->xoffset = xscore + (9 + nbdigit + 1 - nextblock->xsize) / 2;
+    nextblock->yoffset = yscore + 1 + 2 + yoffset;
+    int xhelp = xscore - 1;
+    int yhelp = nextblock->yoffset + nextblock->ysize + yoffset;
+
+    /* help window */
+    int lhelp = helpwindow (help, xhelp, yhelp);
+
+    /* window positions */
+    int xmsg = board_left->xoffset;
+    int ymsg = max (board_left->yoffset + yoffset + 1 + board_left->ysize, yhelp + lhelp + yoffset);
+    int lmsg = xhelp - xmsg + strmaxlen (help, '\n');
+
+    /* resize windows for multiplayer */
+    board_right->xoffset = xhelp + strmaxlen (help, '\n') + xoffset + 1;
+    board_right->yoffset = yoffset + 1;
+    nextblock->xoffset = xscore + (strmaxlen (help, '\n') - nextblock->xsize - 2) / 2;
+    xscore += (strmaxlen (help, '\n') - 11 - 2 * (nbdigit + 1) - 2) / 2;
+    lmsg += xhelp - xmsg;
+
+    /* event loop */
+    int mode = -1;
+    int settle_left = 0;
+    int settle_right = 0;
+    int speed = 5000;
+    int stop = 0;
+    timeval_t blockend_left = {0, 0};
+    timeval_t blockend_right = {0, 0};
+    while (!stop) {
+        char msg[128] = {0};
+        msgwindow (msg, xmsg, ymsg, lmsg);
+
+        switch (mode) {
+        case -1:
+            boardwindow (nextblock, 1);
+            //displayblock (nextblock, blocks + current, -1, -1);
+            sprintf (msg, "Get ready players. Press <s> to start");
+            break;
+        case 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 (blockend_left.tv_sec && isovertime (&blockend_left)) {
+                if (testvalidpos (board_left, cblock_left, xblock_left, yblock_left + 1)) {
+                    yblock_left++;
+                } else {
+                    settle_left = 1;
+                }
+                setendtime (&blockend_left, speed);
+            }
+            if (blockend_right.tv_sec && isovertime (&blockend_right)) {
+                if (testvalidpos (board_right, cblock_right, xblock_right, yblock_right + 1)) {
+                    yblock_right++;
+                } else {
+                    settle_right = 1;
+                }
+                setendtime (&blockend_right, speed);
+            }
+
+            /* Player one */
+            if (settle_left) {
+                settleblock (board_left, cblock_left, xblock_left, yblock_left);
+            }
+            int nblines_left = checkline (board_left, &score_left, &lines);
+            if (nblines_left) {
+                while (nblines_left-- > 0) {
+                    boardwindow (board_left, 0);
+                    stackboard (board_left);
+                    msleep (20 + 200 / (lines / 20 + 1));
+                    refresh ();
+                }
+            }
+            if (settle_left) {
+                if (!testvalidpos (board_left, blocks + next , board_left->width / 2, 0)) {
+                    sprintf (msg, "To bad, player One looses. Score is %d / %d", score_left, score_right);
+                    mode = 2;
+                } else {
+                    cblock_left = drawblock (board_left, blocks, nb_blocks, cblock_left, &current_left, &xblock_left, &yblock_left, &next);
+                    boardwindow (nextblock, 1);
+                    displayblock (nextblock, blocks + next, -1, -1);
+                }
+                settle_left = 0;
+            }
+
+            /* Player two */
+            if (settle_right) {
+                settleblock (board_right, cblock_right, xblock_right, yblock_right);
+            }
+            int nblines_right = checkline (board_right, &score_right, &lines);
+            if (nblines_right) {
+                while (nblines_right-- > 0) {
+                    boardwindow (board_right, 0);
+                    stackboard (board_right);
+                    msleep (20 + 200 / (lines / 20 + 1));
+                    refresh ();
+                }
+            }
+            if (settle_right) {
+                if (!testvalidpos (board_right, blocks + next , board_right->width / 2, 0)) {
+                    sprintf (msg, "To bad, player Two looses. Score is %d / %d", score_left, score_right);
+                    mode = 2;
+                } else {
+                    cblock_right = drawblock (board_right, blocks, nb_blocks, cblock_right, &current_right, &xblock_right, &yblock_right, &next);
+                }
+                settle_right = 0;
+            }
+
+            break;
+        case 2:
+            freeblock (cblock_left);
+            freeblock (cblock_right);
+            cblock_left = NULL;
+            cblock_right = NULL;
+            sprintf (msg, "End of game. Press <escape> to quit");
+        }
+
+        if (*msg) {
+            halfdelay (0);
+            msgwindow (msg, xmsg, ymsg, lmsg);
+            msleep (800);
+        }
+
+        boardwindow (board_left, 0);
+        boardwindow (board_right, 0);
+        scorewindow (xscore, yscore, nbdigit, score_left, score_right, (lines / 20) + 1);
+        int newspeed = 10 + 4900 / (lines / 20 + 1);
+        if (newspeed < speed) {
+            speed = newspeed;
+            setendtime (&blockend_left, speed);
+            setendtime (&blockend_right, speed);
+        }
+        if (mode == 1) {
+            displayblock (board_left, cblock_left, xblock_left, yblock_left);
+            displayblock (board_right, cblock_right, xblock_right, yblock_right);
+        }
+
+        int ch = getch ();
+        switch (mode) {
+        case -1:
+            switch (ch) {
+            case 's':
+                mode = 0;
+                ch = 'p';
+                break;
+            }
+            break;
+        case 1:
+            switch (ch) {
+            case 'a':
+                if (!testvalidpos (board_left, rotateblock (cblock_left, -1), xblock_left, yblock_left)) {
+                    rotateblock (cblock_left, 1);
+                }
+                break;
+            case 'e':
+                if (!testvalidpos (board_left, rotateblock (cblock_left, 1), xblock_left, yblock_left)) {
+                    rotateblock (cblock_left, -1);
+                }
+                break;
+            case KEY_UP:
+            case 'i':
+                while (testvalidpos (board_right, cblock_right, xblock_right, yblock_right + 1)) {
+                    yblock_right++;
+                }
+                settle_right = 1;
+                break;
+            case 'd':
+                if (testvalidpos (board_left, cblock_left, xblock_left + 1, yblock_left)) {
+                    xblock_left++;
+                }
+                break;
+            case KEY_LEFT:
+            case 'j':
+                if (testvalidpos (board_right, cblock_right, xblock_right - 1, yblock_right)) {
+                    xblock_right--;
+                }
+                break;
+            case KEY_DOWN:
+            case 'k':
+                if (testvalidpos (board_right, cblock_right, xblock_right, yblock_right + 1)) {
+                    yblock_right++;
+                } else {
+                    settle_right = 1;
+                }
+                break;
+            case KEY_RIGHT:
+            case 'l':
+                if (testvalidpos (board_right, cblock_right, xblock_right + 1, yblock_right)) {
+                    xblock_right++;
+                }
+                break;
+            case KEY_ENTER:
+            case '\n':
+            case '\r':
+            case 'o':
+                if (!testvalidpos (board_right, rotateblock (cblock_right, 1), xblock_right, yblock_right)) {
+                    rotateblock (cblock_right, -1);
+                }
+                break;
+            case 'q':
+                if (testvalidpos (board_left, cblock_left, xblock_left - 1, yblock_left)) {
+                    xblock_left--;
+                }
+                break;
+            case 's':
+                if (testvalidpos (board_left, cblock_left, xblock_left, yblock_left + 1)) {
+                    yblock_left++;
+                } else {
+                    settle_left = 1;
+                }
+                break;
+            case KEY_BACKSPACE:
+            case KEY_DELETE:
+            case 127:
+            case '\b':
+            case ' ':
+            case 'u':
+                if (!testvalidpos (board_right, rotateblock (cblock_right, -1), xblock_right, yblock_right)) {
+                    rotateblock (cblock_right, 1);
+                }
+                break;
+            case 'z':
+                while (testvalidpos (board_left, cblock_left, xblock_left, yblock_left + 1)) {
+                    yblock_left++;
+                }
+                settle_left = 1;
+            }
+            break;
+        case 2:
+            break;
+        }
+        switch (ch) {
+        case 'p':
+            switch (mode) {
+            case 0:
+                mode = 1;
+                setendtime (&blockend_left, speed);
+                break;
+            case 1:
+                mode = 0;
+                break;
+            }
+            break;
+        case KEY_ESC:
+            stop = 1;
+            break;
+        //case ERR:
+        //default:
+        }
+    }
+
+    endwin ();
+
+    freeblock (cblock_left);
+    freeblock (cblock_right);
+    freeboard (nextblock);
+    freeboard (board_left);
+    freeboard (board_right);
+
+    return 0;
+}
+
+/* vim: set ts=4 sw=4 et: */
diff --git a/twoplayers.h b/twoplayers.h
new file mode 100644 (file)
index 0000000..2ce7f92
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __TWOPLAYERS_H__
+#define __TWOPLAYERS_H__
+
+int twoplayers (int width, int height, int scale);
+
+#endif /* __TWOPLAYERS_H__ */