unofficial version 0.7.1: ui improvements v0.7.1
authorMischa POSLAWSKY <netris@shiar.org>
Tue, 20 Aug 2002 01:23:00 +0000 (03:23 +0200)
committerMischa POSLAWSKY <netris@shiar.org>
Tue, 27 Feb 2007 05:05:01 +0000 (06:05 +0100)
Server fixes, many visual improvements (event messages, piece shadow).

12 files changed:
CHANGES
Configure
TODO [new file with mode: 0644]
VERSION [deleted file]
board.c
curses.c
game.c
inet.c
netris.h
robot.c
server.c
util.c

diff --git a/CHANGES b/CHANGES
index ff4175c9cec35a2a274f2116b4ec173277975adb..be0fa70c3a554da34a6b52be774539d09a9dd2c4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
  * doesn't display fields which don't fit on screen automatically
  * quit key (q by default)
 
+ -- v0.7.811 ------
 
----- near-future: ------------------------------------------------------------
+ * title bar inverted
+ * scorebar less wide (now 3 fields take 82 chars)
 
+ -- v0.7.813 ------
 
----- asap: -------------------------------------------------------------------
+ * blocks are normal text in !curses (not bold or anything)
+ * server handles incoming connections as events too (continuously)
 
- * fix -f
- * fix bot
- * server continuously acceping new connections, and immediate handshake
- * midgame join option
- * optional smaller enemy fields
- * multiplayer stats
+ -- v0.7.814 ------
 
+ * show (paused) game right after receiving game data, before receiving players
+ * server starts game after receiving minimum number of players (--min-players)
+ * client altered to receive players during game loop
+ * server has --max-players option for player limit (default is 8)
+ * (empty) fields are drawn for maximum number of players
+ * server quits correctly, client quits only when no players are left
+ * players join paused when game hasn't started yet
+ * player's pause state is transmitted by server
+ * server does not keep repeating goahead on every join
+ * ^l (by default) redraws screen (doesn't work correctly on all terms yet)
+ * before game has started, '(not) ready' is displayed instead of 'pause'
+ * 'empty' message over empty fields, 'game over' over dead players
+ * player rejoin fixed
 
----- distant future: ---------------------------------------------------------
+ -- v0.7.815 ------
 
- * special blocks
- * tetrinet compatible?
- * remove bot delay (make it humanplayer-like)
- * new+better bot?
+ * server started w/o --continuous exits when just 1 player or team left
+ * players can't join a started non-continuous game
+ * game starts if non-ready player leaves and everybody else is ready
+ * message when you or enemies add junklines
 
+ -- v0.7.817 ------
+
+ * went g/o when one player of a team went g/o instead of all of 'em
+ * improved handling of closing connections in server
+ * naw player's name refreshed on join
+ * clients don't receive death signal from rejected player anymore
+
+ -- v0.7.819 ------
+
+ * shadow piece (preview current piece dropped down)
+ * players are now 'fragged' by the player last adding them lines
+ * ^ when that last player was himself(m/f) (s)he just 'died'
+ * 'Close connection' message no longer displayed
+ * players in teams are displayed in their teamcolor
 
 ------------------------------------------------------------------------------
index a17707ebd95e8f344d1e65a48bfcd1a9605620e6..537142f2b52e1c46528b43686905cc60f99a117d 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -21,8 +21,8 @@
 #
 
 CC="gcc"
-COPT="-O -m486"
-CEXTRA=""
+COPT="-O"
+CEXTRA="-m486"
 LEXTRA=""
 CURSES_HACK=false
 
@@ -32,7 +32,7 @@ while [ $# -ge 1 ]; do
        case "$opt" in
                -g)
                        COPT="-g -O0"
-#                      CEXTRA="-Wall -Wstrict-prototypes"
+#                      CEXTRA="-Wall -Wstrict-prototypes -m486"
                        ;;
                -O*)
                        COPT="$opt"
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..3696e06
--- /dev/null
+++ b/TODO
@@ -0,0 +1,37 @@
+---- near-future: ------------------------------------------------------------
+
+ * everybody in a team
+ * teams are colored
+ * server never quits
+ * 'you won' message, remove 'close connection' echo
+ * (check if commandprompt is below game)
+ * transmit player fields of game in progress to new player
+       * server has to maintain copy of player fields
+ * empty new player's field (in case of recycle)
+ * completely fix redraw
+ * redraw on window resize
+ * message position/size
+ * allow custom nicks
+ * move piece when unable to rotate at screenedge
+
+
+---- asap: -------------------------------------------------------------------
+
+ * observers (join as g/o player)
+ * fix -f
+ * half width enemy fields if out of screen space
+ * fix bot
+ * multiplayer stats
+ * time-based singleplayer leveling?
+ * shapes stored as bitmap, rotate by modifying for
+
+
+---- distant future: ---------------------------------------------------------
+
+ * horizontally _and_ vertically resize enemy fields
+ * special blocks
+ * tetrinet compatible?
+ * remove bot delay (make it humanplayer-like)
+ * new+better bot?
+ * replay ability? (tspec replay compatible?)
+
diff --git a/VERSION b/VERSION
deleted file mode 100644 (file)
index 83fb97f..0000000
--- a/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-0.5.88
diff --git a/board.c b/board.c
index 8524cc5b7adeceff018baa0c2b8df445fca8880a..55983b477de3513218ebab9b019e0db1e029956f 100644 (file)
--- a/board.c
+++ b/board.c
@@ -33,11 +33,18 @@ static BlockType oldBoard[MAX_SCREENS][MAX_BOARD_HEIGHT][MAX_BOARD_WIDTH];
 static unsigned int changed[MAX_SCREENS][MAX_BOARD_HEIGHT];
 static int falling[MAX_SCREENS][MAX_BOARD_WIDTH];
 static int oldFalling[MAX_SCREENS][MAX_BOARD_WIDTH];
+static int shadowy;
 
-ExtFunc void CleanupBoard(int scr)
+
+ExtFunc void ClearField(int scr)
 {
-       CleanupScreen(scr);
-}
+       int y, x;
+
+       for (y = Players[scr].boardHeight - 1; y >= 0; --y)
+               for (x = 0; x < Players[scr].boardWidth; ++x) {
+                       oldBoard[scr][y][x] = board[scr][y][x] = BT_none;
+               }
+} //ClearField
 
 ExtFunc BlockType GetBlock(int scr, int y, int x)
 {
@@ -47,7 +54,7 @@ ExtFunc BlockType GetBlock(int scr, int y, int x)
                return BT_none;
        else
                return abs(board[scr][y][x]);
-}
+} //GetBlock
 
 ExtFunc void SetBlock(int scr, int y, int x, BlockType type)
 {
@@ -58,10 +65,10 @@ ExtFunc void SetBlock(int scr, int y, int x, BlockType type)
                board[scr][y][x] = type;
                changed[scr][y] |= 1 << x;
        }
-}
+} //SetBlock
 
 ExtFunc int RefreshBoard(int scr)
-{
+{ //draw changes to screen
        int y, x, any = 0;
        unsigned int c;
        BlockType b;
@@ -77,7 +84,7 @@ ExtFunc int RefreshBoard(int scr)
                                        RobotCmd(0, " %d", b);
                                }
                                RobotCmd(0, "\n");
-                       }
+                       } //robot
                        changed[scr][y] = 0;
                        any = 1;
                        for (x = 0; c; (c >>= 1), (++x))
@@ -85,9 +92,8 @@ ExtFunc int RefreshBoard(int scr)
                                        PlotBlock(scr, y, x, B_OLD(board[scr][y][x]));
                                        oldBoard[scr][y][x] = B_OLD(board[scr][y][x]);
                                }
-               }
-       if (robotEnable)
-               RobotTimeStamp();
+               } //changed row
+       if (robotEnable) RobotTimeStamp();
        for (x = 0; x < Players[scr].boardWidth; ++x)
                if (oldFalling[scr][x] != !!falling[scr][x]) {
                        oldFalling[scr][x] = !!falling[scr][x];
@@ -95,78 +101,90 @@ ExtFunc int RefreshBoard(int scr)
                        any = 1;
                }
        return any;
-}
+} //RefreshBoard
 
 ExtFunc int GlanceFunc(int scr, int y, int x, BlockType type, void *data)
 {
        PlotBlock1(scr, 20 - y, x * 2, type);
        return 0;
-}
+} //GlanceFunc
+
+ExtFunc int ShadowFunc(int scr, int y, int x, BlockType type, void *data)
+{ //draw shadow
+       SetBlock(scr, y, x, BT_shadow);
+       return 0;
+} //ShadowFunc
 
 ExtFunc int PlotFunc(int scr, int y, int x, BlockType type, void *data)
 {
        SetBlock(scr, y, x, type);
        return 0;
 }
+ExtFunc void PlotShape(Shape *shape, int scr, int y, int x, int falling, int shadow)
+{ //put shape on field
+       if (shadow && scr == me) {
+               for (shadowy = y - 1; shadowy >= 0; shadowy--)
+                       if (!ShapeFits(shape, scr, shadowy, x))
+                               break;
+               ShapeIterate(shape, scr, shadowy + 1, x, falling, ShadowFunc, NULL);
+       } //draw shadow
+       ShapeIterate(shape, scr, y, x, falling, PlotFunc, NULL);
+} //PlotShape
 
 ExtFunc int EraseFunc(int scr, int y, int x, BlockType type, void *data)
 {
        SetBlock(scr, y, x, BT_none);
        return 0;
 }
+ExtFunc void EraseShape(Shape *shape, int scr, int y, int x, int shadow)
+{ //remove block from field
+       ShapeIterate(shape, scr, y, x, 0, EraseFunc, NULL);
+       if (shadow && scr == me) //draw shadow
+               ShapeIterate(shape, scr, shadowy + 1, x, 0, EraseFunc, NULL);
+} //EraseShape
 
 ExtFunc int CollisionFunc(int scr, int y, int x, BlockType type, void *data)
 {
-       return GetBlock(scr, y, x) != BT_none;
+       return GetBlock(scr, y, x) > BT_none;
 }
+ExtFunc int ShapeFits(Shape *shape, int scr, int y, int x)
+{ //check if there's nothing in the way
+       return !ShapeIterate(shape, scr, y, x, 0, CollisionFunc, NULL);
+} //ShapeFits
 
 ExtFunc int VisibleFunc(int scr, int y, int x, BlockType type, void *data)
 {
        return (y >= 0 && y < Players[scr].boardVisible &&
                        x >= 0 && x < Players[scr].boardWidth);
 }
-
-ExtFunc void PlotShape(Shape *shape, int scr, int y, int x, int falling)
-{
-       ShapeIterate(shape, scr, y, x, falling, PlotFunc, NULL);
-}
-
-ExtFunc void EraseShape(Shape *shape, int scr, int y, int x)
-{
-       ShapeIterate(shape, scr, y, x, 0, EraseFunc, NULL);
-}
-
-ExtFunc int ShapeFits(Shape *shape, int scr, int y, int x)
-{
-       return !ShapeIterate(shape, scr, y, x, 0, CollisionFunc, NULL);
-}
-
 ExtFunc int ShapeVisible(Shape *shape, int scr, int y, int x)
 {
        return ShapeIterate(shape, scr, y, x, 0, VisibleFunc, NULL);
-}
+} //ShapeVisible
 
 ExtFunc int MovePiece(int scr, int deltaY, int deltaX)
 {
        int result;
 
        EraseShape(Players[scr].curShape, scr,
-               Players[scr].curY, Players[scr].curX);
+               Players[scr].curY, Players[scr].curX, 1);
        result = ShapeFits(Players[scr].curShape, scr, Players[scr].curY + deltaY,
                                Players[scr].curX + deltaX);
        if (result) {
                Players[scr].curY += deltaY;
                Players[scr].curX += deltaX;
        }
-       PlotShape(Players[scr].curShape, scr, Players[scr].curY, Players[scr].curX, 1);
+       PlotShape(Players[scr].curShape, scr, Players[scr].curY, Players[scr].curX,
+               1, 1);
        return result;
-}
+} //MovePiece
 
 ExtFunc int RotatePiece(int scr, int dir)
 {
        int result;
 
-       EraseShape(Players[scr].curShape, scr, Players[scr].curY, Players[scr].curX);
+       EraseShape(Players[scr].curShape, scr, Players[scr].curY,
+               Players[scr].curX, 1);
        result = ShapeFits(dir ? Players[scr].curShape->rotateTo
                                                   : Players[scr].curShape->rotateFrom,
                scr, Players[scr].curY, Players[scr].curX);
@@ -174,32 +192,32 @@ ExtFunc int RotatePiece(int scr, int dir)
                Players[scr].curShape = dir ? Players[scr].curShape->rotateTo
                                                                        : Players[scr].curShape->rotateFrom;
        PlotShape(Players[scr].curShape, scr,
-                       Players[scr].curY, Players[scr].curX, 1);
+                       Players[scr].curY, Players[scr].curX, 1, 1);
        return result;
-}
+} //RotatePiece
 
 ExtFunc int DropPiece(int scr)
 {
        int count = 0;
 
        EraseShape(Players[scr].curShape, scr,
-               Players[scr].curY, Players[scr].curX);
+               Players[scr].curY, Players[scr].curX, 1);
        while (ShapeFits(Players[scr].curShape, scr,
                        Players[scr].curY - 1, Players[scr].curX)) {
                --Players[scr].curY;
                ++count;
        }
        PlotShape(Players[scr].curShape, scr,
-               Players[scr].curY, Players[scr].curX, 1);
+               Players[scr].curY, Players[scr].curX, 1, 0);
        return count;
-}
+} //DropPiece
 
 ExtFunc int LineIsFull(int scr, int y)
 {
        int x;
 
        for (x = 0; x < Players[scr].boardWidth; ++x)
-               if (GetBlock(scr, y, x) == BT_none)
+               if (GetBlock(scr, y, x) <= BT_none)
                        return 0;
        return 1;
 }
@@ -242,7 +260,7 @@ ExtFunc void InsertJunk(int scr, int count, int column)
        int y, x;
 
        EraseShape(Players[scr].curShape, scr,
-               Players[scr].curY, Players[scr].curX);
+               Players[scr].curY, Players[scr].curX, 1);
        for (y = Players[scr].boardHeight - count - 1; y >= 0; --y)
                CopyLine(scr, y, y + count);
        for (y = 0; y < count; ++y)
@@ -251,10 +269,11 @@ ExtFunc void InsertJunk(int scr, int count, int column)
        Players[scr].curY += count; //move piece up..
        for (y = 0; y < count; ++y)
                if (ShapeFits(Players[scr].curShape, scr, Players[scr].curY - 1, Players[scr].curX))
-                       Players[scr].curY--; //..and down as far as possible
+                       Players[scr].curY--; //..and down again as far as possible
                else break;
-       PlotShape(Players[scr].curShape, scr, Players[scr].curY, Players[scr].curX, 1);
-}
+       PlotShape(Players[scr].curShape, scr, Players[scr].curY, Players[scr].curX,
+               1, 1);
+} //InoertJunk
 
 /*
  * vi: ts=4 ai
index f28a6a36a2ec81cf6c846f87599e187a31713c05..030ed25ceb1d7958e1033782ddc0b9fc54cb8181 100644 (file)
--- a/curses.c
+++ b/curses.c
 # define HAVE_NCURSES
 #endif
 
-#ifdef HAVE_NCURSES
-static struct {
-       BlockType type;
-       short color;
-} myColorTable[] = {
-       { BT_white,             COLOR_WHITE },
-       { BT_blue,              COLOR_BLUE },
-       { BT_magenta,   COLOR_MAGENTA },
-       { BT_cyan,              COLOR_CYAN },
-       { BT_yellow,    COLOR_YELLOW },
-       { BT_green,             COLOR_GREEN },
-       { BT_red,               COLOR_RED },
-       { BT_none,              0 }
-};
-#endif
-
 ExtFunc void PlotBlock1(int scr, int y, int x, BlockType type);
-static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event);
 
+static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event);
 static EventGenRec keyGen =
                { NULL, 0, FT_read, STDIN_FILENO, KeyGenFunc, EM_key };
 
 static int boardYPos[MAX_SCREENS], boardXPos[MAX_SCREENS];
 static int statusYPos, statusXPos;
+static int messageYPos, messageXPos, messageHeight, messageWidth;
 static int haveColor;
 
 static char *term_vi;  /* String to make cursor invisible */
@@ -70,7 +55,7 @@ ExtFunc void InitScreens(void)
         * Ctrl-C during initialization might leave the terminal in a bad state.
         */
        BlockSignals(&oldMask, SIGINT, 0);
-       initscr();
+       initscr();              //start curses
 
 #ifdef CURSES_HACK
        {
@@ -83,44 +68,48 @@ ExtFunc void InitScreens(void)
 #ifdef HAVE_NCURSES
        haveColor = Game.color && has_colors();
        if (haveColor) {
+               static struct {
+                       BlockType type;
+                       short color;
+               } myColorTable[] = {
+                       { BT_white,             COLOR_WHITE },
+                       { BT_blue,              COLOR_BLUE },
+                       { BT_magenta,   COLOR_MAGENTA },
+                       { BT_cyan,              COLOR_CYAN },
+                       { BT_yellow,    COLOR_YELLOW },
+                       { BT_green,             COLOR_GREEN },
+                       { BT_red,               COLOR_RED },
+                       { BT_none,              0 }
+               }; //myColorTable
                int i = 0;
 
                start_color();
+               if (can_change_color()) {
+                       init_color (COLOR_YELLOW, 1000, 1000, 0);
+               } //I've never worked on a color-changable terminal, so no idea..
                for (i = 0; myColorTable[i].type != BT_none; ++i)
                        init_pair(myColorTable[i].type, COLOR_BLACK,
                                        myColorTable[i].color);
-       }
+       } //haveColor
 #else
        haveColor = 0;
 #endif
 
-       AtExit(CleanupScreens);
+       AtExit(CleanupScreens);         //restore everything when done
        RestoreSignals(NULL, &oldMask);
 
-       cbreak();
+       cbreak();                                       //no line buffering
        noecho();
+//     keypad(stdscr, TRUE);           //get arrow/functionkeys 'n stuff
        OutputTermStr(term_vi, 0);
-       AddEventGen(&keyGen);
-
-       move(0, 1);
-       addstr("NETRIS ");
-       addstr(version_string);
-       {
-               int rows, cols;
-
-               getmaxyx(stdscr, rows, cols);
-               move(0, cols - 48);
-               addstr("(C)1994-1996,1999 Mark H. Weaver, (C)2002 Shiar");
-//             addstr("    \"netris -h\" for more info");
-       }
-       statusYPos = 22;
-       statusXPos = 0;
+       AddEventGen(&keyGen);           //key handler
+       standend();                                     //normal text
 } //InitScreens
 
 ExtFunc void CleanupScreens(void)
 {
        RemoveEventGen(&keyGen);
-       endwin();
+       endwin();                                       //end curses
        OutputTermStr(term_ve, 1);
 } //CleanupScreens
 
@@ -188,102 +177,164 @@ ExtFunc void OutputTermStr(char *str, int flush)
        }
 } //OutputTermStr
 
-ExtFunc void DrawField(int scr)
-{ //drow field for player scr
-       {
-               int y, x;
-
-               getmaxyx(stdscr, y, x);
-               if (x < boardXPos[scr] + 2 * Players[scr].boardWidth + 1) {
-                       Players[scr].spy = 0;
-                       return;
-               }
+ExtFunc void DrawTitle(void)
+{
+       int rows, cols;
+       char s[255];
 
-               for (y = Players[scr].boardVisible - 1; y >= 0; --y) {
-                       mvaddch(boardYPos[scr] - y, boardXPos[scr] - 1,
-                               Game.ascii ? '|' : ACS_VLINE); //left
-                       mvaddch(boardYPos[scr] - y,
-                               boardXPos[scr] + 2 * Players[scr].boardWidth,
-                               Game.ascii ? '|' : ACS_VLINE); //right
-               }
-               move(2, boardXPos[scr] - 1); //top
-               addch(Game.ascii ? '+' : ACS_ULCORNER);
-               for (x = Players[scr].boardWidth * 2 - 1; x >= 0; --x)
-                       addch(Game.ascii ? '-' : ACS_HLINE);
-               addch(Game.ascii ? '+' : ACS_URCORNER);
-               move(boardYPos[scr] + 1, boardXPos[scr] - 1); //bottom
-               addch(Game.ascii ? '+' : ACS_LLCORNER);
-               for (x = Players[scr].boardWidth * 2 - 1; x >= 0; --x)
-                       addch(Game.ascii ? '-' : ACS_HLINE);
-               addch(Game.ascii ? '+' : ACS_LRCORNER);
-       } //draw field grid
+#ifdef HAVE_NCURSES
+       attrset(A_REVERSE);
+#else
+       standout();
+#endif
+       getmaxyx(stdscr, rows, cols);
+       sprintf(s, " NETRIS %s", version_string);
+       memset(&s[strlen(s)], ' ', 254 - strlen(s));
+       if (cols > 56 + strlen(version_string))
+               memcpy(&s[cols - 48],
+                       "(C)1994-1996,1999 Mark H. Weaver, (C)2002 Shiar \0", 49);
+       else memcpy(&s[cols], "\0", 1);
+       mvaddstr(0, 0, s);
+       standend();     //normal text
+} //DrawTitle
+
+ExtFunc void DrawBox(int x1, int y1, int x2, int y2)
+{ //draw grid
+       int y, x;
+
+       for (y = y1 + 1; y < y2; y++) {
+               mvaddch(y, x1, Game.ascii ? '|' : ACS_VLINE); //left
+               mvaddch(y, x2, Game.ascii ? '|' : ACS_VLINE); //right
+       }
+       move(y1, x1); //top
+       addch(Game.ascii ? '+' : ACS_ULCORNER);
+       for (x = x1 + 1; x < x2; x++)
+               addch(Game.ascii ? '-' : ACS_HLINE);
+       addch(Game.ascii ? '+' : ACS_URCORNER);
+       move(y2, x1); //bottom
+       addch(Game.ascii ? '+' : ACS_LLCORNER);
+       for (x = x1 + 1; x < x2; x++)
+               addch(Game.ascii ? '-' : ACS_HLINE);
+       addch(Game.ascii ? '+' : ACS_LRCORNER);
+} //DrawBox
 
+ExtFunc void DrawField(int scr)
+{ //draw field for player scr
+       if (!Players[scr].spy) return; 
+       DrawBox(boardXPos[scr] - 1, boardYPos[scr] - Players[scr].boardVisible,
+               boardXPos[scr] + 2 * Players[scr].boardWidth, boardYPos[scr] + 1);
        {
-               char userstr[300];
+               char s[2*Players[scr].boardWidth];
 
+               memset(s, ' ', sizeof(s));
                if (Players[scr].host && Players[scr].host[0])
-                        sprintf(userstr, "%s <%s>", Players[scr].name, Players[scr].host);
-               else sprintf(userstr, "%s", Players[scr].name);
-               userstr[20 - 7*((Players[scr].flags & SCF_usingRobot) != 0)
+                       snprintf(s, sizeof(s), "%s <%s>",
+                               Players[scr].name, Players[scr].host);
+               else snprintf(s, sizeof(s), "%s", Players[scr].name);
+               s[strlen(s)] = ' ';
+               s[sizeof(s) - 7*((Players[scr].flags & SCF_usingRobot) != 0)
                        - 5*((Players[scr].flags & SCF_fairRobot) != 0)] = 0;
-               mvaddstr(1, boardXPos[scr], userstr);
+               mvaddstr(1, boardXPos[scr], s);
 
                if (Players[scr].flags & SCF_usingRobot) {
                        addstr((Players[scr].flags & SCF_fairRobot)
                                ? "(fair robot)" : "(robot)");
-               }
+               } //add robot indicator
        } //display playername/host
 
+       // draw blocks (which is usually just clear field)
+
        ShowPause(scr);
-} //DrawScreen
+} //DrawField
 
-ExtFunc void InitFields()
-{ //place fields for all players
+ExtFunc void InitFields(void)
+{ //calculate positions of all fields
        int scr, prevscr;
+       int y, x;
 
-       statusXPos = 2 * Players[me].boardWidth + 3;
+       getmaxyx(stdscr, y, x);
        boardXPos[me] = 1;
        boardYPos[me] = 22;
+       statusXPos = 2 * Players[me].boardWidth + 3;
+       statusYPos = 22;
+       messageXPos = 2;
+       messageYPos = 25;
+       messageWidth = x - messageXPos - 2;
+       if ((messageHeight = y - messageYPos - 1) < 0) messageHeight = 0;
+       else DrawBox(messageXPos - 2, messageYPos - 1,
+               messageXPos + messageWidth + 1, messageYPos + messageHeight);
        prevscr = me;
-       for (scr = 1; scr <= totalPlayers + 1; scr++) if (scr != me) {
+       for (scr = 1; scr < MAX_SCREENS; scr++) if (scr != me) {
                boardXPos[scr] =
                        boardXPos[prevscr] + 2 * Players[prevscr].boardWidth + 3;
                if (prevscr == me)
-                       boardXPos[scr] += 24; //scorebar
+                       boardXPos[scr] += 14; //scorebar
                boardYPos[scr] = 22;
+               if (x < boardXPos[scr] + 2 * Players[scr].boardWidth + 1)
+                       Players[scr].spy = 0; //field doesn't fit on screen
                prevscr = scr;
        }
-} //InitScreen
+       for (scr = 1; scr <= Game.maxplayers; scr++)
+               DrawField(scr);
+} //InitFields
 
 ExtFunc void CleanupScreen(int scr)
 {
 }
 
+ExtFunc void Messagef(char *fmt, ...)
+{ //print game/bot message
+       static int line = 0;
+       va_list args;
+       char s[255];
+       char *p, *psearch;
+       int i;
+
+       if (!messageHeight) return;
+       va_start(args, fmt);
+       move(messageYPos + line, messageXPos);
+//     vwprintw(stdscr, fmt, args); //doesn't seem to be a vprintw
+       vsprintf(s, fmt, args);
+       p = s;
+       while (psearch = strchr(s, '\\')) {
+               *psearch = '\0';
+               addstr(p);
+               if (haveColor)
+                       attrset(A_REVERSE | COLOR_PAIR(atoi(psearch + 1) + 1));
+               p = psearch + 2;
+       } //search for color escapes (\)
+       addstr(p);
+       if (messageHeight > 1) {
+               char s[messageWidth + 1];
+               line = (line + 1) % messageHeight;
+               memset(s, ' ', messageWidth);
+               s[messageWidth] = 0;
+               mvaddstr(messageYPos + line, messageXPos, s);
+       } //multiple lines
+       if (haveColor) standend();
+       va_end(args);
+} //Message
+
 ExtFunc void PlotBlock1(int scr, int y, int x, BlockType type)
 {
        int colorIndex = abs(type);
 
        move(y, x);
-
-       if (type == BT_none)
-               addstr("  ");
-       else
-       {
-               if (Game.standout)
-               {
+       if (type == BT_none) addstr("  ");
+       else if (type == BT_shadow) addstr("::");
+       else {
+               if (Game.standout) {
 #ifdef HAVE_NCURSES
-                       if (haveColor)
-                               attrset(COLOR_PAIR(colorIndex));
-                       else
+                       if (haveColor) attrset(COLOR_PAIR(colorIndex));
+                       else attrset(A_REVERSE);
 #endif
-                               standout();
                }
-
                addstr(type ? "[]" : "$$");
-               standend();
-       }
+#ifdef HAVE_NCURSES
+               if (Game.standout) standend();
+#endif
+       } //display one brick
 } //PlotBlock1
-
 ExtFunc void PlotBlock(int scr, int y, int x, BlockType type)
 {
        if (y >= 0 && y < Players[scr].boardVisible &&
@@ -291,38 +342,66 @@ ExtFunc void PlotBlock(int scr, int y, int x, BlockType type)
          PlotBlock1(scr, boardYPos[scr] - y, boardXPos[scr] + 2 * x, type);
 } //PlotBlock
 
-ExtFunc void PlotUnderline(int scr, int x, int flag)
+ExtFunc void PlotShadowBlock1(int scr, int y, int x, BlockType type)
+{
+       move(y, x);
+       if (type == BT_none) addstr("  ");
+       else addstr("::");
+} //PlotShadowBlock1
+ExtFunc void PlotShadowBlock(int scr, int y, int x, BlockType type)
+{
+       if (y >= 0 && y < Players[scr].boardVisible &&
+               x >= 0 && x < Players[scr].boardWidth)
+         PlotShadowBlock1(scr, boardYPos[scr] - y, boardXPos[scr] + 2 * x, type);
+} //PlotShadowBlock
+
+ExtFunc void PlotBlockS1(int scr, int y, int x, BlockType type)
+{ //DOESN"T WORK YET...
+       move(y, x);
+       if (type == BT_none) addstr(" ");
+       else {
+               addstr(type ? "O" : "$");
+               standend();
+       } //display one brick
+} //PlotBlock1
+ExtFunc void PlotBlockS(int scr, int y, int x, BlockType type)
 {
+       if (y >= 0 && y < Players[scr].boardVisible &&
+               x >= 0 && x < Players[scr].boardWidth)
+         PlotBlockS1(scr, boardYPos[scr] - y, boardXPos[scr] + x, type);
+} //PlotBlock
+
+ExtFunc void PlotUnderline(int scr, int x, int flag)
+{ //display piece of bottom fieldgrid
   move(boardYPos[scr] + 1, boardXPos[scr] + 2 * x);
   if (Game.ascii)
        addstr(flag ? "==" : "--");
   else {
        addch(flag ? ACS_BTEE : ACS_HLINE);
        addch(flag ? ACS_BTEE : ACS_HLINE);
-  }
+  } //ncurses graphics
 } //PlotUnderline
 
 ExtFunc void ShowScore(int scr, struct _Score score)
 { //show score stuff
        float timer;
 
-       move(6, statusXPos); addstr("Next:          ");
-       move(7, statusXPos + 7);    addstr("        ");
+       mvaddstr(13, statusXPos, "next         ");
+       mvaddstr(14, statusXPos + 5,  "        ");
        ShapeIterate(Players[scr].nextShape, scr,
-         ShapeToNetNum(Players[scr].nextShape) == 15 ? 13 : 14,
-         statusXPos / 2 + 5, 1, GlanceFunc, NULL);
-       move(statusYPos - 21 + 1, statusXPos);
-       printw("Score:%6d  level: %2d", score.score, score.level);
-       move(statusYPos - 20 + 1, statusXPos);
+         ShapeToNetNum(Players[scr].nextShape) == 15 ? 6 : 7,
+         statusXPos / 2 + 4, 1, GlanceFunc, NULL);
+       mvprintw(3, statusXPos, "level   %5d", score.level);
+       mvprintw(5, statusXPos, "score%8d", score.score);
+       mvprintw(6, statusXPos, "lines%8d", score.lines);
        timer = CurTimeval() / 1e6;
-       printw("Lines:%6d", score.lines);
        if (timer > 4) {
-               printw("  ppm:%5.1f", score.drops * 60 / timer);
-               move(statusYPos - 18, statusXPos);
-               if (score.lines > 0)
-                       printw("yield:  %3d%%", 100 * score.adds / score.lines);
-               else addstr("            ");
-               printw("  apm:%5.1f", score.adds * 60 / timer);
+               mvprintw(9, statusXPos, "ppm %9.1f", score.drops * 60 / timer);
+               if (score.lines > 0) {
+                       mvprintw(7, statusXPos,
+                               "yield    %3d%%", 100 * score.adds / score.lines);
+                       mvprintw(10, statusXPos, "apm %9.1f", score.adds * 60 / timer);
+               }
        }
 } //ShowScore
 
@@ -335,7 +414,11 @@ ExtFunc void FieldMessage(int playa, char *message)
                memcpy(&s[Players[playa].boardWidth - strlen(message) / 2],
                        message, strlen(message));
                s[Players[playa].boardWidth * 2] = 0;
-               if (Game.standout) standout();
+#ifdef HAVE_NCURSES
+               attrset(A_REVERSE);
+#else
+               standout();
+#endif
                mvprintw(boardYPos[playa] - Players[playa].boardVisible / 2,
                        boardXPos[playa], "%s", s);
                standend();
@@ -350,31 +433,20 @@ ExtFunc void FieldMessage(int playa, char *message)
 
 ExtFunc void ShowPause(int playa)
 { //put paused over player's field
-       if (Players[playa].flags & SCF_paused)
-               FieldMessage(playa, "P A U S E D");
-       else FieldMessage(playa, NULL);
+       if (Players[playa].alive)
+               if (Players[playa].flags & SCF_paused)
+                       FieldMessage(playa, Game.started > 1
+                               ? "P A U S E D" : "N O T  R E A D Y");
+               else FieldMessage(playa, Game.started > 1 ? NULL : "R E A D Y");
+       else FieldMessage(playa, playa > maxPlayer
+                       ? "E M P T Y" : "G A M E  O V E R");
 } //ShowPause
 
 
-ExtFunc void Message(char *s)
-{
-       static int line = 0;
-
-//     move(statusYPos - 20 + line, statusXPos);
-       move(statusYPos + 2 + line, 1);
-       addstr(s);      /* XXX Should truncate long lines */
-       clrtoeol();
-       line = (line + 1) % 10;
-//     move(statusYPos - 20 + line, statusXPos);
-       move(statusYPos + 2 + line, 1);
-       clrtoeol();
-} //Message
-
 ExtFunc void ShowTime(void)
 { //display timer
-       move(statusYPos, statusXPos);
-       printw("Timer: %.0f ", CurTimeval() / 1e6);
-       move(boardYPos[0] + 1, boardXPos[0] + 2 * Players[0].boardWidth + 1);
+       mvprintw(statusYPos, statusXPos, "timer %7.0f ", CurTimeval() / 1e6);
+//     move(boardYPos[0] + 1, boardXPos[0] + 2 * Players[0].boardWidth + 1);
 //     refresh();
 } //ShowTime
 
diff --git a/game.c b/game.c
index 07dda94705c8d92f3489cd8ed4c4c6de96126257..b88e05d2f789199bbf24cad58cd98a3c19453220 100644 (file)
--- a/game.c
+++ b/game.c
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <sys/types.h>
 #include <netinet/in.h>
+#include <setjmp.h>
 
 static struct option options[] = {
        { "ascii",              2, 0, 'a' },
@@ -61,6 +62,8 @@ static char keyTable[KT_numKeys+1];
 static char *hostStr;
 static int paused = 0;
 
+static sigjmp_buf close_env;
+
 
 ExtFunc void MapKeys(char *newKeys)
 {
@@ -233,7 +236,7 @@ ExtFunc int StartNewPiece(int scr, Shape *shape)
                        Players[scr].curY, Players[scr].curX))
                return 0;
        PlotShape(Players[scr].curShape, scr,
-               Players[scr].curY, Players[scr].curX, 1);
+               Players[scr].curY, Players[scr].curX, 1, 1);
        return 1;
 }
 
@@ -241,103 +244,113 @@ ExtFunc void checkPaused(void)
 { //check whether anyone paused the game
        int i;
 
-       paused = 0;
-       for (i = 1; i <= totalPlayers; i++)
-               if (Players[i].alive)
-                       paused |= Players[i].flags & SCF_paused;
+       paused = Game.started < 1;
+       for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive)
+               paused |= Players[i].flags & SCF_paused;
+       if (paused) paused = 1;
+       else if (Game.started == 1) {
+               Game.started = 2;
+               Messagef("The game has started");
+               for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive)
+                       ShowPause(i);
+       } //everybody ready
 } //checkPaused
 
-ExtFunc void OneGame(int scr)
+ExtFunc void OneGame(void)
 {
        MyEvent event;
        int linesCleared, changed = 0;
-       int spied = 0, dropMode = 0;
+       int dropMode = 0;
        int oldPaused = 0;
        long pauseTimeLeft;
        int pieceCount = 0;
        int key;
        char *p, *cmd;
        int playercount;
+       char lastadd;
        int linevalues[4] = { 40, 100, 400, 1200 }; //= 50*lines! - 10*(lines==1)
        int i;
 
+       maxPlayer = lastadd = me;
        Game.speed = Game.initspeed;
-       for (i = 1; i < Players[scr].score.level; i++)
+       for (i = 1; i < Players[me].score.level; i++)
                Game.speed /= SPEEDINC;
        if (Game.speed < SPEEDMINIMUM)
                Game.speed = SPEEDMINIMUM;
-       ResetBaseTime();
+       ResetBaseTime();                        //reset timer
+       ClearField(me);
        InitFields();
-       for (i = 1; i <= totalPlayers; i++)
-               if (Players[i].spy) DrawField(i);
-       if (totalPlayers > 1) {
-               spied = 1;
-       }
        SetITimer(Game.speed, Game.speed);
        if (robotEnable) {
+               int counter;
                RobotCmd(0, "GameType %s\n", gameNames[game]);
                RobotCmd(0, "BoardSize 0 %d %d\n",
-                       Players[scr].boardVisible, Players[scr].boardWidth);
-               for (i = 1; i <= totalPlayers; i++) {
+                       Players[me].boardVisible, Players[me].boardWidth);
+               for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive && i != me) {
                        RobotCmd(0, "BoardSize %d %d %d\n",
-                               i, Players[i].boardVisible, Players[i].boardWidth);
+                               counter, Players[i].boardVisible, Players[i].boardWidth);
                        RobotCmd(0, "Opponent %d %s %s\n",
-                               i, Players[i].name, Players[i].host);
+                               counter, Players[i].name, Players[i].host);
                        if (Players[i].flags & SCF_usingRobot)
                                RobotCmd(0, "OpponentFlag %d robot\n", i);
                        if (Players[i].flags & SCF_fairRobot)
                                RobotCmd(0, "OpponentFlag %d fairRobot\n", i);
+                       counter++;
                }
                RobotCmd(0, "TickLength %.3f\n", Game.speed / 1.0e6);
                RobotCmd(0, "BeginGame\n");
                RobotTimeStamp();
        }
-       Players[scr].nextShape = ChooseOption(stdOptions);
+       Players[me].nextShape = ChooseOption(stdOptions);
        while (1) {
-               if (Players[scr].alive) {
-                       if (!StartNewPiece(scr, ChooseOption(stdOptions))) {
+               if (Players[me].alive) {
+                       if (!StartNewPiece(me, ChooseOption(stdOptions))) {
                                        netint4 data[4];
-                               Players[scr].alive = 0;
-                               FieldMessage(scr, "G A M E  O V E R");
-                               changed = 1;
+                               Players[me].alive = 0;
+                               if (lastadd == me) Messagef("You died");
+                               else Messagef("\\%d%s fragged you",
+                                       Players[lastadd].team > 7 ? 7 : Players[lastadd].team,
+                                       Players[lastadd].name);
                                if (game == GT_classicTwo)
-                                       SendPacket(scr, NP_argghhh,
-                                               sizeof(Players[0].alive), &Players[scr].alive);
+                                       SendPacket(me, NP_argghhh, sizeof(lastadd), &lastadd);
+                               ShowPause(me);
+                               changed = 1;
                        } //die
                        else {
-                               ShowScore(scr, Players[scr].score);
+                               ShowScore(me, Players[me].score);
                                if (robotEnable && !fairRobot)
                                        RobotCmd(1, "NewPiece %d\n", ++pieceCount);
                                if (spied) {
                                        short shapeNum;
                                        netint2 data[1];
        
-                                       shapeNum = ShapeToNetNum(Players[scr].curShape);
+                                       shapeNum = ShapeToNetNum(Players[me].curShape);
                                        data[0] = hton2(shapeNum);
-                                       SendPacket(scr, NP_newPiece, sizeof(data), data);
+                                       SendPacket(me, NP_newPiece, sizeof(data), data);
                                } //send new piece
                        }
-               }
-               for (;;) {
-                       for (i = 1; i <= totalPlayers; i++) if (Players[i].spy)
-                               changed |= RefreshBoard(i);
+               } //new piece
+               while (1) {
+                       for (i = 1; i < MAX_SCREENS; i++)
+                               if (Players[i].alive && Players[i].spy)
+                                       changed |= RefreshBoard(i);
                        if (changed) {
                                if (!paused) ShowTime();
                                refresh();
                                changed = 0;
-                       }
+                       } //screen update
                        playercount = 0;
-                       for (i = 1; i <= totalPlayers; i++)
+                       for (i = 1; i < MAX_SCREENS; i++)
                                if (Players[i].alive) playercount++;
-                       if (playercount < game + 1) goto gameOver;
+                       if (playercount < 1) goto gameOver;
                        CheckNetConn();
                        switch (WaitMyEvent(&event, EM_any)) {
                                case E_alarm:
-                                       if (Players[scr].alive)
-                                               if (!MovePiece(scr, -1, 0))
+                                       if (!paused && Players[me].alive)
+                                               if (!MovePiece(me, -1, 0))
                                                        goto nextPiece;
                                                else if (spied)
-                                                       SendPacket(scr, NP_down, 0, NULL);
+                                                       SendPacket(me, NP_down, 0, NULL);
                                        break;
                                case E_key:
                                        p = strchr(keyTable, tolower(event.u.key));
@@ -350,49 +363,40 @@ ExtFunc void OneGame(int scr)
                                        } //let robot handle keypress
                                        if (!p) break;
                                keyEvent:
-                                       if (!Players[scr].alive && key != KT_quit) break;
+                                       if (!Players[me].alive && key != KT_quit) break;
                                        if (paused && key < KT_pause) break;
                                        switch(key) {
                                                case KT_left:
-                                                       if (MovePiece(scr, 0, -1) && spied)
-                                                               SendPacket(scr, NP_left, 0, NULL);
+                                                       if (MovePiece(me, 0, -1) && spied)
+                                                               SendPacket(me, NP_left, 0, NULL);
                                                        break;
                                                case KT_right:
-                                                       if (MovePiece(scr, 0, 1) && spied)
-                                                               SendPacket(scr, NP_right, 0, NULL);
+                                                       if (MovePiece(me, 0, 1) && spied)
+                                                               SendPacket(me, NP_right, 0, NULL);
                                                        break;
                                                case KT_rotleft:
-                                                       if (RotatePiece(scr, 0) && spied)
-                                                               SendPacket(scr, NP_rotleft, 0, NULL);
+                                                       if (RotatePiece(me, 0) && spied)
+                                                               SendPacket(me, NP_rotleft, 0, NULL);
                                                        break;
                                                case KT_rotright:
-                                                       if (RotatePiece(scr, 1) && spied)
-                                                               SendPacket(scr, NP_rotright, 0, NULL);
+                                                       if (RotatePiece(me, 1) && spied)
+                                                               SendPacket(me, NP_rotright, 0, NULL);
                                                        break;
                                                case KT_down:
                                                        SetITimer(Game.speed, Game.speed);
-                                                       if (MovePiece(scr, -1, 0)) {
-                                                               if (spied) SendPacket(scr, NP_down, 0, NULL);
+                                                       if (MovePiece(me, -1, 0)) {
+                                                               if (spied) SendPacket(me, NP_down, 0, NULL);
                                                        }
                                                        else goto nextPiece;
                                                        break;
                                                case KT_drop:
                                                        SetITimer(Game.speed, Game.speed);
-                                                       if (DropPiece(scr)) {
-                                                               if (spied) SendPacket(scr, NP_drop, 0, NULL);
-                                                               if (Players[scr].dropmode == 2) goto nextPiece;
+                                                       if (DropPiece(me)) {
+                                                               if (spied) SendPacket(me, NP_drop, 0, NULL);
+                                                               if (Players[me].dropmode == 2) goto nextPiece;
                                                        }
                                                        else goto nextPiece;
-                                                       dropMode = Players[scr].dropmode;
-                                                       break;
-                                               case KT_pause:
-                                                       Players[scr].flags ^= SCF_paused;
-                                                       checkPaused();
-                                                       if (game == GT_classicTwo)
-                                                               SendPacket(scr, NP_pause, 0, NULL);
-                                                       if (robotEnable) RobotCmd(1, "Pause %d\n", paused);
-                                                       ShowPause(scr);
-                                                       changed = 1;
+                                                       dropMode = Players[me].dropmode;
                                                        break;
                                                case KT_faster:
                                                        if (game != GT_onePlayer)
@@ -400,24 +404,44 @@ ExtFunc void OneGame(int scr)
                                                        if ((Game.speed /= SPEEDINC) < SPEEDMINIMUM)
                                                                Game.speed = SPEEDMINIMUM;
                                                        SetITimer(Game.speed, SetITimer(0, 0));
-                                                       Players[scr].score.level++;
-                                                       ShowScore(scr, Players[scr].score);
+                                                       Players[me].score.level++;
+                                                       ShowScore(me, Players[me].score);
+                                                       changed = 1;
+                                                       break;
+                                               case KT_pause:
+                                                       Players[me].flags ^= SCF_paused;
+                                                       if (Game.started > 1)
+                                                               Messagef(Players[me].flags & SCF_paused
+                                                                       ? "You paused the game"
+                                                                       : "You unpaused the game");
+                                                       else
+                                                               Messagef(Players[me].flags & SCF_paused
+                                                                       ? "You are not ready" : "You are ready");
+                                                       checkPaused();
+                                                       if (game == GT_classicTwo)
+                                                               SendPacket(me, NP_pause, 0, NULL);
+                                                       if (robotEnable) RobotCmd(1, "Pause %d\n", paused);
+                                                       ShowPause(me);
                                                        changed = 1;
                                                        break;
                                                case KT_redraw:
-                                                       ScheduleFullRedraw();
-//                                                     if (paused)
-//                                                             RefreshScreen();
+                                                       DrawTitle();
+                                                       InitFields();
+//                                                     ScheduleFullRedraw();
+                                                       for (i = 1; i < MAX_SCREENS; i++)
+                                                               if (Players[i].alive && Players[i].spy)
+                                                                       RefreshBoard(i);
+                                                       refresh();
                                                        break;
                                                case KT_quit:
-                                                       FieldMessage(me, "G A M E  O V E R");
+                                                       ShowPause(me);
                                                        refresh();
                                                        goto gameOver;
                                        } //E_key
-                                       if (dropMode && DropPiece(scr) > 0) {
+                                       if (dropMode && DropPiece(me) > 0) {
                                                SetITimer(Game.speed, Game.speed);
                                                if (spied)
-                                                       SendPacket(scr, NP_drop, 0, NULL);
+                                                       SendPacket(me, NP_drop, 0, NULL);
                                        }
                                        break;
                                case E_robot:
@@ -435,28 +459,13 @@ ExtFunc void OneGame(int scr)
                                                                        num == pieceCount)))
                                                        goto keyEvent;
                                        if (!strcmp(cmd, "Message")) {
-                                               Message(p);
+                                               Messagef(p);
                                                changed = 1;
                                        }
                                        break;
                                } //E_robot
                                case E_net:
                                        switch(event.u.net.type) {
-                                               case NP_giveJunk:
-                                               {
-                                                       netint2 data[2];
-                                                       short column;
-
-                                                       if (!Players[scr].alive) break;
-                                                       memcpy(data, event.u.net.data, sizeof(data[0]));
-                                                       column = Random(0, Players[scr].boardWidth);
-                                                       data[1] = hton2(column);
-                                                       InsertJunk(scr, ntoh2(data[0]), column);
-                                                       if (spied)
-                                                               SendPacket(scr, NP_insertJunk, sizeof(data), data);
-//                                                     Message("Opponent added %d lines");
-                                                       break;
-                                               } //receive junklines
                                                case NP_newPiece:
                                                {
                                                        short shapeNum;
@@ -465,7 +474,8 @@ ExtFunc void OneGame(int scr)
                                                        FreezePiece(event.u.net.uid);
                                                        memcpy(data, event.u.net.data, sizeof(data));
                                                        shapeNum = ntoh2(data[0]);
-                                                       StartNewPiece(event.u.net.uid, NetNumToShape(shapeNum));
+                                                       StartNewPiece(event.u.net.uid,
+                                                               NetNumToShape(shapeNum));
                                                        break;
                                                } //new piece
                                                case NP_down:
@@ -494,12 +504,74 @@ ExtFunc void OneGame(int scr)
                                                        netint2 data[2];
 
                                                        memcpy(data, event.u.net.data, sizeof(data));
-                                                       InsertJunk(event.u.net.uid, ntoh2(data[0]), ntoh2(data[1]));
+                                                       InsertJunk(event.u.net.uid, ntoh2(data[0]),
+                                                               ntoh2(data[1]));
                                                        break;
                                                } //player added junklines
+                                               case NP_giveJunk:
+                                               {
+                                                       netint2 data[2];
+                                                       short column;
+
+                                                       if (!Players[me].alive) break;
+                                                       memcpy(data, event.u.net.data, sizeof(data[0]));
+                                                       column = Random(0, Players[me].boardWidth);
+                                                       data[1] = hton2(column);
+                                                       Messagef("\\%d%s sends %d lines",
+                                                               Players[event.u.net.uid].team > 7 ? 7
+                                                               : Players[event.u.net.uid].team,
+                                                               Players[event.u.net.uid].name, ntoh2(data[0]));
+                                                       lastadd = event.u.net.uid;
+                                                       InsertJunk(me, ntoh2(data[0]), column);
+                                                       if (spied)
+                                                               SendPacket(me, NP_insertJunk, sizeof(data),
+                                                                       data);
+                                                       break;
+                                               } //receive junklines
+                                               case NP_start:
+                                               {
+                                                       Game.started = 1;
+                                                       checkPaused();
+                                                       break;
+                                               } //start game
+                                               case NP_newPlayer:
+                                               {
+                                                       if (event.u.net.uid > maxPlayer)
+                                                               maxPlayer = event.u.net.uid;
+                                                       memcpy(&Players[event.u.net.uid],
+                                                               event.u.net.data, event.u.net.size);
+                                                       ClearField(event.u.net.uid);
+                                                       Messagef("\\%d%s joins the game",
+                                                               Players[event.u.net.uid].team > 7 ? 7
+                                                               : Players[event.u.net.uid].team,
+                                                               Players[event.u.net.uid].name);
+                                                       if (Players[event.u.net.uid].flags & SCF_paused) {
+                                                               checkPaused();
+                                                               if (robotEnable)
+                                                                       RobotCmd(1, "Pause %d\n", paused);
+                                                       } //player has paused
+                                                       DrawField(event.u.net.uid);
+//                                                     ShowPause(event.u.net.uid);
+                                                       changed = 1;
+                                                       break;
+                                               } //player joined
                                                case NP_pause:
                                                {
+                                                       char s[20];
+
                                                        Players[event.u.net.uid].flags ^= SCF_paused;
+                                                       if (Game.started > 1)
+                                                               strcpy(s,
+                                                                       Players[event.u.net.uid].flags & SCF_paused
+                                                                       ? "paused the game" : "unpaused the game");
+                                                       else
+                                                               strcpy(s,
+                                                                       Players[event.u.net.uid].flags & SCF_paused
+                                                                       ? "is not ready" : "is good to go");
+                                                       Messagef("\\%d%s %s",
+                                                               Players[event.u.net.uid].team > 7 ? 7
+                                                               : Players[event.u.net.uid].team,
+                                                               Players[event.u.net.uid].name, s);
                                                        checkPaused();
                                                        if (robotEnable) RobotCmd(1, "Pause %d\n", paused);
                                                        ShowPause(event.u.net.uid);
@@ -508,10 +580,21 @@ ExtFunc void OneGame(int scr)
                                                } //(un)pause
                                                case NP_argghhh:
                                                {
-                                                       memcpy(&Players[event.u.net.uid].alive,
-                                                               event.u.net.data, sizeof(Players[0].alive));
-//                                                     checkPaused();
-                                                       FieldMessage(event.u.net.uid, "G A M E  O V E R");
+                                                       char i;
+                                                       memcpy(&i, event.u.net.data, sizeof(i));
+                                                       Players[event.u.net.uid].alive = 0;
+                                                       if (i == me) Messagef("You fragged %s",
+                                                                       Players[event.u.net.uid].name);
+                                                       else if (i == event.u.net.uid)
+                                                               Messagef("\\%d%s died",
+                                                                       Players[i].team > 7 ? 7 : Players[i].team,
+                                                                       Players[i].name);
+                                                       else Messagef("\\%d%s fragged %s",
+                                                                       Players[i].team > 7 ? 7 : Players[i].team,
+                                                                       Players[i].name,
+                                                                       Players[event.u.net.uid].name);
+                                                       checkPaused();
+                                                       ShowPause(event.u.net.uid);
                                                        changed = 1;
                                                        break;
                                                } //G/O
@@ -539,23 +622,23 @@ ExtFunc void OneGame(int scr)
                } //game loop
        nextPiece:
                dropMode = 0;
-               FreezePiece(scr);
-               Players[scr].score.drops++;
-               Players[scr].score.score++;
-               if ((linesCleared = ClearFullLines(scr)) > 0) {
+               FreezePiece(me);
+               Players[me].score.drops++;
+               Players[me].score.score++;
+               if ((linesCleared = ClearFullLines(me)) > 0) {
                        if (game == GT_onePlayer)
-                               if ((Players[scr].score.lines / 10) <
-                                               ((Players[scr].score.lines + linesCleared) / 10)) {
+                               if ((Players[me].score.lines / 10) <
+                                               ((Players[me].score.lines + linesCleared) / 10)) {
                                        if ((Game.speed /= SPEEDINC) < SPEEDMINIMUM)
                                                Game.speed = SPEEDMINIMUM;
                                        SetITimer(Game.speed, SetITimer(0, 0));
-                                       Players[scr].score.level++;
+                                       Players[me].score.level++;
                                } //level up
-                       Players[scr].score.score += linevalues[linesCleared];
-                       Players[scr].score.lines += linesCleared;
-                       Players[scr].score.adds += linesCleared - (linesCleared < 4);
+                       Players[me].score.score += linevalues[linesCleared - 1];
+                       Players[me].score.lines += linesCleared;
+                       Players[me].score.adds += linesCleared - (linesCleared < 4);
                        if (spied)
-                               SendPacket(scr, NP_clear, 0, NULL);
+                               SendPacket(me, NP_clear, 0, NULL);
                }
                if (game == GT_classicTwo && linesCleared > 1) {
                        short junkLines;
@@ -563,13 +646,19 @@ ExtFunc void OneGame(int scr)
 
                        junkLines = linesCleared - (linesCleared < 4);
                        data[0] = hton2(junkLines);
-                       SendPacket(scr, NP_giveJunk, sizeof(data), data);
-               }
+                       SendPacket(me, NP_giveJunk, sizeof(data), data);
+                       Messagef("You sent %d lines", junkLines);
+               } //send junk to others
        } //new piece loop
 gameOver:
        SetITimer(0, 0);
 }
 
+ExtFunc void CatchInt(int sig)
+{
+       siglongjmp(close_env, 1);
+}
+
 ExtFunc int main(int argc, char **argv)
 {
        char ch;
@@ -582,19 +671,20 @@ ExtFunc int main(int argc, char **argv)
                int i;
                char *userName;
 
-               for (i = 0; i <= MAX_SCREENS; i++)
+               for (i = 0; i < MAX_SCREENS; i++) {
                        Players[i].score.level = Players[i].spy = 1;
+                       Players[i].boardWidth = 10;
+                       Players[i].boardHeight = MAX_BOARD_HEIGHT;
+                       Players[i].boardVisible = 20;
+                       strcpy(Players[i].name, "???");
+               }
                if (!(userName = getenv("LOGNAME")) || !userName[0])
                        if (!(userName = getenv("USER")) || !userName[0])
                                userName = "Anonymous";
                strncpy(Players[0].name, userName, 16); //sizeof(Player.name)
                Players[0].name[16] = 0;
-               Players[0].boardWidth = 10;
-               Players[0].boardHeight = MAX_BOARD_HEIGHT;
-               Players[0].boardVisible = 20;
-               Players[0].spy = 1;
                Players[0].alive = 1;
-       }
+       } //set defaults
 
 //     if (getopt(argc, argv, "f:") == 'f')
 //             ReadConf(optarg);
@@ -611,22 +701,27 @@ ExtFunc int main(int argc, char **argv)
                fatal("You can't use the -F option without the -r option");
 //     WriteConf();
 
-       InitUtil();
-       InitScreens();
+       SRandom(time(0));                       //randomize
+       if (sigsetjmp(close_env, 1))
+               exit(0);
+       signal(SIGINT, CatchInt);       //handle exit (^C)
+       InitScreens();                          //setup screen
+       DrawTitle();
        if (initConn) {
                game = GT_classicTwo;
-               Players[0].flags |= SCF_paused;
-               paused = SCF_paused;
+               spied = 1;
                InitiateConnection(hostStr, port);
                HandShake();
-               OneGame(me);
+               checkPaused();
+               OneGame();
        } //client
        else {
                game = GT_onePlayer;
-               totalPlayers = 1;
+               Game.started = 2;
+               Game.maxplayers = 1;
                me = 1;
                memcpy(&Players[me], &Players[0], sizeof(Player));
-               OneGame(me);
+               OneGame();
        } //singleplay
        return 0;
 }
diff --git a/inet.c b/inet.c
index b21b1374437b668bcbf4251401f3809676ea37b1..2caca525b91fb3c6b336cf6bc41868186c6c5c60 100644 (file)
--- a/inet.c
+++ b/inet.c
@@ -33,9 +33,8 @@
 #define HEADER_SIZE3 sizeof(netint4[3])
 
 ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
-
-EventGenRec netGen[MAX_SCREENS] = {
-       { NULL, 0, FT_read, -1, NetGenFunc, EM_net, 0, "\0", 0, HEADER_SIZE3 } };
+EventGenRec netGen =
+       { NULL, 0, FT_read, -1, NetGenFunc, EM_net, 0, "\0", 0, HEADER_SIZE3 };
 
 
 ExtFunc int InitiateConnection(char *hostStr, short port)
@@ -53,17 +52,16 @@ ExtFunc int InitiateConnection(char *hostStr, short port)
        addr.sin_family = host->h_addrtype;
        memcpy(&addr.sin_addr, host->h_addr, host->h_length);
        addr.sin_port = htons(port);
-       if ((netGen[0].fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+       if ((netGen.fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
                die("socket");
-       if (connect(netGen[0].fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+       if (connect(netGen.fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
                if (errno != ECONNREFUSED)
                        die("connect");
-               close(netGen[0].fd);
+               close(netGen.fd);
                sleep(1);
                goto again;
        }
-       AddEventGen(&netGen[0]);
-       totalPlayers = 1;
+       AddEventGen(&netGen);
        return 0;
 } //InitiateConnection
 
@@ -88,25 +86,29 @@ ExtFunc void HandShake(void)
                                fprintf(stderr, "Accepted (%s) as #%d (%s)\n",
                                        event.u.net.data, me, Players[me].name);
                                SendPacket(0, NP_newPlayer,
-                                       sizeof(Player) - sizeof(Players[me].host) - sizeof(Players[me].spy),
+                                       sizeof(Player) - sizeof(Players[me].host)
+                                       - sizeof(Players[me].spy) - sizeof(Players[me].small),
                                        &Players[me]);
                                break;
                        }
                        case NP_gamedata:
                        {
-                               memcpy(&Game, event.u.net.data, event.u.net.size);
+                               static struct {
+                                       int playerflags;
+                                       int maxplayers; //1
+                                       int started;    //2
+                                       int continuous; //3
+                                       long seed;              //4
+                                       int initspeed;  //5
+                               } data;
+
+                               memcpy(&data, event.u.net.data, event.u.net.size);
+                               memcpy(&Players[me].flags, &data, sizeof(data.playerflags));
+                               memcpy(&Game, &data.maxplayers,
+                                       sizeof(data) - sizeof(data.playerflags));
                                SRandom(Game.seed);
                                break;
                        }
-                       case NP_newPlayer:
-                       {
-                               totalPlayers++;
-                               memcpy(&Players[event.u.net.uid],
-                                       event.u.net.data, event.u.net.size);
-                               fprintf(stderr, "Receiving player #%d (%s)\n",
-                                       event.u.net.uid, Players[event.u.net.uid].name);
-                               break;
-                       }
                        case NP_error:
                        {
                                fprintf(stderr, "Rejected by server: %s\n", event.u.net.data);
@@ -118,69 +120,7 @@ ExtFunc void HandShake(void)
                else
                        fatal("Hm, the party apparantly ended prematurely.");
        }
-       while (event.u.net.type != NP_goAhead);
-
-       // send Players[0]
-       // receive seed, initspeed
-               // receive #players
-               // receive Players[*]
-
-       /*
-                       {
-                       netint4 data[3];
-                       int len;
-                       int seed;
-
-                       if (protocolVersion >= 3)
-                               len = sizeof(data);
-                       else
-                               len = sizeof(netint4[2]);
-                       if ((Players[0].flags & SCF_setSeed))
-                               seed = Game.seed;
-                       else
-                               seed = time(0);
-                       if (waitConn)
-                               SRandom(seed);
-                       data[0] = hton4(Players[0].flags);
-                       data[1] = hton4(seed);
-                       data[2] = hton4(Game.initspeed);
-                       SendPackets(0, NP_startConn, len, data);
-                       if (WaitMyEvent(&event, EM_net) != E_net ||
-                                       event.u.net.type != NP_startConn)
-                               fatal("Network negotiation failed");
-                       memcpy(data, event.u.net.data, len);
-                       Players[1].flags = ntoh4(data[0]);
-                       seed = ntoh4(data[1]);
-                       if (initConn) {
-                               if ((Players[0].flags & SCF_setSeed) != (Players[1].flags & SCF_setSeed))
-                                       fatal("If one player sets the random number seed, "
-                                                       "both must.");
-                               if ((Players[0].flags & SCF_setSeed) && seed != Game.seed)
-                                       fatal("Both players have set the random number seed, "
-                                                       "and they are unequal.");
-                               if (protocolVersion >= 3 && Game.initspeed != ntoh4(data[2]))
-                                       fatal("Your opponent is using a different step-down "
-                                               "interval (-i).\nYou must both use the same one.");
-                               SRandom(seed);
-                       }
-               }
-               */
-//             SendPackets(0, NP_initData, strlen(Players[0].name) + 1, Players[0].name);
-
-/*
-                       if (WaitMyEvent(&event, EM_net) != E_net ||
-                                       event.u.net.type != NP_userName)
-                               fatal("Network negotiation failed");
-                       strncpy(Players[1].name, event.u.net.data,
-                               sizeof(Players[1].name) - 1);
-                       Players[1].name[sizeof(Players[1].name)-1] = 0;
-                       for (i = 0; Players[1].name[i]; ++i)
-                               if (!isprint(Players[1].name[i]))
-                                       Players[1].name[i] = '?';
-                       for (i = 0; Players[1].host[i]; ++i)
-                               if (!isprint(Players[1].host[i]))
-                                       Players[1].host[i] = '?';
-*/
+       while (event.u.net.type != NP_gamedata);
 } //HandShake
 
 ExtFunc void CheckNetConn(void)
@@ -218,10 +158,7 @@ ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
        event->u.net.type = type;
        event->u.net.size = size - HEADER_SIZE3;
        event->u.net.data = gen->buf + HEADER_SIZE3;
-       if (type == NP_endConn) {
-               fprintf(stderr, "Close connection\n");
-               return E_lostConn;
-       }
+       if (type == NP_endConn) return E_lostConn;
        return E_net;
 } //NetGenFunc
 
@@ -232,9 +169,9 @@ ExtFunc void SendPacket(short uid, NetPacketType type, int size, void *data)
        header[0] = hton4(uid);
        header[1] = hton4(type);
        header[2] = hton4(size + HEADER_SIZE3);
-       if (MyWrite(netGen[0].fd, header, HEADER_SIZE3) != HEADER_SIZE3)
+       if (MyWrite(netGen.fd, header, HEADER_SIZE3) != HEADER_SIZE3)
                die("write (header)");
-       if (size > 0 && data && MyWrite(netGen[0].fd, data, size) != size)
+       if (size > 0 && data && MyWrite(netGen.fd, data, size) != size)
                die("write");
 } //SendPacket
 
@@ -242,13 +179,13 @@ ExtFunc void CloseNet(void)
 { //kick some connection's ass!
        MyEvent event;
 
-       if (netGen[0].fd >= 0) {
+       if (netGen.fd >= 0) {
                SendPacket(0, NP_endConn, 0, NULL);
-               close(netGen[0].fd);
-               netGen[0].fd = -1;
+               close(netGen.fd);
+               netGen.fd = -1;
        }
-       if (netGen[0].next)
-               RemoveEventGen(&netGen[0]);
+       if (netGen.next)
+               RemoveEventGen(&netGen);
 } //CloseNet
 
 /*
index 30ce772a3262e6e0a2d5e12bd507a6172b31dbeb..7bbfc3ce3fe25fda603f08c7f5b6579dcfd9f16b 100644 (file)
--- a/netris.h
+++ b/netris.h
@@ -28,7 +28,7 @@
 #include <stdio.h>
 #include <signal.h>
 
-#define version_string         "0.5.810"
+#define version_string         "0.7.819"
 
 #define ExtFunc                /* Marks functions that need prototypes */
 
@@ -80,24 +80,45 @@ typedef long netint4;
 #define EM_key                         000002
 #define EM_net                         000004
 #define EM_robot                       000010
+#define EM_connect                     000020
 #define EM_any                         000777
 
 typedef enum _GameType { GT_onePlayer, GT_classicTwo, GT_len } GameType;
 typedef enum _BlockTypeA {
-       BT_none, BT_white, BT_blue, BT_magenta, BT_cyan, BT_yellow, BT_green,
-       BT_red, BT_wall, BT_len
+       BT_shadow, BT_none,
+       BT_green, BT_cyan, BT_blue, BT_magenta, BT_red, BT_yellow, BT_white,
+       BT_wall, BT_len
 } BlockTypeA;
 typedef enum _Dir { D_down, D_right, D_up, D_left } Dir;
 typedef enum _Cmd { C_end, C_forw, C_back, C_left, C_right, C_plot } Cmd;
 typedef enum _FDType { FT_read, FT_write, FT_except, FT_len } FDType;
 typedef enum _MyEventType {
-       E_none, E_alarm, E_key, E_net, E_lostConn, E_robot, E_lostRobot
+       E_none, E_alarm, E_key, E_connect, E_net, E_lostConn, E_robot, E_lostRobot
 } MyEventType;
 typedef enum _NetPacketType {
-       NP_endConn, NP_byeBye,
-       NP_error, NP_hello, NP_gamedata, NP_newPlayer, NP_goAhead,
-       NP_pause, NP_argghhh, NP_giveJunk, NP_newPiece, NP_down, NP_left, NP_right,
-       NP_rotright, NP_rotleft, NP_drop, NP_clear, NP_insertJunk
+       NP_endConn,             //client/server quits
+       NP_byeBye,              //unused atm
+       NP_error,               //handshake error
+       NP_hello,               //check versions
+       NP_gamedata,    //game options
+
+       NP_start,               //game ok to start
+       NP_pause,               //player (un)pauses
+       NP_stop,                //game ended
+       NP_newPlayer,   //add new player
+       NP_argghhh,             //player died
+
+       NP_newPiece,    //new piece info
+       NP_rotright,    //rotate piece clockwise
+       NP_rotleft,             //rotate piece counterclockwise
+       NP_left,                //move piece left
+       NP_right,               //move piece right
+       NP_down,                //move piece one down
+       NP_drop,                //drop piece to bottom
+       NP_clear,               //line cleared
+       NP_insertJunk,  //player added junk
+
+       NP_giveJunk             //player has to add junk
 } NetPacketType;
 
 typedef signed char BlockType;
@@ -133,7 +154,6 @@ typedef struct _EventGenRec {
        char buf[512];
        int bufSize, bufGoal;
 } EventGenRec;
-EXT EventGenRec netGen[MAX_SCREENS];
 
 MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
 
@@ -158,8 +178,6 @@ typedef int (*ShapeDrawFunc)(int scr, int y, int x,
 #define SCF_fairRobot          000002
 #define SCF_paused                     000004
 
-EXT int totalPlayers;
-
 typedef struct _Player {
        int alive;
        char name[16];
@@ -175,18 +193,23 @@ typedef struct _Player {
                int drops, lines, adds;
        } score;
        char host[256]; //last-1
-       int spy;                //last
+       int spy,small;  //last
 } Player;
 EXT Player Players[MAX_SCREENS];
 EXT short me;
+EXT short maxPlayer;
+EXT int spied; //in player.flags
 
 #define DEFAULT_INTERVAL       1000000 /* Step-down interval in microseconds */
 #define SPEEDINC                       1.2
 #define SPEEDMINIMUM           40000
 
 typedef struct __Game {
-       long seed;              //1st
-       int initspeed;  //2nd
+       int maxplayers; //1
+       int started;    //2
+       int continuous; //3
+       long seed;              //4
+       int initspeed;  //5
        int speed;
        int standout, color, ascii;
 } _Game;
diff --git a/robot.c b/robot.c
index 23875a3bd4b9984bf0c1815e95e7970c5f8318e2..31bb5d8b913c4948dc8b14998b33056f328e2a0e 100644 (file)
--- a/robot.c
+++ b/robot.c
@@ -30,7 +30,6 @@
 #include <errno.h>
 
 static MyEventType RobotGenFunc(EventGenRec *gen, MyEvent *event);
-
 static EventGenRec robotGen =
                { NULL, 0, FT_read, -1, RobotGenFunc, EM_robot };
 
index 9297b13a96374dbfe4c44f70a4db165cdd490d65..f67721f6eb3019366f229df40e20b4e9721b0240 100644 (file)
--- a/server.c
+++ b/server.c
 static struct option options[] = {
        { "wait",               0, 0, 'w' },
        { "port",               1, 0, 'p' },
-       { "connections",1, 0, 'c' },
+       { "min-players",1, 0, 'm' },
+       { "max-players",1, 0, 'x' },
+       { "continuous", 1, 0, 'c' },
        { "speed",              1, 0, 'i' },
        { "seed",               1, 0, 's' },
+       { "verbose",    0, 0, 'v' },
        { "info",               0, 0, 'H' },
        { "help",               0, 0, 'h' },
        { 0,                    0, 0,  0 }
 };
 
-static char Connections = 2;
+static char minplayers = 2;
+static char countPlayers = 0;
+static char verbose = 0;
+
+struct sockaddr_in addr;
 
 static char *gameNames[GT_len] = { "OnePlayer", "ClassicTwo" };
 
 ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
-
-EventGenRec netGen[MAX_SCREENS] = {
+static EventGenRec netGen[MAX_SCREENS] = {
        { NULL, 0, FT_read, -1, NetGenFunc, EM_net, 0, "\0", 0, HEADER_SIZE } };
 
 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event);
 static EventGenRec alarmGen =
-               { &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm };
+       { &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm };
+
+static MyEventType ConnGenFunc(EventGenRec *gen, MyEvent *event);
+static EventGenRec connGen =
+       { NULL, 0, FT_read, -1, ConnGenFunc, EM_connect };
+
 static EventGenRec *nextGen = &alarmGen;
 
 static sigjmp_buf close_env;
 
+
 ExtFunc volatile void die(char *msg)
 {
        perror(msg);
@@ -101,10 +113,25 @@ ExtFunc int MyWrite(int fd, void *data, int len)
        return len;
 } //MyWrite
 
+ExtFunc void SendPacketTo(short playa, short uid, NetPacketType type, int size, void *data)
+{ //send to someone
+       netint4 header[3];
+
+       if (netGen[playa].fd >= 0) {
+               header[0] = hton4(uid);
+               header[1] = hton4(type);
+               header[2] = hton4(size + HEADER_SIZE);
+               if (MyWrite(netGen[playa].fd, header, HEADER_SIZE) != HEADER_SIZE)
+                       die("write (header)");
+               if (size > 0 && data && MyWrite(netGen[playa].fd, data, size) != size)
+                       die("write");
+       }
+} //SendPacketTo
+
 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event)
 {
        return E_alarm;
-}
+} //AlarmGenFunc
 
 ExtFunc void AddEventGen(EventGenRec *gen)
 {
@@ -125,6 +152,39 @@ ExtFunc void RemoveEventGen(EventGenRec *gen)
        }
 } //RemoveEventGen
 
+ExtFunc void AtExit(void (*handler)(void))
+{ //setup something to do at exit (^C)
+#ifdef HAS_ON_EXIT
+       on_exit((void *)handler, NULL);
+#else
+       atexit(handler);
+#endif
+} //AtExit
+
+ExtFunc void SCloseNet(short playa)
+{ //kick some connection's ass!
+       MyEvent event;
+
+       if (netGen[playa].fd >= 0) {
+               SendPacketTo(playa, 0, NP_endConn, 0, NULL);
+               do{} while (WaitMyEvent(&event, EM_net) != E_lostConn);
+               close(netGen[playa].fd);
+               netGen[playa].fd = -1;
+       }
+       if (netGen[playa].next)
+               RemoveEventGen(&netGen[playa]);
+} //SCloseNet
+
+ExtFunc void CloseNets(void)
+{ //nou oogjes dicht en snaveltjes toe
+       int i;
+
+       fprintf(stderr, "- Closing connections...\n");
+       for (i = 1; i < MAX_SCREENS; i++)
+               SCloseNet(i); //bye everybuddy
+       fprintf(stderr, "* All Done\n\n");
+} //CloseNets
+
 ExtFunc MyEventType WaitMyEvent(MyEvent *event, int mask)
 { //poll
        int i, retry = 0;
@@ -178,13 +238,6 @@ ExtFunc MyEventType WaitMyEvent(MyEvent *event, int mask)
        }
 } //WaitMyEvent
 
-ExtFunc void ByeClient(int playa)
-{ //client went away
-       fprintf(stderr, "Close connection #%d\n", playa);
-       close(netGen[playa].fd);
-       netGen[playa].fd = -1;
-} //ByeClient
-
 ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
 { //receive
        int result;
@@ -194,9 +247,8 @@ ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
        result = MyRead(gen->fd, gen->buf + gen->bufSize,
                gen->bufGoal - gen->bufSize);
        if (result < 0) {
-               ByeClient(gen->player);
-               type = NP_endConn;
-               return E_net;
+               fprintf(stderr, "- Closed connection to player #%d\n", gen->player);
+               return E_lostConn;
        }
        gen->bufSize += result;
        if (gen->bufSize < gen->bufGoal)
@@ -215,206 +267,228 @@ ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
        event->u.net.type = type;
        event->u.net.size = size - HEADER_SIZE;
        event->u.net.data = gen->buf + HEADER_SIZE;
-       if (type == NP_endConn)
-               ByeClient(gen->player);
+       if (type == NP_endConn) {
+               fprintf(stderr, "- Quit player #%d\n", gen->player);
+               return E_lostConn;
+       } //client sent quit signal
        return E_net;
 } //NetGenFunc
 
-ExtFunc void SendPacketTo(short playa, short uid, NetPacketType type, int size, void *data)
-{ //send to someone
-       netint4 header[3];
-
-       if (netGen[playa].fd >= 0) {
-               header[0] = hton4(uid);
-               header[1] = hton4(type);
-               header[2] = hton4(size + HEADER_SIZE);
-               if (MyWrite(netGen[playa].fd, header, HEADER_SIZE) != HEADER_SIZE)
-                       die("write (header)");
-               if (size > 0 && data && MyWrite(netGen[playa].fd, data, size) != size)
-                       die("write");
-       }
-} //SendPacketTo
 
-
-ExtFunc void AtExit(void (*handler)(void))
-{
-#ifdef HAS_ON_EXIT
-       on_exit((void *)handler, NULL);
-#else
-       atexit(handler);
-#endif
-}
-
-ExtFunc void SCloseNet(short playa)
-{ //kick some connection's ass!
-       MyEvent event;
-
-       if (netGen[playa].fd >= 0) {
-               SendPacketTo(playa, 0, NP_endConn, 0, NULL);
-               do{} while (WaitMyEvent(&event, EM_net) != E_lostConn);
-               close(netGen[playa].fd);
-               netGen[playa].fd = -1;
-       }
-       if (netGen[playa].next)
-               RemoveEventGen(&netGen[playa]);
-} //SCloseNet
-
-ExtFunc void CloseNets(void)
-{ //nou oogjes dicht en snaveltjes toe
-       int i;
-
-       for (i = 1; i <= totalPlayers; i++)
-               SCloseNet(i);
-} //CloseNets
-
-ExtFunc int WaitForConnection(short port)
+static MyEventType ConnGenFunc(EventGenRec *gen, MyEvent *event)
 {
-       struct sockaddr_in addr;
-       struct hostent *host;
-       int sockListen;
        int addrLen;
-       int val1;
        struct linger val2;
-       int i;
-
-       AtExit(CloseNets);
-       for (i = 1; i < MAX_SCREENS; i++)
-               memcpy(&netGen[i], &netGen[0], sizeof(EventGenRec));
-
-       memset(&addr, 0, sizeof(addr));
-       addr.sin_family = AF_INET;
-       addr.sin_port = htons(port);
-       addr.sin_addr.s_addr = htonl(INADDR_ANY);
-       if ((sockListen = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-               die("socket");
-       val1 = 1;
-       setsockopt(sockListen, SOL_SOCKET, SO_REUSEADDR,
-                       (void *)&val1, sizeof(val1));
-       if (bind(sockListen, (struct sockaddr *)&addr, sizeof(addr)) < 0)
-               die("bind");
-       if (listen(sockListen, 1) < 0)
-               die("listen");
+       int new;
 
        addrLen = sizeof(addr);
-       for (i = 1; i <= Connections; i++) {
-               if ((netGen[i].fd = accept(sockListen, (struct sockaddr *)&addr, &addrLen)) < 0)
+       for (new = 1; new <= MAX_SCREENS; new++)
+               if (netGen[new].fd < 0) break;
+       if (new > Game.maxplayers) return;
+
+       if ((netGen[new].fd =
+               accept(gen->fd, (struct sockaddr *)&addr, &addrLen)) < 0)
                        die("accept");
-               fprintf(stderr, "Connection: %s\n", inet_ntoa(addr.sin_addr));
-               val2.l_onoff = 1;
-               val2.l_linger = 0;
-               setsockopt(netGen[i].fd, SOL_SOCKET, SO_LINGER, (void *)&val2, sizeof(val2));
-               sprintf(Players[i].host, "%s", inet_ntoa(addr.sin_addr));
-               if (addr.sin_family == AF_INET) {
-                       host = gethostbyaddr((void *)&addr.sin_addr,
-                                       sizeof(struct in_addr), AF_INET);
-                       if (host) {
-                               strncpy(Players[i].host, host->h_name, sizeof(Players[i].host) - 1);
-                               Players[i].host[sizeof(Players[i].host) - 1] = 0;
-                       }
-               }
-               AddEventGen(&netGen[i]);
-               netGen[i].player = i;
-               totalPlayers++;
-               {
-                       MyEvent event;
-
-                       do {} while ((WaitMyEvent(&event, EM_net) != E_net) ||
-                                       (event.u.net.sender != i));
-                       if (event.u.net.type != NP_hello) ByeClient(i);
-                       else {
-                               netint4 versiondata[2];
-                               char data[255];
-                               int major;
-                               memcpy(versiondata, event.u.net.data, sizeof(versiondata));
-                               major = ntoh4(versiondata[0]);
-                               protocolVersion = ntoh4(versiondata[1]);
-                               if (major != MAJOR_VERSION || protocolVersion != PROTOCOL_VERSION) {
-                                       snprintf(data, sizeof(data), "Version mismatch: received %d.%d",
-                                               major, protocolVersion);
-                                       fprintf(stderr, "Byebye client #%d (%s)\n",
-                                               event.u.net.sender, data);
-                                       SendPacketTo(event.u.net.sender, 0, NP_error, strlen(data)+1, data);
-                                       SCloseNet(event.u.net.sender);
-                               } //version mismatch
-                               fprintf(stderr, "Accepted #%d\n", event.u.net.sender);
-                       } //NP_hello
-               }
-       }
-       close(sockListen);
-       return 0;
-} //WaitForConnection
+       fprintf(stderr, "+ Connection: %s\n", inet_ntoa(addr.sin_addr));
+       val2.l_onoff = 1;
+       val2.l_linger = 0;
+       setsockopt(netGen[new].fd, SOL_SOCKET, SO_LINGER,(void *)&val2,
+               sizeof(val2));
+       AddEventGen(&netGen[new]);
+       netGen[new].player = event->u.net.uid = new;
+                       { //new connection; netGen already initialized in GenFunc
+                               struct hostent *host;
+
+                               sprintf(Players[new].host, "%s", inet_ntoa(addr.sin_addr));
+                               if (addr.sin_family == AF_INET) {
+                                       host = gethostbyaddr((void *)&addr.sin_addr,
+                                                       sizeof(struct in_addr), AF_INET);
+                                       if (host) {
+                                               strncpy(Players[new].host, host->h_name,
+                                                       sizeof(Players[new].host) - 1);
+                                               Players[new].host[sizeof(Players[new].host) - 1] = 0;
+                                       } //set player's hostname
+                               }
+                       } //E_connect
+       return E_connect;
+} //ConnGenFunc
 
 ExtFunc int StartServer(void)
 {
        MyEvent event;
+       netint2 currentpiece[MAX_SCREENS];
        int playercount;
        int playersReady = 0;
        int i;
 
-       {
-               char serverdata[255];
-               for (i = 1; i <= totalPlayers; i++) {
-                       sprintf(serverdata, "Netris server %s", version_string);
-                       SendPacketTo(i, i, NP_hello, strlen(serverdata)+1, serverdata);
-               }
-       }
-
        do {
-               if (WaitMyEvent(&event, EM_net) == E_net) {
-//                     fprintf(stderr, "in %d: %d\n",
-//                             netGen[event.u.net.sender].fd, event.u.net.type);
-                       switch(event.u.net.type) {
-                               case NP_endConn:
-                               { //client went away :(
-                                       Players[event.u.net.sender].alive = 0;
-                                       for (i = 1; i <= totalPlayers; i++)
+               switch (WaitMyEvent(&event, EM_any)) {
+                       case E_lostConn: //client went away :(
+                               Players[event.u.net.sender].alive = 0;
+                               for (i = 1; i < MAX_SCREENS; i++)
+                                       if (Players[i].alive)
                                                SendPacketTo(i, event.u.net.sender,
                                                        NP_argghhh, sizeof(Players[0].alive),
                                                        &Players[event.u.net.sender].alive);
-                                       break;
-                               } //NP_endConn
-                               case NP_hello:
-                                       break;
-                               case NP_newPlayer:
-                               { //receive player details and return other players
-                                       memcpy(&Players[event.u.net.sender],
-                                               event.u.net.data, event.u.net.size);
-                                       if (!Players[event.u.net.sender].team)
-                                               Players[event.u.net.sender].team = 256 - event.u.net.sender;
-                                       fprintf(stderr, "player %d: %s <%s>\n", event.u.net.sender,
-                                               event.u.net.data, //Players[event.u.net.sender].name
-                                               Players[event.u.net.sender].host);
-                                       SendPacketTo(event.u.net.sender, 0, NP_gamedata,
-                                               sizeof(Game.seed)+sizeof(Game.initspeed), &Game);
-                                       for (i = 1; i <= totalPlayers; i++)
-                                               if (i != event.u.net.sender)
-                                                       SendPacketTo(i, event.u.net.sender, event.u.net.type,
-                                                               sizeof(Player) - sizeof(Players[0].spy),
-                                                               &Players[event.u.net.sender]);
-                                       if (++playersReady >= totalPlayers) {
-                                               fprintf(stderr, "Starting game (%010d)\n", Game.seed);
-                                               for (i = 1; i <= totalPlayers; i++)
-                                                       SendPacketTo(i, 0, NP_goAhead, 0, NULL);
-                                       } //give go ahead
-                                       break;
-                               } //NP_playerdata
-                               default:
-                               { //relay data to all players
-       //                              if (event.u.net.type >= NP_pause)
-                                       for (i = 1; i <= totalPlayers; i++)
-                                               if (i != event.u.net.sender)
-                                               if (event.u.net.type != NP_giveJunk
-                                               || Players[i].team != Players[event.u.net.sender].team)
-                                                       SendPacketTo(i, event.u.net.sender, event.u.net.type,
-                                                               event.u.net.size, event.u.net.data);
-                                       break;
+                               SCloseNet(event.u.net.sender);
+                               break; //NP_endConn
+                       case E_net:
+                               if (verbose) fprintf(stderr, ": %d sent %d\n",
+                                       netGen[event.u.net.sender].fd, event.u.net.type);
+                               switch(event.u.net.type) {
+                                       case NP_hello:
+//                                             if (event.u.net.type != NP_hello) ByeClient(new);
+                                       {
+                                               netint4 versiondata[2];
+                                               char data[255];
+                                               int major;
+
+                                               memcpy(versiondata, event.u.net.data,
+                                                       sizeof(versiondata));
+                                               major = ntoh4(versiondata[0]);
+                                               protocolVersion = ntoh4(versiondata[1]);
+                                               if (major != MAJOR_VERSION
+                                               || protocolVersion != PROTOCOL_VERSION) {
+                                                       snprintf(data, sizeof(data),
+                                                               "Version mismatch: received %d.%d",
+                                                               major, protocolVersion);
+                                                       fprintf(stderr, "= Wrong version player #%d (%s)\n",
+                                                               event.u.net.sender, data);
+                                                       SendPacketTo(event.u.net.sender, 0, NP_error,
+                                                               strlen(data)+1, data);
+                                                       SCloseNet(event.u.net.sender);
+                                               } //version mismatch
+                                               fprintf(stderr, "* Accepted player #%d\n",
+                                                       event.u.net.sender);
+                                               break;
+                                       } //NP_hello
+                                       case NP_newPlayer:
+                                       //receive player details and return other players
+                                               memcpy(&Players[event.u.net.sender],
+                                                       event.u.net.data, event.u.net.size);
+                                               if (!Players[event.u.net.sender].team)
+                                                       Players[event.u.net.sender].team =
+                                                               256 - event.u.net.sender;
+                                               if (Game.started < 2)
+                                                       Players[event.u.net.sender].flags |= SCF_paused;
+                                               if (!Game.continuous && Game.started >= 2) {
+                                                       char data[40];
+                                                       strcpy(data,"Can't join: Game has already started");
+                                                       fprintf(stderr, "- Can't join player #%d in "
+                                                               "non-continuous game\n", event.u.net.sender);
+                                                       SendPacketTo(event.u.net.sender, 0, NP_error,
+                                                               strlen(data)+1, data);
+//                                                     SCloseNet(event.u.net.sender, 0);
+                                                       break;
+                                               } //can't join started game
+                                               {
+                                                       static struct {
+                                                               int playerflags;
+                                                               int maxplayers; //1
+                                                               int started;    //2
+                                                               int continuous; //3
+                                                               long seed;              //4
+                                                               int initspeed;  //5
+                                                       } data;
+
+                                                       memcpy(&data, &Players[event.u.net.sender].flags,
+                                                               sizeof(data.playerflags));
+                                                       memcpy(&data.maxplayers, &Game,
+                                                               sizeof(data) - sizeof(data.playerflags));
+                                                       SendPacketTo(event.u.net.sender, 0, NP_gamedata,
+                                                               sizeof(data), &data);
+                                               } //send game options
+                                               for (i = 1; i < MAX_SCREENS; i++)
+                                                       if (netGen[i].fd >= 0 && i != event.u.net.sender) {
+                                                               SendPacketTo(event.u.net.sender, i,
+                                                                       NP_newPlayer, sizeof(Player)
+                                                                       - sizeof(Players[0].spy)
+                                                                       - sizeof(Players[0].small),
+                                                                       &Players[i]);
+                                                               SendPacketTo(event.u.net.sender, i,
+                                                                       NP_newPiece, sizeof(currentpiece[i]),
+                                                                       &currentpiece[i]);
+                                                               SendPacketTo(i, event.u.net.sender,
+                                                                       NP_newPlayer, sizeof(Player)
+                                                                       - sizeof(Players[0].spy)
+                                                                       - sizeof(Players[0].small),
+                                                                       &Players[event.u.net.sender]);
+                                                       } //send (to) players
+                                               fprintf(stderr, "> Joined player #%d: %s <%s>\n",
+                                                       event.u.net.sender,
+                                                       Players[event.u.net.sender].name,
+                                                       Players[event.u.net.sender].host);
+                                               if (++playersReady >= minplayers) {
+                                                       if (Game.started)
+                                                               SendPacketTo(event.u.net.sender, 0,
+                                                                       NP_start, 0, NULL);
+                                                       else {
+                                                               fprintf(stderr, "* Starting game (%010d)\n",
+                                                                       Game.seed);
+                                                               for (i = 1; i < MAX_SCREENS; i++)
+                                                                       SendPacketTo(i, 0, NP_start, 0, NULL);
+                                                               Game.started++;
+                                                       } //first goahead (to all)
+                                               } //give go ahead
+                                               break; //NP_playerdata
+                                       case NP_newPiece:
+                                               memcpy(&currentpiece[event.u.net.sender],
+                                                       event.u.net.data, sizeof(currentpiece[0]));
+                                               goto sendtoall;
+                                       case NP_argghhh:
+                                               Players[event.u.net.sender].alive = 0;
+                                               fprintf(stderr, "< Player #%d died\n",
+                                                       event.u.net.sender);
+                                               //check for unpaused game
+                                       case NP_pause:
+                                       {
+                                               int paused;
+                                               Players[event.u.net.sender].flags ^= SCF_paused;
+                                               paused = Game.started < 1;
+                                               for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive)
+                                                       paused |= Players[i].flags & SCF_paused;
+                                               if (paused) paused = 1;
+                                               else if (Game.started == 1) Game.started++;
+                                               goto sendtoall;
+                                       } //NP_pause
+                                       default: //relay data to all players
+                                       sendtoall:
+//                                             if (event.u.net.type >= NP_pause)
+                                               for (i = 1; i < MAX_SCREENS; i++)
+                                                       if (i != event.u.net.sender)
+                                                       if (event.u.net.type != NP_giveJunk ||
+                                                       Players[i].team != Players[event.u.net.sender].team)
+                                                               SendPacketTo(i, event.u.net.sender,
+                                                                       event.u.net.type, event.u.net.size,
+                                                                       event.u.net.data);
+                                               break; //>=NP_paused
                                }
-                       }
-               } //E_net
-               playercount = 0;
-               for (i = 1; i <= totalPlayers; i++)
-                       if (netGen[i].fd >= 0) playercount++;
-       } while (playercount > 1);
+                               break; //E_net
+                       case E_connect:
+                       { //new connection; netGen already initialized in GenFunc
+                               char serverdata[255];
+
+                               sprintf(serverdata, "Netris server %s", version_string);
+                               SendPacketTo(event.u.net.uid, event.u.net.uid, NP_hello,
+                                       strlen(serverdata)+1, serverdata);
+                               break;
+                       } //E_connect
+               } //event
+               {
+                       int j;
+                       playercount = 0;
+                       for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive) {
+                               if (Players[i].team < 128) for (j = 1; j < i; j++)
+                                       if (Players[j].alive
+                                       && (Players[j].team == Players[i].team)) {
+                                               playercount--;
+                                               break;
+                                       } //player of same team counted before
+                               playercount++;
+                       } //player alive
+               } //count players
+       } while (Game.started < 2 || playercount > 1 || Game.continuous);
+       fprintf(stderr, "* Exiting server\n");
 } //StartServer
 
 
@@ -438,6 +512,9 @@ ExtFunc void Usage(void)
          "\n"
          "  -s, --seed <seed>\tStart with given random seed\n"
          "  -i, --speed <sec>\tSet the initial step-down interval, in seconds\n"
+         "  -m, --min-players <2>\tNumber of players required before starting the game\n"
+         "  -x, --max-players <8>\tMaximum number of players allowed in the game\n"
+         "  -c, --continuous\tDon'n quit the game\n"
          "\n", DEFAULT_PORT);
 }
 
@@ -480,11 +557,22 @@ ExtFunc void WriteConf(void)
 ExtFunc void HandleOption(char tag, char *value)
 {
        switch (tag) {
+               case 'v':       //verbose
+                       verbose = 1;
+                       break;
                case 'p':       //port
                        port = atoi(value);
                        break;
-               case 'c':       //connections
-                       Connections = atoi(value);
+               case 'c':       //min-players
+                       Game.continuous = atoi(value);
+                       break;
+               case 'm':       //min-players
+                       minplayers = atoi(value);
+                       break;
+               case 'x':       //max-players
+                       Game.maxplayers = atoi(value);
+                       if (Game.maxplayers >= MAX_SCREENS)
+                               Game.maxplayers = MAX_SCREENS;
                        break;
                case 'i':       //speed (of level 1)
                        Game.initspeed = atof(value) * 1e6;
@@ -515,7 +603,8 @@ ExtFunc void ReadConf(char *filename)
                        if ((ch = strchr(buf, '#')))
                                *ch = '\0'; // truncate string from # char
                        for (i = strlen(buf)-1; i >= 0; i--)
-                               if (buf[i] == ' ' || buf[i] == '\n' || buf[i] == '\t' || buf[i] == 13)
+                               if (buf[i] == ' ' || buf[i] == '\t'
+                               || buf[i] == '\n' || buf[i] == 13)
                                        buf[i] = '\0';
                                else break;
 
@@ -547,6 +636,7 @@ ExtFunc int main(int argc, char **argv)
        if (sigsetjmp(close_env, 1)) exit(0);
        signal(SIGINT, CatchInt);
        port = DEFAULT_PORT;
+       Game.maxplayers = 8;
        Game.initspeed = DEFAULT_INTERVAL;
        Game.seed = time(0);
 
@@ -555,7 +645,7 @@ ExtFunc int main(int argc, char **argv)
 //     else
        ReadConf(CONFIG_FILE);
        while ((ch = getopt_long(argc, argv,
-                       "hHp:i:s:c:", options, NULL)) != -1)
+                       "hHvp:i:s:c:m:x:", options, NULL)) != -1)
                HandleOption(ch, optarg);
        if (optind < argc) {
                Usage();
@@ -564,8 +654,38 @@ ExtFunc int main(int argc, char **argv)
 //     WriteConf();
 
        Header();
-       WaitForConnection(port);
-       StartServer();
+
+       {
+               int i;
+
+               for (i = 1; i < MAX_SCREENS; i++)
+                       memcpy(&netGen[i], &netGen[0], sizeof(EventGenRec));
+       } //setup netGen var
+
+       AtExit(CloseNets);
+
+       {
+               int val1;
+
+               memset(&addr, 0, sizeof(addr));
+               addr.sin_family = AF_INET;
+               addr.sin_port = htons(port);
+               addr.sin_addr.s_addr = htonl(INADDR_ANY);
+               if ((connGen.fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+                       die("socket");
+               val1 = 1;
+               setsockopt(connGen.fd, SOL_SOCKET, SO_REUSEADDR,
+                               (void *)&val1, sizeof(val1));
+               if (bind(connGen.fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+                       die("bind");
+               if (listen(connGen.fd, 1) < 0)
+                       die("listen");
+
+               AddEventGen(&connGen);
+       } //setup listening sock
+
+       StartServer(); //server loop
+
        return 0;
 }
 
diff --git a/util.c b/util.c
index b32592fe0da16e75c400584077619ec8ef622f28..2f7c2e5d7ad346b1f30562fbd43417c49763afe1 100644 (file)
--- a/util.c
+++ b/util.c
 #include <sys/time.h>
 #include <netdb.h>
 #include <errno.h>
-#include <setjmp.h>
 
 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event);
-
 static EventGenRec alarmGen =
                { &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm };
 static EventGenRec *nextGen = &alarmGen;
 
-static sigjmp_buf close_env;
-
 static int myRandSeed = 1;
 
 static long baseTimeval;
@@ -75,11 +71,10 @@ ExtFunc void Usage(void)
          "  -a, --ascii\t\tUse ascii characters\n"
          "  -C, --color=0\t\tDisable color\n"
          "\n"
-         "  -w, --wait\t\tWait for connection\n"
          "  -c, --connect <host>\tInitiate connection\n"
          "  -p, --port <port>\tSet port number (default is %d)\n"
          "\n"
-         "  -i, --speed <sec>\tSet the initial step-down interval, in seconds\n"
+         "  -t, --team <team>\tJoin a team (don't receive lines from your teammates)\n"
          "  -l, --level <lvl>\tBegin at a higher level (can be used as handicap)\n"
          "  -k, --keys <keys>\tRemap keys (default is \"%s\" for cursors)\n"
          "  -d, --dropmode\tDrops go into drop mode\n"
@@ -136,14 +131,6 @@ ExtFunc void Rules(void)
 
 ///////////// RANDOM /////////////
 
-ExtFunc void InitUtil(void)
-{
-       SRandom(time(0));
-       if (sigsetjmp(close_env, 1)) exit(0);
-       signal(SIGINT, CatchInt);
-       ResetBaseTime();
-} //InitUtil
-
 /*
  * My really crappy random number generator follows
  * Should be more than sufficient for our purposes though
@@ -208,11 +195,6 @@ ExtFunc void NormalizeTime(struct timeval *tv)
        }
 }
 
-ExtFunc void CatchInt(int sig)
-{
-       siglongjmp(close_env, 1);
-}
-
 ExtFunc void CatchAlarm(int sig)
 {
        alarmGen.ready = 1;
@@ -300,7 +282,7 @@ ExtFunc volatile void fatal(char *msg)
 {
        fprintf(stderr, "%s\n", msg);
        exit(1);
-}
+} //fatal
 
 ExtFunc void BlockSignals(MySigSet *saved, ...)
 {
@@ -327,7 +309,7 @@ ExtFunc void BlockSignals(MySigSet *saved, ...)
        *saved = sigblock(set);
 #endif
        va_end(args);
-}
+} //BlockSignals
 
 ExtFunc void RestoreSignals(MySigSet *saved, MySigSet *set)
 {
@@ -339,7 +321,7 @@ ExtFunc void RestoreSignals(MySigSet *saved, MySigSet *set)
        else
                sigsetmask(*set);
 #endif
-}
+} //RestoreSignals
 
 ///////////// EVENTS /////////////