From 21add7c13bc1df386e45aad2939ee5ff2a152c2b Mon Sep 17 00:00:00 2001 From: Mischa POSLAWSKY Date: Sun, 11 Aug 2002 00:01:00 +0200 Subject: [PATCH] unofficial version 0.7: multiplayer improvements - common seed - teams - related ui updates --- CHANGES | 45 +++++++++++--- Configure | 9 +-- FAQ | 2 +- curses.c | 125 +++++++++++++++++++------------------- game.c | 179 ++++++++++++++++++++++++++++++++---------------------- inet.c | 24 ++------ netris.h | 40 ++++++------ server.c | 74 ++++++++++++---------- util.c | 8 +-- 9 files changed, 273 insertions(+), 233 deletions(-) diff --git a/CHANGES b/CHANGES index 0aa3d64..ff4175c 100644 --- 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 ------- @@ -61,31 +70,47 @@ * 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? ------------------------------------------------------------------------------ diff --git a/Configure b/Configure index 97479db..a17707e 100755 --- 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 4148983..3a7f294 100644 --- 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. diff --git a/curses.c b/curses.c index 4f8ddbd..f28a6a3 100644 --- a/curses.c +++ b/curses.c @@ -31,12 +31,10 @@ #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 87208fb..07dda94 100644 --- 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 85b1b70..b21b137 100644 --- 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: diff --git a/netris.h b/netris.h index b04e040..30ce772 100644 --- a/netris.h +++ b/netris.h @@ -28,20 +28,16 @@ #include #include +#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" diff --git a/server.c b/server.c index 7e0aca1..9297b13 100644 --- a/server.c +++ b/server.c @@ -33,13 +33,11 @@ #include #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 f93b8c8..b32592f 100644 --- a/util.c +++ b/util.c @@ -79,7 +79,6 @@ ExtFunc void Usage(void) " -c, --connect \tInitiate connection\n" " -p, --port \tSet port number (default is %d)\n" "\n" - " -s, --seed \tStart with given random seed\n" " -i, --speed \tSet the initial step-down interval, in seconds\n" " -l, --level \tBegin at a higher level (can be used as handicap)\n" " -k, --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 -- 2.30.0