unofficial version 0.7.1: ui improvements
[netris.git] / server.c
index 9297b13a96374dbfe4c44f70a4db165cdd490d65..f67721f6eb3019366f229df40e20b4e9721b0240 100644 (file)
--- a/server.c
+++ b/server.c
 static struct option options[] = {
        { "wait",               0, 0, 'w' },
        { "port",               1, 0, 'p' },
-       { "connections",1, 0, 'c' },
+       { "min-players",1, 0, 'm' },
+       { "max-players",1, 0, 'x' },
+       { "continuous", 1, 0, 'c' },
        { "speed",              1, 0, 'i' },
        { "seed",               1, 0, 's' },
+       { "verbose",    0, 0, 'v' },
        { "info",               0, 0, 'H' },
        { "help",               0, 0, 'h' },
        { 0,                    0, 0,  0 }
 };
 
-static char Connections = 2;
+static char minplayers = 2;
+static char countPlayers = 0;
+static char verbose = 0;
+
+struct sockaddr_in addr;
 
 static char *gameNames[GT_len] = { "OnePlayer", "ClassicTwo" };
 
 ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
-
-EventGenRec netGen[MAX_SCREENS] = {
+static EventGenRec netGen[MAX_SCREENS] = {
        { NULL, 0, FT_read, -1, NetGenFunc, EM_net, 0, "\0", 0, HEADER_SIZE } };
 
 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event);
 static EventGenRec alarmGen =
-               { &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm };
+       { &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm };
+
+static MyEventType ConnGenFunc(EventGenRec *gen, MyEvent *event);
+static EventGenRec connGen =
+       { NULL, 0, FT_read, -1, ConnGenFunc, EM_connect };
+
 static EventGenRec *nextGen = &alarmGen;
 
 static sigjmp_buf close_env;
 
+
 ExtFunc volatile void die(char *msg)
 {
        perror(msg);
@@ -101,10 +113,25 @@ ExtFunc int MyWrite(int fd, void *data, int len)
        return len;
 } //MyWrite
 
+ExtFunc void SendPacketTo(short playa, short uid, NetPacketType type, int size, void *data)
+{ //send to someone
+       netint4 header[3];
+
+       if (netGen[playa].fd >= 0) {
+               header[0] = hton4(uid);
+               header[1] = hton4(type);
+               header[2] = hton4(size + HEADER_SIZE);
+               if (MyWrite(netGen[playa].fd, header, HEADER_SIZE) != HEADER_SIZE)
+                       die("write (header)");
+               if (size > 0 && data && MyWrite(netGen[playa].fd, data, size) != size)
+                       die("write");
+       }
+} //SendPacketTo
+
 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event)
 {
        return E_alarm;
-}
+} //AlarmGenFunc
 
 ExtFunc void AddEventGen(EventGenRec *gen)
 {
@@ -125,6 +152,39 @@ ExtFunc void RemoveEventGen(EventGenRec *gen)
        }
 } //RemoveEventGen
 
+ExtFunc void AtExit(void (*handler)(void))
+{ //setup something to do at exit (^C)
+#ifdef HAS_ON_EXIT
+       on_exit((void *)handler, NULL);
+#else
+       atexit(handler);
+#endif
+} //AtExit
+
+ExtFunc void SCloseNet(short playa)
+{ //kick some connection's ass!
+       MyEvent event;
+
+       if (netGen[playa].fd >= 0) {
+               SendPacketTo(playa, 0, NP_endConn, 0, NULL);
+               do{} while (WaitMyEvent(&event, EM_net) != E_lostConn);
+               close(netGen[playa].fd);
+               netGen[playa].fd = -1;
+       }
+       if (netGen[playa].next)
+               RemoveEventGen(&netGen[playa]);
+} //SCloseNet
+
+ExtFunc void CloseNets(void)
+{ //nou oogjes dicht en snaveltjes toe
+       int i;
+
+       fprintf(stderr, "- Closing connections...\n");
+       for (i = 1; i < MAX_SCREENS; i++)
+               SCloseNet(i); //bye everybuddy
+       fprintf(stderr, "* All Done\n\n");
+} //CloseNets
+
 ExtFunc MyEventType WaitMyEvent(MyEvent *event, int mask)
 { //poll
        int i, retry = 0;
@@ -178,13 +238,6 @@ ExtFunc MyEventType WaitMyEvent(MyEvent *event, int mask)
        }
 } //WaitMyEvent
 
-ExtFunc void ByeClient(int playa)
-{ //client went away
-       fprintf(stderr, "Close connection #%d\n", playa);
-       close(netGen[playa].fd);
-       netGen[playa].fd = -1;
-} //ByeClient
-
 ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
 { //receive
        int result;
@@ -194,9 +247,8 @@ ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
        result = MyRead(gen->fd, gen->buf + gen->bufSize,
                gen->bufGoal - gen->bufSize);
        if (result < 0) {
-               ByeClient(gen->player);
-               type = NP_endConn;
-               return E_net;
+               fprintf(stderr, "- Closed connection to player #%d\n", gen->player);
+               return E_lostConn;
        }
        gen->bufSize += result;
        if (gen->bufSize < gen->bufGoal)
@@ -215,206 +267,228 @@ ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
        event->u.net.type = type;
        event->u.net.size = size - HEADER_SIZE;
        event->u.net.data = gen->buf + HEADER_SIZE;
-       if (type == NP_endConn)
-               ByeClient(gen->player);
+       if (type == NP_endConn) {
+               fprintf(stderr, "- Quit player #%d\n", gen->player);
+               return E_lostConn;
+       } //client sent quit signal
        return E_net;
 } //NetGenFunc
 
-ExtFunc void SendPacketTo(short playa, short uid, NetPacketType type, int size, void *data)
-{ //send to someone
-       netint4 header[3];
-
-       if (netGen[playa].fd >= 0) {
-               header[0] = hton4(uid);
-               header[1] = hton4(type);
-               header[2] = hton4(size + HEADER_SIZE);
-               if (MyWrite(netGen[playa].fd, header, HEADER_SIZE) != HEADER_SIZE)
-                       die("write (header)");
-               if (size > 0 && data && MyWrite(netGen[playa].fd, data, size) != size)
-                       die("write");
-       }
-} //SendPacketTo
 
-
-ExtFunc void AtExit(void (*handler)(void))
-{
-#ifdef HAS_ON_EXIT
-       on_exit((void *)handler, NULL);
-#else
-       atexit(handler);
-#endif
-}
-
-ExtFunc void SCloseNet(short playa)
-{ //kick some connection's ass!
-       MyEvent event;
-
-       if (netGen[playa].fd >= 0) {
-               SendPacketTo(playa, 0, NP_endConn, 0, NULL);
-               do{} while (WaitMyEvent(&event, EM_net) != E_lostConn);
-               close(netGen[playa].fd);
-               netGen[playa].fd = -1;
-       }
-       if (netGen[playa].next)
-               RemoveEventGen(&netGen[playa]);
-} //SCloseNet
-
-ExtFunc void CloseNets(void)
-{ //nou oogjes dicht en snaveltjes toe
-       int i;
-
-       for (i = 1; i <= totalPlayers; i++)
-               SCloseNet(i);
-} //CloseNets
-
-ExtFunc int WaitForConnection(short port)
+static MyEventType ConnGenFunc(EventGenRec *gen, MyEvent *event)
 {
-       struct sockaddr_in addr;
-       struct hostent *host;
-       int sockListen;
        int addrLen;
-       int val1;
        struct linger val2;
-       int i;
-
-       AtExit(CloseNets);
-       for (i = 1; i < MAX_SCREENS; i++)
-               memcpy(&netGen[i], &netGen[0], sizeof(EventGenRec));
-
-       memset(&addr, 0, sizeof(addr));
-       addr.sin_family = AF_INET;
-       addr.sin_port = htons(port);
-       addr.sin_addr.s_addr = htonl(INADDR_ANY);
-       if ((sockListen = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-               die("socket");
-       val1 = 1;
-       setsockopt(sockListen, SOL_SOCKET, SO_REUSEADDR,
-                       (void *)&val1, sizeof(val1));
-       if (bind(sockListen, (struct sockaddr *)&addr, sizeof(addr)) < 0)
-               die("bind");
-       if (listen(sockListen, 1) < 0)
-               die("listen");
+       int new;
 
        addrLen = sizeof(addr);
-       for (i = 1; i <= Connections; i++) {
-               if ((netGen[i].fd = accept(sockListen, (struct sockaddr *)&addr, &addrLen)) < 0)
+       for (new = 1; new <= MAX_SCREENS; new++)
+               if (netGen[new].fd < 0) break;
+       if (new > Game.maxplayers) return;
+
+       if ((netGen[new].fd =
+               accept(gen->fd, (struct sockaddr *)&addr, &addrLen)) < 0)
                        die("accept");
-               fprintf(stderr, "Connection: %s\n", inet_ntoa(addr.sin_addr));
-               val2.l_onoff = 1;
-               val2.l_linger = 0;
-               setsockopt(netGen[i].fd, SOL_SOCKET, SO_LINGER, (void *)&val2, sizeof(val2));
-               sprintf(Players[i].host, "%s", inet_ntoa(addr.sin_addr));
-               if (addr.sin_family == AF_INET) {
-                       host = gethostbyaddr((void *)&addr.sin_addr,
-                                       sizeof(struct in_addr), AF_INET);
-                       if (host) {
-                               strncpy(Players[i].host, host->h_name, sizeof(Players[i].host) - 1);
-                               Players[i].host[sizeof(Players[i].host) - 1] = 0;
-                       }
-               }
-               AddEventGen(&netGen[i]);
-               netGen[i].player = i;
-               totalPlayers++;
-               {
-                       MyEvent event;
-
-                       do {} while ((WaitMyEvent(&event, EM_net) != E_net) ||
-                                       (event.u.net.sender != i));
-                       if (event.u.net.type != NP_hello) ByeClient(i);
-                       else {
-                               netint4 versiondata[2];
-                               char data[255];
-                               int major;
-                               memcpy(versiondata, event.u.net.data, sizeof(versiondata));
-                               major = ntoh4(versiondata[0]);
-                               protocolVersion = ntoh4(versiondata[1]);
-                               if (major != MAJOR_VERSION || protocolVersion != PROTOCOL_VERSION) {
-                                       snprintf(data, sizeof(data), "Version mismatch: received %d.%d",
-                                               major, protocolVersion);
-                                       fprintf(stderr, "Byebye client #%d (%s)\n",
-                                               event.u.net.sender, data);
-                                       SendPacketTo(event.u.net.sender, 0, NP_error, strlen(data)+1, data);
-                                       SCloseNet(event.u.net.sender);
-                               } //version mismatch
-                               fprintf(stderr, "Accepted #%d\n", event.u.net.sender);
-                       } //NP_hello
-               }
-       }
-       close(sockListen);
-       return 0;
-} //WaitForConnection
+       fprintf(stderr, "+ Connection: %s\n", inet_ntoa(addr.sin_addr));
+       val2.l_onoff = 1;
+       val2.l_linger = 0;
+       setsockopt(netGen[new].fd, SOL_SOCKET, SO_LINGER,(void *)&val2,
+               sizeof(val2));
+       AddEventGen(&netGen[new]);
+       netGen[new].player = event->u.net.uid = new;
+                       { //new connection; netGen already initialized in GenFunc
+                               struct hostent *host;
+
+                               sprintf(Players[new].host, "%s", inet_ntoa(addr.sin_addr));
+                               if (addr.sin_family == AF_INET) {
+                                       host = gethostbyaddr((void *)&addr.sin_addr,
+                                                       sizeof(struct in_addr), AF_INET);
+                                       if (host) {
+                                               strncpy(Players[new].host, host->h_name,
+                                                       sizeof(Players[new].host) - 1);
+                                               Players[new].host[sizeof(Players[new].host) - 1] = 0;
+                                       } //set player's hostname
+                               }
+                       } //E_connect
+       return E_connect;
+} //ConnGenFunc
 
 ExtFunc int StartServer(void)
 {
        MyEvent event;
+       netint2 currentpiece[MAX_SCREENS];
        int playercount;
        int playersReady = 0;
        int i;
 
-       {
-               char serverdata[255];
-               for (i = 1; i <= totalPlayers; i++) {
-                       sprintf(serverdata, "Netris server %s", version_string);
-                       SendPacketTo(i, i, NP_hello, strlen(serverdata)+1, serverdata);
-               }
-       }
-
        do {
-               if (WaitMyEvent(&event, EM_net) == E_net) {
-//                     fprintf(stderr, "in %d: %d\n",
-//                             netGen[event.u.net.sender].fd, event.u.net.type);
-                       switch(event.u.net.type) {
-                               case NP_endConn:
-                               { //client went away :(
-                                       Players[event.u.net.sender].alive = 0;
-                                       for (i = 1; i <= totalPlayers; i++)
+               switch (WaitMyEvent(&event, EM_any)) {
+                       case E_lostConn: //client went away :(
+                               Players[event.u.net.sender].alive = 0;
+                               for (i = 1; i < MAX_SCREENS; i++)
+                                       if (Players[i].alive)
                                                SendPacketTo(i, event.u.net.sender,
                                                        NP_argghhh, sizeof(Players[0].alive),
                                                        &Players[event.u.net.sender].alive);
-                                       break;
-                               } //NP_endConn
-                               case NP_hello:
-                                       break;
-                               case NP_newPlayer:
-                               { //receive player details and return other players
-                                       memcpy(&Players[event.u.net.sender],
-                                               event.u.net.data, event.u.net.size);
-                                       if (!Players[event.u.net.sender].team)
-                                               Players[event.u.net.sender].team = 256 - event.u.net.sender;
-                                       fprintf(stderr, "player %d: %s <%s>\n", event.u.net.sender,
-                                               event.u.net.data, //Players[event.u.net.sender].name
-                                               Players[event.u.net.sender].host);
-                                       SendPacketTo(event.u.net.sender, 0, NP_gamedata,
-                                               sizeof(Game.seed)+sizeof(Game.initspeed), &Game);
-                                       for (i = 1; i <= totalPlayers; i++)
-                                               if (i != event.u.net.sender)
-                                                       SendPacketTo(i, event.u.net.sender, event.u.net.type,
-                                                               sizeof(Player) - sizeof(Players[0].spy),
-                                                               &Players[event.u.net.sender]);
-                                       if (++playersReady >= totalPlayers) {
-                                               fprintf(stderr, "Starting game (%010d)\n", Game.seed);
-                                               for (i = 1; i <= totalPlayers; i++)
-                                                       SendPacketTo(i, 0, NP_goAhead, 0, NULL);
-                                       } //give go ahead
-                                       break;
-                               } //NP_playerdata
-                               default:
-                               { //relay data to all players
-       //                              if (event.u.net.type >= NP_pause)
-                                       for (i = 1; i <= totalPlayers; i++)
-                                               if (i != event.u.net.sender)
-                                               if (event.u.net.type != NP_giveJunk
-                                               || Players[i].team != Players[event.u.net.sender].team)
-                                                       SendPacketTo(i, event.u.net.sender, event.u.net.type,
-                                                               event.u.net.size, event.u.net.data);
-                                       break;
+                               SCloseNet(event.u.net.sender);
+                               break; //NP_endConn
+                       case E_net:
+                               if (verbose) fprintf(stderr, ": %d sent %d\n",
+                                       netGen[event.u.net.sender].fd, event.u.net.type);
+                               switch(event.u.net.type) {
+                                       case NP_hello:
+//                                             if (event.u.net.type != NP_hello) ByeClient(new);
+                                       {
+                                               netint4 versiondata[2];
+                                               char data[255];
+                                               int major;
+
+                                               memcpy(versiondata, event.u.net.data,
+                                                       sizeof(versiondata));
+                                               major = ntoh4(versiondata[0]);
+                                               protocolVersion = ntoh4(versiondata[1]);
+                                               if (major != MAJOR_VERSION
+                                               || protocolVersion != PROTOCOL_VERSION) {
+                                                       snprintf(data, sizeof(data),
+                                                               "Version mismatch: received %d.%d",
+                                                               major, protocolVersion);
+                                                       fprintf(stderr, "= Wrong version player #%d (%s)\n",
+                                                               event.u.net.sender, data);
+                                                       SendPacketTo(event.u.net.sender, 0, NP_error,
+                                                               strlen(data)+1, data);
+                                                       SCloseNet(event.u.net.sender);
+                                               } //version mismatch
+                                               fprintf(stderr, "* Accepted player #%d\n",
+                                                       event.u.net.sender);
+                                               break;
+                                       } //NP_hello
+                                       case NP_newPlayer:
+                                       //receive player details and return other players
+                                               memcpy(&Players[event.u.net.sender],
+                                                       event.u.net.data, event.u.net.size);
+                                               if (!Players[event.u.net.sender].team)
+                                                       Players[event.u.net.sender].team =
+                                                               256 - event.u.net.sender;
+                                               if (Game.started < 2)
+                                                       Players[event.u.net.sender].flags |= SCF_paused;
+                                               if (!Game.continuous && Game.started >= 2) {
+                                                       char data[40];
+                                                       strcpy(data,"Can't join: Game has already started");
+                                                       fprintf(stderr, "- Can't join player #%d in "
+                                                               "non-continuous game\n", event.u.net.sender);
+                                                       SendPacketTo(event.u.net.sender, 0, NP_error,
+                                                               strlen(data)+1, data);
+//                                                     SCloseNet(event.u.net.sender, 0);
+                                                       break;
+                                               } //can't join started game
+                                               {
+                                                       static struct {
+                                                               int playerflags;
+                                                               int maxplayers; //1
+                                                               int started;    //2
+                                                               int continuous; //3
+                                                               long seed;              //4
+                                                               int initspeed;  //5
+                                                       } data;
+
+                                                       memcpy(&data, &Players[event.u.net.sender].flags,
+                                                               sizeof(data.playerflags));
+                                                       memcpy(&data.maxplayers, &Game,
+                                                               sizeof(data) - sizeof(data.playerflags));
+                                                       SendPacketTo(event.u.net.sender, 0, NP_gamedata,
+                                                               sizeof(data), &data);
+                                               } //send game options
+                                               for (i = 1; i < MAX_SCREENS; i++)
+                                                       if (netGen[i].fd >= 0 && i != event.u.net.sender) {
+                                                               SendPacketTo(event.u.net.sender, i,
+                                                                       NP_newPlayer, sizeof(Player)
+                                                                       - sizeof(Players[0].spy)
+                                                                       - sizeof(Players[0].small),
+                                                                       &Players[i]);
+                                                               SendPacketTo(event.u.net.sender, i,
+                                                                       NP_newPiece, sizeof(currentpiece[i]),
+                                                                       &currentpiece[i]);
+                                                               SendPacketTo(i, event.u.net.sender,
+                                                                       NP_newPlayer, sizeof(Player)
+                                                                       - sizeof(Players[0].spy)
+                                                                       - sizeof(Players[0].small),
+                                                                       &Players[event.u.net.sender]);
+                                                       } //send (to) players
+                                               fprintf(stderr, "> Joined player #%d: %s <%s>\n",
+                                                       event.u.net.sender,
+                                                       Players[event.u.net.sender].name,
+                                                       Players[event.u.net.sender].host);
+                                               if (++playersReady >= minplayers) {
+                                                       if (Game.started)
+                                                               SendPacketTo(event.u.net.sender, 0,
+                                                                       NP_start, 0, NULL);
+                                                       else {
+                                                               fprintf(stderr, "* Starting game (%010d)\n",
+                                                                       Game.seed);
+                                                               for (i = 1; i < MAX_SCREENS; i++)
+                                                                       SendPacketTo(i, 0, NP_start, 0, NULL);
+                                                               Game.started++;
+                                                       } //first goahead (to all)
+                                               } //give go ahead
+                                               break; //NP_playerdata
+                                       case NP_newPiece:
+                                               memcpy(&currentpiece[event.u.net.sender],
+                                                       event.u.net.data, sizeof(currentpiece[0]));
+                                               goto sendtoall;
+                                       case NP_argghhh:
+                                               Players[event.u.net.sender].alive = 0;
+                                               fprintf(stderr, "< Player #%d died\n",
+                                                       event.u.net.sender);
+                                               //check for unpaused game
+                                       case NP_pause:
+                                       {
+                                               int paused;
+                                               Players[event.u.net.sender].flags ^= SCF_paused;
+                                               paused = Game.started < 1;
+                                               for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive)
+                                                       paused |= Players[i].flags & SCF_paused;
+                                               if (paused) paused = 1;
+                                               else if (Game.started == 1) Game.started++;
+                                               goto sendtoall;
+                                       } //NP_pause
+                                       default: //relay data to all players
+                                       sendtoall:
+//                                             if (event.u.net.type >= NP_pause)
+                                               for (i = 1; i < MAX_SCREENS; i++)
+                                                       if (i != event.u.net.sender)
+                                                       if (event.u.net.type != NP_giveJunk ||
+                                                       Players[i].team != Players[event.u.net.sender].team)
+                                                               SendPacketTo(i, event.u.net.sender,
+                                                                       event.u.net.type, event.u.net.size,
+                                                                       event.u.net.data);
+                                               break; //>=NP_paused
                                }
-                       }
-               } //E_net
-               playercount = 0;
-               for (i = 1; i <= totalPlayers; i++)
-                       if (netGen[i].fd >= 0) playercount++;
-       } while (playercount > 1);
+                               break; //E_net
+                       case E_connect:
+                       { //new connection; netGen already initialized in GenFunc
+                               char serverdata[255];
+
+                               sprintf(serverdata, "Netris server %s", version_string);
+                               SendPacketTo(event.u.net.uid, event.u.net.uid, NP_hello,
+                                       strlen(serverdata)+1, serverdata);
+                               break;
+                       } //E_connect
+               } //event
+               {
+                       int j;
+                       playercount = 0;
+                       for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive) {
+                               if (Players[i].team < 128) for (j = 1; j < i; j++)
+                                       if (Players[j].alive
+                                       && (Players[j].team == Players[i].team)) {
+                                               playercount--;
+                                               break;
+                                       } //player of same team counted before
+                               playercount++;
+                       } //player alive
+               } //count players
+       } while (Game.started < 2 || playercount > 1 || Game.continuous);
+       fprintf(stderr, "* Exiting server\n");
 } //StartServer
 
 
@@ -438,6 +512,9 @@ ExtFunc void Usage(void)
          "\n"
          "  -s, --seed <seed>\tStart with given random seed\n"
          "  -i, --speed <sec>\tSet the initial step-down interval, in seconds\n"
+         "  -m, --min-players <2>\tNumber of players required before starting the game\n"
+         "  -x, --max-players <8>\tMaximum number of players allowed in the game\n"
+         "  -c, --continuous\tDon'n quit the game\n"
          "\n", DEFAULT_PORT);
 }
 
@@ -480,11 +557,22 @@ ExtFunc void WriteConf(void)
 ExtFunc void HandleOption(char tag, char *value)
 {
        switch (tag) {
+               case 'v':       //verbose
+                       verbose = 1;
+                       break;
                case 'p':       //port
                        port = atoi(value);
                        break;
-               case 'c':       //connections
-                       Connections = atoi(value);
+               case 'c':       //min-players
+                       Game.continuous = atoi(value);
+                       break;
+               case 'm':       //min-players
+                       minplayers = atoi(value);
+                       break;
+               case 'x':       //max-players
+                       Game.maxplayers = atoi(value);
+                       if (Game.maxplayers >= MAX_SCREENS)
+                               Game.maxplayers = MAX_SCREENS;
                        break;
                case 'i':       //speed (of level 1)
                        Game.initspeed = atof(value) * 1e6;
@@ -515,7 +603,8 @@ ExtFunc void ReadConf(char *filename)
                        if ((ch = strchr(buf, '#')))
                                *ch = '\0'; // truncate string from # char
                        for (i = strlen(buf)-1; i >= 0; i--)
-                               if (buf[i] == ' ' || buf[i] == '\n' || buf[i] == '\t' || buf[i] == 13)
+                               if (buf[i] == ' ' || buf[i] == '\t'
+                               || buf[i] == '\n' || buf[i] == 13)
                                        buf[i] = '\0';
                                else break;
 
@@ -547,6 +636,7 @@ ExtFunc int main(int argc, char **argv)
        if (sigsetjmp(close_env, 1)) exit(0);
        signal(SIGINT, CatchInt);
        port = DEFAULT_PORT;
+       Game.maxplayers = 8;
        Game.initspeed = DEFAULT_INTERVAL;
        Game.seed = time(0);
 
@@ -555,7 +645,7 @@ ExtFunc int main(int argc, char **argv)
 //     else
        ReadConf(CONFIG_FILE);
        while ((ch = getopt_long(argc, argv,
-                       "hHp:i:s:c:", options, NULL)) != -1)
+                       "hHvp:i:s:c:m:x:", options, NULL)) != -1)
                HandleOption(ch, optarg);
        if (optind < argc) {
                Usage();
@@ -564,8 +654,38 @@ ExtFunc int main(int argc, char **argv)
 //     WriteConf();
 
        Header();
-       WaitForConnection(port);
-       StartServer();
+
+       {
+               int i;
+
+               for (i = 1; i < MAX_SCREENS; i++)
+                       memcpy(&netGen[i], &netGen[0], sizeof(EventGenRec));
+       } //setup netGen var
+
+       AtExit(CloseNets);
+
+       {
+               int val1;
+
+               memset(&addr, 0, sizeof(addr));
+               addr.sin_family = AF_INET;
+               addr.sin_port = htons(port);
+               addr.sin_addr.s_addr = htonl(INADDR_ANY);
+               if ((connGen.fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+                       die("socket");
+               val1 = 1;
+               setsockopt(connGen.fd, SOL_SOCKET, SO_REUSEADDR,
+                               (void *)&val1, sizeof(val1));
+               if (bind(connGen.fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+                       die("bind");
+               if (listen(connGen.fd, 1) < 0)
+                       die("listen");
+
+               AddEventGen(&connGen);
+       } //setup listening sock
+
+       StartServer(); //server loop
+
        return 0;
 }