diff -urN xpilot-4.2.0.orig/Local.config xpilot-4.2.0dc2000a1/Local.config
--- xpilot-4.2.0.orig/Local.config	Mon Mar 13 20:11:16 2000
+++ xpilot-4.2.0dc2000a1/Local.config	Sun Mar 19 04:53:42 2000
@@ -178,8 +178,8 @@
       VERSION_MINOR = 2
  VERSION_PATCHLEVEL = 0
     VERSION_WINDOWS = 13
-     VERSION_STATUS = 
-        RELEASEDATE = Mar 13th, 2000
+     VERSION_STATUS = DC2000a1
+        RELEASEDATE = Mar 19th, 2000
 
 
 /*
diff -urN xpilot-4.2.0.orig/src/common/config.c xpilot-4.2.0dc2000a1/src/common/config.c
--- xpilot-4.2.0.orig/src/common/config.c	Sat Mar 18 14:26:42 2000
+++ xpilot-4.2.0dc2000a1/src/common/config.c	Sun Mar 19 04:53:42 2000
@@ -46,9 +46,9 @@
 
 #ifndef	DEFAULT_MAP
 #    ifdef	_WINDOWS
-#         define DEFAULT_MAP		"default.xp"
+#         define DEFAULT_MAP		"dc2000.xp"
 #    else
-#         define DEFAULT_MAP		"globe.xp"
+#         define DEFAULT_MAP		"dc2000.xp"
 #    endif
 #endif
 
diff -urN xpilot-4.2.0.orig/src/common/version.h xpilot-4.2.0dc2000a1/src/common/version.h
--- xpilot-4.2.0.orig/src/common/version.h	Sat Mar 18 14:26:45 2000
+++ xpilot-4.2.0dc2000a1/src/common/version.h	Sun Mar 19 04:53:42 2000
@@ -28,15 +28,15 @@
 #if defined(__hpux)
 #   pragma COPYRIGHT_DATE	"1991-2000"
 #   pragma COPYRIGHT		"Bjørn Stabell, Ken Ronny Schouten, Bert Gijsbers & Dick Balaska"
-#   pragma VERSIONID		"XPilot 4.2.0"
+#   pragma VERSIONID		"XPilot 4.2.0-DC2000a1"
 #endif
 
-#define VERSION			"4.2.0"
+#define VERSION			"4.2.0-DC2000a1"
 #ifdef	_WINDOWS
-#define	TITLE			"4.2.0-NT13"
+#define	TITLE			"4.2.0-DC2000a1-NT13"
 #define	VERSION_WINDOWS	"13"
 #else
-#define TITLE			"XPilot 4.2.0"
+#define TITLE			"XPilot 4.2.0-DC2000a1"
 #endif
 #define AUTHORS			"Bjørn Stabell, Ken Ronny Schouten, Bert Gijsbers & Dick Balaska"
 #define COPYRIGHT		"Copyright © 1991-2000 by Bjørn Stabell, Ken Ronny Schouten, Bert Gijsbers & Dick Balaska"
diff -urN xpilot-4.2.0.orig/src/server/cmdline.c xpilot-4.2.0dc2000a1/src/server/cmdline.c
--- xpilot-4.2.0.orig/src/server/cmdline.c	Sat Mar 18 14:26:52 2000
+++ xpilot-4.2.0dc2000a1/src/server/cmdline.c	Sun Mar 19 04:53:42 2000
@@ -40,6 +40,7 @@
 #include "defaults.h"
 #include "error.h"
 #include "portability.h"
+#include "status.h"
 
 char cmdline_version[] = VERSION;
 
@@ -234,6 +235,17 @@
 
 bool		ignore20MaxFPS;		/* ignore client maxFPS request if it is 20 */
 
+bool		useWreckage;		/* create wreckage or not? */
+int		timerResolution;	/* OS timer resolution (times/s) */
+char		*password;		/* password for operator status */
+int		numberOfRounds;		/* how many rounds to play */
+/* BEGIN - TEAMCUP */
+bool		teamcup;		/* Is this a teamcup match? */
+char		*statServer;		/* Status server to report to */
+int		statPort;		/* Port to use on the status server */
+int		matchNumber;		/* The number of the match */
+/* END - TEAMCUP */
+
 extern char	conf_default_map_string[];	/* from common/config.c */
 extern char	conf_robotfile_string[];	/* from common/config.c */
 
@@ -2538,7 +2550,90 @@
 	"Whether the server is prevented from being swapped out of memory.\n",
 	MAP("General")
     },
-
+    {
+	"wreckage",
+	"wreckage",
+	"true",
+	&useWreckage,
+	valBool,
+	tuner_dummy,
+	"Do destroyed ships leave wreckage?\n",
+	MAP(NULL)
+    },
+    {
+	"timerResolution",
+	"timerResolution",
+	"0",
+	&timerResolution,
+	valInt,
+	tuner_none,
+	"If set to nonzero, xpilots will requests signals from the OS at\n"
+	"1/timerResolution second intervals. Server will then compute a new\n"
+	"frame FPS times out of every timerResolution signals.\n",
+	MAP(NULL)
+    },
+    {
+	"password",
+	"password",
+	NULL,
+	&password,
+	valString,
+	tuner_dummy,
+	"The password needed to get operator privileges.\n",
+	MAP(NULL)
+    },
+    {
+	"numberOfRounds",
+	"numRounds",
+	"0",
+	&numberOfRounds,
+	valInt,
+	tuner_dummy,
+	"The number of rounds to play. If 0, unlimited.\n",
+	MAP(NULL)
+    },
+    /* BEGIN - TEAMCUP */
+    {
+	"teamcup",
+	"teamcup",
+	false,
+	&teamcup,
+	valBool,
+	tuner_dummy,
+	"Is this a teamcup match?.\n",
+	MAP(NULL)
+    },
+    {
+	"statServer",
+	"statServer",
+	"shell.e.kth.se",
+	&statServer,
+	valString,
+	tuner_dummy,
+	"Status server to report to.\n",
+	MAP(NULL)
+    },
+    {
+	"statPort",
+	"statPort",
+	STATUS_PORTSTR,
+	&statPort,
+	valInt,
+	tuner_dummy,
+	"Port of the status server.\n",
+	MAP(NULL)
+    },
+    {
+	"match",
+	"match",
+	"-1",
+	&matchNumber,
+	valInt,
+	tuner_dummy,
+	"The number of the match.\n",
+	MAP(NULL)
+    }
+    /* END - TEAMCUP */
 };
 
 
@@ -2712,7 +2807,7 @@
 
 int Parser(int argc, char **argv)
 {
-    int			i, j;
+    int			i, j, gotmatch = 0;
     char		*fname;
 
 
@@ -2742,6 +2837,9 @@
 	    puts(TITLE);
 		return(FALSE);
 	}
+	if (strcmp("-match", argv[i]) == 0 && i + 1 != argc) {
+		gotmatch = 1;
+	}
 
 	if (argv[i][0] == '-' || argv[i][0] == '+') {
 	    for (j = 0; j < NELEM(options); j++) {
@@ -2772,6 +2870,12 @@
 	}
 	errno = 0;
 	error("Unknown option '%s'", argv[i]);
+    }
+    if (!gotmatch) {
+	xpprintf("\n\n"
+		 "!!! You must use the '-match' option to start this server.\n"
+		 "!!! To practise you may use '-match 0'.\n\n\n");
+	return(FALSE);
     }
 
     /*
diff -urN xpilot-4.2.0.orig/src/server/contact.c xpilot-4.2.0dc2000a1/src/server/contact.c
--- xpilot-4.2.0.orig/src/server/contact.c	Sat Mar 18 14:26:53 2000
+++ xpilot-4.2.0dc2000a1/src/server/contact.c	Sun Mar 19 04:53:43 2000
@@ -825,7 +825,7 @@
     long			last_ack_recv;
 };
 
-static struct queued_player	*qp_list;
+struct queued_player	*qp_list;
 
 static void Queue_remove(struct queued_player *qp, struct queued_player *prev)
 {
diff -urN xpilot-4.2.0.orig/src/server/event.c xpilot-4.2.0dc2000a1/src/server/event.c
--- xpilot-4.2.0.orig/src/server/event.c	Sat Mar 18 14:26:53 2000
+++ xpilot-4.2.0dc2000a1/src/server/event.c	Sun Mar 19 04:53:43 2000
@@ -236,6 +236,7 @@
     int			i;
 
     if (onoff != 0 && !BIT(pl->status, PAUSE)) { /* Turn pause mode on */
+	Swappers[pl->team] = -1;
 	pl->count = 10*FPS;
 	pl->updateVisibility = 1;
 	CLR_BIT(pl->status, SELF_DESTRUCT|PLAYING);
diff -urN xpilot-4.2.0.orig/src/server/frame.c xpilot-4.2.0dc2000a1/src/server/frame.c
--- xpilot-4.2.0.orig/src/server/frame.c	Sat Mar 18 14:26:53 2000
+++ xpilot-4.2.0dc2000a1/src/server/frame.c	Sun Mar 19 04:53:43 2000
@@ -954,7 +954,7 @@
 		&& frame_loops % 5 >= 3) {
 		continue;
 	    }
-	    Frame_radar_buffer_add((int)x, (int)y, 3);
+	    Frame_radar_buffer_add((int)x, (int)y, TEAM(i, ind) ? 3+0x80 : 3);
 	}
     }
 }
@@ -1135,6 +1135,9 @@
     } else {
 	msg = message;
     }
+    /* BEGIN - TEAMCUP */
+    teamcup_log("    %s\n", message);
+    /* END - TEAMCUP */
     for (i = 0; i < NumPlayers; i++) {
 	pl = Players[i];
 	if (pl->conn != NOT_CONNECTED) {
diff -urN xpilot-4.2.0.orig/src/server/global.h xpilot-4.2.0dc2000a1/src/server/global.h
--- xpilot-4.2.0.orig/src/server/global.h	Sat Mar 18 14:26:53 2000
+++ xpilot-4.2.0dc2000a1/src/server/global.h	Sun Mar 19 04:53:43 2000
@@ -51,6 +51,7 @@
  */
 #ifdef SERVER
 #define FPS			framesPerSecond
+extern int		Swappers[MAX_TEAMS];	/* person swapping to a team */
 extern player		**Players;
 extern object		*Obj[];
 extern pulse_t		*Pulses[];
@@ -58,6 +59,7 @@
 extern trans_t		*Transporters[];
 extern long		frame_loops;
 extern int		NumPlayers;
+extern int		NumOperators;
 extern int		NumPseudoPlayers;
 extern int		NumQueuedPlayers;
 extern int		NumObjs;
@@ -245,6 +247,37 @@
 
 extern bool		useWreckage;
 extern bool		ignore20MaxFPS;
+
+extern int		timerResolution;
+extern char		*password;
+extern int		numberOfRounds;
+
+/* BEGIN - TEAMCUP */
+extern char		*statServer;
+extern int		statPort;
+extern int		matchNumber;
+extern FILE		*teamcup_score_file;
+extern bool		teamcup;
+#if !defined(STDVA)
+#   if defined(__STDC__) && !defined(__sun__) || defined(__cplusplus)
+#	define STDVA	1		/* has ANSI stdarg stuff */
+#   else
+#	define STDVA	0		/* nope, still the K&R way */
+#   endif
+#endif
+#if STDVA
+void teamcup_log(const char *fmt, ...);
+#else
+void teamcup_log();
+#endif
+void teamcup_round_start();
+void teamcup_round_end(int winning_team);
+void teamcup_open_score_file();
+void teamcup_close_score_file();
+
+extern int			teamcup_match_inited;
+extern int			teamcup_status_fd;
+/* END - TEAMCUP */
 
 #endif
 
diff -urN xpilot-4.2.0.orig/src/server/netserver.c xpilot-4.2.0dc2000a1/src/server/netserver.c
--- xpilot-4.2.0.orig/src/server/netserver.c	Sat Mar 18 14:26:54 2000
+++ xpilot-4.2.0dc2000a1/src/server/netserver.c	Sun Mar 19 04:53:43 2000
@@ -1888,6 +1888,10 @@
 {
     connection_t *connp = &Conn[ind];
 
+    if (connp->version < 0x4101 && size >= 0x80) {
+	/* Friends and enemies look the same to old clients. */
+	size -= 0x80;
+    }
     return Packet_printf(&connp->w, "%c%hd%hd%c", PKT_RADAR, x, y, size);
 }
 
@@ -2517,6 +2521,41 @@
     return 1;
 }
 
+static int Ind_by_name(char *name)
+{
+    int i, j, len;
+
+    if (!name) return -1;
+
+    if (isdigit(*name)) {     /* Id given directly */
+	i = atoi(name);
+	if (i > 0 && i <= NUM_IDS && (j=GetInd[i]) >= 0 && j < NumPlayers
+	    && Players[j]->id == i) {
+	    return j;
+	} else {
+	    return -1;
+	}
+    }
+
+    /* first look for an exact match on player nickname. */
+    for (i = 0; i < NumPlayers; i++) {
+	if (strcasecmp(Players[i]->name, name) == 0) {
+	    return i;
+	}
+    }
+
+    /* now look for a partial match on both nick and realname. */
+    len = strlen(name);
+    for (j = -1, i = 0; i < NumPlayers; i++) {
+	if (strncasecmp(Players[i]->name, name, len) == 0
+	    || strncasecmp(Players[i]->realname, name, len) == 0) {
+	    j = (j == -1) ? i : -2;
+	}
+    }
+
+    return j;
+}
+
 /*
  * If a message contains a colon then everything before that colon is
  * either a unique player name prefix, or a team number with players.
@@ -2578,22 +2617,7 @@
 	}
     }
     else {						/* Player message */
-	sent = -1;
-	/* first look for an exact match on player nickname. */
-	for (i = 0; i < NumPlayers; i++) {
-	    if (strcasecmp(Players[i]->name, str) == 0) {
-		sent = i;
-		break;
-	    }
-	}
-	if (sent == -1) {
-	    /* now look for a partial match on both nick and realname. */
-	    for (sent = -1, i = 0; i < NumPlayers; i++) {
-		if (strncasecmp(Players[i]->name, str, len) == 0
-		    || strncasecmp(Players[i]->realname, str, len) == 0)
-		    sent = (sent == -1) ? i : -2;
-	    }
-	}
+	sent = Ind_by_name(str);
 	switch (sent) {
 	case -2:
 	    sprintf(msg, "Message not sent, %s matches more than one player!",
@@ -2616,6 +2640,522 @@
     }
 }
 
+int Swappers[MAX_TEAMS] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; /* fix this */
+
+static void Send_all_info(player *pl)
+{
+    int i;
+
+    for (i=0;i<NumPlayers;i++) {
+	if (Players[i]->conn != NOT_CONNECTED) {
+	    Send_player(Players[i]->conn,pl->id);
+	    Send_score(Players[i]->conn,pl->id,pl->score,pl->life,
+		       pl->mychar);
+	    Send_base(Players[i]->conn,pl->id,pl->home_base);
+	}
+    }
+}
+
+static void Swap_team(int ind, char *args)
+{
+    int      i,team;
+    player   *pl=Players[ind];
+    char      msg[MSG_LEN*2];
+
+    for (i=0;i<MAX_TEAMS;i++) {
+	/* can't queue to two teams at once */
+	if (Swappers[i]==pl->id) {
+	    Swappers[i]=-1;
+	}
+    }
+
+    if (!args) {
+	sprintf(msg,"Not swapping to any team.");
+    } else {
+	team=atoi(args);
+	if (pl->team >= MAX_TEAMS) {
+	    sprintf(msg,"You do not currently have a team. Swapping doesn't work.");
+	} else if (team<0 || team>=MAX_TEAMS ||
+		 World.teams[team].NumBases == 0) {
+	    sprintf(msg,"There are no bases for team %d on this map.",team);
+	} else if (reserveRobotTeam && team==robotTeam) {
+	    sprintf(msg,"You cannot join the robot team on this server.");
+	} else if (team ==  pl->team) {
+	    sprintf(msg,"You already are on team %d.",team);
+	} else if (World.teams[team].NumBases - World.teams[team].NumMembers > 0) {
+	    sprintf(msg,"%s has swapped to team %d.", pl->name,team);
+	    Set_message(msg);
+	    if (BIT(pl->have, OBJ_BALL)) {
+		Detach_ball(ind, -1);
+	    }
+	    World.teams[pl->team].NumMembers--;
+	    pl->team=team;
+	    World.teams[pl->team].NumMembers++;
+	    if (BIT(pl->mode, LIMITED_LIVES)) {
+		for (i = 0; i < NumPlayers; i++) {
+		    if (!TEAM(ind, i) && !BIT(Players[i]->status,PAUSE)) {
+			if (pl->mychar == ' ') {
+			    pl->mychar	= 'W';
+			}
+			pl->prev_life = pl->life = 0;
+			SET_BIT(pl->status, GAME_OVER|PLAYING);
+			CLR_BIT(pl->status, SELF_DESTRUCT);
+			pl->count=-1;
+			break;
+		    }
+		}
+	    }
+	    Pick_startpos(GetInd[pl->id]);
+	    Send_all_info(pl);
+	    return;
+	} else {
+	    i=Swappers[pl->team];
+	    while (i != -1) {
+		if ( (i=Players[GetInd[i]]->team) != team) {
+		    i=Swappers[i];
+		} else {
+		    int xbase=pl->home_base, xteam=pl->team,xbase2,xteam2;
+		    player *pl2=pl;
+
+		    do {
+			pl2=Players[GetInd[Swappers[xteam]]];
+			Swappers[xteam]=-1;
+			xbase2=pl2->home_base;
+			xteam2=pl2->team;
+			if (BIT(pl2->have, OBJ_BALL))
+			    Detach_ball(GetInd[pl2->id], -1);
+			pl2->team=xteam;
+			pl2->home_base=xbase;
+			if (pl2->mychar == ' ')
+			    pl2->mychar	= 'W';
+			pl2->prev_life = pl2->life = 0;
+			SET_BIT(pl2->status, GAME_OVER|PLAYING);
+			CLR_BIT(pl2->status, SELF_DESTRUCT);
+			pl2->count=-1;
+			Go_home(GetInd[pl2->id]);
+			Send_all_info(pl2); 
+			/* This can send a huge amount of data if several players swap.
+			   Unfortunately all player data, even shipshape, has to be
+			   resent to change the team of a player. This should probably
+			   be changed somehow to prevent disturbing other players. */
+			xbase=xbase2;
+			xteam=xteam2;
+		    } while (xteam != team);
+		    if (BIT(pl->have, OBJ_BALL)) {
+			Detach_ball(ind, -1);
+		    }
+		    pl->team=team;
+		    pl->home_base=xbase;
+		    if (pl->mychar == ' ') {
+			pl->mychar = 'W';
+		    }
+		    pl->prev_life = pl->life = 0;
+		    SET_BIT(pl->status, GAME_OVER|PLAYING);
+		    CLR_BIT(pl->status, SELF_DESTRUCT);
+		    pl->count=-1;
+		    Go_home(ind);
+		    Send_all_info(pl);
+		    sprintf(msg,"Some players swapped teams.");
+		    Set_message(msg);
+		    return;
+		}
+	    }
+      
+	    for (i = NumPlayers - 1; i >= 0; i--) {
+		if (Players[i]->conn != NOT_CONNECTED 
+		    && BIT(Players[i]->status, PAUSE)
+		    && (Players[i]->team == team)) {
+		    sprintf(msg,"%s has swapped with paused %s.",pl->name,
+			    Players[i]->name);
+		    Set_message(msg);
+		    if (BIT(pl->have, OBJ_BALL))
+			Detach_ball(GetInd[pl->id], -1);
+		    Players[i]->team=pl->team;
+		    pl->team=team;
+		    team=Players[i]->home_base;
+		    Players[i]->home_base=pl->home_base;
+		    Go_home(i);
+		    pl->home_base=team;
+		    Send_all_info(Players[i]);
+		    if (BIT(pl->mode, LIMITED_LIVES)) {
+			for (i = 0; i < NumPlayers; i++) {
+			    if (!TEAM(ind, i) && !BIT(Players[i]->status,PAUSE)) {
+				if (pl->mychar == ' ') {
+				    pl->mychar	= 'W';
+				}
+				pl->prev_life = pl->life = 0;
+				SET_BIT(pl->status, GAME_OVER|PLAYING);
+				CLR_BIT(pl->status, SELF_DESTRUCT);
+				pl->count=-1;
+				Go_home(ind);
+				break;
+			    }
+			}
+		    }
+		    Send_all_info(pl);
+		    return;
+		}
+	    }
+	    sprintf(msg,"You are queued for swap to team %d.",team);
+	    Swappers[team]=pl->id;
+	}
+    }
+    sprintf(msg+strlen(msg)," [*Server reply*]");
+    Set_player_message(pl,msg);
+    return;
+}
+
+extern int game_lock;
+
+extern void Reset_all_players(void);
+
+extern int roundCounter;
+
+struct queued_player {
+    struct queued_player	*next;
+    char			real_name[MAX_CHARS];
+    char			nick_name[MAX_CHARS];
+    char			disp_name[MAX_CHARS];
+    char			host_name[MAX_CHARS];
+    char			host_addr[24];
+    int				port;
+    int				team;
+    unsigned			version;
+    int				login_port;
+    long			last_ack_sent;
+    long			last_ack_recv;
+};
+
+extern struct queued_player *qp_list;
+
+enum Command {
+    KICK_CMD, VERSION_CMD, HELP_CMD, RESET_CMD, TEAM_CMD,
+    PASSWORD_CMD, LOCK_CMD, SET_CMD, PAUSE_CMD, SHOW_CMD, 
+    ADVANCE_CMD, NO_CMD
+};
+
+typedef struct {
+    const char *name;
+    const char *sname;
+    const char *help;
+    int operOnly;
+    enum Command number;
+} commandInfo;
+
+static commandInfo commands[] = {
+    {
+	"help",
+	"h",
+	"Without arguments, prints command list. /help <command> gives more info.",
+	0,
+	HELP_CMD
+    },
+    {
+	"team",
+	"t",
+	"/team <team number> swaps you to given team. "
+	"Can be used with full teams too.",
+	0,
+	TEAM_CMD
+    },
+    {
+	"version",
+	"v",
+	"Print server version.",
+	0,
+	VERSION_CMD
+    },
+    {
+	"lock",
+	"l",
+	"Just /lock tells lock status. /lock 1 locks, /lock 0 unlocks. (operator)",
+	0,      /* checked in the function */
+	LOCK_CMD
+    },
+    {
+	"password",
+	"pas",
+	"/password <string>. If string matches -password option, "
+	"gives operator status.",
+	0,
+	PASSWORD_CMD
+    },
+    {
+	"pause",
+	"pau",
+	"/pause <player name or ID number>. Pauses player. (operator)",
+	1,
+	PAUSE_CMD
+    },
+    {
+	"reset",
+	"r",
+	"Just /reset re-starts the round. "
+	"/reset all also sets scores to 0. (operator)",
+	1,
+	RESET_CMD
+    },
+    {
+	"set",
+	"set",
+	"/set <option> <value> sets a server option. (operator)",
+	1,
+	SET_CMD
+    },
+    {
+	"kick",
+	"k",
+	"/kick <player name or ID number>. Remove a player from game. (operator)",
+	1,
+	KICK_CMD
+    },
+    {
+	"show",
+	"sh",
+	"/show queue. Show the names of players waiting to enter.",
+	0,
+	SHOW_CMD
+    },
+    {
+	"advance",
+	"adv",
+	"/advance <name of player in the queue>. "
+	"Move the player to the front of the queue. (operator)",
+	1,
+	ADVANCE_CMD
+    }
+};
+
+static void Handle_command(int ind, char *cmd)   /* no leading / */
+{
+    connection_t	*connp = &Conn[ind];
+    int                 plind  = GetInd[connp->id];
+    player		*pl = Players[plind];
+    int			i;
+    char		*args, msg[MSG_LEN * 2];
+
+    if (args=strchr(cmd,' '))
+	*args++=0;               /* separate arguments from command */
+
+    for (i=0; i<NELEM(commands); i++)
+	if (!strncasecmp(cmd, commands[i].sname, strlen(commands[i].sname)))
+	    break;
+    if (i==NELEM(commands)) {
+	i=NO_CMD;
+	sprintf(msg,"Unknown command %s",cmd);
+    }
+    else if (!pl->isoperator && commands[i].operOnly) {
+	i=NO_CMD;
+	sprintf(msg,"You need operator status to use this command.");
+    }
+    else
+	i=commands[i].number;
+
+    switch(i) {
+    case NO_CMD:
+	break;
+
+    case ADVANCE_CMD:
+	if (!args)
+	    sprintf(msg, "You must give a player name as an argument.");
+	else {
+	    struct queued_player *last=qp_list, *p;
+
+	    if (!last || !(p=last->next)) {
+		sprintf(msg, "There are less than 2 players in the queue.");
+		break;
+	    }
+	    if (!strcasecmp(last->nick_name, args)) {
+		sprintf(msg, "Already first.");
+		break;
+	    }
+	    while (1)
+		if (strcasecmp(p->nick_name, args)) {
+		    last=p;
+		    p=p->next;
+		    if (!p) {
+			sprintf(msg, "No player named %s in the queue.",args);
+			break;
+		    }
+		} else {
+		    last->next=p->next;
+		    p->next=qp_list;
+		    qp_list=p;
+		    sprintf(msg, "Done.");
+		    break;
+		}
+	}
+	break;
+	
+    case SHOW_CMD:
+	if (!args)
+	    sprintf(msg,"Show what?");
+	else if (!strncasecmp(args, "q", 1)) { /* queue */
+	    int len=0, i, count;
+	    struct queued_player *p=qp_list;
+
+	    if (!p) {
+		sprintf(msg, "The queue is empty.");
+		break;
+	    }
+	    sprintf(msg, "Queue: ");
+	    len=strlen(msg);
+	    count=1;
+	    do {
+		sprintf(msg+len, "%d. %s  ", count++, p->nick_name);
+		len+=strlen(msg+len);
+		p=p->next;
+	    } while (p && len < MSG_LEN - 25);
+	    *(msg+len-2)=0;                  /* -2 to strip spaces */
+	} else
+	    sprintf(msg,"Unrecognized argument to /show.");
+	break;
+
+    case TEAM_CMD:
+	Swap_team(plind,args);
+	return;
+
+    case KICK_CMD:
+	if ( (i=Ind_by_name(args)) >= 0) {
+	    sprintf(msg,"%s kicked %s out! [*Server notice*]",
+		    pl->name, Players[i]->name);
+	    Set_message(msg);
+	    if (Players[i]->conn == NOT_CONNECTED)
+		Delete_player(i);
+	    else
+		Destroy_connection(Players[i]->conn, "kicked out");
+	    return;
+	}
+	else if (i==-1)
+	    sprintf(msg,"Name does not match any player.");
+	else if (i==-2)
+	    sprintf(msg,"Name matches several players.");
+	else
+	    sprintf(msg,"Error.");
+	break;
+
+    case VERSION_CMD:
+	sprintf(msg, "Xpilot %s", VERSION);
+	break;
+
+    case HELP_CMD:
+	if (!args)
+	    sprintf(msg,"Commands: help team version lock password pause "\
+		    "reset set kick show advance");
+	else {
+	    for (i=0;i<NELEM(commands);i++)
+		if (!strncasecmp(args, commands[i].sname,
+				 strlen(commands[i].sname))) {
+		    break;
+		}
+	    if (i==NELEM(commands))
+		sprintf(msg,"No help for nonexistent command '%s'.",args);
+	    else 
+		sprintf(msg,"%s",commands[i].help);
+	}
+	break;
+
+    case RESET_CMD:
+	if (args && !strcasecmp(args, "all")) {
+	    for (i = NumPlayers-1; i >= 0; i--) {
+		Players[i]->score = 0;
+	    }
+	    Reset_all_players();
+	    roundCounter = 1;
+	    if (gameDuration == -1) gameDuration = 0;
+	    sprintf(msg," < Total reset by %s! >", pl->name);
+	    Set_message(msg);
+	    /* BEGIN - TEAMCUP */
+	    teamcup_close_score_file();
+	    teamcup_open_score_file();
+	    teamcup_round_start();
+	    /* END - TEAMCUP */
+	    return;
+	} else {
+	    Reset_all_players();
+	    if (gameDuration == -1) gameDuration = 0;
+#if 0 /* No thanks... /Adamel */
+	    if (roundCounter == numberOfRounds+1) {
+		numberOfRounds = 0;
+	    }
+#endif
+	    sprintf(msg," < Round reset by %s! >", pl->name);
+	    Set_message(msg);
+	    return;
+	}
+	break;
+
+    case PASSWORD_CMD:
+	if (!password || !args || strcmp(args,password))
+	    sprintf(msg,"Wrong.");
+	else {
+	    if (!pl->isoperator)
+		NumOperators++;
+	    pl->isoperator=1;
+	    sprintf(msg,"You got operator status.");
+	}
+	break;
+
+    case LOCK_CMD:
+	if (!args)
+	    sprintf(msg,"The game is currently %s.",game_lock?"locked":"unlocked");
+	else if (!pl->isoperator)
+	    sprintf(msg,"You need operator status for this.");
+	else if (atoi(args)) {
+	    sprintf(msg," < The game has been locked by %s! >",pl->name);
+	    Set_message(msg);
+	    game_lock=1;
+	    return;
+	}
+	else {
+	    sprintf(msg," < The game has been unlocked by %s! >",pl->name);
+	    Set_message(msg);
+	    game_lock=0;
+	    return;
+	}
+	break;
+
+    case SET_CMD:
+	if (!args || !(args=strtok(args," ")) || !(cmd=strtok(NULL," ")) )
+	    sprintf(msg,"Usage: /set option value.");
+	else if ((i=Tune_option(args,cmd)) == 1) {
+	    if (!strcasecmp(args,"password"))
+		sprintf(msg,"Operation successful.");
+	    else {
+		sprintf(msg," < Option %s set to %s by %s. >",
+			args,cmd,pl->name);
+		Set_message(msg);
+		return;
+	    }
+	}
+	else if (i==0)
+	    sprintf(msg,"Invalid value.");
+	else if (i==-1)
+	    sprintf(msg,"This option cannot be changed at runtime.");
+	else if (i==-2)
+	    sprintf(msg,"No option named \"%s\".",args);
+	else
+	    sprintf(msg,"Error.");
+	break;
+
+    case PAUSE_CMD:
+	if ((i=Ind_by_name(args))>=0 && Players[i]->conn != NOT_CONNECTED) {
+	    if (BIT(Players[i]->status, PLAYING|PAUSE|GAME_OVER|KILLED) == PLAYING)
+		Kill_player(i);
+	    Pause_player(i,1);
+	    sprintf(msg,"%s was paused by %s.",Players[i]->name,pl->name);
+	    Set_message(msg);
+	    return;
+	}
+	sprintf(msg,"Invalid player id.");
+	break;
+    }
+
+    sprintf(msg+strlen(msg)," [*Server reply*]");
+    Set_player_message(pl,msg);
+    return;
+}
+
 static int Receive_talk(int ind)
 {
     connection_t	*connp = &Conn[ind];
@@ -2638,7 +3178,11 @@
 	    return n;
 	}
 	connp->talk_sequence_num = seq;
-	Handle_talk (ind, str);
+	if (*str == '/') {
+	    Handle_command(ind,str+1);
+	} else {
+	    Handle_talk (ind, str);
+	}
     }
     return 1;
 }
diff -urN xpilot-4.2.0.orig/src/server/object.h xpilot-4.2.0dc2000a1/src/server/object.h
--- xpilot-4.2.0.orig/src/server/object.h	Sat Mar 18 14:26:54 2000
+++ xpilot-4.2.0dc2000a1/src/server/object.h	Sun Mar 19 04:53:43 2000
@@ -421,6 +421,8 @@
 
     int		isowner;		/* If player started this server. */
 
+    int		isoperator;		/* Player has operator privileges */
+
 #ifdef __cplusplus
 		player() {}
 #endif
diff -urN xpilot-4.2.0.orig/src/server/player.c xpilot-4.2.0dc2000a1/src/server/player.c
--- xpilot-4.2.0.orig/src/server/player.c	Sat Mar 18 14:26:55 2000
+++ xpilot-4.2.0dc2000a1/src/server/player.c	Sun Mar 19 04:53:43 2000
@@ -44,6 +44,7 @@
 #include "saudio.h"
 #include "error.h"
 #include "objpos.h"
+#include "status.h"
 
 char player_version[] = VERSION;
 
@@ -501,6 +502,8 @@
 
     pl->isowner = 0;
 
+    pl->isoperator = 0;
+
     return pl->id;
 }
 
@@ -594,7 +597,7 @@
 }
 
 
-static void Reset_all_players(void)
+void Reset_all_players(void)
 {
     player		*pl;
     int			i, j;
@@ -885,6 +888,26 @@
 	  "[Winner]");
 }
 
+extern int roundCounter;
+
+static void Count_rounds(void)
+{
+    char msg[100];
+
+    if (!numberOfRounds) return;
+
+    sprintf(msg," < Round %d out of %d completed. >",roundCounter,numberOfRounds);
+    Set_message(msg);
+    if (roundCounter==numberOfRounds) Game_Over();
+    roundCounter++;
+
+    /* BEGIN - TEAMCUP */
+    teamcup_round_start();
+    /* END - TEAMCUP */
+
+    return;
+}
+
 void Team_game_over(int winning_team, const char *reason)
 {
     int			i, j;
@@ -948,8 +971,14 @@
 	}
     }
 
+    /* BEGIN - TEAMCUP */
+    teamcup_round_end(winning_team);
+    /* END - TEAMCUP */
+
     Reset_all_players();
 
+    Count_rounds();
+
     free(best_players);
 }
 
@@ -1147,6 +1176,8 @@
     }
 
     Reset_all_players();
+
+    Count_rounds();
 }
 
 
@@ -1588,6 +1619,8 @@
     }
 }
 
+extern int game_lock;
+
 void Delete_player(int ind)
 {
     player		*pl = Players[ind];
@@ -1599,6 +1632,21 @@
 	Robot_destroy(ind);
     }
 
+    if (pl->isoperator) {
+	if (!--NumOperators && game_lock) {
+	    game_lock = 0;
+	    Set_message(" < Game has been unlocked as the last operator left! >");
+	}
+    }
+
+    /* Won't be swapping anywhere */
+    for (i=MAX_TEAMS-1; i >= 0; i--) {
+	if (Swappers[i] == id) {
+	    Swappers[i] = -1;
+	}
+    }
+    Swappers[pl->team] = -1;	/* change this behavior later (pause too) */
+
     /* Delete remaining shots */
     for (i = NumObjs - 1; i >= 0; i--) {
 	obj = Obj[i];
@@ -1848,3 +1896,129 @@
     pl->used	&= ~(USED_KILL);
     pl->used	&= pl->have;
 }
+
+/* BEGIN - TEAMCUP */
+void teamcup_round_start()
+{
+    if (!teamcup) {
+	return;
+    }
+
+    teamcup_log("\nRound %d\n", roundCounter);
+}
+
+void teamcup_round_end(int winning_team)
+{
+    int i;
+    int j;
+    int *list;
+    int team_score[MAX_TEAMS];
+    int team_players[MAX_TEAMS];
+    int best_score;
+    int best;
+    player *pl;
+
+    if (!teamcup) {
+	return;
+    }
+
+    list = malloc(NumPlayers * sizeof(int));
+    if (list == NULL) {
+	error("Can't allocate memory for list");
+	End_game();
+    }
+
+    for (i = 0; i < NumPlayers; i++) {
+	list[i] = i;
+    }
+
+    for (i = 0; i < MAX_TEAMS; i++) {
+	team_score[i] = INT_MAX;
+    }
+
+    for (i = 0; i < MAX_TEAMS; i++) {
+	team_players[i] = 0;
+    }
+
+    for (i = 0; i < NumPlayers; i++) {
+	best = NumPlayers;
+	for (j = 0; j < NumPlayers; j++) {
+	    if (list[j] == NumPlayers) {
+		continue;
+	    }
+	    pl = Players[j];
+	    if (best == NumPlayers || pl->score > best_score) {
+		best_score = pl->score;
+		best = j;
+	    }
+	}
+
+	list[best] = NumPlayers;
+	pl = Players[best];
+	teamcup_log("%d\t%d\t%2d/%d\t%s\n", pl->team, pl->score, pl->kills,
+		    pl->deaths, pl->name);
+
+	if (team_score[pl->team] == INT_MAX) {
+	    team_score[pl->team] = 0;
+	}
+	team_score[pl->team] += pl->score;
+	team_players[pl->team]++;
+    }
+
+    for (i = 0; i < MAX_TEAMS; i++) {
+	if (team_score[i] != INT_MAX) {
+	    teamcup_log("Team %d\t%d\n", i, team_score[i]);
+	}
+    }
+    if (teamcup_score_file != NULL) {
+	fflush(teamcup_score_file);
+    }
+
+    if (teamcup_status_fd) {
+	struct round_end rend;
+
+	if (!teamcup_match_inited) {
+	    struct match_init minit;
+
+	    minit.magic = htons(INIT_MATCH_MAGIC);
+	    minit.matchno = htons(matchNumber);
+	    minit.t2players = team_players[2];
+	    minit.t4players = team_players[4];
+	    write(teamcup_status_fd, &minit, sizeof(minit));
+
+	    for (i = 0; i < NumPlayers; i++) {
+		struct player_init pinit;
+
+		pl = Players[i];
+		pinit.magic = htons(INIT_PLAYER_MAGIC);
+		pinit.id = htons(i);
+		pinit.team = pl->team;
+		pinit.namelen = strlen(pl->name);
+		write(teamcup_status_fd, &pinit, sizeof(pinit));
+		write(teamcup_status_fd, &pl->name, pinit.namelen);
+	    }
+
+	    teamcup_match_inited = 1;
+	}
+
+	for (i = 0; i < NumPlayers; i++) {
+	    struct player_status pstat;
+
+	    pl = Players[i];
+	    pstat.magic = htons(PLAYER_STATUS_MAGIC);
+	    pstat.id = htons(i);
+	    pstat.score = htons(pl->score);
+	    pstat.kills = pl->kills;
+	    pstat.deaths = pl->deaths;
+	    write(teamcup_status_fd, &pstat, sizeof(pstat));
+	}
+
+	rend.magic = htons(ROUND_END_MAGIC);
+	rend.roundno = roundCounter;
+	rend.winner = winning_team;
+	write(teamcup_status_fd, &rend, sizeof(rend));
+    }
+
+    free(list);
+}
+/* END - TEAMCUP */
diff -urN xpilot-4.2.0.orig/src/server/sched.c xpilot-4.2.0dc2000a1/src/server/sched.c
--- xpilot-4.2.0.orig/src/server/sched.c	Sat Mar 18 14:26:56 2000
+++ xpilot-4.2.0dc2000a1/src/server/sched.c	Sun Mar 19 04:53:43 2000
@@ -126,6 +126,8 @@
  */
 static void catch_timer(int signum)
 {
+    static unsigned int count = 0;
+
 #ifdef OS2DEBUG
     static int counter = 0;
 
@@ -137,7 +139,11 @@
 	fflush( stdout );
     }
 #endif
-    timer_ticks++;
+    count += FPS;
+    if (count >= timerResolution) {
+	count -= timerResolution;
+	timer_ticks++;
+    }
 }
 
 #ifdef _OS2_
diff -urN xpilot-4.2.0.orig/src/server/server.c xpilot-4.2.0dc2000a1/src/server/server.c
--- xpilot-4.2.0.orig/src/server/server.c	Sat Mar 18 14:26:57 2000
+++ xpilot-4.2.0dc2000a1/src/server/server.c	Sun Mar 19 04:53:43 2000
@@ -69,6 +69,7 @@
 #include "error.h"
 #include "portability.h"
 #include "server.h"
+#include "status.h"
 
 char server_version[] = VERSION;
 
@@ -82,6 +83,7 @@
  * Global variables
  */
 int			NumPlayers = 0;
+int			NumOperators = 0;
 int			NumObjs = 0;
 int			NumPulses = 0;
 int			NumEcms = 0;
@@ -98,6 +100,7 @@
 char			ShutdownReason[MAX_CHARS];
 int 			framesPerSecond = 18;
 long			main_loops = 0;		/* needed in events.c */
+int			roundCounter = 1;
 
 static int		serverSocket;
 #ifdef LOG
@@ -115,6 +118,189 @@
 extern void Main_loop(void);
 static void Handle_signal(int sig_no);
 
+/* BEGIN - TEAMCUP */
+static char		*teamcup_score_file_name = NULL;
+FILE			*teamcup_score_file = NULL;
+int			teamcup_match_inited = 0;
+int			teamcup_status_fd = -1;
+static int		teamcup_have_fork = 0;
+static int		teamcup_child_pid = 0;
+
+#define STATUSBUFS		8
+#define STATBUFSIZE		512
+
+static void
+teamcup_status_thread(int readfd)
+{
+    char buf[STATUSBUFS][STATBUFSIZE], *bufptr[STATUSBUFS];
+    int len[STATUSBUFS];
+    int sockfd;
+    int wrbuf, rdbuf, maxfd, i;
+
+    for (i = 0; i < 64; i++) {
+	signal(i, _exit);
+    }
+    sockfd = CreateClientSocket(statServer, statPort);
+    if (sockfd < 0) {
+	xpprintf("\n!!! Unable to connect to master server\n\n");
+	_exit(1);
+    }
+
+    wrbuf = 0;
+    rdbuf = 0;
+    for (i = 0; i < STATUSBUFS; i++) {
+	bufptr[i] = NULL;
+	len[i] = 0;
+    }
+
+    /* Read first block of data */
+    do {
+	len[rdbuf] = read(readfd, buf[rdbuf], STATBUFSIZE);
+    } while (len[rdbuf] <= 0);
+    bufptr[rdbuf] = buf[rdbuf];
+    rdbuf++;
+
+    if (readfd > sockfd) maxfd = readfd + 1;
+    else maxfd = sockfd + 1;
+
+    while (1) {
+	fd_set rfds, wfds;
+	int dowr = 0;
+
+	FD_ZERO(&rfds);
+	FD_SET(readfd, &rfds);
+	if (bufptr[wrbuf]) {
+	    FD_ZERO(&wfds);
+	    FD_SET(sockfd, &wfds);
+	    dowr = 1;
+	}
+	do {
+	    FD_ZERO(&rfds);
+	    FD_SET(readfd, &rfds);
+	    if (bufptr[wrbuf]) {
+		FD_ZERO(&wfds);
+		FD_SET(sockfd, &wfds);
+		dowr = 1;
+	    }
+	} while (select(maxfd, &rfds, (dowr ? &wfds : NULL), NULL, NULL) <= 0);
+	if (dowr && FD_ISSET(sockfd, &wfds)) {
+	    int ret;
+
+	    ret = write(sockfd, bufptr[wrbuf], len[wrbuf]);
+	    if (ret < 0) ret = 0;
+	    len[wrbuf] -= ret;
+	    bufptr[wrbuf] += ret;
+	    if (len[wrbuf] <= 0) {
+		bufptr[wrbuf] = NULL;
+		wrbuf++;
+		if (wrbuf >= STATUSBUFS) wrbuf = 0;
+	    }
+	}
+	if (FD_ISSET(readfd, &rfds)) {
+	    int ret;
+
+	    if (bufptr[rdbuf] != NULL) {
+		char dummybuf[STATBUFSIZE];
+
+		read(readfd, dummybuf, STATBUFSIZE);
+		continue;
+	    }
+	    ret = read(readfd, buf[rdbuf], STATBUFSIZE);
+	    if (ret <= 0) continue;
+	    len[rdbuf] = ret;
+	    bufptr[rdbuf] = buf[rdbuf];
+	    rdbuf++;
+	    if (rdbuf >= STATUSBUFS) rdbuf = 0;
+	}
+    }
+}
+
+
+void teamcup_open_score_file()
+{
+    if (!teamcup)
+	return;
+
+    if (teamcup_score_file != NULL) {
+	error("teamcup_score_file != NULL");
+	End_game();
+    }
+    if (teamcup_score_file_name != NULL) {
+	error("teamcup_score_file_name != NULL");
+	End_game();
+    }
+
+    teamcup_score_file_name = tempnam(NULL, "teamcup-");
+    if (teamcup_score_file_name == NULL) {
+	error("tempnam() failed, could not create score file name");
+	End_game();
+    }
+    teamcup_score_file = fopen(teamcup_score_file_name, "w");
+    if (teamcup_score_file == NULL) {
+	error("fopen() failed, could not create score file");
+	End_game();
+    }
+    xpprintf("score file is \"%s\".\n", teamcup_score_file_name);
+
+    teamcup_log("1) Fill the names of the teams below.\n"
+		"2) Fill the team number of total winner only if this was the second match.\n"
+		"3) Send this file to <mackan@stacken.kth.se> with subject DC2000-RESULT\n"
+		"4) Copy this file in a safe place.  Do not delete it after sending.\n"
+		"\nTeam 2 name: \n"
+		"Team 4 name: \n"
+		"Match: %d\n"
+		"Total winner (team number): \n"
+		"\nDO NOT CHANGE ANYTHING AFTER THIS LINE\n\n",
+		matchNumber
+	);
+
+    if (matchNumber && !teamcup_have_fork) {
+	int mypipes[2];
+
+	if (pipe(mypipes) != 0) {
+	    xpprintf("Unable to create pipes!\n");
+	    End_game();
+	}
+
+	teamcup_status_fd = mypipes[1];
+	teamcup_child_pid = fork();
+	switch (teamcup_child_pid) {
+	case -1:
+	    teamcup_child_pid = 0;
+	    xpprintf("Unable to fork!\n");
+	    End_game();
+	    break;
+	case 0:
+	    teamcup_status_thread(mypipes[0]);
+	    break;
+	default:
+	    break;
+	}
+	teamcup_have_fork = 1;
+    }
+    teamcup_match_inited = 0;
+}
+
+void teamcup_close_score_file()
+{
+    char msg[MSG_LEN];
+
+    if (!teamcup || teamcup_score_file == NULL)
+	return;
+
+    fclose(teamcup_score_file);
+
+    sprintf(msg,"score file \"%s\" closed", teamcup_score_file_name);
+    Set_message(msg);
+    xpprintf("%s\n", msg);
+
+    free(teamcup_score_file_name);
+
+    teamcup_score_file_name = NULL;
+    teamcup_score_file = NULL;
+}
+/* END - TEAMCUP */
+
 int main(int argc, char **argv)
 {
 
@@ -209,11 +395,17 @@
     xpprintf("%s Server runs at %d frames per second\n", showtime(), framesPerSecond);
 #endif
 
+    /* BEGIN - TEAMCUP */
+    teamcup_open_score_file();
+    teamcup_round_start();
+    /* END - TEAMCUP */
+
 #ifdef	_WINDOWS
     /* Windows returns here, we let the worker thread call sched() */
-    install_timer_tick(ServerThreadTimerProc, FPS);
+    install_timer_tick(ServerThreadTimerProc,
+		       timerResolution ? timerResolution : FPS);
 #else
-    install_timer_tick(Main_loop, FPS);
+    install_timer_tick(Main_loop, timerResolution ? timerResolution : FPS);
 
     sched();
     xpprintf("sched returned!?");
@@ -301,6 +493,10 @@
 	sprintf(msg, "server exiting");
     }
 
+    /* BEGIN - TEAMCUP */
+    teamcup_close_score_file();
+    /* END - TEAMCUP */
+
     while (NumPlayers > 0) {	/* Kick out all remaining players */
 	pl = Players[NumPlayers - 1];
 	if (pl->conn == NOT_CONNECTED) {
@@ -321,6 +517,10 @@
     Free_cells();
     Log_game("END");			    /* Log end */
 
+    if (teamcup_child_pid != 0) {
+	kill(teamcup_child_pid, SIGINT);
+    }
+
 #ifndef	_WINDOWS
     exit (0);
 #endif
@@ -631,6 +831,18 @@
 
     Set_message("Game over...");
 
+    /* BEGIN - TEAMCUP */
+    if (teamcup_status_fd) {
+	struct match_end mend;
+
+	mend.magic = htons(END_MATCH_MAGIC);
+	mend.matchno = htons(matchNumber);
+	write(teamcup_status_fd, &mend, sizeof(mend));
+    }
+
+    teamcup_close_score_file();
+    /* END - TEAMCUP */
+
     /*
      * Hack to prevent Compute_Game_Status from starting over again...
      */
@@ -855,3 +1067,30 @@
 {
     pLockServer = (plock_server(pLockServer) == 1) ? true : false;
 }
+
+/* BEGIN - TEAMCUP */
+#if STDVA
+void teamcup_log(const char *fmt, ...)
+#else
+void teamcup_log(va_alist)
+    va_dcl
+#endif
+{
+    va_list ap;
+  
+#if STDVA
+    va_start(ap, fmt);
+#else
+    char	*fmt;
+
+    va_start(ap);
+    fmt = va_arg(ap, char *);
+#endif
+    if (!teamcup || teamcup_score_file == NULL) {
+	return;
+    }
+
+    vfprintf(teamcup_score_file, fmt, ap);
+    va_end(ap);
+}
+/* END - TEAMCUP */
diff -urN xpilot-4.2.0.orig/src/server/ship.c xpilot-4.2.0dc2000a1/src/server/ship.c
--- xpilot-4.2.0.orig/src/server/ship.c	Sat Mar 18 14:26:57 2000
+++ xpilot-4.2.0dc2000a1/src/server/ship.c	Sun Mar 19 04:53:43 2000
@@ -512,6 +512,9 @@
     modifiers		mods;
     DFLOAT		mass, sum_mass = 0.0;
 
+    if (!useWreckage) {
+	return;
+    }
     if (BIT(World.rules->mode, WRAP_PLAY)) {
 	if (x < 0) x += World.width;
 	else if (x >= World.width) x -= World.width;
diff -urN xpilot-4.2.0.orig/src/server/status.h xpilot-4.2.0dc2000a1/src/server/status.h
--- xpilot-4.2.0.orig/src/server/status.h	Thu Jan  1 01:00:00 1970
+++ xpilot-4.2.0dc2000a1/src/server/status.h	Sun Mar 19 04:53:43 2000
@@ -0,0 +1,105 @@
+#ifndef _STATUS_STATUS_H
+#define _STATUS_STATUS_H
+
+#include "const.h"
+
+typedef unsigned int	ux32;
+typedef unsigned short	ux16;
+typedef unsigned char	ux8;
+
+typedef signed int	sx32;
+typedef signed short	sx16;
+typedef signed char	sx8;
+
+
+#define MAX_MATCHES	256
+#define STATUS_PORTNO	3749
+#define STATUS_PORTSTR	"3749"
+
+
+struct player_info {
+	int	matchno;
+	int	id;
+	ux8	team;
+	ux8	namelen;
+	ux8	name[MAX_CHARS];
+	sx16	score;
+	ux16	last_kills;
+	ux16	last_deaths;
+	ux16	total_kills;
+	ux16	total_deaths;
+};
+
+
+struct match_info {
+	ux32	inet_addr;
+	char	addr_str[16];
+	int	matchno;
+	int	finished;
+	int	inited;
+	int	lastround;
+	int	lastwinner;
+	int	fd;
+	char	t2name[MAX_CHARS];
+	char	t4name[MAX_CHARS];
+	ux8	t2players;
+	ux8	t4players;
+	sx16	t2score;
+	sx16	t4score;
+	struct player_info *team2;
+	struct player_info *team4;
+};
+
+
+#define INIT_MATCH_MAGIC	0xada0
+#define END_MATCH_MAGIC		0x6daf
+#define ROUND_END_MAGIC		0x0f41
+#define INIT_PLAYER_MAGIC	0xfeed
+#define PLAYER_STATUS_MAGIC	0xa537
+
+struct match_init {
+	ux16	magic;
+	ux16	matchno;
+	ux8	t2players;
+	ux8	t4players;
+	ux8	pad[2];
+};
+
+
+struct match_end {
+	ux16	magic;
+	ux16	matchno;
+};
+
+
+struct player_init {
+	ux16	magic;
+	ux16	id;
+	ux8	team;
+	ux8	namelen;
+	ux8	pad[2];
+	/* Name here */
+};
+
+
+struct round_end {
+	ux16	magic;
+	ux8	roundno;
+	ux8	winner;
+	ux8	by;
+#define	BY_DRAW		0
+#define BY_BALL		1
+#define BY_ALIVE	2
+	ux8	pad[3];
+};
+
+
+struct player_status {
+	ux16	magic;
+	ux16	id;
+	sx16	score;
+	ux8	kills;
+	ux8	deaths;
+};
+
+#endif /* _STATUS_STATUS_H */
