unofficial version 0.7: multiplayer improvements v0.7
authorMischa POSLAWSKY <netris@shiar.org>
Sat, 10 Aug 2002 22:01:00 +0000 (00:01 +0200)
committerMischa POSLAWSKY <netris@shiar.org>
Tue, 27 Feb 2007 04:56:51 +0000 (05:56 +0100)
- common seed
- teams
- related ui updates

CHANGES
Configure
FAQ
curses.c
game.c
inet.c
netris.h
server.c
util.c

diff --git a/CHANGES b/CHANGES
index 0aa3d642ff62b8675affeb58f25a1326d6d8f585..ff4175c9cec35a2a274f2116b4ec173277975adb 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,11 @@
+       [][]    []   [][][]  [][][][] [][][]  [][]   [] [][][]
+       [][]    []   []         []    []   [] [][] [][]     []
+          []   []              []     [][][]      []
+       [] [][] []  [][][][]    [][]  []       []    [][][][]
+       []   []                  []   [] []    []           []
+       []    [][]   []        [][]   [] [][]  []  []     [][]
+       []    [][]   [][][]      []   []   []  []  [][][] []
+
 ---- done: -------------------------------------------------------------------
 
  -- v0.6 ---------- 31.VII.02
@@ -20,6 +28,7 @@
  
  -- v0.6.83 -------
 
+ * conffile can have comments (#) and tabs instead of spaces
  * level up every 10 lines (speed x1.2)
  
  -- v0.6.84 -------
  * fix multiplay g/o (close connection at g/o or server signal)
  * spy=n0 in configfile disables spying for player n
 
+ -- v0.6.810 ------
 
----- near-future: ------------------------------------------------------------
+ * seed and initspeed given by server
+ * exits when only 1 player left (or 0 in singleplayer)
+ * version_string in netris.h
+ * fixed pause for multiple players
+ * paused message displayed over pausing player's field
+ * all players start paused in multiplayer
+ * your own hostname isn't displayed
 
- * teams
- * send game options
- * fix multplay pause
- * server continuously acceping new connections, and immediate handshake
- * fix g/o (server should count, maybe reorder players)
- * everybody start paused?
- * show n fields (improved spy parameter)
+ -- v0.7 ---------- 10.VIII.02
+
+ * display game over over dead player's field
+ * number of connections can be set with server -c
+ * exiting client automatically goes game over
+ * dead players can't pause the game
+ * -t sets team. players in same team don't get junklines from each other
+ * client no longer displays seed
+ * doesn't display fields which don't fit on screen automatically
+ * quit key (q by default)
+
+
+---- near-future: ------------------------------------------------------------
 
 
 ---- asap: -------------------------------------------------------------------
 
  * fix -f
+ * fix bot
+ * server continuously acceping new connections, and immediate handshake
  * midgame join option
- * optional enemy field resize
+ * optional smaller enemy fields
  * multiplayer stats
- * pause message over player's field
 
 
 ---- distant future: ---------------------------------------------------------
 
  * special blocks
  * tetrinet compatible?
+ * remove bot delay (make it humanplayer-like)
+ * new+better bot?
 
 
 ------------------------------------------------------------------------------
index 97479dbb54247710f890d26b793ad4220fcd4846..a17707ebd95e8f344d1e65a48bfcd1a9605620e6 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -138,8 +138,7 @@ fi
 rm -f test.c test.o a.out
 
 ORIG_SOURCES="game- curses- shapes- board- util- inet- robot-"
-GEN_SOURCES="version-"
-SOURCES="$ORIG_SOURCES $GEN_SOURCES"
+SOURCES="$ORIG_SOURCES"
 
 SRCS="`echo $SOURCES | sed -e s/-/.c/g`"
 OBJS="`echo $SOURCES | sed -e s/-/.o/g`"
@@ -192,10 +191,6 @@ Makefile config.h: Configure
        @echo "Run ./Configure now"
        @false
 
-version.c: VERSION
-       @echo "Creating version.c"
-       @sed -e 's/^\(.*\)$$/char *version_string = "\1";/' VERSION > $@
-
 proto.h: $(SRCS)
        @touch $@
        @mv $@ $@.old
@@ -226,7 +221,7 @@ dist: $(DISTFILES)
        tar -cvzof $$dir.tar.gz $$dir
 
 clean:
-       rm -f proto.h proto.chg $(PROG) $(OBJS) version.c test.c a.out sr sr.o server server.o
+       rm -f proto.h proto.chg $(PROG) $(OBJS) test.c a.out sr sr.o server server.o
 
 cleandir: clean
        rm -f .depend Makefile config.h
diff --git a/FAQ b/FAQ
index 4148983c4e22f5b90199842fe071a057005f4174..3a7f294cdc983f715108e4cafce4d999dd20c44b 100644 (file)
--- a/FAQ
+++ b/FAQ
@@ -57,7 +57,7 @@ Answers
 [3] If I drop a piece and then slide it off a cliff, shouldn't
     it automatically drop again?
 
-    Try the -D option.
+    Try the -d option.
 
 [4] When I try to play a networked game, it just hangs.
 
index 4f8ddbdf7e3536342f350c29356172a59c8a3278..f28a6a36a2ec81cf6c846f87599e187a31713c05 100644 (file)
--- a/curses.c
+++ b/curses.c
 #endif
 
 #ifdef HAVE_NCURSES
-static struct
-{
+static struct {
        BlockType type;
        short color;
-} myColorTable[] =
-{
+} myColorTable[] = {
        { BT_white,             COLOR_WHITE },
        { BT_blue,              COLOR_BLUE },
        { BT_magenta,   COLOR_MAGENTA },
@@ -44,7 +42,7 @@ static struct
        { BT_yellow,    COLOR_YELLOW },
        { BT_green,             COLOR_GREEN },
        { BT_red,               COLOR_RED },
-       { BT_none, 0 }
+       { BT_none,              0 }
 };
 #endif
 
@@ -117,14 +115,14 @@ ExtFunc void InitScreens(void)
        }
        statusYPos = 22;
        statusXPos = 0;
-}
+} //InitScreens
 
 ExtFunc void CleanupScreens(void)
 {
        RemoveEventGen(&keyGen);
        endwin();
        OutputTermStr(term_ve, 1);
-}
+} //CleanupScreens
 
 ExtFunc void GetTermcapInfo(void)
 {
@@ -180,22 +178,27 @@ ExtFunc void GetTermcapInfo(void)
        }
        if (!term_vi || !term_ve)
                term_vi = term_ve = NULL;
-}
+} //GetTermcapInfo
 
 ExtFunc void OutputTermStr(char *str, int flush)
 {
        if (str) {
                fputs(str, stdout);
-               if (flush)
-                       fflush(stdout);
+               if (flush) fflush(stdout);
        }
-}
+} //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;
+               }
+
                for (y = Players[scr].boardVisible - 1; y >= 0; --y) {
                        mvaddch(boardYPos[scr] - y, boardXPos[scr] - 1,
                                Game.ascii ? '|' : ACS_VLINE); //left
@@ -218,7 +221,9 @@ ExtFunc void DrawField(int scr)
        {
                char userstr[300];
 
-               sprintf(userstr, "%s <%s>", Players[scr].name, Players[scr].host);
+               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)
                        - 5*((Players[scr].flags & SCF_fairRobot) != 0)] = 0;
                mvaddstr(1, boardXPos[scr], userstr);
@@ -228,12 +233,15 @@ ExtFunc void DrawField(int scr)
                                ? "(fair robot)" : "(robot)");
                }
        } //display playername/host
+
+       ShowPause(scr);
 } //DrawScreen
 
 ExtFunc void InitFields()
-{
+{ //place fields for all players
        int scr, prevscr;
 
+       statusXPos = 2 * Players[me].boardWidth + 3;
        boardXPos[me] = 1;
        boardYPos[me] = 22;
        prevscr = me;
@@ -245,7 +253,6 @@ ExtFunc void InitFields()
                boardYPos[scr] = 22;
                prevscr = scr;
        }
-       statusXPos = 2 * Players[me].boardWidth + 3;
 } //InitScreen
 
 ExtFunc void CleanupScreen(int scr)
@@ -275,14 +282,14 @@ ExtFunc void PlotBlock1(int scr, int y, int x, BlockType type)
                addstr(type ? "[]" : "$$");
                standend();
        }
-}
+} //PlotBlock1
 
 ExtFunc void PlotBlock(int scr, int y, int x, BlockType type)
 {
        if (y >= 0 && y < Players[scr].boardVisible &&
                x >= 0 && x < Players[scr].boardWidth)
          PlotBlock1(scr, boardYPos[scr] - y, boardXPos[scr] + 2 * x, type);
-}
+} //PlotBlock
 
 ExtFunc void PlotUnderline(int scr, int x, int flag)
 {
@@ -293,34 +300,10 @@ ExtFunc void PlotUnderline(int scr, int x, int flag)
        addch(flag ? ACS_BTEE : ACS_HLINE);
        addch(flag ? ACS_BTEE : ACS_HLINE);
   }
-}
-
-ExtFunc void ShowDisplayInfo(void)
-{
-  move(statusYPos - 9, statusXPos);
-  printw("Seed: %010d", Game.seed);
-  //   move(statusYPos - 8, statusXPos);
-  //   printw("Speed: %dms ", speed / 1000);
-  if (robotEnable) {
-       move(statusYPos - 6, statusXPos);
-       if (fairRobot)
-         addstr("Controlled by a fair robot");
-       else
-         addstr("Controlled by a robot");
-       //              clrtoeol();
-  }
-  if (Players[1].flags & SCF_usingRobot) {
-       move(statusYPos - 5, statusXPos);
-       if (Players[1].flags & SCF_fairRobot)
-         addstr("The opponent is a fair robot");
-       else
-         addstr("The opponent is a robot");
-       //              clrtoeol();
-  }
-}
+} //PlotUnderline
 
 ExtFunc void ShowScore(int scr, struct _Score score)
-{
+{ //show score stuff
        float timer;
 
        move(6, statusXPos); addstr("Next:          ");
@@ -341,21 +324,37 @@ ExtFunc void ShowScore(int scr, struct _Score score)
                else addstr("            ");
                printw("  apm:%5.1f", score.adds * 60 / timer);
        }
-}
+} //ShowScore
+
+ExtFunc void FieldMessage(int playa, char *message)
+{ //put a message over playa's field
+       if (!Players[playa].spy) return;
+       if (message) {
+               char s[MAX_BOARD_WIDTH+1];
+               memset(s, ' ', MAX_BOARD_WIDTH);
+               memcpy(&s[Players[playa].boardWidth - strlen(message) / 2],
+                       message, strlen(message));
+               s[Players[playa].boardWidth * 2] = 0;
+               if (Game.standout) standout();
+               mvprintw(boardYPos[playa] - Players[playa].boardVisible / 2,
+                       boardXPos[playa], "%s", s);
+               standend();
+       } //display
+       else {
+               int x, y;
+               y = Players[playa].boardVisible / 2;
+               for (x = 0; x <= Players[playa].boardWidth; x++)
+                       PlotBlock(playa, y, x, GetBlock(playa, y, x));
+       } //restore field
+} //FieldMessage
+
+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);
+} //ShowPause
 
-ExtFunc void ShowPause(int pausedByMe, int pausedByThem)
-{
-       move(statusYPos - 3, statusXPos);
-       if (pausedByThem)
-               addstr("Game paused by opponent");
-       else
-               addstr("                       ");
-       move(statusYPos - 2, statusXPos);
-       if (pausedByMe)
-               addstr("Game paused by you");
-       else
-               addstr("                  ");
-}
 
 ExtFunc void Message(char *s)
 {
@@ -369,28 +368,28 @@ ExtFunc void Message(char *s)
 //     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);
 //     refresh();
-}
+} //ShowTime
 
 ExtFunc void ScheduleFullRedraw(void)
 {
        touchwin(stdscr);
-}
+} //ScheduleFullRedraw
 
 static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event)
-{
+{ //read keypresses
        if (MyRead(gen->fd, &event->u.key, 1))
                return E_key;
        else
                return E_none;
-}
+} //KeyGenFunc
 
 /*
  * vi: ts=4 ai
diff --git a/game.c b/game.c
index 87208fbf3ee10f2863f5afecbfdd0e36d0950f4f..07dda94705c8d92f3489cd8ed4c4c6de96126257 100644 (file)
--- a/game.c
+++ b/game.c
@@ -31,10 +31,9 @@ static struct option options[] = {
        { "ascii",              2, 0, 'a' },
        { "connect",    1, 0, 'c' },
        { "port",               1, 0, 'p' },
-       { "speed",              1, 0, 'i' },
        { "level",              1, 0, 'l' },
+       { "team",               1, 0, 't' },
        { "spy",                1, 0,  1  },
-       { "seed",               1, 0, 's' },
        { "robot",              1, 0, 'r' },
        { "fair-robot", 0, 0, 'F' },
        { "dropmode",   2, 0, 'd' },
@@ -49,16 +48,19 @@ static struct option options[] = {
 };
 
 enum { KT_left, KT_right, KT_rotright, KT_rotleft, KT_drop, KT_down,
-               KT_toggleSpy, KT_pause, KT_faster, KT_redraw, KT_numKeys };
+               KT_faster, KT_pause, KT_redraw, KT_quit, KT_numKeys };
 
 static char *keyNames[KT_numKeys+1] = {
        "Left", "Right", "RotRight", "RotLeft", "Drop", "Down",
-       "ToggleSpy", "Pause", "Faster", "Redraw", NULL };
+       "Faster", "Pause", "Redraw", "Quit", NULL };
 
 static char *gameNames[GT_len] = { "OnePlayer", "ClassicTwo" };
 
 static char keyTable[KT_numKeys+1];
 
+static char *hostStr;
+static int paused = 0;
+
 
 ExtFunc void MapKeys(char *newKeys)
 {
@@ -121,7 +123,8 @@ ExtFunc void HandleOption(char tag, char *value)
                        hostStr = value;
                        break;
                case 'p':       //port
-                       portStr = value; break;
+                       port = atoi(value);
+                       break;
                case 'i':       //speed (of level 1)
                        Game.initspeed = atof(value) * 1e6;
                        break;
@@ -131,6 +134,9 @@ ExtFunc void HandleOption(char tag, char *value)
                        if (Players[0].score.level > 15)
                                Players[0].score.level = 15;
                        break;
+               case 't':       //team
+                       Players[0].team = atoi(value);
+                       break;
                case 1:         //spy
                        {
                                int i;
@@ -138,9 +144,6 @@ ExtFunc void HandleOption(char tag, char *value)
                                Players[i / 10].spy = i % 10;
                        }
                        break;
-               case 's':       //seed
-                       Game.seed = atoi(value);
-                       break;
                case 'r':       //robot
                        robotEnable = 1;
                        Players[0].flags |= SCF_usingRobot;
@@ -234,16 +237,27 @@ ExtFunc int StartNewPiece(int scr, Shape *shape)
        return 1;
 }
 
+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;
+} //checkPaused
+
 ExtFunc void OneGame(int scr)
 {
        MyEvent event;
        int linesCleared, changed = 0;
        int spied = 0, dropMode = 0;
-       int oldPaused = 0, paused = 0, pausedByMe = 0, pausedByThem = 0;
+       int oldPaused = 0;
        long pauseTimeLeft;
        int pieceCount = 0;
        int key;
        char *p, *cmd;
+       int playercount;
        int linevalues[4] = { 40, 100, 400, 1200 }; //= 50*lines! - 10*(lines==1)
        int i;
 
@@ -254,18 +268,17 @@ ExtFunc void OneGame(int scr)
                Game.speed = SPEEDMINIMUM;
        ResetBaseTime();
        InitFields();
-       for (i = 1; i <= totalPlayers + 1; i++)
+       for (i = 1; i <= totalPlayers; i++)
                if (Players[i].spy) DrawField(i);
-       if (totalPlayers > 0) {
+       if (totalPlayers > 1) {
                spied = 1;
        }
-       ShowDisplayInfo();
        SetITimer(Game.speed, Game.speed);
        if (robotEnable) {
                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 + 1; i++) {
+               for (i = 1; i <= totalPlayers; i++) {
                        RobotCmd(0, "BoardSize %d %d %d\n",
                                i, Players[i].boardVisible, Players[i].boardWidth);
                        RobotCmd(0, "Opponent %d %s %s\n",
@@ -280,34 +293,51 @@ ExtFunc void OneGame(int scr)
                RobotTimeStamp();
        }
        Players[scr].nextShape = ChooseOption(stdOptions);
-       while (StartNewPiece(scr, ChooseOption(stdOptions))) {
-               ShowScore(scr, Players[scr].score);
-               if (robotEnable && !fairRobot)
-                       RobotCmd(1, "NewPiece %d\n", ++pieceCount);
-               if (spied) {
-                       short shapeNum;
-                       netint2 data[1];
-
-                       shapeNum = ShapeToNetNum(Players[scr].curShape);
-                       data[0] = hton2(shapeNum);
-                       SendPacket(scr, NP_newPiece, sizeof(data), data);
+       while (1) {
+               if (Players[scr].alive) {
+                       if (!StartNewPiece(scr, ChooseOption(stdOptions))) {
+                                       netint4 data[4];
+                               Players[scr].alive = 0;
+                               FieldMessage(scr, "G A M E  O V E R");
+                               changed = 1;
+                               if (game == GT_classicTwo)
+                                       SendPacket(scr, NP_argghhh,
+                                               sizeof(Players[0].alive), &Players[scr].alive);
+                       } //die
+                       else {
+                               ShowScore(scr, Players[scr].score);
+                               if (robotEnable && !fairRobot)
+                                       RobotCmd(1, "NewPiece %d\n", ++pieceCount);
+                               if (spied) {
+                                       short shapeNum;
+                                       netint2 data[1];
+       
+                                       shapeNum = ShapeToNetNum(Players[scr].curShape);
+                                       data[0] = hton2(shapeNum);
+                                       SendPacket(scr, NP_newPiece, sizeof(data), data);
+                               } //send new piece
+                       }
                }
                for (;;) {
-                       changed = RefreshBoard(scr) || changed;
-                       for (i = 1; i <= totalPlayers+1; i++) if (Players[i].spy && i != me)
-                               changed = RefreshBoard(i) || changed;
+                       for (i = 1; i <= totalPlayers; i++) if (Players[i].spy)
+                               changed |= RefreshBoard(i);
                        if (changed) {
                                if (!paused) ShowTime();
                                refresh();
                                changed = 0;
                        }
+                       playercount = 0;
+                       for (i = 1; i <= totalPlayers; i++)
+                               if (Players[i].alive) playercount++;
+                       if (playercount < game + 1) goto gameOver;
                        CheckNetConn();
                        switch (WaitMyEvent(&event, EM_any)) {
                                case E_alarm:
-                                       if (!MovePiece(scr, -1, 0))
-                                               goto nextPiece;
-                                       else if (spied)
-                                               SendPacket(scr, NP_down, 0, NULL);
+                                       if (Players[scr].alive)
+                                               if (!MovePiece(scr, -1, 0))
+                                                       goto nextPiece;
+                                               else if (spied)
+                                                       SendPacket(scr, NP_down, 0, NULL);
                                        break;
                                case E_key:
                                        p = strchr(keyTable, tolower(event.u.key));
@@ -317,12 +347,11 @@ ExtFunc void OneGame(int scr)
                                                                (int)(unsigned char)event.u.key,
                                                                p ? keyNames[key] : "?");
                                                break;
-                                       }
-                                       if (!p)
-                                               break;
+                                       } //let robot handle keypress
+                                       if (!p) break;
                                keyEvent:
-                                       if (paused && (key != KT_pause) && (key != KT_redraw))
-                                               break;
+                                       if (!Players[scr].alive && key != KT_quit) break;
+                                       if (paused && key < KT_pause) break;
                                        switch(key) {
                                                case KT_left:
                                                        if (MovePiece(scr, 0, -1) && spied)
@@ -357,18 +386,12 @@ ExtFunc void OneGame(int scr)
                                                        dropMode = Players[scr].dropmode;
                                                        break;
                                                case KT_pause:
-                                                       pausedByMe = !pausedByMe;
-                                                       if (game == GT_classicTwo) {
-                                                               netint2 data[1];
-
-                                                               data[0] = hton2(pausedByMe);
-                                                               SendPacket(scr, NP_pause, sizeof(data), data);
-                                                       }
-                                                       paused = pausedByMe || pausedByThem;
-                                                       if (robotEnable)
-                                                               RobotCmd(1, "Pause %d %d\n", pausedByMe,
-                                                                       pausedByThem);
-                                                       ShowPause(pausedByMe, pausedByThem);
+                                                       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;
                                                        break;
                                                case KT_faster:
@@ -386,7 +409,11 @@ ExtFunc void OneGame(int scr)
 //                                                     if (paused)
 //                                                             RefreshScreen();
                                                        break;
-                                       }
+                                               case KT_quit:
+                                                       FieldMessage(me, "G A M E  O V E R");
+                                                       refresh();
+                                                       goto gameOver;
+                                       } //E_key
                                        if (dropMode && DropPiece(scr) > 0) {
                                                SetITimer(Game.speed, Game.speed);
                                                if (spied)
@@ -412,7 +439,7 @@ ExtFunc void OneGame(int scr)
                                                changed = 1;
                                        }
                                        break;
-                               }
+                               } //E_robot
                                case E_net:
                                        switch(event.u.net.type) {
                                                case NP_giveJunk:
@@ -420,6 +447,7 @@ ExtFunc void OneGame(int scr)
                                                        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);
@@ -428,7 +456,7 @@ ExtFunc void OneGame(int scr)
                                                                SendPacket(scr, NP_insertJunk, sizeof(data), data);
 //                                                     Message("Opponent added %d lines");
                                                        break;
-                                               }
+                                               } //receive junklines
                                                case NP_newPiece:
                                                {
                                                        short shapeNum;
@@ -439,7 +467,7 @@ ExtFunc void OneGame(int scr)
                                                        shapeNum = ntoh2(data[0]);
                                                        StartNewPiece(event.u.net.uid, NetNumToShape(shapeNum));
                                                        break;
-                                               }
+                                               } //new piece
                                                case NP_down:
                                                        MovePiece(event.u.net.uid, -1, 0);
                                                        break;
@@ -468,31 +496,35 @@ ExtFunc void OneGame(int scr)
                                                        memcpy(data, event.u.net.data, sizeof(data));
                                                        InsertJunk(event.u.net.uid, ntoh2(data[0]), ntoh2(data[1]));
                                                        break;
-                                               }
+                                               } //player added junklines
                                                case NP_pause:
                                                {
-                                                       netint2 data[1];
-
-                                                       memcpy(data, event.u.net.data, sizeof(data));
-                                                       pausedByThem = ntoh2(data[0]);
-                                                       paused = pausedByMe || pausedByThem;
-                                                       if (robotEnable)
-                                                               RobotCmd(1, "Pause %d %d\n", pausedByMe,
-                                                                       pausedByThem);
-                                                       ShowPause(pausedByMe, pausedByThem);
+                                                       Players[event.u.net.uid].flags ^= SCF_paused;
+                                                       checkPaused();
+                                                       if (robotEnable) RobotCmd(1, "Pause %d\n", paused);
+                                                       ShowPause(event.u.net.uid);
+                                                       changed = 1;
+                                                       break;
+                                               } //(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");
                                                        changed = 1;
                                                        break;
-                                               }
+                                               } //G/O
                                                default:
                                                        break;
-                                       }
+                                       } //E_net
                                        break;
                                case E_lostRobot:
                                case E_lostConn:
                                        goto gameOver;
                                default:
                                        break;
-                       }
+                       } //handle event
                        if (paused != oldPaused) {
                                if (paused) {
                                        PauseTime();
@@ -503,8 +535,8 @@ ExtFunc void OneGame(int scr)
                                        ResumeTime();
                                }
                                oldPaused = paused;
-                       }
-               }
+                       } //(un)pause
+               } //game loop
        nextPiece:
                dropMode = 0;
                FreezePiece(scr);
@@ -533,7 +565,7 @@ ExtFunc void OneGame(int scr)
                        data[0] = hton2(junkLines);
                        SendPacket(scr, NP_giveJunk, sizeof(data), data);
                }
-       }
+       } //new piece loop
 gameOver:
        SetITimer(0, 0);
 }
@@ -542,6 +574,7 @@ ExtFunc int main(int argc, char **argv)
 {
        char ch;
 
+       port = DEFAULT_PORT;
        Game.standout = Game.color = 1;
        Game.initspeed = DEFAULT_INTERVAL;
        MapKeys(DEFAULT_KEYS);
@@ -560,7 +593,7 @@ ExtFunc int main(int argc, char **argv)
                Players[0].boardHeight = MAX_BOARD_HEIGHT;
                Players[0].boardVisible = 20;
                Players[0].spy = 1;
-               strcpy(Players[0].host, "localhost");
+               Players[0].alive = 1;
        }
 
 //     if (getopt(argc, argv, "f:") == 'f')
@@ -568,7 +601,7 @@ ExtFunc int main(int argc, char **argv)
 //     else
        ReadConf(CONFIG_FILE);
        while ((ch = getopt_long(argc, argv,
-                       "hHRs:r:Fk:c:odDSCap:i:l:", options, NULL)) != -1)
+                       "hHRr:Fk:c:odDSCap:i:l:t:", options, NULL)) != -1)
                HandleOption(ch, optarg);
        if (optind < argc) {
                Usage();
@@ -582,13 +615,15 @@ ExtFunc int main(int argc, char **argv)
        InitScreens();
        if (initConn) {
                game = GT_classicTwo;
-               InitiateConnection(hostStr, portStr);
+               Players[0].flags |= SCF_paused;
+               paused = SCF_paused;
+               InitiateConnection(hostStr, port);
                HandShake();
                OneGame(me);
        } //client
        else {
                game = GT_onePlayer;
-               totalPlayers = 0;
+               totalPlayers = 1;
                me = 1;
                memcpy(&Players[me], &Players[0], sizeof(Player));
                OneGame(me);
diff --git a/inet.c b/inet.c
index 85b1b70a1fc384f6911e306cd7cc6ce6d3e504e5..b21b1374437b668bcbf4251401f3809676ea37b1 100644 (file)
--- a/inet.c
+++ b/inet.c
@@ -37,30 +37,13 @@ ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
 EventGenRec netGen[MAX_SCREENS] = {
        { NULL, 0, FT_read, -1, NetGenFunc, EM_net, 0, "\0", 0, HEADER_SIZE3 } };
 
-//static char netBuf[64];
-//static int netBufSize, netBufGoal = HEADER_SIZE3;
 
-ExtFunc void make_netGen(void)
-{
-       int i;
-
-       for (i = 1; i <= MAX_SCREENS; i++)
-               memcpy(netGen+i, &netGen[0], sizeof(EventGenRec));
-} //Make_netGen
-
-
-ExtFunc int InitiateConnection(char *hostStr, char *portStr)
+ExtFunc int InitiateConnection(char *hostStr, short port)
 { //connect to host
        struct sockaddr_in addr;
        struct hostent *host;
-       short port;
 
-//     make_netGen();
        AtExit(CloseNet);
-       if (portStr)
-               port = atoi(portStr);   /* XXX Error checking */
-       else
-               port = DEFAULT_PORT;
        host = gethostbyname(hostStr);
        if (!host)
                die("gethostbyname");
@@ -80,7 +63,7 @@ ExtFunc int InitiateConnection(char *hostStr, char *portStr)
                goto again;
        }
        AddEventGen(&netGen[0]);
-       totalPlayers = 0;
+       totalPlayers = 1;
        return 0;
 } //InitiateConnection
 
@@ -111,7 +94,8 @@ ExtFunc void HandShake(void)
                        }
                        case NP_gamedata:
                        {
-                               fprintf(stderr, ": %d\n", event.type);
+                               memcpy(&Game, event.u.net.data, event.u.net.size);
+                               SRandom(Game.seed);
                                break;
                        }
                        case NP_newPlayer:
index b04e04036b2d04274fe18871b4d2c97d6e72ea7a..30ce772a3262e6e0a2d5e12bd507a6172b31dbeb 100644 (file)
--- a/netris.h
+++ b/netris.h
 #include <stdio.h>
 #include <signal.h>
 
+#define version_string         "0.5.810"
+
 #define ExtFunc                /* Marks functions that need prototypes */
 
-#ifdef NOEXT
+#ifdef NOEXT   //prevent re-declaration
 # define EXT
-# define IN(a) a
 #else
 # define EXT extern
-# define IN(a)
 #endif
 
-/*#ifndef NULL
-  # define NULL ((void *)0)
-  #endif*/
-
 #ifdef HAS_SIGPROCMASK
 typedef sigset_t MySigSet;
 #else
@@ -71,13 +67,13 @@ typedef long netint4;
 
 #define CONFIG_FILE "netris.conf"
 
-//#define DEFAULT_KEYS "hlkj mspf^l"
-//#define DEFAULT_KEYS "4685 2spf^l"
-#define DEFAULT_KEYS "dcaf b^sp^f^l"
+//#define DEFAULT_KEYS "hlkj mfp^lq"
+//#define DEFAULT_KEYS "4685 2fp^lq"
+#define DEFAULT_KEYS "dcaf b^fp^lq"
 
 #define MAX_BOARD_WIDTH                32
 #define MAX_BOARD_HEIGHT       64
-#define MAX_SCREENS                    5
+#define MAX_SCREENS                    9 //8 players
 
 /* Event masks */
 #define EM_alarm                       000001
@@ -100,7 +96,7 @@ typedef enum _MyEventType {
 typedef enum _NetPacketType {
        NP_endConn, NP_byeBye,
        NP_error, NP_hello, NP_gamedata, NP_newPlayer, NP_goAhead,
-       NP_pause, NP_giveJunk, NP_newPiece, NP_down, NP_left, NP_right,
+       NP_pause, NP_argghhh, NP_giveJunk, NP_newPiece, NP_down, NP_left, NP_right,
        NP_rotright, NP_rotleft, NP_drop, NP_clear, NP_insertJunk
 } NetPacketType;
 
@@ -137,7 +133,7 @@ typedef struct _EventGenRec {
        char buf[512];
        int bufSize, bufGoal;
 } EventGenRec;
-extern EventGenRec netGen[MAX_SCREENS];
+EXT EventGenRec netGen[MAX_SCREENS];
 
 MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
 
@@ -160,13 +156,15 @@ typedef int (*ShapeDrawFunc)(int scr, int y, int x,
 /* NP_startConn flags */
 #define SCF_usingRobot         000001
 #define SCF_fairRobot          000002
-#define SCF_setSeed                    000004
+#define SCF_paused                     000004
 
 EXT int totalPlayers;
 
 typedef struct _Player {
+       int alive;
        char name[16];
        int flags;
+       int team;
        int dropmode;
        int boardHeight, boardWidth, boardVisible;
        int curX, curY;
@@ -176,8 +174,8 @@ typedef struct _Player {
                long score;
                int drops, lines, adds;
        } score;
-       char host[256];
-       int spy;
+       char host[256]; //last-1
+       int spy;                //last
 } Player;
 EXT Player Players[MAX_SCREENS];
 EXT short me;
@@ -187,8 +185,9 @@ EXT short me;
 #define SPEEDMINIMUM           40000
 
 typedef struct __Game {
-       long seed;
-       long initspeed, speed;
+       long seed;              //1st
+       int initspeed;  //2nd
+       int speed;
        int standout, color, ascii;
 } _Game;
 EXT _Game Game;
@@ -197,13 +196,12 @@ EXT GameType game;
 EXT int robotEnable, robotVersion, fairRobot;
 EXT int protocolVersion;
 
-EXT int initConn, waitConn;
-EXT char *hostStr, *portStr;
+EXT int initConn;
+EXT short port;
 
 EXT char scratch[1024];
 
 extern ShapeOption stdOptions[];
-extern char *version_string;
 
 #include "proto.h"
 
index 7e0aca1eb91de6d4df5d8b30e79093d4d19a28e0..9297b13a96374dbfe4c44f70a4db165cdd490d65 100644 (file)
--- a/server.c
+++ b/server.c
 #include <setjmp.h>
 
 #define HEADER_SIZE sizeof(netint4[3])
-#define MAX_CONNECTIONS 3
-
-char *version_string = "0.5.89";
 
 static struct option options[] = {
        { "wait",               0, 0, 'w' },
        { "port",               1, 0, 'p' },
+       { "connections",1, 0, 'c' },
        { "speed",              1, 0, 'i' },
        { "seed",               1, 0, 's' },
        { "info",               0, 0, 'H' },
@@ -47,6 +45,8 @@ static struct option options[] = {
        { 0,                    0, 0,  0 }
 };
 
+static char Connections = 2;
+
 static char *gameNames[GT_len] = { "OnePlayer", "ClassicTwo" };
 
 ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
@@ -296,7 +296,7 @@ ExtFunc int WaitForConnection(short port)
                die("listen");
 
        addrLen = sizeof(addr);
-       for (i = 1; i <= MAX_CONNECTIONS; i++) {
+       for (i = 1; i <= Connections; i++) {
                if ((netGen[i].fd = accept(sockListen, (struct sockaddr *)&addr, &addrLen)) < 0)
                        die("accept");
                fprintf(stderr, "Connection: %s\n", inet_ntoa(addr.sin_addr));
@@ -344,38 +344,33 @@ ExtFunc int WaitForConnection(short port)
        return 0;
 } //WaitForConnection
 
-ExtFunc int StartServer(char *portStr)
+ExtFunc int StartServer(void)
 {
        MyEvent event;
-       char serverdata[255];
        int playercount;
+       int playersReady = 0;
        int i;
 
        {
-               short port;
-
-               if (portStr)
-                       port = atoi(portStr);   /* XXX Error checking */
-               else
-                       port = DEFAULT_PORT;
-               WaitForConnection(port);
-       }
-
-       playercount = MAX_CONNECTIONS;
-
-       for (i = 1; i <= playercount; i++) {
-               sprintf(serverdata, "Netris server %s", version_string);
-               SendPacketTo(i, i, NP_hello, strlen(serverdata)+1, serverdata);
+               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);
+               }
        }
 
-       while(1) {
+       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 :(
-                                       //tell the others! :)
+                                       Players[event.u.net.sender].alive = 0;
+                                       for (i = 1; i <= totalPlayers; i++)
+                                               SendPacketTo(i, event.u.net.sender,
+                                                       NP_argghhh, sizeof(Players[0].alive),
+                                                       &Players[event.u.net.sender].alive);
                                        break;
                                } //NP_endConn
                                case NP_hello:
@@ -384,19 +379,22 @@ ExtFunc int StartServer(char *portStr)
                                { //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 (--playercount == 0) {
-                                               fprintf(stderr, "Starting game\n");
+                                       if (++playersReady >= totalPlayers) {
+                                               fprintf(stderr, "Starting game (%010d)\n", Game.seed);
                                                for (i = 1; i <= totalPlayers; i++)
                                                        SendPacketTo(i, 0, NP_goAhead, 0, NULL);
-                                               playercount++;
                                        } //give go ahead
                                        break;
                                } //NP_playerdata
@@ -405,13 +403,18 @@ ExtFunc int StartServer(char *portStr)
        //                              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;
                                }
-                       } //E_net
-               }
-       } //loop
+                       }
+               } //E_net
+               playercount = 0;
+               for (i = 1; i <= totalPlayers; i++)
+                       if (netGen[i].fd >= 0) playercount++;
+       } while (playercount > 1);
 } //StartServer
 
 
@@ -478,13 +481,16 @@ ExtFunc void HandleOption(char tag, char *value)
 {
        switch (tag) {
                case 'p':       //port
-                       portStr = value; break;
+                       port = atoi(value);
+                       break;
+               case 'c':       //connections
+                       Connections = atoi(value);
+                       break;
                case 'i':       //speed (of level 1)
                        Game.initspeed = atof(value) * 1e6;
                        break;
                case 's':       //seed
                        Game.seed = atoi(value);
-                       Players[0].flags |= SCF_setSeed;
                        break;
                case 'H':       //info
                        DistInfo(); exit(0);
@@ -540,15 +546,16 @@ ExtFunc int main(int argc, char **argv)
 
        if (sigsetjmp(close_env, 1)) exit(0);
        signal(SIGINT, CatchInt);
-       Game.standout = Game.color = 1;
+       port = DEFAULT_PORT;
        Game.initspeed = DEFAULT_INTERVAL;
+       Game.seed = time(0);
 
 //     if (getopt(argc, argv, "f:") == 'f')
 //             ReadConf(optarg);
 //     else
        ReadConf(CONFIG_FILE);
        while ((ch = getopt_long(argc, argv,
-                       "hHp:i:s:", options, NULL)) != -1)
+                       "hHp:i:s:c:", options, NULL)) != -1)
                HandleOption(ch, optarg);
        if (optind < argc) {
                Usage();
@@ -557,7 +564,8 @@ ExtFunc int main(int argc, char **argv)
 //     WriteConf();
 
        Header();
-       StartServer(portStr);
+       WaitForConnection(port);
+       StartServer();
        return 0;
 }
 
diff --git a/util.c b/util.c
index f93b8c857881b39b15b206c11fda7391cf12b1c2..b32592fe0da16e75c400584077619ec8ef622f28 100644 (file)
--- a/util.c
+++ b/util.c
@@ -79,7 +79,6 @@ ExtFunc void Usage(void)
          "  -c, --connect <host>\tInitiate connection\n"
          "  -p, --port <port>\tSet port number (default is %d)\n"
          "\n"
-         "  -s, --seed <seed>\tStart with given random seed\n"
          "  -i, --speed <sec>\tSet the initial step-down interval, in seconds\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"
@@ -139,10 +138,7 @@ ExtFunc void Rules(void)
 
 ExtFunc void InitUtil(void)
 {
-       if (Game.seed)
-               SRandom(Game.seed);
-       else
-               SRandom(time(0));
+       SRandom(time(0));
        if (sigsetjmp(close_env, 1)) exit(0);
        signal(SIGINT, CatchInt);
        ResetBaseTime();
@@ -159,7 +155,7 @@ ExtFunc void SRandom(int seed)
 } //SRandom
 
 ExtFunc int Random(int min, int max1)
-{
+{ //return a random value
        myRandSeed = (myRandSeed * 31751 + 15437) % 32767;
        return myRandSeed % (max1 - min) + min;
 } //Random