Author: Tomas Berndtsson <tomas@nocrew.org>	vim:ft=diff:
Description: Add multi game support with scoring

Index: netris-0.52/curses.c
===================================================================
--- netris-0.52.orig/curses.c
+++ netris-0.52/curses.c
@@ -201,6 +201,8 @@ ExtFunc void InitScreen(int scr)
 	for (y = boardVisible[scr] - 1; y >= 0; --y) {
 		move(boardYPos[scr] - y, boardXPos[scr] - 1);
 		addch('|');
+		for (x = boardWidth[scr] - 1; x >= 0; --x)
+			addstr("  ");
 		move(boardYPos[scr] - y, boardXPos[scr] + 2 * boardWidth[scr]);
 		addch('|');
 	}
@@ -256,6 +258,23 @@ ExtFunc void PlotUnderline(int scr, int
 
 ExtFunc void ShowDisplayInfo(void)
 {
+	move(statusYPos - 3, statusXPos);
+	printw("Won:  %3d", won);
+	move(statusYPos - 2, statusXPos);
+	printw("Lost: %3d", lost);
+
+	move(statusYPos - 1, statusXPos);
+	switch(gameState) {
+	case STATE_WAIT_CONNECTION:
+		addstr("Waiting for opponent...      ");
+		break;
+	case STATE_WAIT_KEYPRESS:
+		addstr("Press the key for a new game.");
+		break;
+	default:
+		addstr("                             ");
+	}
+
 	move(statusYPos - 9, statusXPos);
 	printw("Seed: %d", initSeed);
 	clrtoeol();
Index: netris-0.52/netris.h
===================================================================
--- netris-0.52.orig/netris.h
+++ netris-0.52/netris.h
@@ -65,7 +65,7 @@ typedef long netint4;
 
 #define DEFAULT_PORT 9284	/* Very arbitrary */
 
-#define DEFAULT_KEYS "jkl mspf^l"
+#define DEFAULT_KEYS "jkl mspf^ln"
 
 /* Protocol versions */
 #define MAJOR_VERSION		1	
@@ -152,6 +152,13 @@ typedef struct _ShapeOption {
 typedef int (*ShapeDrawFunc)(int scr, int y, int x,
 					BlockType type, void *data);
 
+enum States {
+	STATE_STARTING,
+	STATE_PLAYING,
+	STATE_WAIT_CONNECTION,
+	STATE_WAIT_KEYPRESS
+};
+
 EXT GameType game;
 EXT int boardHeight[MAX_SCREENS];
 EXT int boardVisible[MAX_SCREENS], boardWidth[MAX_SCREENS];
@@ -167,6 +174,9 @@ EXT long stepDownInterval, speed;
 
 EXT int myFlags, opponentFlags;
 
+EXT int won, lost;
+EXT enum States gameState;
+
 EXT char scratch[1024];
 
 extern ShapeOption stdOptions[];
Index: netris-0.52/util.c
===================================================================
--- netris-0.52.orig/util.c
+++ netris-0.52/util.c
@@ -35,7 +35,7 @@ static EventGenRec alarmGen =
 		{ &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm };
 static EventGenRec *nextGen = &alarmGen;
 
-static myRandSeed = 1;
+static int myRandSeed = 1;
 
 static struct timeval baseTimeval;
 
@@ -74,7 +74,7 @@ ExtFunc void Usage(void)
 	  "  -p <port>	Set port number (default is %d)\n"
 	  "  -k <keys>	Remap keys.  The argument is a prefix of the string\n"
 	  "		  containing the keys in order: left, rotate, right, drop,\n"
-	  "		  down-faster, toggle-spying, pause, faster, redraw.\n"
+	  "		  down-faster, toggle-spying, pause, faster, redraw, new.\n"
 	  "		  \"^\" prefixes controls.  (default is \"%s\")\n"
 	  "  -i <sec>	Set the step-down interval, in seconds\n"
 	  "  -r <robot>	Execute <robot> (a command) as a robot controlling\n"
Index: netris-0.52/game.c
===================================================================
--- netris-0.52.orig/game.c
+++ netris-0.52/game.c
@@ -28,11 +28,11 @@
 #include <netinet/in.h>
 
 enum { KT_left, KT_rotate, KT_right, KT_drop, KT_down,
-	KT_toggleSpy, KT_pause, KT_faster, KT_redraw, KT_numKeys };
+	KT_toggleSpy, KT_pause, KT_faster, KT_redraw, KT_new, KT_numKeys };
 
 static char *keyNames[KT_numKeys+1] = {
 	"Left", "Rotate", "Right", "Drop", "Down", "ToggleSpy", "Pause",
-	"Faster", "Redraw", NULL };
+	"Faster", "Redraw", "New", NULL };
 
 static char *gameNames[GT_len] = { "OnePlayer", "ClassicTwo" };
 
@@ -40,6 +40,10 @@ static char keyTable[KT_numKeys+1];
 static int dropModeEnable = 0;
 static char *robotProg;
 
+static int wonLast = 0;
+int lost = 0, won = 0;
+enum States gameState = STATE_STARTING;
+
 ExtFunc void MapKeys(char *newKeys)
 {
 	int i, k, ch;
@@ -323,6 +327,7 @@ ExtFunc void OneGame(int scr, int scr2)
 					break;
 				case E_lostRobot:
 				case E_lostConn:
+					wonLast = 1;
 					goto gameOver;
 				default:
 					break;
@@ -350,14 +355,17 @@ ExtFunc void OneGame(int scr, int scr2)
 			SendPacket(NP_giveJunk, sizeof(data), data);
 		}
 	}
+	wonLast = 0;
+
 gameOver:
 	SetITimer(0, 0);
 }
 
 ExtFunc int main(int argc, char **argv)
 {
-	int initConn = 0, waitConn = 0, ch;
+	int initConn = 0, waitConn = 0, ch, done = 0;
 	char *hostStr = NULL, *portStr = NULL;
+	MyEvent event;
 
 	standoutEnable = colorEnable = 1;
 	stepDownInterval = DEFAULT_INTERVAL;
@@ -422,112 +430,139 @@ ExtFunc int main(int argc, char **argv)
 	if (fairRobot && !robotEnable)
 		fatal("You can't use the -F option without the -r option");
 	InitUtil();
-	if (robotEnable)
-		InitRobot(robotProg);
-	InitNet();
 	InitScreens();
-	if (initConn || waitConn) {
-		MyEvent event;
-
-		game = GT_classicTwo;
-		if (initConn)
-			InitiateConnection(hostStr, portStr);
-		else if (waitConn)
-			WaitForConnection(portStr);
-		{
-			netint4 data[2];
-			int major;
-
-			data[0] = hton4(MAJOR_VERSION);
-			data[1] = hton4(PROTOCOL_VERSION);
-			SendPacket(NP_version, sizeof(data), data);
-			if (WaitMyEvent(&event, EM_net) != E_net)
-				fatal("Network negotiation failed");
-			memcpy(data, event.u.net.data, sizeof(data));
-			major = ntoh4(data[0]);
-			protocolVersion = ntoh4(data[1]);
-			if (event.u.net.type != NP_version || major < MAJOR_VERSION)
-				fatal("Your opponent is using an old, incompatible version\n"
-					"of Netris.  They should get the latest version.");
-			if (major > MAJOR_VERSION)
-				fatal("Your opponent is using an newer, incompatible version\n"
-					"of Netris.  Get the latest version.");
-			if (protocolVersion > PROTOCOL_VERSION)
-				protocolVersion = PROTOCOL_VERSION;
-		}
-		if (protocolVersion < 3 && stepDownInterval != DEFAULT_INTERVAL)
-			fatal("Your opponent's version of Netris predates the -i option.\n"
-					"For fairness, you shouldn't use the -i option either.");
-		{
-			netint4 data[3];
-			int len;
-			int seed;
+	while(!done) {
+		if (robotEnable)
+			InitRobot(robotProg);
+		InitNet();
+		if (!initSeed)
+			SRandom(time(0));
+		if (initConn || waitConn) {
+			game = GT_classicTwo;
+			if(gameState != STATE_STARTING) {
+				gameState = STATE_WAIT_CONNECTION;
+				ShowDisplayInfo();
+				RefreshScreen();
+			}
+			if (initConn)
+				InitiateConnection(hostStr, portStr);
+			else if (waitConn)
+				WaitForConnection(portStr);
+			gameState = STATE_PLAYING;
+			ShowDisplayInfo();
+			RefreshScreen();
+			{
+				netint4 data[2];
+				int major;
+
+				data[0] = hton4(MAJOR_VERSION);
+				data[1] = hton4(PROTOCOL_VERSION);
+				SendPacket(NP_version, sizeof(data), data);
+				if (WaitMyEvent(&event, EM_net) != E_net)
+					fatal("Network negotiation failed");
+				memcpy(data, event.u.net.data, sizeof(data));
+				major = ntoh4(data[0]);
+				protocolVersion = ntoh4(data[1]);
+				if (event.u.net.type != NP_version || major < MAJOR_VERSION)
+					fatal("Your opponent is using an old, incompatible version\n"
+					      "of Netris.  They should get the latest version.");
+				if (major > MAJOR_VERSION)
+					fatal("Your opponent is using an newer, incompatible version\n"
+					      "of Netris.  Get the latest version.");
+				if (protocolVersion > PROTOCOL_VERSION)
+					protocolVersion = PROTOCOL_VERSION;
+			}
+			if (protocolVersion < 3 && stepDownInterval != DEFAULT_INTERVAL)
+				fatal("Your opponent's version of Netris predates the -i option.\n"
+				      "For fairness, you shouldn't use the -i option either.");
+			{
+				netint4 data[3];
+				int len;
+				int seed;
 
-			if (protocolVersion >= 3)
-				len = sizeof(data);
-			else
-				len = sizeof(netint4[2]);
-			if ((myFlags & SCF_setSeed))
-				seed = initSeed;
-			else
-				seed = time(0);
-			if (waitConn)
-				SRandom(seed);
-			data[0] = hton4(myFlags);
-			data[1] = hton4(seed);
-			data[2] = hton4(stepDownInterval);
-			SendPacket(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);
-			opponentFlags = ntoh4(data[0]);
-			seed = ntoh4(data[1]);
-			if (initConn) {
-				if ((opponentFlags & SCF_setSeed) != (myFlags & SCF_setSeed))
-					fatal("If one player sets the random number seed, "
-							"both must.");
-				if ((myFlags & SCF_setSeed) && seed != initSeed)
-					fatal("Both players have set the random number seed, "
-							"and they are unequal.");
-				if (protocolVersion >= 3 && stepDownInterval != ntoh4(data[2]))
-					fatal("Your opponent is using a different step-down "
-						"interval (-i).\nYou must both use the same one.");
-				SRandom(seed);
+				if (protocolVersion >= 3)
+					len = sizeof(data);
+				else
+					len = sizeof(netint4[2]);
+				if ((myFlags & SCF_setSeed))
+					seed = initSeed;
+				else
+					seed = time(0);
+				if (waitConn)
+					SRandom(seed);
+				data[0] = hton4(myFlags);
+				data[1] = hton4(seed);
+				data[2] = hton4(stepDownInterval);
+				SendPacket(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);
+				opponentFlags = ntoh4(data[0]);
+				seed = ntoh4(data[1]);
+				if (initConn) {
+					if ((opponentFlags & SCF_setSeed) != (myFlags & SCF_setSeed))
+						fatal("If one player sets the random number seed, "
+						      "both must.");
+					if ((myFlags & SCF_setSeed) && seed != initSeed)
+						fatal("Both players have set the random number seed, "
+						      "and they are unequal.");
+					if (protocolVersion >= 3 && stepDownInterval != ntoh4(data[2]))
+						fatal("Your opponent is using a different step-down "
+						      "interval (-i).\nYou must both use the same one.");
+					SRandom(seed);
+				}
+			}
+			{
+				char *userName;
+				int len, i;
+
+				userName = getenv("LOGNAME");
+				if (!userName || !userName[0])
+					userName = getenv("USER");
+				if (!userName || !userName[0])
+					strcpy(userName, "???");
+				len = strlen(userName)+1;
+				if (len > sizeof(opponentName))
+					len = sizeof(opponentName);
+				SendPacket(NP_userName, len, userName);
+				if (WaitMyEvent(&event, EM_net) != E_net ||
+				    event.u.net.type != NP_userName)
+					fatal("Network negotiation failed");
+				strncpy(opponentName, event.u.net.data,
+					sizeof(opponentName)-1);
+				opponentName[sizeof(opponentName)-1] = 0;
+				for (i = 0; opponentName[i]; ++i)
+					if (!isprint(opponentName[i]))
+						opponentName[i] = '?';
+				for (i = 0; opponentHost[i]; ++i)
+					if (!isprint(opponentHost[i]))
+						opponentHost[i] = '?';
 			}
+			OneGame(0, 1);
 		}
-		{
-			char *userName;
-			int len, i;
-
-			userName = getenv("LOGNAME");
-			if (!userName || !userName[0])
-				userName = getenv("USER");
-			if (!userName || !userName[0])
-				strcpy(userName, "???");
-			len = strlen(userName)+1;
-			if (len > sizeof(opponentName))
-				len = sizeof(opponentName);
-			SendPacket(NP_userName, len, userName);
-			if (WaitMyEvent(&event, EM_net) != E_net ||
-					event.u.net.type != NP_userName)
-				fatal("Network negotiation failed");
-			strncpy(opponentName, event.u.net.data,
-				sizeof(opponentName)-1);
-			opponentName[sizeof(opponentName)-1] = 0;
-			for (i = 0; opponentName[i]; ++i)
-				if (!isprint(opponentName[i]))
-					opponentName[i] = '?';
-			for (i = 0; opponentHost[i]; ++i)
-				if (!isprint(opponentHost[i]))
-					opponentHost[i] = '?';
+		else {
+			game = GT_onePlayer;
+			OneGame(0, -1);
+		}
+		if (wonLast) {
+			won++;
+		} else {
+			lost++;
+			WaitMyEvent(&event, EM_net);
+		}
+		CloseNet();
+		if (robotEnable) {
+			CloseRobot();
+		} else {
+			gameState = STATE_WAIT_KEYPRESS;
+			ShowDisplayInfo();
+			RefreshScreen();
+			while(getchar() != keyTable[KT_new])
+				;
 		}
-		OneGame(0, 1);
-	}
-	else {
-		game = GT_onePlayer;
-		OneGame(0, -1);
 	}
+
 	return 0;
 }
 
Index: netris-0.52/board.c
===================================================================
--- netris-0.52.orig/board.c
+++ netris-0.52/board.c
@@ -36,6 +36,18 @@ static int oldFalling[MAX_SCREENS][MAX_B
 
 ExtFunc void InitBoard(int scr)
 {
+	int s,w,h;
+
+	for(s = 0 ; s < MAX_SCREENS ; s++)
+		for(h = 0 ; h < MAX_BOARD_HEIGHT ; h++)
+			for(w = 0 ; w < MAX_BOARD_WIDTH ; w++) {
+				board[s][h][w] = 0;
+				oldBoard[s][h][w] = 0;
+				changed[s][h] = 0;
+				falling[s][w] = 0;
+				oldFalling[s][w] = 0;
+			}
+
 	boardHeight[scr] = MAX_BOARD_HEIGHT;
 	boardVisible[scr] = 20;
 	boardWidth[scr] = 10;
