Author: Tomas Berndtsson vim:ft=diff: Description: Add multi game support with scoring Index: b/curses.c =================================================================== --- a/curses.c +++ b/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: b/netris.h =================================================================== --- a/netris.h +++ b/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: b/util.c =================================================================== --- a/util.c +++ b/util.c @@ -74,7 +74,7 @@ ExtFunc void Usage(void) " -p Set port number (default is %d)\n" " -k 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 Set the step-down interval, in seconds\n" " -r Execute (a command) as a robot controlling\n" Index: b/game.c =================================================================== --- a/game.c +++ b/game.c @@ -28,11 +28,11 @@ #include 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: b/board.c =================================================================== --- a/board.c +++ b/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;