diff -burN xpilot-4.U.3/Local.config xpilot-4.U.4a3/Local.config
--- xpilot-4.U.3/Local.config	Mon Aug 30 00:24:56 1999
+++ xpilot-4.U.4a3/Local.config	Mon Aug 30 00:22:09 1999
@@ -173,10 +173,10 @@
  */
       VERSION_MAJOR = 4
       VERSION_MINOR = U
- VERSION_PATCHLEVEL = 3
+ VERSION_PATCHLEVEL = 4
     VERSION_WINDOWS = 13
-     VERSION_STATUS =
-        RELEASEDATE = Mar 21th, 1999
+     VERSION_STATUS = alpha3
+        RELEASEDATE = May 30th, 1999
 
 
 /*
diff -burN xpilot-4.U.3/src/client/client.c xpilot-4.U.4a3/src/client/client.c
--- xpilot-4.U.3/src/client/client.c	Wed Sep 16 20:35:40 1998
+++ xpilot-4.U.4a3/src/client/client.c	Mon Aug 30 00:22:09 1999
@@ -56,6 +56,8 @@
 
 #define MAX_CHECKPOINT	26
 
+char *fast_msgs[N_MSGS];
+
 int			scoresChanged = 0;
 int			RadarHeight = 0;
 
diff -burN xpilot-4.U.3/src/client/client.h xpilot-4.U.4a3/src/client/client.h
--- xpilot-4.U.3/src/client/client.h	Wed Sep 16 20:35:40 1998
+++ xpilot-4.U.4a3/src/client/client.h	Mon Aug 30 00:22:09 1999
@@ -252,6 +252,8 @@
 extern int 	maxVolume;		/* maximum volume (in percent) */
 #endif /* SOUND */
 
+extern int	snoopEyesId;		/* client's view of game */
+
 int Fuel_by_pos(int x, int y);
 int Target_alive(int x, int y, int *damage);
 int Target_by_index(int ind, int *xp, int *yp, int *dead_time, int *damage);
diff -burN xpilot-4.U.3/src/client/colors.c xpilot-4.U.4a3/src/client/colors.c
--- xpilot-4.U.3/src/client/colors.c	Fri Oct  2 20:39:21 1998
+++ xpilot-4.U.4a3/src/client/colors.c	Mon Aug 30 00:22:09 1999
@@ -502,15 +502,18 @@
      * planes at once.
      */
     for (p=0; p<2; p++) {
+	int num=0;
+
 	dpl_1[p] = dpl_2[p] = 0;
 
 	for (i=0; i<32; i++) {
 	    if (!((1<<i)&dbuf_state->masks[p])) {
-		if (dpl_1[p]) {
-		    dpl_2[p] |= 1<<i;
+	        num++;
+		if (num==1 || num==3 ) {
+		    dpl_1[p] |= 1<<i;   /* planes with moving radar objects */
 		}
 		else {
-		    dpl_1[p] |= 1<<i;
+		    dpl_2[p] |= 1<<i;   /* constant map part of radar */
 		}
 	    }
 	}
diff -burN xpilot-4.U.3/src/client/default.c xpilot-4.U.4a3/src/client/default.c
--- xpilot-4.U.3/src/client/default.c	Tue Oct  6 16:52:19 1998
+++ xpilot-4.U.4a3/src/client/default.c	Mon Aug 30 00:22:09 1999
@@ -71,6 +71,10 @@
 
 char default_version[] = VERSION;
 
+extern char *fast_msgs[];
+char fast_temp_buf[7];   /* can handle up to 999 fast msgs */
+char *fast_temp_buf_big;
+
 #ifndef	lint
 static char sourceid[] =
     "@(#)$Id: default.c,v 4.7 1998/10/06 14:52:19 bert Exp $";
@@ -771,7 +775,7 @@
     {
 	"maxColors",
 	NULL,
-	"4",
+	"8",
 	KEY_DUMMY,
 	"The number of colors to use.  Valid values are 4, 8 and 16.\n"
     },
@@ -979,6 +983,13 @@
 	"Valid values are all even numbers smaller than maxColors.\n"
     },
     {
+        "oldTextColor",
+	NULL,
+	"4",
+	KEY_DUMMY,
+	"Which color number to use for drawing old text strings.\n"
+    },
+    {
 	"outlineDecor",
 	NULL,
 	"No",
@@ -1658,7 +1669,286 @@
 	"Specifies the device name of the frame buffer.\n"
     },
 #endif    
-
+    {
+	"keySendMsg1",
+	NULL,
+	"F1",
+	KEY_MSG_1,
+	"Sends the talkmessage stored in msg1.\n"
+    },
+    {
+	"msg1",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 1.\n"
+    },
+    {
+	"keySendMsg2",
+	NULL,
+	"F2",
+	KEY_MSG_2,
+	"Sends the talkmessage stored in msg2.\n"
+    },
+    {
+	"msg2",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 2.\n"
+    },
+    {
+	"keySendMsg3",
+	NULL,
+	"F3",
+	KEY_MSG_3,
+	"Sends the talkmessage stored in msg3.\n"
+    },
+    {
+	"msg3",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 3.\n"
+    },
+    {
+	"keySendMsg4",
+	NULL,
+	"F4",
+	KEY_MSG_4,
+	"Sends the talkmessage stored in msg4.\n"
+    },
+    {
+	"msg4",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 4.\n"
+    },
+    {
+	"keySendMsg5",
+	NULL,
+	"F5",
+	KEY_MSG_5,
+	"Sends the talkmessage stored in msg5.\n"
+    },
+    {
+	"msg5",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 5.\n"
+    },
+    {
+	"keySendMsg6",
+	NULL,
+	"F6",
+	KEY_MSG_6,
+	"Sends the talkmessage stored in msg6.\n"
+    },
+    {
+	"msg6",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 6.\n"
+    },
+    {
+	"keySendMsg7",
+	NULL,
+	"F7",
+	KEY_MSG_7,
+	"Sends the talkmessage stored in msg7.\n"
+    },
+    {
+	"msg7",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 7.\n"
+    },
+    {
+	"keySendMsg8",
+	NULL,
+	"F8",
+	KEY_MSG_8,
+	"Sends the talkmessage stored in msg8.\n"
+    },
+    {
+	"msg8",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 8.\n"
+    },
+    {
+	"keySendMsg9",
+	NULL,
+	"F9",
+	KEY_MSG_9,
+	"Sends the talkmessage stored in msg9.\n"
+    },
+    {
+	"msg9",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 9.\n"
+    },
+    {
+	"keySendMsg10",
+	NULL,
+	"F10",
+	KEY_MSG_10,
+	"Sends the talkmessage stored in msg10.\n"
+    },
+    {
+	"msg10",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 10.\n"
+    },
+    {
+	"keySendMsg11",
+	NULL,
+	"F11",
+	KEY_MSG_11,
+	"Sends the talkmessage stored in msg11.\n"
+    },
+    {
+	"msg11",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 11.\n"
+    },
+    {
+	"keySendMsg12",
+	NULL,
+	"F12",
+	KEY_MSG_12,
+	"Sends the talkmessage stored in msg12.\n"
+    },
+    {
+	"msg12",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 12.\n"
+    },
+    {
+	"keySendMsg13",
+	NULL,
+	"",
+	KEY_MSG_13,
+	"Sends the talkmessage stored in msg13.\n"
+    },
+    {
+	"msg13",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 13.\n"
+    },
+    {
+	"keySendMsg14",
+	NULL,
+	"",
+	KEY_MSG_14,
+	"Sends the talkmessage stored in msg14.\n"
+    },
+    {
+	"msg14",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 14.\n"
+    },
+    {
+	"keySendMsg15",
+	NULL,
+	"",
+	KEY_MSG_15,
+	"Sends the talkmessage stored in msg15.\n"
+    },
+    {
+	"msg15",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 15.\n"
+    },
+    {
+	"keySendMsg16",
+	NULL,
+	"",
+	KEY_MSG_16,
+	"Sends the talkmessage stored in msg16.\n"
+    },
+    {
+	"msg16",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 16.\n"
+    },
+    {
+	"keySendMsg17",
+	NULL,
+	"",
+	KEY_MSG_17,
+	"Sends the talkmessage stored in msg17.\n"
+    },
+    {
+	"msg17",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 17.\n"
+    },
+    {
+	"keySendMsg18",
+	NULL,
+	"",
+	KEY_MSG_18,
+	"Sends the talkmessage stored in msg18.\n"
+    },
+    {
+	"msg18",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 18.\n"
+    },
+    {
+	"keySendMsg19",
+	NULL,
+	"",
+	KEY_MSG_19,
+	"Sends the talkmessage stored in msg19.\n"
+    },
+    {
+	"msg19",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 19.\n"
+    },
+    {
+	"keySendMsg20",
+	NULL,
+	"",
+	KEY_MSG_20,
+	"Sends the talkmessage stored in msg20.\n"
+    },
+    {
+	"msg20",
+	NULL,
+	"",
+	KEY_DUMMY,
+	"Talkmessage 20.\n"
+    },
 };
 
 
@@ -2271,6 +2561,20 @@
 
 #endif	/* _WINDOWS */
 
+    if ((fast_temp_buf_big = (char *)malloc(FAST_MSG_SIZE)) != NULL)
+    {
+        for (i = 0; i < N_MSGS; ++i)
+        {
+            sprintf (fast_temp_buf, "msg%d", i + 1);
+            Get_resource(rDB, fast_temp_buf, fast_temp_buf_big, FAST_MSG_SIZE);
+            fast_msgs[i] = strdup (fast_temp_buf_big);
+        }
+        free (fast_temp_buf_big);
+    }
+    else
+      for (i = 0; i < N_MSGS; ++i)
+        fast_msgs[i] = NULL;
+
     Get_bool_resource(rDB, "ignoreWindowManager", &ignoreWindowManager);
 
     Get_resource(rDB, "name", nickName, MAX_NAME_LEN);
@@ -2433,6 +2737,7 @@
     Get_int_resource(rDB, "decorColor", &decorColor);
     Get_int_resource(rDB, "decorRadarColor", &decorRadarColor);
     Get_int_resource(rDB, "targetRadarColor", &targetRadarColor);
+    Get_int_resource(rDB, "oldTextColor", &oldTextColor);
     Get_resource(rDB, "sparkColors", sparkColors, MSG_LEN);
 
     instruments = 0;
diff -burN xpilot-4.U.3/src/client/netclient.c xpilot-4.U.4a3/src/client/netclient.c
--- xpilot-4.U.3/src/client/netclient.c	Sun Aug 30 18:36:50 1998
+++ xpilot-4.U.4a3/src/client/netclient.c	Mon Aug 30 00:22:09 1999
@@ -1486,7 +1486,8 @@
     if (debris_colors > num_spark_colors) {
 	debris_colors = num_spark_colors;
     }
-    if (view_width != draw_width || view_height != draw_height) {
+    if (view_width != (int)(draw_width*scaleFactor) ||
+	view_height != (int)(draw_height*scaleFactor)) {
 	Send_display();
     }
     Game_over_action(stat);
@@ -2408,6 +2409,336 @@
     return 0;
 }
 
+#define TEAM_PLAY               (1<<8)  /* defined in rules.h */
+#define LIMITED_LIVES           (1<<3)  /* defined in rules.h */
+#define MSG_PARSED_FIELD_LEN      20
+
+/* Returns a pointer to the first character after the fields */
+char *Fields_info (char *buf, int *n_fields)
+{
+    int  end_found = 0, level = 0;
+    
+    *n_fields = 0;
+    while (!end_found)
+    {
+	switch (*buf)
+	{
+	case START_DELIMITER:
+	    if (level++ == 0)
+		(*n_fields)++;
+	    break;
+	case MIDDLE_DELIMITER:
+	    if (level == 1)
+		(*n_fields)++;
+	    break;
+	case END_DELIMITER:
+	    level--;
+	    if (level == 0)
+		end_found = 1;
+	    else if (level < 0)
+		return NULL;
+	    break;
+	case '\0':
+	    return NULL;
+	    break;
+	default:
+	    break;
+	}
+	buf++;
+    }
+    return buf;
+}
+
+/* Returns a string pointer to the wanted_field 
+ * This pointer must be freed after using it
+ */
+char *Field_get (char *buf, int wanted_field)
+{
+    int  finished = 0, level = 0, field = 0, len;
+    char *field_ptr, *start_ptr = NULL, *end_ptr = NULL;
+    
+    while (!finished)
+    {
+	switch (*buf)
+	{
+	case START_DELIMITER:
+	    if (level == 0)
+	    {
+		field++;
+		if (field == wanted_field)
+		    start_ptr = buf + 1;
+	    }
+	    level++;
+	    break;
+	case MIDDLE_DELIMITER:
+	    if (level == 1)
+	    {
+		field++;
+		if (field == wanted_field)
+		    start_ptr = buf + 1;
+		else if (field == wanted_field + 1)
+		{
+		    end_ptr = buf;
+		    finished = 1;
+		}
+	    }
+	    break;
+	case END_DELIMITER:
+	    level--;
+	    if (level == 0)
+	    {
+		if (field == wanted_field)
+		    end_ptr = buf;
+		finished = 1;
+	    }
+	    else if (level < 0)
+		return NULL;
+	    break;
+	case '\0':
+	    return NULL;
+	    break;
+	default:
+	    break;
+	}
+	buf++;
+	
+    }
+    len = end_ptr - start_ptr;
+    field_ptr = (char *) malloc (len + 1);
+    strncpy (field_ptr, start_ptr, len);
+    field_ptr[len] = '\0';
+    return field_ptr;
+}
+
+int Net_talk_parsed(char *str)
+{
+    /* Comment: sizeof talk_str === MAX_CHARS */
+    if (str == NULL)
+	return 1;
+    
+    if (Parse (talk_str, str, 0L, MAX_CHARS) > 0)
+    {
+	talk_pending = ++talk_sequence_num;
+	talk_last_send = last_loops - TALK_RETRY;
+    }
+    return 0;
+}
+
+int Parse(char *outbuf, char *inbuf, long pos, long max)
+{
+    FILE *fp;
+    char c;
+    long fsize;
+    int i, n_fields;
+    char *tmpptr, *tmpptr1, *tmpptr2, *tmpptr3, *nextpos, *filename;
+    other_t *player=NULL;
+
+    
+    while ((c = *inbuf++) != '\0')
+    {
+	if (pos >= max - 2)
+	{
+	    if (outbuf == talk_str) /* parsing to the talk buffer */
+	    {
+		outbuf[pos] = '\0';
+		talk_pending = ++talk_sequence_num;
+		if (Packet_printf(&wbuf, "%c%ld%s", PKT_TALK,
+				  talk_pending, outbuf) == -1)
+		    return -1;
+		pos = 0;
+	    }
+	    else
+		goto done;
+	}
+	if (player != NULL)
+	{
+	    switch (c)
+	    {
+	    case 'l':
+		if (BIT(Setup->mode, LIMITED_LIVES))
+		    outbuf[pos++] = player->life + '0';
+		break;
+	    case 'n':
+		tmpptr = player->name;
+		for (i = 0; tmpptr[i] != '\0' && pos < max - 2; ++i)
+		    outbuf[pos++] = tmpptr[i];
+		break;
+	    case 's':
+		if (pos < max - 1 - 6) /* short - "-16535" max no of chars */
+		    pos += sprintf (outbuf+pos, "%d", player->score);
+		break;
+	    case 't':
+		if (BIT(Setup->mode, TEAM_PLAY))
+		    outbuf[pos++] = player->team + '0';
+		break;
+	    default:
+		break;
+	    }
+	    player = NULL;
+	}
+	else
+	{
+	    switch (c)
+	    {
+	    case SPECIAL_TALK_CHAR:
+		if ((c = *inbuf++) == '\0')
+		    goto done;
+		switch (c) {
+		case '=':  /* String comparison */
+		    nextpos = Fields_info (inbuf, &n_fields);
+		    if (n_fields < 3 || n_fields > 4 || nextpos == NULL)
+			break;
+		    /* parse field 1 */
+		    if ((tmpptr = Field_get (inbuf, 1)) == NULL)
+		    {
+			printf ("Field_get (1) error!...\n");
+			break;
+		    }
+		    tmpptr1 = (char *)malloc (MSG_PARSED_FIELD_LEN);
+		    Parse (tmpptr1, tmpptr, 0, MSG_PARSED_FIELD_LEN);
+		    free (tmpptr);
+		    /* parse field 2 */
+		    if ((tmpptr = Field_get (inbuf, 2)) == NULL)
+		    {
+			printf ("Field_get (2) error!...\n");
+			break;
+		    }
+		    tmpptr2 = (char *)malloc (MSG_PARSED_FIELD_LEN);
+		    Parse (tmpptr2, tmpptr, 0, MSG_PARSED_FIELD_LEN);
+		    free (tmpptr);
+		    if (!strcmp(tmpptr1, tmpptr2))
+		    {
+			/* True */
+                        if ((tmpptr3 = Field_get (inbuf, 3)) == NULL)
+			{
+			    printf ("Field_get (3) error!...\n");
+			    free (tmpptr1);
+			    free (tmpptr2);
+			    break;
+			}
+			pos = Parse (outbuf, tmpptr3, pos, max);
+		    }
+		    else if (n_fields == 4)
+		    {
+			/* False */
+			if ((tmpptr3 = Field_get (inbuf, 4)) == NULL)
+			{
+			    printf ("Field_get (4) error!...\n");
+			    free (tmpptr1);
+			    free (tmpptr2);
+			    break;
+			}
+			pos = Parse (outbuf, tmpptr3, pos, max);
+		    }
+		    inbuf = nextpos;
+		    free (tmpptr);
+		    free (tmpptr1);
+		    free (tmpptr2);
+		    free (tmpptr3);
+		    break;
+		case 'f':
+		    nextpos = Fields_info (inbuf, &n_fields);
+		    if (n_fields != 1 || nextpos == NULL)
+			break;
+		    if ((tmpptr = Field_get (inbuf, 1)) == NULL)
+		    {
+			printf ("Field_get error!...\n");
+			break;
+		    }
+		    inbuf = nextpos;
+		    filename = (char *)malloc (MSG_FNLEN);
+		    Parse (filename, tmpptr, 0, MSG_FNLEN);
+		    free (tmpptr);
+		    if ((fp = fopen (filename, "r")) == NULL)
+		    {
+			printf ("Couldn't open file %s\n", tmpptr);
+			free (filename);
+			break;
+		    }
+		    free (filename);
+		    
+		    /* Get filesize */
+		    fseek (fp, 0L, SEEK_END);
+		    fsize = ftell (fp);
+		    rewind (fp);
+		    
+		    if ((tmpptr = (char *)malloc(fsize+1)) == NULL)
+		    {
+			fclose (fp);
+			break;
+		    }
+		    fread (tmpptr, 1, fsize, fp);
+		    tmpptr[fsize] = '\0';
+		    fclose (fp);
+		    pos = Parse (outbuf, tmpptr, pos, max);
+		    free (tmpptr);
+		    break;
+		case 'h':
+		    tmpptr = getenv ("HOME");
+		    while (*tmpptr != '\0' && pos < max - 2)
+		      outbuf[pos++] = *tmpptr++;
+		    break;
+		case 'r':
+		    nextpos = Fields_info (inbuf, &n_fields);
+		    if (n_fields <= 0 || nextpos == NULL)
+		      break;
+		    if ((tmpptr = Field_get (inbuf, rand() % n_fields + 1))
+			== NULL)
+		    {
+			printf ("Field_get error (random) \n");
+			break;
+		    }
+		    inbuf = nextpos;
+		    pos = Parse (outbuf, tmpptr, pos, max);
+		    free (tmpptr); 
+		    break;
+		case 'n':
+		    outbuf[pos] = '\0';
+		    talk_pending = ++talk_sequence_num;
+		    if (Packet_printf(&wbuf, "%c%ld%s", PKT_TALK,
+				      talk_pending, outbuf) == -1)
+		      return -1;
+		    pos = 0;
+		    break;
+		case 'l':
+                    if ( Other_by_id(snoopEyesId) == self 
+			    || Other_by_id(snoopEyesId) == NULL ){
+                        if ((player = Other_by_id(lock_id)) == NULL) {
+                          pos = 0;
+                          goto done;
+                        }
+                    } else {
+                        if ((player = Other_by_id(snoopEyesId)) == NULL) {
+                          pos = 0;
+                          goto done;
+                        }
+		    }
+                    break;
+		case 's':
+		    player = self;
+		    break;
+		case 't':
+		    if (BIT(Setup->mode, TEAM_PLAY))
+		      outbuf[pos++] = self->team + '0';
+		    break;
+			case SPECIAL_TALK_CHAR:
+		    outbuf[pos++] = c;
+		    break;
+			default:
+		    break;
+		}
+	    case '\n':
+		break;
+	    default:
+		outbuf[pos++] = c;
+		break;
+	    }
+	}
+    }
+done:
+    outbuf[pos] = '\0';
+    return pos;
+}
 
 int Send_talk(void)
 {
@@ -2433,8 +2764,6 @@
 		      draw_width, draw_height, num_spark_colors, spark_rand) == -1) {
 #else
 		      (int)(draw_width*scaleFactor), (int)(draw_height*scaleFactor), num_spark_colors, spark_rand) == -1) {
-	draw_width  = (int)(draw_width*scaleFactor);
-	draw_height = (int)(draw_height*scaleFactor);
 #endif
 	return -1;
     }
diff -burN xpilot-4.U.3/src/client/netclient.h xpilot-4.U.4a3/src/client/netclient.h
--- xpilot-4.U.3/src/client/netclient.h	Thu Apr 16 19:39:29 1998
+++ xpilot-4.U.4a3/src/client/netclient.h	Mon Aug 30 00:22:09 1999
@@ -113,5 +113,7 @@
 int Send_audio_request(int onoff);
 int Send_fps_request(int fps);
 int Receive_loseitem(void);
+int Net_talk_parsed(char *str);
+int Parse(char *outbuf, char *inbuf, long pos, long max);
 
 #endif
diff -burN xpilot-4.U.3/src/client/paint.h xpilot-4.U.4a3/src/client/paint.h
--- xpilot-4.U.3/src/client/paint.h	Thu Apr 16 19:39:31 1998
+++ xpilot-4.U.4a3/src/client/paint.h	Mon Aug 30 00:22:09 1999
@@ -182,6 +182,7 @@
 extern int	targetRadarColor;	/* Color index for targets on radar */
 extern int	decorColor;		/* Color index for decoration drawing */
 extern int	decorRadarColor;	/* Color index for decorations on radar */
+extern int      oldTextColor;           /* Color index for old text */
 extern bool	gotFocus;
 extern bool	talk_mapped;
 extern short	view_width, view_height;	/* Visible area from server */
diff -burN xpilot-4.U.3/src/client/painthud.c xpilot-4.U.4a3/src/client/painthud.c
--- xpilot-4.U.3/src/client/painthud.c	Wed Sep 16 20:35:41 1998
+++ xpilot-4.U.4a3/src/client/painthud.c	Mon Aug 30 00:22:09 1999
@@ -72,6 +72,7 @@
 
 int	hudColor;		/* Color index for HUD drawing */
 int	hudLockColor;		/* Color index for lock on HUD drawing */
+int     oldTextColor;           /* Color index for old text */
 DFLOAT	charsPerTick = 0.0;	/* Output speed of messages */
 
 message_t	*TalkMsg[MAX_MSGS], *GameMsg[MAX_MSGS];
@@ -680,7 +681,7 @@
 	if (msg->life > MSG_FLASH)
 	    XSetForeground(dpy, messageGC, colors[RED].pixel);
 	else
-	    XSetForeground(dpy, messageGC, colors[WHITE].pixel);
+	    XSetForeground(dpy, messageGC, colors[oldTextColor].pixel);
 	len = (int)(charsPerTick * (MSG_DURATION - msg->life));
 	len = MIN(msg->len, len);
 	rd.drawString(dpy, p_draw, messageGC,
diff -burN xpilot-4.U.3/src/client/paintobjects.c xpilot-4.U.4a3/src/client/paintobjects.c
--- xpilot-4.U.3/src/client/paintobjects.c	Wed Sep 16 20:35:41 1998
+++ xpilot-4.U.4a3/src/client/paintobjects.c	Mon Aug 30 00:22:09 1999
@@ -651,6 +651,7 @@
     }
 
     if (num_ship > 0) {
+	snoopEyesId = -1;
 	for (i = 0; i < num_ship; i++) {
 	    x = ship_ptr[i].x;
 	    y = ship_ptr[i].y;
@@ -665,6 +666,14 @@
 		points[cnt].y = WINSCALE(Y(y + ship->pts[cnt][dir].y));
 	    }
 	    points[cnt++] = points[0];
+
+            /*
+             * ship in the center? (svenska-hack)
+             */
+	    if ( abs(X(x)-view_width/2) <=1 && abs(Y(y)-view_height/2) <=1
+	&& Other_by_id(ship_ptr[i].id) != NULL ){
+		  snoopEyesId = ship_ptr[i].id;
+	    }
 
 	    /*
 	     * Determine if the name of the player should be drawn below
diff -burN xpilot-4.U.3/src/client/paintradar.c xpilot-4.U.4a3/src/client/paintradar.c
--- xpilot-4.U.3/src/client/paintradar.c	Wed Sep 23 21:42:43 1998
+++ xpilot-4.U.4a3/src/client/paintradar.c	Mon Aug 30 00:22:09 1999
@@ -145,7 +145,18 @@
     }
     for (i = 0; i<num_radar; i++) {
 	int s;
-	if ((s = radar_ptr[i].size) <= 0)
+
+	s = radar_ptr[i].size;
+	if (s >= 0x80) {         /* from the same team */
+	    if (maxColors == 4)
+	      XSetForeground(dpy, radarGC, colors[RED].pixel);
+	    /* RED doesn't work with color switching, */
+	    /* default maxColors changed to 8         */
+	    else
+	      XSetForeground(dpy, radarGC, colors[4].pixel);
+ 	    s-=0x80;
+	}
+	if (s == 0)
 	    s = 1;
 	x = (int)(radar_ptr[i].x * xf + 0.5) - s / 2;
 	y = RadarHeight - (int)(radar_ptr[i].y * yf + 0.5) - 1 - s / 2;
@@ -168,6 +179,7 @@
 		}
 	    }
 	}
+	XSetForeground(dpy, radarGC, colors[WHITE].pixel);
     }
     if (num_radar) {
 	RELEASE(radar_ptr, num_radar, max_radar);
diff -burN xpilot-4.U.3/src/client/xevent.c xpilot-4.U.4a3/src/client/xevent.c
--- xpilot-4.U.3/src/client/xevent.c	Tue Oct  6 16:52:19 1998
+++ xpilot-4.U.4a3/src/client/xevent.c	Mon Aug 30 00:22:10 1999
@@ -57,6 +57,8 @@
 
 char xevent_version[] = VERSION;
 
+extern char *fast_msgs[];
+
 extern setup_t		*Setup;
 
 static BITV_DECL(keyv, NUM_KEYS);
@@ -283,6 +285,9 @@
 
 static bool Key_press(keys_t key)
 {
+   if (key >= KEY_MSG_1 && key < KEY_MSG_1 + N_MSGS)
+	Net_talk_parsed (fast_msgs[key - KEY_MSG_1]);
+
     switch (key) {
     case KEY_ID_MODE:
 	showRealName = showRealName ? false : true;
diff -burN xpilot-4.U.3/src/client/xinit.c xpilot-4.U.4a3/src/client/xinit.c
--- xpilot-4.U.3/src/client/xinit.c	Fri Oct  2 20:39:22 1998
+++ xpilot-4.U.4a3/src/client/xinit.c	Mon Aug 30 00:22:10 1999
@@ -469,6 +469,8 @@
 	|| ((targetRadarColor & 1) && colorSwitch)) {
 	targetRadarColor = BLUE;
     }
+    if (oldTextColor >= maxColors || oldTextColor < 0)
+        oldTextColor = WHITE;
     if (decorColor >= maxColors || decorColor <= 0) {
 	decorColor = RED;
     }
diff -burN xpilot-4.U.3/src/client/xpilot.c xpilot-4.U.4a3/src/client/xpilot.c
--- xpilot-4.U.3/src/client/xpilot.c	Thu Apr 16 19:39:56 1998
+++ xpilot-4.U.4a3/src/client/xpilot.c	Mon Aug 30 00:22:10 1999
@@ -96,6 +96,8 @@
 char			**Argv;
 int			Argc;
 
+int			snoopEyesId = -1;
+
 static void Check_client_versions(void);
 
 
diff -burN xpilot-4.U.3/src/common/const.h xpilot-4.U.4a3/src/common/const.h
--- xpilot-4.U.3/src/common/const.h	Sat Aug 29 21:49:53 1998
+++ xpilot-4.U.4a3/src/common/const.h	Mon Aug 30 00:22:10 1999
@@ -405,4 +405,12 @@
 extern char* strdup(const char*);
 #endif
 
+#define N_MSGS 20
+#define FAST_MSG_SIZE 400
+#define MSG_FNLEN         100
+#define START_DELIMITER   '['
+#define END_DELIMITER     ']'
+#define MIDDLE_DELIMITER  '|'
+#define SPECIAL_TALK_CHAR '#'
+
 #endif
diff -burN xpilot-4.U.3/src/common/keys.h xpilot-4.U.4a3/src/common/keys.h
--- xpilot-4.U.3/src/common/keys.h	Thu Apr 16 19:40:42 1998
+++ xpilot-4.U.4a3/src/common/keys.h	Mon Aug 30 00:22:10 1999
@@ -116,6 +116,27 @@
      * retaining compatibility.  Change this at the next major cleanup.
      */
     ,
+    KEY_MSG_1,
+    KEY_MSG_2,
+    KEY_MSG_3,
+    KEY_MSG_4,
+    KEY_MSG_5,
+    KEY_MSG_6,
+    KEY_MSG_7,
+    KEY_MSG_8,
+    KEY_MSG_9,
+    KEY_MSG_10,
+    KEY_MSG_11,
+    KEY_MSG_12,
+    KEY_MSG_13,
+    KEY_MSG_14,
+    KEY_MSG_15,
+    KEY_MSG_16,
+    KEY_MSG_17,
+    KEY_MSG_18,
+    KEY_MSG_19,
+    KEY_MSG_20,
+
     KEY_ID_MODE,
     KEY_TOGGLE_OWNED_ITEMS,
     KEY_TOGGLE_MESSAGES,
diff -burN xpilot-4.U.3/src/common/pack.h xpilot-4.U.4a3/src/common/pack.h
--- xpilot-4.U.3/src/common/pack.h	Sun Aug 30 17:40:54 1998
+++ xpilot-4.U.4a3/src/common/pack.h	Mon Aug 30 00:22:10 1999
@@ -90,7 +90,7 @@
  * 3.8.0.0: new items (deflector, hyperjump, phasing), keyboardsize and rounddelay.
  * 4.1.0.0: new item (mirror).
  */
-#define	MAGIC		0x4100F4ED
+#define	MAGIC		0x4101F4ED
 
 #define MAGIC2VERSION(M)	(((M) >> 16) & 0xFFFF)
 #define VERSION2MAGIC(V)	((((V) & 0xFFFF) << 16) | (MAGIC & 0xFFFF))
diff -burN xpilot-4.U.3/src/common/version.h xpilot-4.U.4a3/src/common/version.h
--- xpilot-4.U.3/src/common/version.h	Mon Aug 30 00:24:56 1999
+++ xpilot-4.U.4a3/src/common/version.h	Mon Aug 30 00:22:10 1999
@@ -28,15 +28,15 @@
 #if defined(__hpux)
 #   pragma COPYRIGHT_DATE	"1991-1998"
 #   pragma COPYRIGHT		"Bjørn Stabell, Ken Ronny Schouten, Bert Gijsbers & Dick Balaska"
-#   pragma VERSIONID		"XPilot 4.U.3"
+#   pragma VERSIONID		"XPilot 4.U.4alpha3"
 #endif
 
-#define VERSION			"4.U.3"
+#define VERSION			"4.U.4alpha3"
 #ifdef	_WINDOWS
-#define	TITLE			"4.U.3-NT13"
+#define	TITLE			"4.U.4alpha3-NT13"
 #define	VERSION_WINDOWS	"13"
 #else
-#define TITLE			"XPilot 4.U.3"
+#define TITLE			"XPilot 4.U.4alpha3"
 #endif
 #define AUTHORS			"Bjørn Stabell, Ken Ronny Schouten, Bert Gijsbers & Dick Balaska"
 #define COPYRIGHT		"Copyright © 1991-1998 by Bjørn Stabell, Ken Ronny Schouten, Bert Gijsbers & Dick Balaska"
diff -burN xpilot-4.U.3/src/replay/xp-replay.c xpilot-4.U.4a3/src/replay/xp-replay.c
--- xpilot-4.U.3/src/replay/xp-replay.c	Sat Apr 18 14:53:08 1998
+++ xpilot-4.U.4a3/src/replay/xp-replay.c	Mon Aug 30 00:22:10 1999
@@ -88,6 +88,7 @@
 #include "items/itemTractorBeam.xbm"
 #include "items/itemAutopilot.xbm"
 #include "items/itemEmergencyShield.xbm"
+#include "items/itemMirror.xbm"
 
 #include "tools/eject.xbm"
 #include "tools/fastf.xbm"
@@ -1386,7 +1387,8 @@
     itemEmergencyShield_bits,
     itemDeflector_bits,
     itemHyperJump_bits,
-    itemPhasingDevice_bits
+    itemPhasingDevice_bits,
+    itemMirror_bits
 };
 
 static XFontStruct *loadQueryFont(const char *fontName, GC gc)
diff -burN xpilot-4.U.3/src/server/cmdline.c xpilot-4.U.4a3/src/server/cmdline.c
--- xpilot-4.U.3/src/server/cmdline.c	Mon Aug 30 00:24:57 1999
+++ xpilot-4.U.4a3/src/server/cmdline.c	Mon Aug 30 00:22:10 1999
@@ -232,12 +232,13 @@
 
 bool		pLockServer;		/* Is server swappable out of memory?  */
 
-int             FPSMultiplier;          /* Slow everything by this factor */
-bool            useWreckage;            /* Create wreckage or not? */
-bool            ignore20MaxFPS;         /* Ignore client maxFPS request if it is 20 */
+int             FPSMultiplier;          /* slow everything by this factor */
+bool            useWreckage;            /* create wreckage or not? */
+bool            ignore20MaxFPS;         /* ignore client maxFPS request if it is 20 */
 int             timerResolution;        /* OS timer resolution (times/s) */
 char            *password;              /* password for operator status */
 int             numberOfRounds;         /* how many rounds to play */
+int             playerLimit;            /* allow less players than bases */
 
 const char default_map[] = DEFAULT_MAP;
 
@@ -2332,6 +2333,15 @@
 	valInt,
 	tuner_dummy,
 	"The number of rounds to play. If 0, unlimited.\n"
+    },
+    {
+        "playerLimit",
+	"playerLimit",
+	"0",
+	&playerLimit,
+	valInt,
+	tuner_dummy,
+	"Allow only (number of bases)-playerLimit players to enter.\n"
     }
 };
 
diff -burN xpilot-4.U.3/src/server/collision.c xpilot-4.U.4a3/src/server/collision.c
--- xpilot-4.U.3/src/server/collision.c	Mon Aug 30 00:24:57 1999
+++ xpilot-4.U.4a3/src/server/collision.c	Mon Aug 30 00:22:10 1999
@@ -1594,7 +1594,7 @@
 		obj->vel.y = (y - CLICK_TO_FLOAT(obj->pos.cy))*FPSMultiplier;
 		/* changed from = x - obj->pos.x to make lasers disappear
 		   less frequently when wrapping. There's still a small
-		   change of it happening though. Didn't bother to really
+		   chance of it happening though. Didn't bother to really
 		   fix the code to completely prevent that. */
 		Move_object(objnum);
 		if (obj->life == 0) {
diff -burN xpilot-4.U.3/src/server/contact.c xpilot-4.U.4a3/src/server/contact.c
--- xpilot-4.U.3/src/server/contact.c	Sat Aug 29 21:49:54 1998
+++ xpilot-4.U.4a3/src/server/contact.c	Mon Aug 30 00:22:10 1999
@@ -736,7 +736,7 @@
     /*
      * Is the game full?
      */
-    if (NumPlayers - NumPseudoPlayers + login_in_progress + NumQueuedPlayers >= World.NumBases) {
+    if (NumPlayers - NumPseudoPlayers + login_in_progress + NumQueuedPlayers >= World.NumBases - playerLimit) {
 	if (NumQueuedPlayers > 0) {
 	    return E_GAME_FULL;
 	}
@@ -745,7 +745,7 @@
 		return E_GAME_FULL;
 	    }
 	}
-	if (NumPlayers - NumPseudoPlayers + login_in_progress + NumQueuedPlayers >= World.NumBases) {
+	if (NumPlayers - NumPseudoPlayers + login_in_progress + NumQueuedPlayers >= World.NumBases - playerLimit) {
 	    return E_GAME_FULL;
 	}
     }
@@ -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)
 {
@@ -902,11 +902,11 @@
 	if (last_unqueued_loops + 2 + (FPS >> 2) < main_loops) {
 
 	    /* is there a homebase available? */
-	    if (NumPlayers - NumPseudoPlayers + login_in_progress < World.NumBases
+	    if (NumPlayers - NumPseudoPlayers + login_in_progress < World.NumBases - playerLimit
 		|| (Kick_robot_players(TEAM_NOT_SET)
-		    && NumPlayers - NumPseudoPlayers + login_in_progress < World.NumBases)
+		    && NumPlayers - NumPseudoPlayers + login_in_progress < World.NumBases - playerLimit)
 		|| (Kick_paused_players(TEAM_NOT_SET)
-		    && NumPlayers - NumPseudoPlayers + login_in_progress < World.NumBases)) {
+		    && NumPlayers - NumPseudoPlayers + login_in_progress < World.NumBases - playerLimit)) {
 
 		/* find a team for this fellow. */
 		if (BIT(World.rules->mode, TEAM_PLAY)) {
diff -burN xpilot-4.U.3/src/server/event.c xpilot-4.U.4a3/src/server/event.c
--- xpilot-4.U.3/src/server/event.c	Mon Aug 30 00:24:57 1999
+++ xpilot-4.U.4a3/src/server/event.c	Mon Aug 30 00:22:10 1999
@@ -193,7 +193,7 @@
 	if (i == lock
 	    || (BIT(Players[i]->status, PLAYING|PAUSE|GAME_OVER) != PLAYING)
 	    || !Player_lock_allowed(ind, i)
-	    || lockOtherTeam && TEAM(ind,i)) {
+	    || TEAM(ind,i)) {
 	    continue;
 	}
 	l = Wrap_length(Players[i]->pos.x - pl->pos.x,
@@ -297,7 +297,8 @@
 	}
 	pressed = BITV_ISSET(pl->last_keyv, key) != 0;
 	BITV_TOGGLE(pl->prev_keyv, key);
-	pl->frame_last_busy = frame_loops;
+	if (key != KEY_SHIELD)               /* Client might automatically */
+	  pl->frame_last_busy = frame_loops; /* keep shields up */
 
 	/*
 	 * Allow these functions before a round has started.
@@ -480,7 +481,7 @@
 		    if (i == j)
 			break;
 		} while (i == ind
-			 || BIT(Players[i]->status, GAME_OVER)
+			 || BIT(Players[i]->status, GAME_OVER|PAUSE)
 			 || !Player_lock_allowed(ind, i));
 		if (i == ind) {
 		    CLR_BIT(pl->lock.tagged, LOCK_PLAYER);
@@ -717,7 +718,8 @@
 			*l = pl->lock.pl_id;
 		    }
 		} else {
-		    if (Player_lock_allowed(ind, GetInd[*l])) {
+		    if ((*l!=NOT_CONNECTED)
+			    && Player_lock_allowed(ind, GetInd[*l])) {
 			pl->lock.pl_id = *l;
 			SET_BIT(pl->lock.tagged, LOCK_PLAYER);
 		    }
diff -burN xpilot-4.U.3/src/server/frame.c xpilot-4.U.4a3/src/server/frame.c
--- xpilot-4.U.3/src/server/frame.c	Mon Aug 30 00:24:57 1999
+++ xpilot-4.U.4a3/src/server/frame.c	Mon Aug 30 00:22:10 1999
@@ -819,7 +819,7 @@
 		&& frame_loops % 5 >= 3) {
 		continue;
 	    }
-	    Send_radar(conn, (int)x, (int)y, 3);
+	    Send_radar(conn, (int)x, (int)y, TEAM(i,ind) ? 3+0x80:3);
 	}
     }
 }
diff -burN xpilot-4.U.3/src/server/global.h xpilot-4.U.4a3/src/server/global.h
--- xpilot-4.U.3/src/server/global.h	Mon Aug 30 00:24:57 1999
+++ xpilot-4.U.4a3/src/server/global.h	Mon Aug 30 00:22:11 1999
@@ -251,6 +251,7 @@
 extern int              timerResolution;
 extern char             *password;
 extern int              numberOfRounds;
+extern int              playerLimit;
 #endif
 
 #endif /* GLOBAL_H */
diff -burN xpilot-4.U.3/src/server/netserver.c xpilot-4.U.4a3/src/server/netserver.c
--- xpilot-4.U.3/src/server/netserver.c	Mon Aug 30 00:24:57 1999
+++ xpilot-4.U.4a3/src/server/netserver.c	Mon Aug 30 00:22:11 1999
@@ -1776,6 +1776,8 @@
 {
     connection_t	*connp = &Conn[ind];
 
+    if (connp->version < 0x4101 && size >= 0x80)
+      size-=0x80;      /* friends and enemies look the same to old clients */
     return Packet_printf(&connp->w, "%c%hd%hd%c", PKT_RADAR, x, y, size);
 }
 
@@ -2664,9 +2666,27 @@
 
 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, NO_CMD
+  PASSWORD_CMD, LOCK_CMD, SET_CMD, PAUSE_CMD, SHOW_CMD, 
+  ADVANCE_CMD, NO_CMD
 };
 
 typedef struct {
@@ -2692,7 +2712,7 @@
   },
   {
     "version",
-    "Prints server version.",
+    "Print server version.",
     0,
     VERSION_CMD
   },
@@ -2730,9 +2750,22 @@
   },
   {
     "kick",
-    "/kick <player name or ID number>. Removes player from game. (operator)",
+    "/kick <player name or ID number>. Remove a player from game. (operator)",
     1,
     KICK_CMD
+  },
+  {
+    "show",
+    "/show queue. Show the names of players waiting to enter.",
+    0,
+    SHOW_CMD
+  },
+  {
+    "advance",
+    "/advance <name of player in the queue>. "
+         "Move the player to the front of the queue. (operator)",
+    1,
+    ADVANCE_CMD
   }
 };
 
@@ -2765,6 +2798,62 @@
     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 (!strcasecmp(args,"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;
@@ -2789,13 +2878,13 @@
       break;
       
     case VERSION_CMD:
-      sprintf(msg,"Xpilot 4.1.0 + patch 4.U.3");
+      sprintf(msg,"Xpilot 4.1.0 + patch 4.U.4alpha2");
       break;
       
     case HELP_CMD:
       if (!args)
 	sprintf(msg,"Commands: help team version lock password pause "\
-		"reset set kick");
+		"reset set kick show");
       else {
 	for (i=0;i<NELEM(commands);i++)
 	  if (!strcasecmp(args,commands[i].name))
@@ -3261,7 +3350,7 @@
     }
     pl = Players[GetInd[connp->id]];
     if (BIT(pl->used, OBJ_AUTOPILOT))
-	Autopilot(ind, 0);
+	Autopilot(GetInd[connp->id], 0);
     turnspeed = movement * pl->turnspeed / MAX_PLAYER_TURNSPEED;
     if (turnspeed < 0) {
 	turndir = -1.0;
@@ -3307,7 +3396,7 @@
 	pl = Players[GetInd[connp->id]];
 	pl->player_fps = fps;
 	if (fps > FPS) pl->player_fps = FPS;
-	if (fps < (FPS / 2)) pl->player_fps = FPS / 2;
+	if (fps < (FPS / 2)) pl->player_fps = (FPS+1) / 2;
 	if (fps == 0) pl->player_fps = FPS;
 	if ((fps == 20) && ignore20MaxFPS) pl->player_fps = FPS;
 	n = FPS - pl->player_fps;
diff -burN xpilot-4.U.3/src/server/walls.c xpilot-4.U.4a3/src/server/walls.c
--- xpilot-4.U.3/src/server/walls.c	Mon Aug 30 00:24:58 1999
+++ xpilot-4.U.4a3/src/server/walls.c	Mon Aug 30 00:22:11 1999
@@ -1000,7 +1000,7 @@
 		     * Ball has been brought back to home treasure.
 		     * The team should be punished.
 		     */
-		    sprintf(msg," < The ball was loose %d frames >",
+		    sprintf(msg," < The ball was loose for %d frames >",
 			    LONG_MAX - mi->obj->life);
 		    Set_message(msg);
 		    if (Punish_team(GetInd[mi->obj->owner],
