diff redraw.c @ 3:5a977ccbc7a9 default tip

Empty changelog
author darius
date Sat, 06 Dec 1997 05:41:29 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/redraw.c	Sat Dec 06 05:41:29 1997 +0000
@@ -0,0 +1,2564 @@
+/*
+ * redraw.c
+ */
+#include "copyright.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <math.h>
+#include <ctype.h>
+#include "Wlib.h"
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "packets.h"
+#include "proto.h"
+#include "gameconf.h"
+#ifdef SOUND
+#include "Slib.h"
+#endif
+#include "sound.h"
+
+typedef struct tractor Tractor;
+struct tractor {
+    int     sx, sy, d1x, d1y, d2x, d2y;	/* source (x,y) dest (x1,y1) (x2,y2) */
+    Tractor *next;
+}      *tracthead = NULL, *tractcurrent = NULL, *tractrunner;
+
+struct _clearzone *
+new_czone()
+{
+    if (clearzone == 0) {
+	czsize = 10;
+	clearzone = (struct _clearzone *) malloc(sizeof(*clearzone) * czsize);
+	clearcount = 0;
+    } else if (clearcount >= czsize) {
+	clearzone = (struct _clearzone *) realloc(clearzone,
+					sizeof(*clearzone) * (czsize *= 2));
+    }
+    return &clearzone[clearcount++];
+}
+
+/* Prototypes */
+static void local P((void));
+#ifndef COW_HAS_IT_WHY_SHOULDNT_WE
+static
+#endif
+void map P((void));
+static void redraw P((void));
+/* static void stline P((int flag));*/
+static W_Icon planetBitmap P((struct planet * p));
+static W_Icon planetmBitmap P((struct planet * p));
+
+void
+intrupt()
+{
+    static long lastread;
+    static struct timeval lastredraw = {0, 0};
+    struct timeval t;
+    static int needredraw=0;
+
+#ifndef __osf__
+    long    time();
+#endif
+
+    udcounter++;
+    
+    needredraw += readFromServer();
+
+    gettimeofday(&t, NULL);
+    if (needredraw && ((unsigned int) redrawDelay * 100000 <
+                       (unsigned int) ((t.tv_sec - lastredraw.tv_sec) * 1000000
+                                       + (t.tv_usec - lastredraw.tv_usec)))) {
+	needredraw = 0;
+        lastredraw=t;
+#if 0
+	lastread = time(NULL);
+#endif
+#ifdef RECORDER
+	if (!playback || (pb_update && 
+			  ((!pb_scan) || !(udcounter % pb_advance))))
+#endif
+	{
+	    redraw();
+	    playerlist2();
+	}
+#ifdef RECORDER
+	if (playback) {
+	    if(!pb_scan) {
+		if (pb_advance > 0) {
+		    if ((pb_advance -= pb_update) <= 0) {
+			pb_advance = 0;
+			paused = 1;
+		    }
+		} else if (pb_advance < 0) {
+		    switch (pb_advance) {
+		    case PB_REDALERT:
+			if (me->p_flags & PFRED) {
+			    pb_advance = 0;
+			    paused = 1;
+			}
+			break;
+		    case PB_YELLOWALERT:
+			if (me->p_flags & PFYELLOW) {
+			    pb_advance = 0;
+			    paused = 1;
+			}
+			break;
+		    case PB_DEATH:
+		    default:
+			if (me->p_status != PALIVE) {
+			    pb_advance = 0;
+			paused = 1;
+			}
+			break;
+		    }
+		}
+	    }
+	    pb_update = 0;
+	}
+	if (recordGame)
+	    writeUpdateMarker();
+#endif
+    }
+#if 0
+    if (lastread + 3 < time(NULL)) {
+	/*
+	   We haven't heard from server for awhile... Strategy:  send a
+	   useless packet to "ping" server.
+	*/
+	sendWarReq(me->p_hostile);
+    }
+#endif
+    if (me->p_status == POUTFIT) {
+	death();
+    }
+}
+
+static void
+redraw()
+{
+
+    /* erase warning line if necessary */
+    if ((warntimer <= udcounter) && (warncount > 0)) {
+#ifndef AMIGA
+	/* XFIX */
+	W_ClearArea(warnw, 5, 5, W_Textwidth * warncount, W_Textheight);
+#else
+	W_ClearWindow(warnw);
+#endif
+	warncount = 0;
+    }
+    if (W_FastClear) {
+	W_ClearWindow(w);
+	clearcount = 0;
+	clearlcount = 0;
+	tractcurrent = tracthead;
+    } else {
+#if 0
+	/* just to save a little time on all the function calls */
+	/* all the normal clear functions are implemented as well. */
+	W_FlushClearZones(w, clearzone, clearcount);
+	clearcount = 0;
+#else
+	while (clearcount) {
+	    clearcount--;
+	    /* XFIX */
+	    W_CacheClearArea(w, clearzone[clearcount].x,
+		       clearzone[clearcount].y, clearzone[clearcount].width,
+			     clearzone[clearcount].height);
+
+	    /*
+	       W_ClearArea(w, clearzone[clearcount].x,
+	       clearzone[clearcount].y, clearzone[clearcount].width,
+	       clearzone[clearcount].height);
+	    */
+	}
+#endif
+	while (clearlcount) {
+	    clearlcount--;
+	    /* XFIX */
+	    W_CacheLine(w, clearline[0][clearlcount],
+			clearline[1][clearlcount], clearline[2][clearlcount],
+			clearline[3][clearlcount], backColor);
+	    /*
+	       W_MakeLine(w, clearline[0][clearlcount],
+	       clearline[1][clearlcount], clearline[2][clearlcount],
+	       clearline[3][clearlcount], backColor);
+	    */
+	}
+	/* XFIX */
+#ifndef AMIGA
+	W_FlushClearAreaCache(w);
+	W_FlushLineCaches(w);
+#endif
+	/* erase the tractor lines [BDyess] */
+	for (tractrunner = tracthead; tractrunner != tractcurrent;
+	     tractrunner = tractrunner->next) {
+	    W_MakeTractLine(w, tractrunner->sx, tractrunner->sy,
+			    tractrunner->d1x, tractrunner->d1y,
+			    backColor);
+	    W_MakeTractLine(w, tractrunner->sx, tractrunner->sy,
+			    tractrunner->d2x, tractrunner->d2y,
+			    backColor);
+	}
+	tractcurrent = tracthead;
+    }
+
+    local();			/* redraw local window */
+
+#ifdef AMIGA			/* would do it in W_EventsPending, just have
+				   it here so the display is updated sooner. */
+    W_Flush();
+#endif
+
+    /* XFIX */
+    W_FlushLineCaches(w);
+
+    stline(0);
+
+    if (W_IsMapped(statwin))
+	updateStats();
+
+    updateInform();		/* check and update info window [BDyess] */
+
+    /* XFIX: last since its least accurate information */
+    if (mapmode)
+	map();
+
+}
+
+static W_Icon terrainBitmap(int x, int y)
+{
+   int aster_bm = 0;
+   int aster_fluff = 0;
+   
+   /* is no asteroids, then return fluff if adjacent 'roids */
+   if (!(terrainInfo[x*250 + y].types & T_ASTEROIDS)) aster_fluff = 1;
+
+   /* check surrounding terrain */
+   if (x > 0)
+      if (terrainInfo[(x-1)*250 + y].types & T_ASTEROIDS)
+	 aster_bm |= (1<<0);
+   if (x < 249)
+      if (terrainInfo[(x+1)*250 + y].types & T_ASTEROIDS) 
+	 aster_bm |= (1<<2);
+   if (y > 0)
+      if (terrainInfo[x*250 + y-1].types & T_ASTEROIDS) 
+	 aster_bm |= (1<<3);
+   if (y < 249)
+      if (terrainInfo[x*250 + y+1].types & T_ASTEROIDS) 
+	 aster_bm |= (1<<1);
+   
+   if (aster_fluff && aster_bm) return asteroidfluff[(x*250 + y)%3];
+   else return asteroidBM[aster_bm];
+}
+
+static  W_Icon
+planetBitmap(p)
+    register struct planet *p;
+{
+    int     i;
+    if (paradise) {
+	switch (PL_TYPE(*p)) {
+	case PLWHOLE:
+	    return wormBM[udcounter % WORMFRAMES];
+	    break;
+	case PLSTAR:
+	    return starBM[udcounter % STARFRAMES];
+	    break;
+	case PLAST:
+	    return basteroid[0];
+	}
+    }
+    if (showlocal == 2) {
+	return (bplanets[0]);
+    } else if (p->pl_info & idx_to_mask(me->p_teami)) {
+	if (showlocal == 1 || showlocal == 4) {
+	    i = 0;
+	    if ((paradise) && (p->pl_flags & PLSHIPYARD))
+		i += 8;
+	    if (p->pl_armies > 4)
+		i += 4;
+	    if (p->pl_flags & PLREPAIR)
+		i += 2;
+	    if (p->pl_flags & PLFUEL)
+		i += 1;
+	    return ((showlocal == 1 ? bplanets2 : bplanetsMOO)[i]);
+	} else if (showlocal == 0) {
+	    int     team = mask_to_idx(p->pl_owner);
+	    if (team < -1)
+		team = -1;
+	    else if (team >= number_of_teams)
+		team = number_of_teams - 1;
+	    return (bplanets[1 + team]);
+	} else {
+	    int     mask;
+	    if (paradise)
+		mask = (p->pl_flags & PLSURMASK) >> PLSURSHIFT;
+	    else {
+		mask = ((p->pl_flags & PLFUEL) ? 1 : 0)
+		    | ((p->pl_flags & PLREPAIR) ? 2 : 0)
+		    | ((p->pl_flags & PLAGRI) ? 4 : 0);
+	    }
+	    return bplanetsr[mask];
+	}
+    } else {
+	return (bplanets[5]);
+    }
+}
+
+
+static  W_Icon
+planetmBitmap(p)
+    register struct planet *p;
+{
+    int     i;
+    if (paradise) {
+	switch (p->pl_flags & PLTYPEMASK) {
+	case PLSTAR:
+	    return mstarBM;
+	case PLAST:
+	    return mbasteroid[0];
+#ifdef VISIBLE_WORMHOLES
+	case PLWHOLE:
+	    return mholeBM;
+#endif /*VISIBLE_WORMHOLES*/
+	}
+    }
+    if (showgalactic == 2) {
+	return (mbplanets[0]);
+    } else if (showgalactic == 4) {
+	int     infoage = 4;
+	if (!(p->pl_info & idx_to_mask(me->p_teami)))
+	    return mbplanetsA[NSCOUTAGES - 1];
+	if (p->pl_owner == idx_to_mask(me->p_teami))
+	    return mbplanetsA[0];
+
+	for (i = 0;
+	   i < NSCOUTAGES - 1 && infoage < status2->clock - p->pl_timestamp;
+	     i++, infoage = infoage * 5 / 3) {
+	}
+	return mbplanetsA[i];
+    } else if (p->pl_info & idx_to_mask(me->p_teami)) {
+	if (showgalactic == 1 || showgalactic == 5) {
+	    i = 0;
+	    if ((paradise) && (p->pl_flags & PLSHIPYARD))
+		i += 8;
+	    if (p->pl_armies > 4)
+		i += 4;
+	    if (p->pl_flags & PLREPAIR)
+		i += 2;
+	    if (p->pl_flags & PLFUEL)
+		i += 1;
+	    return ((showgalactic == 1 ? mbplanets2 : mbplanetsMOO)[i]);
+	} else if (showgalactic == 0) {
+	    int     team = mask_to_idx(p->pl_owner);
+	    if (team < -1)
+		team = -1;
+	    else if (team >= number_of_teams)
+		team = number_of_teams - 1;
+	    return (mbplanets[1 + team]);
+	} else {
+	    int     mask;
+	    if (paradise)
+		mask = (p->pl_flags & PLSURMASK) >> PLSURSHIFT;
+	    else {
+		mask = ((p->pl_flags & PLFUEL) ? 1 : 0)
+		    | ((p->pl_flags & PLREPAIR) ? 2 : 0)
+		    | ((p->pl_flags & PLAGRI) ? 4 : 0);
+	    }
+	    return mbplanetsr[mask];
+	}
+    } else {
+	return (mbplanets[5]);
+    }
+}
+
+/* call this from local for each player, instead of having an extra loop! */
+static void
+redraw_photon_torps(j)
+    struct player *j;
+{
+    int     i, h;
+    struct torp *k;
+    int     dx, dy;
+    int     view;
+    struct _clearzone *cz;
+
+    view = SCALE * WINSIDE / 2;
+    i = j->p_no;
+    if (!j->p_ntorp)
+	return;
+    for (h = 0, k = &torps[ntorps * i + h]; h < ntorps; h++, k++) {
+	if (!k->t_status)
+	    continue;
+	dx = k->t_x - me->p_x;
+	dy = k->t_y - me->p_y;
+	if (ABS(dx) > view || ABS(dy) > view) {
+	    /* Call any torps off screen "free" (if owned by other) */
+	    if (k->t_status == TEXPLODE && j != me) {
+		k->t_status = TFREE;
+		j->p_ntorp--;
+	    }
+	    continue;
+	}
+	dx = dx / SCALE + WINSIDE / 2;
+	dy = dy / SCALE + WINSIDE / 2;
+#ifdef UNIX_SOUND
+        if ((k->t_status == TEXPLODE) && (k->t_fuse == 5)) play_sound (SND_TORPHIT);
+#endif
+	if (k->t_status == TEXPLODE) {
+
+	    k->t_fuse--;
+	    if (k->t_fuse <= 0) {
+		k->t_status = TFREE;
+		j->p_ntorp--;
+		continue;
+	    }
+	    if (k->t_fuse >= NUMDETFRAMES) {
+		k->t_fuse = NUMDETFRAMES - 1;
+	    }
+	    W_WriteBitmap(dx - (cloud_width / 2), dy - (cloud_height / 2),
+			  cloud[k->t_fuse], torpColor(k));
+	    cz = new_czone();
+	    cz->x = dx - (cloud_width / 2);
+	    cz->y = dy - (cloud_height / 2);
+	    cz->width = cloud_width;
+	    cz->height = cloud_height;
+	} else if (k->t_owner != me->p_no && ((k->t_war & idx_to_mask(me->p_teami)) ||
+					      (idx_to_mask(players[k->t_owner].p_teami) & (me->p_hostile | me->p_swar)))) {
+	    /*
+	       solid.  Looks strange. W_FillArea(w, dx - (etorp_width/2), dy
+	       - (etorp_height/2), etorp_width, etorp_height, torpColor(k));
+	    */
+
+#ifdef BORGTEST
+	    W_CacheLine(w, dx - (etorp_width / 2), dy - (etorp_height / 2),
+			dx + (etorp_width / 2), dy + (etorp_height / 2),
+			(k->t_turns == 32767) ? notColor(k) : torpColor(k));
+	    W_CacheLine(w, dx + (etorp_width / 2), dy - (etorp_height / 2),
+			dx - (etorp_width / 2), dy + (etorp_height / 2),
+			(k->t_turns == 32767) ? notColor(k) : torpColor(k));
+#else
+#ifdef TORPBITS
+	    /*
+	       went back to this for Amiga, one bitmap is faster than 2
+	       lines.
+	     */
+	    W_WriteBitmap(dx - (etorp_width / 2), dy - (etorp_height / 2),
+			  etorp, torpColor(k));
+#else
+	    /* XFIX */
+	    if (0 && k->frame) {
+		W_CacheLine(w, dx - 2, dy,
+			    dx + 2, dy, torpColor(k));
+		W_CacheLine(w, dx, dy - 2,
+			    dx, dy + 2, torpColor(k));
+	    } else {
+		W_CacheLine(w, dx - 1, dy - 1,
+			    dx + 1, dy + 1, torpColor(k));
+		W_CacheLine(w, dx + 1, dy - 1,
+			    dx - 1, dy + 1, torpColor(k));
+	    }
+	    k->frame = !k->frame;
+#endif				/* TORPBITS */
+#endif
+
+	    cz = new_czone();
+	    cz->x = dx - (etorp_width / 2);
+	    cz->y = dy - (etorp_height / 2);
+	    cz->width = etorp_width;
+	    cz->height = etorp_height;
+	} else {
+	    /* XFIX */
+
+	    if (0 /* animateTorps */ ) {
+		switch (k->frame) {
+		case 0:
+		    W_CacheLine(w, dx - (mtorp_width / 2), dy, dx,
+				dy, torpColor(k));
+		    break;
+		case 1:
+		    W_CacheLine(w, dx - (mtorp_width / 2), dy - (mtorp_width / 2),
+				dx, dy, torpColor(k));
+		    break;
+		case 2:
+		    W_CacheLine(w, dx, dy, dx,
+				dy + (mtorp_width / 2), torpColor(k));
+		    break;
+		case 3:
+		    W_CacheLine(w, dx, dy,
+				dx + (mtorp_width / 2), dy - (mtorp_width / 2), torpColor(k));
+		    break;
+		case 4:
+		    W_CacheLine(w, dx, dy, dx + (mtorp_width / 2),
+				dy, torpColor(k));
+		    break;
+		case 5:
+		    W_CacheLine(w, dx - (mtorp_width / 2), dy - (mtorp_width / 2),
+				dx, dy, torpColor(k));
+		    break;
+		case 6:
+		    W_CacheLine(w, dx, dy - (mtorp_width / 2), dx,
+				dy, torpColor(k));
+		    break;
+		case 7:
+		    W_CacheLine(w, dx - (mtorp_width / 2), dy - (mtorp_width / 2),
+				dx, dy, torpColor(k));
+		    break;
+		}
+		k->frame++;
+		if (k->frame > 7)
+		    k->frame = 0;
+	    } else {
+#ifdef TORPBITS
+		W_WriteBitmap(dx - (mtorp_width / 2), dy - (mtorp_height / 2),
+			      mtorp, torpColor(k));
+#else
+		W_CacheLine(w, dx - (mtorp_width / 2), dy,
+			    dx + (mtorp_width / 2), dy, torpColor(k));
+		W_CacheLine(w, dx, dy - (mtorp_width / 2),
+			    dx, dy + (mtorp_width / 2), torpColor(k));
+#endif
+	    }
+
+	    cz = new_czone();
+	    cz->x = dx - (mtorp_width / 2);
+	    cz->y = dy - (mtorp_height / 2);
+	    cz->width = mtorp_width;
+	    cz->height = mtorp_height;
+	}
+    }
+}
+
+static void
+draw_one_thingy(k)
+    struct thingy *k;
+{
+    int     dx, dy;
+    int     view;
+    struct _clearzone *cz;
+    view = SCALE * WINSIDE / 2;
+
+    if (k->t_shape == SHP_BLANK)
+	return;
+    /* printf("%d,%d - %d,%d\n", me->p_x, me->p_y, k->t_x, k->t_y); */
+    dx = k->t_x - me->p_x;
+    dy = k->t_y - me->p_y;
+    if (ABS(dx) > view || ABS(dy) > view) {
+	return;
+    }
+    dx = dx / SCALE + WINSIDE / 2;
+    dy = dy / SCALE + WINSIDE / 2;
+    switch (k->t_shape) {
+    case SHP_BOOM:
+	k->t_fuse--;
+	if (k->t_fuse <= 0) {
+	    k->t_shape = SHP_BLANK;
+	    return;
+	}
+	if (k->t_fuse >= NUMDETFRAMES) {
+	    k->t_fuse = NUMDETFRAMES - 1;
+	}
+	W_WriteBitmap(dx - (cloud_width / 2), dy - (cloud_height / 2),
+		      cloud[k->t_fuse], droneColor(k));
+	cz = new_czone();
+	cz->x = dx - (cloud_width / 2);
+	cz->y = dy - (cloud_height / 2);
+	cz->width = cloud_width;
+	cz->height = cloud_height;
+	break;
+    case SHP_MISSILE:
+	{
+	    int     dview = (int) (k->t_dir * NDRONEVIEWS + 128) / 256;
+	    if (dview >= NDRONEVIEWS)
+		dview -= NDRONEVIEWS;
+	    W_WriteBitmap
+		(dx - (drone_width / 2), dy - (drone_height / 2),
+		 drone_bm[dview],
+		 droneColor(k));
+	}
+	cz = new_czone();
+	cz->x = dx - (drone_width / 2);
+	cz->y = dy - (drone_height / 2);
+	cz->width = drone_width;
+	cz->height = drone_height;
+	break;
+    case SHP_TORP:
+	if (k->t_owner != me->p_no &&
+	    ((k->t_war & idx_to_mask(me->p_teami)) ||
+	     (idx_to_mask(players[k->t_owner].p_teami) & (me->p_hostile | me->p_swar)))) {
+	    W_CacheLine(w, dx - (etorp_width / 2), dy - (etorp_height / 2),
+	     dx + (etorp_width / 2), dy + (etorp_height / 2), torpColor(k));
+	    W_CacheLine(w, dx + (etorp_width / 2), dy - (etorp_height / 2),
+	     dx - (etorp_width / 2), dy + (etorp_height / 2), torpColor(k));
+	    cz = new_czone();
+	    cz->x = dx - (etorp_width / 2);
+	    cz->y = dy - (etorp_height / 2);
+	    cz->width = etorp_width;
+	    cz->height = etorp_height;
+	} else {
+	    W_CacheLine(w, dx - (mtorp_width / 2), dy, dx + (mtorp_width / 2), dy,
+			torpColor(k));
+	    W_CacheLine(w, dx, dy - (mtorp_width / 2), dx, dy + (mtorp_width / 2),
+			torpColor(k));
+	    cz = new_czone();
+	    cz->x = dx - (mtorp_width / 2);
+	    cz->y = dy - (mtorp_height / 2);
+	    cz->width = mtorp_width;
+	    cz->height = mtorp_height;
+	}
+	break;
+    case SHP_PLASMA:
+    case SHP_MINE:		/* use plasma until I get a nifty bitmap */
+	if (k->t_owner != me->p_no &&
+	    ((k->t_war & idx_to_mask(me->p_teami)) ||
+	     (idx_to_mask(players[k->t_owner].p_teami) & (me->p_hostile | me->p_swar)))) {
+	    W_WriteBitmap(dx - (eplasmatorp_width / 2),
+			  dy - (eplasmatorp_height / 2),
+			  eplasmatorp, torpColor(k));
+	    cz = new_czone();
+	    cz->x = dx - (eplasmatorp_width / 2);
+	    cz->y = dy - (eplasmatorp_height / 2);
+	    cz->width = eplasmatorp_width;
+	    cz->height = eplasmatorp_height;
+	} else {
+	    W_WriteBitmap(dx - (mplasmatorp_width / 2),
+			  dy - (mplasmatorp_height / 2),
+			  mplasmatorp, torpColor(k));
+	    cz = new_czone();
+	    cz->x = dx - (mplasmatorp_width / 2);
+	    cz->y = dy - (mplasmatorp_height / 2);
+	    cz->width = mplasmatorp_width;
+	    cz->height = mplasmatorp_height;
+	}
+	break;
+    case SHP_PBOOM:
+	k->t_fuse--;
+	if (k->t_fuse <= 0) {
+	    k->t_shape = SHP_BLANK;
+	    return;
+	}
+	if (k->t_fuse >= NUMDETFRAMES) {
+	    k->t_fuse = NUMDETFRAMES - 1;
+	}
+	W_WriteBitmap(dx - (plasmacloud_width / 2),
+		      dy - (plasmacloud_height / 2),
+		      plasmacloud[k->t_fuse], torpColor(k));
+	cz = new_czone();
+	cz->x = dx - (plasmacloud_width / 2);
+	cz->y = dy - (plasmacloud_height / 2);
+	cz->width = plasmacloud_width;
+	cz->height = plasmacloud_height;
+	break;
+    case SHP_FIGHTER:
+	{
+	    int     fview = (int) (k->t_dir * VIEWS + 128) / 256;
+	    if (fview >= VIEWS)
+		fview -= VIEWS;
+	    W_WriteBitmap(dx - (fighter_width / 2),
+			  dy - (fighter_height / 2),
+			  fighter[fview], torpColor(k));
+	    cz = new_czone();
+	    cz->x = dx - (fighter_width / 2);
+	    cz->y = dy - (fighter_height / 2);
+	    cz->width = fighter_width;
+	    cz->height = fighter_height;
+	}
+	break;
+    case SHP_WARP_BEACON:
+	{
+	    cz = new_czone();
+	    cz->x = dx - (warpbeacon_width / 2);
+	    cz->y = dy - (warpbeacon_height / 2);
+	    cz->width = warpbeacon_width;
+	    cz->height = warpbeacon_height;
+	    W_WriteBitmap(cz->x, cz->y,
+			  warpbeacon, W_White);
+	    if (k->t_fuse > 4) {
+		W_WriteBitmap(cz->x, cz->y,
+			      wbflash, shipCol[1 + mask_to_idx(k->t_owner)]);
+	    }
+	    if (++(k->t_fuse) > 6)
+		k->t_fuse = 0;
+	}
+    }
+}
+
+static void
+redraw_drones(j)
+    struct player *j;
+{
+    int     i, h;
+    int     count;
+
+    i = j->p_no;
+
+    if (!j->p_ndrone)
+	return;
+    count = 0;
+
+    for (h = i * npthingies; h < npthingies * (i + 1); h++) {
+	draw_one_thingy(&thingies[h]);
+	if (thingies[h].t_shape != SHP_BLANK)
+	    count++;
+    }
+    j->p_ndrone = count;
+}
+
+static void
+redraw_other_drones()
+{
+    int     h;
+
+    for (h = 0; h < ngthingies; h++)
+	draw_one_thingy(&thingies[nplayers * npthingies + h]);
+}
+
+static void
+redraw_plasma_torps(j)
+    struct player *j;
+{
+    int     h, i;
+    register struct plasmatorp *pt;
+    struct _clearzone *cz;
+
+    int     dx, dy;
+    int     view;
+
+    view = SCALE * WINSIDE / 2;
+    i = j->p_no;
+
+    if (!j->p_nplasmatorp)
+	return;
+    for (h = 0, pt = &plasmatorps[nplasmas * i + h]; h < nplasmas; h++, pt++) {
+	if (!pt->pt_status)
+	    continue;
+	dx = pt->pt_x - me->p_x;
+	dy = pt->pt_y - me->p_y;
+	if (ABS(dx) > view || ABS(dy) > view)
+	    continue;
+	dx = dx / SCALE + WINSIDE / 2;
+	dy = dy / SCALE + WINSIDE / 2;
+#ifdef UNIX_SOUND
+        if ((pt->pt_status == TEXPLODE) && (pt->pt_fuse == 5))
+                play_sound (SND_TORPHIT); /* Torp Hit used for Plasma Hit */
+#endif
+	if (pt->pt_status == PTEXPLODE) {
+	    pt->pt_fuse--;
+	    if (pt->pt_fuse <= 0) {
+		pt->pt_status = PTFREE;
+		j->p_nplasmatorp--;
+		continue;
+	    }
+	    if (pt->pt_fuse >= NUMDETFRAMES) {
+		pt->pt_fuse = NUMDETFRAMES - 1;
+	    }
+	    W_WriteBitmap(dx - (plasmacloud_width / 2),
+			  dy - (plasmacloud_height / 2),
+			  plasmacloud[pt->pt_fuse], plasmatorpColor(pt));
+	    cz = new_czone();
+	    cz->x = dx - (plasmacloud_width / 2);
+	    cz->y = dy - (plasmacloud_height / 2);
+	    cz->width = plasmacloud_width;
+	    cz->height = plasmacloud_height;
+	}
+	/* needmore: if(pt->pt_war & idx_to_mask(me->p_teami)) */
+	else if (pt->pt_owner != me->p_no && ((pt->pt_war & idx_to_mask(me->p_teami)) ||
+					      (idx_to_mask(players[pt->pt_owner].p_teami) & (me->p_hostile | me->p_swar)))) {
+	    W_WriteBitmap(dx - (eplasmatorp_width / 2),
+			  dy - (eplasmatorp_height / 2),
+			  eplasmatorp, plasmatorpColor(pt));
+	    cz = new_czone();
+	    cz->x = dx - (eplasmatorp_width / 2);
+	    cz->y = dy - (eplasmatorp_height / 2);
+	    cz->width = eplasmatorp_width;
+	    cz->height = eplasmatorp_height;
+	} else {
+	    W_WriteBitmap(dx - (mplasmatorp_width / 2),
+			  dy - (mplasmatorp_height / 2),
+			  mplasmatorp, plasmatorpColor(pt));
+	    cz = new_czone();
+	    cz->x = dx - (mplasmatorp_width / 2);
+	    cz->y = dy - (mplasmatorp_height / 2);
+	    cz->width = mplasmatorp_width;
+	    cz->height = mplasmatorp_height;
+	}
+    }
+}
+
+#ifdef HOCKEY
+void tactical_hockey P((void));
+#endif
+
+void
+redraw_terrain()
+{
+   int i,j;
+   int view;
+   int nx, ny; /* for adjusted coords, based on ship position */
+   int tx, ty, x; /* terrain grid x and y for 0,0 on the local */
+   struct _clearzone *cz;
+   
+   view = SCALE * WINSIDE / 2;
+   
+   nx = (int) ((me->p_x - view) / SCALE)%terrain_width;
+   ny = (int) ((me->p_y - view) / SCALE)%terrain_height;
+
+   ty = (int) ((me->p_y - view)/(GWIDTH/250));
+   x = tx = (int) ((me->p_x - view)/(GWIDTH/250));
+   if (ty < 0) ty = 0;
+   if (tx < 0) {
+      tx = 0;
+      x = 0;
+   }
+
+   if(received_terrain_info) {
+      for (i=0; i < WINSIDE; i += terrain_height) {
+	 for (j=0; j < WINSIDE; j += terrain_width) {
+	    if ((terrainInfo[tx*250+ty].types & T_ASTEROIDS) ||
+		((tx > 0) && (terrainInfo[(tx-1)*250+ty].types & T_ASTEROIDS)) ||
+		((tx < 249) && (terrainInfo[(tx+1)*250+ty].types & T_ASTEROIDS)) ||
+		((ty > 0) && (terrainInfo[tx*250+(ty-1)].types & T_ASTEROIDS)) ||
+		((tx < 249) && (terrainInfo[tx*250+(ty+1)].types & T_ASTEROIDS))) {
+	       W_WriteBitmap(j-nx, i-ny, terrainBitmap(tx,ty), W_Grey);
+	       cz = new_czone();
+	       cz->x = j-nx;
+	       cz->y = i-ny;
+	       cz->width = terrain_width;
+	       cz->height = terrain_height;
+	    } 
+	    tx++;
+	    if (tx >= 250) {
+	       tx = x;
+	       break;
+	    }
+	 }
+	 ty++;
+	 if (ty >= 250) break;
+	 tx = x;
+      }
+   }
+}
+
+void
+redraw_all_planets()
+{
+    int     view;
+    int     i;
+    int     dx, dy;
+    struct _clearzone *cz;
+    struct planet *l;
+    int     nplan;
+
+    view = SCALE * WINSIDE / 2;
+    nplan = paradise ? nplanets : 40;
+
+#ifdef HOCKEY
+    if(hockey) {
+      tactical_hockey();
+    }
+#endif /*HOCKEY*/
+    for (i = 0, l = &planets[i]; i < nplan; i++, l++) {
+	dx = l->pl_x - me->p_x;
+	dy = l->pl_y - me->p_y;
+	if (ABS(dx) > view || ABS(dy) > view)
+	    continue;
+	dx = dx / SCALE + WINSIDE / 2;
+	dy = dy / SCALE + WINSIDE / 2;
+	if (PL_TYPE(*l) == PLWHOLE)
+	   W_WriteBitmap(dx - (wormhole_width / 2), dy - (wormhole_height / 2),
+		      planetBitmap(l),
+		      ((paradise) && (PL_TYPE(*l) == PLWHOLE))
+		       ? textColor
+		       : planetColor(l));
+	else
+	W_WriteBitmap(dx - (planet_width / 2), dy - (planet_height / 2),
+		      planetBitmap(l),
+			 ((paradise) && (PL_TYPE(*l) == PLSTAR))
+		      ? textColor
+		      : planetColor(l));
+#ifdef SHOW_IND
+	if (showIND && (l->pl_info & idx_to_mask(me->p_teami)) && (l->pl_owner == NOBODY) && l->pl_flags & PLPLANET)
+	{
+	    W_CacheLine (w, dx - (planet_width / 2), dy - (planet_height / 2),
+			 dx + (planet_width / 2 - 1), dy + (planet_height / 2 - 1),
+			 W_White);
+	    W_CacheLine (w, dx + (planet_width / 2 - 1), dy - (planet_height / 2),
+			 dx - (planet_width / 2), dy + (planet_height / 2 - 1),
+			 W_White);
+	}
+#endif
+	if (namemode) {
+	   if (PL_TYPE(*l) != PLWHOLE) {
+	    W_MaskText(w, dx - l->pl_namelen * W_Textwidth / 2, dy + (planet_height / 2),
+			 ((paradise) && (PL_TYPE(*l) == PLSTAR))
+		       ? textColor
+		       : planetColor(l),
+		       l->pl_name, l->pl_namelen, planetFont(l));
+	    cz = new_czone();
+	    cz->x = dx - l->pl_namelen * W_Textwidth / 2;
+	    cz->y = dy + (planet_height / 2);
+	    cz->width = W_Textwidth * l->pl_namelen;
+	    cz->height = W_Textheight;
+	}
+	}
+				/* put letters and number next to */
+				/* planet bitmaps for resources and */
+				/* armies */
+	 if (paradise && tacPlanetInfo) {
+	      if (PL_TYPE(*l) == PLPLANET) {
+		   char dspstr[8];
+		   if (tacPlanetInfo & 1) 
+			sprintf(dspstr, "%d", l->pl_armies);
+		   if ((tacPlanetInfo & 2) && (l->pl_flags & PLREPAIR)) 
+			strcat(dspstr, "R");
+		   if ((tacPlanetInfo & 4) && (l->pl_flags & PLFUEL)) 
+			strcat(dspstr, "F");
+		   if ((tacPlanetInfo & 8) && (l->pl_flags & PLAGRI)) 
+			strcat(dspstr, "A");
+		   if ((tacPlanetInfo & 16) && (l->pl_flags & PLSHIPYARD)) 
+			strcat(dspstr, "S");
+		   cz = new_czone();
+		   cz->x = dx + planet_width/2 + 2;
+		   cz->y = dy;
+		   cz->width = W_Textwidth * strlen(dspstr);
+		   cz->height = W_Textheight;
+		   W_MaskText(w, cz->x, cz->y,
+			      planetColor(l), dspstr, strlen(dspstr),
+				   planetFont(l));
+	      }
+	 }
+
+	/*--------draw tactical lock*/
+	if ((showLock & 2) && (me->p_flags & PFPLLOCK) && (me->p_planet == l->pl_no)) {
+	    W_WriteTriangle(w, dx, dy - (planet_height) / 2 - 6, 5, 0, foreColor);
+	    cz=new_czone();
+	    cz->x=dx-5;
+	    cz->y=dy - (planet_height) / 2 - 12;
+	    cz->width=11;
+	    cz->height=7;
+	}
+	cz = new_czone();
+	if (PL_TYPE(*l) == PLWHOLE) {
+	   cz->x = dx - (wormhole_width / 2);
+	   cz->y = dy - (wormhole_height / 2);
+	   cz->width = wormhole_width;
+	   cz->height = wormhole_height;
+	} else {
+	cz->x = dx - (planet_width / 2);
+	/*cz->y = dy - (planet_height / 2) - 13;*/
+	cz->y = dy - (planet_height / 2);
+	cz->width = planet_width;
+	/*cz->height = planet_height + 26;*/
+	cz->height = planet_height;
+	}
+    }
+}
+
+void 
+doShowMySpeed(dx, dy, ship_bits, j)
+    int     dx, dy;
+    struct ship_shape *ship_bits;
+    struct player *j;
+{
+    struct _clearzone *cz;
+    char    idbuf[5];
+    int     len;
+    int     color;
+
+    sprintf(idbuf, "%c,%d", *(shipnos + j->p_no), me->p_speed);
+    len = strlen(idbuf);
+    /*
+       color the playernum,speed based on warp/afterburn/warpprep state
+       [BDyess]
+    */
+    switch (me->p_flags & (PFWARP | PFAFTER | PFWARPPREP)) {
+    case PFWARP:
+	color = W_Cyan;
+	me->p_flags &= ~PFWARPPREP;
+	break;
+    case PFAFTER:
+	color = rColor;
+	break;
+    case PFWARPPREP:
+	color = yColor;
+	break;
+    default:			/* impulse */
+	if (me->p_speed > 0) {
+	    color = gColor;
+	} else {		/* stopped */
+	    color = textColor;
+	}
+	break;
+    }
+    dx += ship_bits->width / 2;
+    dy -= ship_bits->height / 2;
+    /* underline number,speed if warp is suspended [BDyess] */
+    W_MaskText(w, dx, dy, color, idbuf, len, (me->p_flags & PFWPSUSPENDED) ?
+	       W_UnderlineFont : shipFont(j));
+
+    cz = new_czone();
+    cz->x = dx;
+    cz->y = dy;
+    cz->width = len * W_Textwidth;
+    cz->height = W_Textheight;
+}
+
+#ifdef LOCAL_SHIPSTATS
+/* show just about anything next to ship on local display
+   DSFAPWE - for each letter in statString, show a line for:
+   Damage, Shields, Fuel, Armies, sPeed, Wtemp, Etemp 
+
+   lower case = reverse length
+ */
+static void
+doLocalShipstats()
+{
+    char *sptr;
+    int num=0, len, x=localStatsX, i;
+    struct _clearzone *cz;
+    W_Color color;
+
+    for(sptr=statString;*sptr;sptr++) {
+	switch(toupper(*sptr)) {
+	case 'W':
+	    len=(statHeight*me->p_wtemp) / me->p_ship->s_maxwpntemp;
+	    break;
+	case 'E':
+	    len=(statHeight*me->p_etemp) / me->p_ship->s_maxegntemp;
+	    break;
+	case 'P':
+	    len=(statHeight*me->p_speed)/me->p_ship->s_maxspeed;
+	    break;
+	case 'D':
+	    len=(statHeight*me->p_damage)/me->p_ship->s_maxdamage;
+	    break;
+	case 'S':
+	    len=statHeight - ((statHeight*me->p_shield)/me->p_ship->s_maxshield);
+	    break;
+	case 'F':
+	    len=statHeight - ((statHeight*me->p_fuel)/me->p_ship->s_maxfuel);
+	    break;
+	case 'A':
+	    len= me->p_ship->s_maxarmies ?
+		(statHeight*me->p_armies)/me->p_ship->s_maxarmies : 0;
+	    break;
+	default:
+	    continue;
+	}
+	if(islower(*sptr))
+	    len=statHeight - len;
+	if(len>statHeight)
+	    len=statHeight;
+
+	if(len>2*(statHeight/3) || toupper(*sptr) == 'A')
+	    color=W_Red;
+	else if(len<(statHeight/3))
+	    color=W_Green;
+	else
+	    color=W_Yellow;
+	if(len>0)
+	    W_CacheLine(w,x+W_Textwidth/2,localStatsY-len,x+W_Textwidth/2,localStatsY,color);
+	W_MaskText(w,x,localStatsY+1,W_White,sptr,1,W_RegularFont);
+	x+=W_Textwidth;
+    }
+    if(x>localStatsX) {
+	W_CacheLine(w,localStatsX,localStatsY-statHeight,x,localStatsY-statHeight,W_White);
+	W_CacheLine(w,localStatsX,localStatsY,x,localStatsY,W_White);
+	cz=new_czone();
+	cz->x=localStatsX;
+	cz->y=localStatsY-statHeight+1;
+	cz->width=x-localStatsX;
+	cz->height=statHeight-2;
+    }
+}
+#endif
+
+static void
+local()
+{
+    register int i;
+    register struct player *j;
+    register struct phaser *php;
+    struct _clearzone *cz;
+
+    int     dx, dy;
+    int     view;
+    char    idbuf[10];
+    struct ship_shape *ship_bits;
+    if (showKitchenSink) {
+	cz = new_czone();
+	cz->width = 76;
+	cz->height = 60;
+	cz->x = 500 - cz->width;
+	cz->y = 0;
+	W_WriteBitmap(cz->x, cz->y, kitchenSink, W_Grey);
+    }
+    /*
+       Kludge to try to fix missing ID chars on tactical (short range)
+       display.
+    */
+    idbuf[0] = '0';
+    idbuf[1] = '\0';
+    /* Draw Terrain */
+    redraw_terrain();
+    /* Draw Planets */
+    redraw_all_planets();
+    /* Draw ships */
+    view = SCALE * WINSIDE / 2;
+    for (i = 0, j = &players[i]; i < nplayers; i++, j++) {
+	int     tx, ty;
+	if (me->p_x < 0)
+	    continue;
+
+	/* more efficient than using a separate loop for this */
+	redraw_photon_torps(j);
+	redraw_drones(j);
+	redraw_plasma_torps(j);
+
+	if ((j->p_status != PALIVE) && (j->p_status != PEXPLODE))
+	    continue;
+
+#ifdef UNIX_SOUND
+        if (myPlayer(j) && (j->p_flags & PFCLOAK) &&
+           (j->p_cloakphase == 0)) play_sound (SND_CLOAK);
+        if (myPlayer(j) && (!(j->p_flags & PFCLOAK)) && 
+           (j->p_cloakphase == 6)) play_sound (SND_CLOAK);
+#endif
+
+	if (j->p_flags & PFCLOAK) {
+	    if (j->p_cloakphase < (CLOAK_PHASES - 1)) {
+		j->p_cloakphase++;
+	    }
+	} else {
+	    if (j->p_cloakphase) {
+		j->p_cloakphase--;
+	    }
+	}
+	dx = j->p_x - me->p_x;
+	dy = j->p_y - me->p_y;
+	if (ABS(dx) > view || ABS(dy) > view) {
+	    if(j->p_status == PEXPLODE)
+		j->p_explode++;
+	    continue;
+	}
+	dx = dx / SCALE + WINSIDE / 2;
+	dy = dy / SCALE + WINSIDE / 2;
+	if (j->p_status == PALIVE) {
+
+	    ship_bits = shape_of_ship(j->p_teami, j->p_ship->s_bitmap);
+
+	    if (j->p_flags & PFCLOAK && (j->p_cloakphase == (CLOAK_PHASES - 1))) {
+		if (myPlayer(j)) {
+		    W_WriteBitmap(dx - (cloak_width / 2), dy - (cloak_height / 2),
+				  cloakicon, myColor);
+		    cz = new_czone();
+		    cz->x = dx - (ship_bits->width / 2 + 1);
+		    cz->y = dy - (ship_bits->height / 2 + 1);
+		    cz->width = ship_bits->width + 2;
+		    cz->height = ship_bits->height + 2;
+		    doShields(dx, dy, ship_bits, j);
+#ifdef VARY_HULL
+		    doHull(dx, dy, ship_bits, j);
+#endif				/* VARY_HULL */
+		    if (showMySpeed)
+			doShowMySpeed(dx, dy, ship_bits, j);
+		}
+		continue;
+	    }
+	    cz = new_czone();
+#ifdef BEEPLITE
+	    if (emph_player_seq_n[j->p_no] > 0 &&
+		((F_beeplite_flags & LITE_PLAYERS_LOCAL) ||
+		 ((j == me) && (F_beeplite_flags & LITE_SELF)))) {
+		int     seq_n = emph_player_seq_n[j->p_no] % emph_player_seql_frames;
+
+		cz->x = dx - (emph_player_seql_width / 2);
+		cz->y = dy - (emph_player_seql_height / 2);
+		cz->width = emph_player_seql_width;
+		cz->height = emph_player_seql_height;
+
+		W_WriteBitmap(dx - (emph_player_seql_width / 2),
+			      dy - (emph_player_seql_height / 2),
+			      emph_player_seql[seq_n],
+			      emph_player_color[j->p_no]);
+	    } else
+#endif
+	    {
+		cz->x = dx - (ship_bits->width / 2);
+		cz->y = dy - (ship_bits->height / 2);
+		cz->width = ship_bits->width;
+		cz->height = ship_bits->height;
+	    }
+	    W_WriteBitmap(dx - (ship_bits->width / 2),
+			  dy - (ship_bits->height / 2),
+			  ship_bits->bmap[rosette((int) j->p_dir,
+				 (int) ship_bits->nviews)], playerColor(j));
+	    if (j->p_cloakphase > 0) {
+		W_WriteBitmap(dx - (cloak_width / 2),
+			dy - (cloak_height / 2), cloakicon, playerColor(j));
+		doShields(dx, dy, ship_bits, j);
+		if (j == me) {
+#ifdef VARY_HULL
+		    doHull(dx, dy, ship_bits, j);
+#endif				/* VARY_HULL */
+		    if (showMySpeed)
+			doShowMySpeed(dx, dy, ship_bits, j);
+		}
+		continue;
+	    }
+	    if (showLock & 2) {
+		if ((me->p_flags & PFPLOCK) && (me->p_playerl == j->p_no)) {
+		    W_WriteTriangle(w, dx, dy + (ship_bits->width / 2),
+				    4, 1, foreColor);
+		    cz = new_czone();
+		    cz->x = dx - 4;
+		    cz->y = dy + (ship_bits->height / 2);
+		    cz->width = 9;
+		    cz->height = 5;
+		}
+	    }
+	    doShields(dx, dy, ship_bits, j);
+#ifdef VARY_HULL
+	    doHull(dx, dy, ship_bits, j);
+#endif				/* VARY_HULL */
+	    if (showMySpeed && j == me)
+		doShowMySpeed(dx, dy, ship_bits, j);
+	    else {
+		int     color = playerColor(j);
+		idbuf[0] = *(shipnos + j->p_no);
+
+		W_MaskText(w, dx + (ship_bits->width / 2),
+			   dy - (ship_bits->height / 2), color,
+			   idbuf, 1, shipFont(j));
+
+		cz = new_czone();
+		cz->x = dx + (ship_bits->width / 2);
+		cz->y = dy - (ship_bits->height / 2);
+		cz->width = W_Textwidth;
+		cz->height = W_Textheight;
+	    }
+	} else if (j->p_status == PEXPLODE) {
+	    int     i;
+	    i = j->p_explode;
+	    if (i < EX_FRAMES || (i < SBEXPVIEWS && j->p_ship->s_type == STARBASE)) {
+
+#ifdef SOUND
+		if(i==0)
+		    S_PlaySound(S_EXPLOSION);
+#endif
+#ifdef UNIX_SOUND
+                if (i==0)
+                {
+                    if (j->p_ship->s_type == STARBASE)
+                    play_sound(SND_EXP_SB);         /* Starbase Explode */
+                    else play_sound(SND_EXPLOSION); /* Ship Explosion */
+                }
+#endif 
+    
+		cz = new_czone();
+		if (j->p_ship->s_type == STARBASE) {
+		    W_WriteBitmap(dx - (sbexp_width / 2),
+				  dy - (sbexp_height / 2), sbexpview[i],
+				  playerColor(j));
+		    cz->x = dx - (sbexp_width / 2);
+		    cz->y = dy - (sbexp_height / 2);
+		    cz->width = sbexp_width;
+		    cz->height = sbexp_height;
+		} else {
+		    W_WriteBitmap(dx - (ex_width / 2), dy - (ex_height / 2),
+				  expview[i], playerColor(j));
+		    cz->x = dx - (ex_width / 2);
+		    cz->y = dy - (ex_height / 2);
+		    cz->width = ex_width;
+		    cz->height = ex_height;
+		}
+		j->p_explode++;
+	    }
+	}
+	/* Now draw his phaser (if it exists) */
+	php = &phasers[j->p_no];
+	if (php->ph_status != PHFREE) {
+	    if (php->ph_status == PHMISS) {
+		/* Here I will have to compute end coordinate */
+		tx = j->p_x + j->p_ship->s_phaserrange * Cos[php->ph_dir];
+		ty = j->p_y + j->p_ship->s_phaserrange * Sin[php->ph_dir];
+		tx = (tx - me->p_x) / SCALE + WINSIDE / 2;
+		ty = (ty - me->p_y) / SCALE + WINSIDE / 2;
+	    } else if (php->ph_status == PHHIT2) {
+		tx = (php->ph_x - me->p_x) / SCALE + WINSIDE / 2;
+		ty = (php->ph_y - me->p_y) / SCALE + WINSIDE / 2;
+	    } else {		/* Start point is dx, dy */
+		tx = (players[php->ph_target].p_x - me->p_x) /
+		    SCALE + WINSIDE / 2;
+		ty = (players[php->ph_target].p_y - me->p_y) /
+		    SCALE + WINSIDE / 2;
+	    }
+
+
+	    php->ph_fuse++;
+
+#ifdef CHECK_DROPPED
+	    if (php->ph_fuse > longest_ph_fuse + 1 && php->ph_status != PHGHOST) {
+		if (reportDroppedPackets)
+		    printf("Dropped phaser free, player %d (fuse)\n", j->p_no);
+		php->ph_status = PHGHOST;
+	    }
+	    if (php->ph_status != PHGHOST) {
+#endif
+#ifdef W_PHASERLINE
+/*
+ * an old redraw.c I used for the Amiga port(not this port) had this.
+ * Draws a dashed line instead of solid..different pattern from tractor
+ * lines.   At least that's what I guessed for amigawindow.c :-) -JR
+ */
+
+		if (j->p_teami != me->p_teami)
+		    W_MakePhaserLine(w, dx, dy, tx, ty,
+			    (php->ph_fuse % 2 && php->ph_status != PHMISS) ?
+				     foreColor :
+				     shipCol[1 + j->p_teami],
+				     php->ph_fuse);
+		else
+#endif
+		{
+		    W_Color ph_col;
+		    if (jubileePhasers) {
+
+			switch (php->ph_fuse % 4) {
+			case 0:
+			    ph_col = W_Red;
+			    break;
+			case 1:
+			    ph_col = W_Yellow;
+			    break;
+			case 2:
+			    ph_col = W_Green;
+			    break;
+			case 3:
+			    ph_col = W_Cyan;
+			    break;
+			}
+			if (php->ph_status == PHMISS)
+			    ph_col = W_White;
+		    } else {
+			ph_col = (php->ph_fuse % 2 && php->ph_status != PHMISS) ?
+			    foreColor :
+			    shipCol[1 + j->p_teami];
+		    }
+		    W_CacheLine(w, dx, dy, tx, ty, ph_col);
+		}
+		clearline[0][clearlcount] = dx;
+		clearline[1][clearlcount] = dy;
+		clearline[2][clearlcount] = tx;
+		clearline[3][clearlcount] = ty;
+		clearlcount++;
+#ifdef CHECK_DROPPED
+	    }			/* PHGHOST */
+#endif
+	}
+    }
+
+    /* ATM - show tractor/pressor beams (modified by James Collins) */
+    /* showTractorPressor is a variable set by xtrekrc. */
+    /* modified to show all T/P's 1/28/94 [BDyess] */
+    /* fixed display bug 1/29/94 [BDyess] */
+    dx = WINSIDE / 2;
+    dy = WINSIDE / 2;
+    if (showTractorPressor) {
+	double  theta;
+	unsigned char dir;
+	int     lx[2], ly[2], px, py, target_width;
+	struct player *victim = &players[me->p_tractor];
+	int     last;
+	if (paradise && showAllTractorPressor && allowShowAllTractorPressor) {
+	    /* check everybody */
+	    last = nplayers;
+	    j = &players[0];
+	    i = 0;
+	} else {
+	    /* only check self */
+	    last = me->p_no + 1;
+	    j = me;
+	    i = me->p_no;
+	}
+	for (; i < last; i++, j++) {
+	    if (!(j->p_flags & (PFTRACT | PFPRESS) && isAlive(j)))
+		continue;
+	    if (!paradise && RSA_Client > 0 && j != me)
+		continue;
+	    victim = &players[j->p_tractor];
+	    if (victim->p_flags & PFCLOAK)
+		break;		/* can't see tractors on cloaked opponents */
+	    if (j == me) {
+		dx = dy = WINSIDE / 2;
+	    } else {
+		dx = (j->p_x - me->p_x) / SCALE + WINSIDE / 2;
+		dy = (j->p_y - me->p_y) / SCALE + WINSIDE / 2;
+	    }
+	    if (PtOutsideWin(dx, dy))
+		continue;	/* he's off the screen */
+	    px = (victim->p_x - me->p_x) / SCALE + WINSIDE / 2;
+	    py = (victim->p_y - me->p_y) / SCALE + WINSIDE / 2;
+	    if (px == dx && py == dy)
+		break;
+#define XPI     3.1415926
+	    theta = atan2((double) (px - dx), (double) (dy - py)) + XPI / 2.0;
+	    dir = (unsigned char) (theta / XPI * 128.0);
+	    target_width = shape_of_ship(victim->p_teami,
+					 victim->p_ship->s_bitmap)->width;
+	    if (!(victim->p_flags & PFSHIELD))
+		target_width /= 2;
+	    lx[0] = px + (Cos[dir] * (target_width / 2));
+	    ly[0] = py + (Sin[dir] * (target_width / 2));
+	    lx[1] = px - (Cos[dir] * (target_width / 2));
+	    ly[1] = py - (Sin[dir] * (target_width / 2));
+#undef XPI
+	    if (j->p_flags & PFPRESS) {
+		W_MakeTractLine(w, dx, dy, lx[0], ly[0], W_Yellow);
+		W_MakeTractLine(w, dx, dy, lx[1], ly[1], W_Yellow);
+	    } else {
+		W_MakeTractLine(w, dx, dy, lx[0], ly[0], W_Green);
+		W_MakeTractLine(w, dx, dy, lx[1], ly[1], W_Green);
+	    }
+	    /*
+	       keeping track of tractors seperately from other lines allows
+	       clearing them diffently.  Clearing them the same as other
+	       solid lines caused occasional bits to be left on the screen.
+	       This is the fix.  [BDyess]
+	    */
+	    if (tractcurrent == NULL) {	/* just starting */
+		tractcurrent = tracthead = (Tractor *) malloc(sizeof(Tractor));
+		tracthead->next = NULL;
+	    }
+	    tractcurrent->sx = dx;
+	    tractcurrent->sy = dy;
+	    tractcurrent->d1x = lx[0];
+	    tractcurrent->d1y = ly[0];
+	    tractcurrent->d2x = lx[1];
+	    tractcurrent->d2y = ly[1];
+	    /* get ready for the next run through */
+	    if (tractcurrent->next) {	/* already malloc'd before */
+		tractcurrent = tractcurrent->next;
+	    } else {		/* new maximum, create a new struct */
+		tractcurrent->next = (Tractor *) malloc(sizeof(Tractor));
+		tractcurrent = tractcurrent->next;
+		tractcurrent->next = NULL;
+	    }
+	}
+    }
+    /* changed torps/drones/plasmas to one call per player, in the above loop */
+    /* still have leftover drones to draw: */
+    redraw_other_drones();
+
+    /* Draw Edges */
+    if (me->p_x < (WINSIDE / 2) * SCALE) {
+	int     sy, ey;
+	dx = (WINSIDE / 2) - (me->p_x) / SCALE;
+	sy = (WINSIDE / 2) + (0 - me->p_y) / SCALE;
+	ey = (WINSIDE / 2) + (blk_gwidth - me->p_y) / SCALE;
+	if (sy < 0)
+	    sy = 0;
+	if (ey > WINSIDE - 1)
+	    ey = WINSIDE - 1;
+	/* XFIX */
+	W_CacheLine(w, dx, sy, dx, ey, warningColor);
+	/*
+	   W_MakeLine(w, dx, sy, dx, ey, warningColor);
+	*/
+	clearline[0][clearlcount] = dx;
+	clearline[1][clearlcount] = sy;
+	clearline[2][clearlcount] = dx;
+	clearline[3][clearlcount] = ey;
+	clearlcount++;
+    }
+    if ((blk_gwidth - me->p_x) < (WINSIDE / 2) * SCALE) {
+	int     sy, ey;
+	dx = (WINSIDE / 2) + (blk_gwidth - me->p_x) / SCALE;
+	sy = (WINSIDE / 2) + (0 - me->p_y) / SCALE;
+	ey = (WINSIDE / 2) + (blk_gwidth - me->p_y) / SCALE;
+	if (sy < 0)
+	    sy = 0;
+	if (ey > WINSIDE - 1)
+	    ey = WINSIDE - 1;
+	/* XFIX */
+	W_CacheLine(w, dx, sy, dx, ey, warningColor);
+	/*
+	   W_MakeLine(w, dx, sy, dx, ey, warningColor);
+	*/
+	clearline[0][clearlcount] = dx;
+	clearline[1][clearlcount] = sy;
+	clearline[2][clearlcount] = dx;
+	clearline[3][clearlcount] = ey;
+	clearlcount++;
+    }
+    if (me->p_y < (WINSIDE / 2) * SCALE) {
+	int     sx, ex;
+	dy = (WINSIDE / 2) - (me->p_y) / SCALE;
+	sx = (WINSIDE / 2) + (0 - me->p_x) / SCALE;
+	ex = (WINSIDE / 2) + (blk_gwidth - me->p_x) / SCALE;
+	if (sx < 0)
+	    sx = 0;
+	if (ex > WINSIDE - 1)
+	    ex = WINSIDE - 1;
+	/* XFIX */
+	W_CacheLine(w, sx, dy, ex, dy, warningColor);
+	/*
+	   W_MakeLine(w, sx, dy, ex, dy, warningColor);
+	*/
+	clearline[0][clearlcount] = sx;
+	clearline[1][clearlcount] = dy;
+	clearline[2][clearlcount] = ex;
+	clearline[3][clearlcount] = dy;
+	clearlcount++;
+    }
+    if ((blk_gwidth - me->p_y) < (WINSIDE / 2) * SCALE) {
+	int     sx, ex;
+	dy = (WINSIDE / 2) + (blk_gwidth - me->p_y) / SCALE;
+	sx = (WINSIDE / 2) + (0 - me->p_x) / SCALE;
+	ex = (WINSIDE / 2) + (blk_gwidth - me->p_x) / SCALE;
+	if (sx < 0)
+	    sx = 0;
+	if (ex > WINSIDE - 1)
+	    ex = WINSIDE - 1;
+	/* XFIX */
+	W_CacheLine(w, sx, dy, ex, dy, warningColor);
+	/*
+	   W_MakeLine(w, sx, dy, ex, dy, warningColor);
+	*/
+	clearline[0][clearlcount] = sx;
+	clearline[1][clearlcount] = dy;
+	clearline[2][clearlcount] = ex;
+	clearline[3][clearlcount] = dy;
+	clearlcount++;
+    }
+    /* Change border color to signify alert status */
+
+#ifdef UNIX_SOUND
+    if (oldalert != (me->p_flags & (PFGREEN | PFYELLOW | PFRED))) 
+    {
+      if (me->p_flags & PFRED)
+            maybe_play_sound (SND_REDALERT);   /* Red Alert, play ONLY once */
+      else  sound_completed  (SND_REDALERT);   /* Done with Red Alert */
+    }
+#endif
+
+    if (oldalert != (me->p_flags & (PFGREEN | PFYELLOW | PFRED))) {
+	if(paradise && auto_zoom_timer<udcounter && (autoZoom || autoUnZoom)) {
+	    int old_zoom=blk_zoom;
+	    switch(autoZoom) {
+	    case 1:
+		if(me->p_flags & (PFYELLOW | PFRED))
+		    blk_zoom = 1;
+		break;
+	    case 2:
+		if(me->p_flags & (PFRED))
+		    blk_zoom = 1;
+		break;
+	    }
+	    switch(autoUnZoom) {
+	    case 1:
+		if(me->p_flags & (PFGREEN))
+		    blk_zoom = 0;
+		break;
+	    case 2:
+		if(me->p_flags & (PFYELLOW | PFGREEN))
+		    blk_zoom = 0;
+		break;
+	    }
+	    if(old_zoom != blk_zoom)
+		redrawall=1;
+	}
+	oldalert = (me->p_flags & (PFGREEN | PFYELLOW | PFRED));
+	if (infoIcon && iconified)
+	    drawIcon();
+	switch (oldalert) {
+	case PFGREEN:
+	    if (extraBorder)
+		W_ChangeBorder(w, gColor);
+	    W_ChangeBorder(baseWin, gColor);
+	    W_ChangeBorder(iconWin, gColor);
+	    break;
+	case PFYELLOW:
+	    if (extraBorder)
+		W_ChangeBorder(w, yColor);
+	    W_ChangeBorder(baseWin, yColor);
+	    W_ChangeBorder(iconWin, yColor);
+	    break;
+	case PFRED:
+	    if (extraBorder)
+		W_ChangeBorder(w, rColor);
+	    W_ChangeBorder(baseWin, rColor);
+	    W_ChangeBorder(iconWin, rColor);
+	    break;
+	}
+    }
+    /* draw stars */
+
+    if (blk_showStars)
+	drawStars();
+
+#ifdef LOCAL_SHIPSTATS
+    if(localShipStats)
+	doLocalShipstats();
+#endif
+
+
+}
+#define DRAWGRID		4
+
+int
+zoom_offset(v)
+    int     v;
+{
+    if (blk_zoom) {
+	register gwidth, ov;
+	/* dimension of zoom area */
+	gwidth = blk_gwidth / 2;
+	/* offset to bring us into new zoom area */
+	ov = (v / (int) gwidth) * gwidth;
+	if (blk_zoom > 1)
+	    return ov;
+	else
+	    /* sector offset into new zoom area */
+	    return ov + (((v - ov) / GRIDSIZE) * GRIDSIZE) - GRIDSIZE;
+    } else
+	return v;
+}
+
+#ifdef HOCKEY
+void galactic_hockey P((void));
+#endif
+
+#ifndef COW_HAS_IT_WHY_SHOULDNT_WE
+static 
+#endif
+void
+map()
+{
+    int     nplan;
+    register int i, k, tmp = blk_gwidth/250;
+    register struct player *j;
+    register struct planet *l;
+    register int dx, dy, odx, ody;
+    static  osx = 0, osy = 0;	/* old square */
+    static  last_offsetx, last_offsety;
+    static int grid_fuse;	/* TSH */
+    register int gwidth, offsetx, offsety;
+    int     color, pl = 0;
+    /*
+       last_lock is used to hold the begin/end point for lock line; [0] holds
+       me->; [1] holds target lock; lockx[2] holds status of line so we can
+       erase if line is there but lock if off
+    */
+    static  last_lockx[3] = {0, 0, 0}, last_locky[2];
+    int     me_galx, me_galy;
+
+    grid_fuse++;		/* we only draw the grids every DRAWGRID
+				   interval */
+
+    /* set number of planets for later */
+    nplan = (paradise) ? nplanets : 40;
+
+    if (reinitPlanets) {
+	initPlanets();
+	reinitPlanets = 0;
+#ifdef HOCKEY
+	/* planets moved so the lines need updating [BDyess] */
+	if(hockey) hockeyInit();
+#endif /*HOCKEY*/
+    }
+
+#ifdef HOCKEY
+    galactic_hockey();
+#endif /*HOCKEY*/
+
+    if (blk_zoom) {
+	gwidth = blk_gwidth / 2;
+	offsetx = zoom_offset(me->p_x);
+	offsety = zoom_offset(me->p_y);
+
+	if (offsetx != last_offsetx || offsety != last_offsety)
+	    redrawall = 1;
+
+	last_offsetx = offsetx;
+	last_offsety = offsety;
+    } else {
+	gwidth = blk_gwidth;
+	offsetx = 0;
+	offsety = 0;
+    }
+
+    me_galx = (me->p_x - offsetx) * WINSIDE / gwidth;
+    me_galy = (me->p_y - offsety) * WINSIDE / gwidth;
+
+/* draw asteroid dots -- this is a test only.  MDM */
+    if( received_terrain_info && paradise ){
+      /* but avoid that SEGV! */
+      for( i = 0; i < 250; i++ ){
+        for( k = udcounter%10; k < 250; k += 10){
+          if(terrainInfo[i*250+k].types & T_ASTEROIDS) {
+            W_DrawPoint( mapw, 
+	                (i*tmp - offsetx) * WINSIDE / gwidth,
+	                (k*tmp - offsety) * WINSIDE / gwidth, 
+			W_White);
+	  }
+	  if (terrainInfo[i*250+k].types & T_NEBULA) {
+	     W_DrawPoint( mapw, 
+			 ((i*tmp - offsetx) * WINSIDE / gwidth) + 1,
+			 ((k*tmp - offsety) * WINSIDE / gwidth) + 1, 
+			 W_Red);
+	  }
+        }
+      }
+    }
+
+    if (redrawall)
+	W_ClearWindow(mapw);
+
+    /* draw grid on galactic */
+    if ((redrawall || (grid_fuse % DRAWGRID) == 0) && (paradise) && (drawgrid)) {
+	int     x, y, w, h, grid;
+	char    numbuf[1];
+	grid = GRIDSIZE * WINSIDE / gwidth;
+	for (i = 1; i <= 6 / (blk_zoom ? 2 : 1); i++) {
+	    /* looks nasty but we only have to do it 3 times if blk_zoom */
+
+	    /* horizontal line */
+	    x = 0;
+	    y = i * grid;
+	    w = WINSIDE;
+	    numbuf[0] = '0' + (char) i;
+	    if (blk_zoom) {
+		/* we might have to clip */
+		dy = i * GRIDSIZE + offsety;
+		if (dy >= 0 && dy <= blk_gwidth + 2 * GRIDSIZE) {
+		    if (offsetx < 0) {
+			x = grid;
+			w = 2 * x;
+		    } else if (offsetx + 3 * GRIDSIZE > blk_gwidth) {
+			w = 2 * grid;
+		    }
+		    W_MakeTractLine(mapw, x, y, x + w, y, W_Grey);
+		}
+		if (sectorNums) {
+		    numbuf[0] = '0' + (char) (i + offsety / 33333);
+		    if ((numbuf[0] == '0') || (numbuf[0] == '7'))
+			numbuf[0] = ' ';
+		    if (i == 1)	/* so numbers dont overwrite in 1st box */
+			W_WriteText(mapw, x + 2, y - grid + 11, W_Grey, numbuf, 1,
+				    W_RegularFont);
+		    else
+			W_WriteText(mapw, x + 2, y - grid + 2, W_Grey, numbuf, 1,
+				    W_RegularFont);
+		}
+	    } else {
+		W_MakeTractLine(mapw, x, y, x + w, y, W_Grey);
+		if (sectorNums) {
+		    W_WriteText(mapw, x + 2, y - grid + 2, W_Grey, numbuf, 1, W_RegularFont);
+		}
+	    }
+	    /* vertical line */
+	    x = i * grid;
+	    y = 0;
+	    h = WINSIDE;
+
+	    if (blk_zoom) {
+		/* we might have to clip */
+		dx = i * GRIDSIZE + offsetx;
+		if (dx >= 0 && dx <= blk_gwidth + 2 * GRIDSIZE) {
+		    if (offsety < 0) {
+			y = grid;
+			h = 2 * y;
+		    } else if (offsety + 3 * GRIDSIZE > blk_gwidth) {
+			h = 2 * grid;
+		    }
+		    W_MakeTractLine(mapw, x, y, x, y + h, W_Grey);
+		}
+		if (sectorNums) {
+		    numbuf[0] = '0' + (char) (i + offsetx / 33333);
+		    if ((numbuf[0] == '0') || (numbuf[0] == '7'))
+			numbuf[0] = ' ';
+		    if (i == 1)
+			W_WriteText(mapw, x - grid + 11, y + 2, W_Grey, numbuf, 1,
+				    W_RegularFont);
+		    else
+			W_WriteText(mapw, x - grid + 2, y + 2, W_Grey, numbuf, 1,
+				    W_RegularFont);
+		}
+	    } else {
+		W_MakeTractLine(mapw, x, y, x, y + h, W_Grey);
+		if (sectorNums) {
+		    W_WriteText(mapw, x - grid + 2, y + 2, W_Grey, numbuf, 1,
+				W_RegularFont);
+		}
+	    }
+	}
+
+	dx = ((me->p_x - offsetx) / GRIDSIZE) * GRIDSIZE;
+	dy = ((me->p_y - offsety) / GRIDSIZE) * GRIDSIZE;
+	if (!redrawall && ((osx != dx) || (osy != dy))) {
+
+	    /* clear old sector */
+	    x = osx * WINSIDE / gwidth;
+	    y = osy * WINSIDE / gwidth;
+	    w = h = grid;
+
+	    W_DrawSectorHighlight(mapw, x, y, w, h, backColor);
+
+	    osx = dx;
+	    osy = dy;
+	}
+	/* draw our current sector */
+	x = dx * WINSIDE / gwidth;
+	w = h = grid;
+	y = dy * WINSIDE / gwidth;
+
+	W_DrawSectorHighlight(mapw, x, y, w, h, yColor);
+    }
+    /* Erase ships */
+    for (i = 0, j = &players[i]; i < nplayers; i++, j++) {
+	lastUpdate[i]++;
+	/*
+	   Erase the guy if: redrawPlayer[i] is set and the mapmode setting
+	   allows it.
+	*/
+	if (!redrawPlayer[i] || (mapmode == GMAP_INFREQUENT && lastUpdate[i] < 5))
+	    continue;
+	lastUpdate[i] = 0;
+	/* Clear his old image... */
+	if (mclearzone[2][i]) {
+	    /* XFIX */
+	    if (!redrawall) {
+		W_ClearArea(mapw, mclearzone[0][i], mclearzone[1][i],
+			    mclearzone[2][i], mclearzone[3][i]);
+		/* Redraw the hole just left next update */
+		checkRedraw(mclearzone[4][i], mclearzone[5][i]);
+	    }
+	    mclearzone[2][i] = 0;
+	}
+    }
+    /* Draw Planets */
+#ifdef HOCKEY
+    if(! (hockey && cleanHockeyGalactic)) {
+#endif
+      for (i = 0, l = &planets[i]; i < nplan; i++, l++) {
+	  char    buf[4];
+	  int     color;
+	  if (!(l->pl_flags & PLREDRAW) && (!redrawall))
+	      continue;
+	  l->pl_flags &= ~PLREDRAW;	/* Turn redraw flag off! */
+
+	  dx = (l->pl_x - offsetx) * WINSIDE / gwidth;
+	  dy = (l->pl_y - offsety) * WINSIDE / gwidth;
+
+	  if (PtOutsideWin(dx, dy))
+	      continue;
+
+	  if (0 == strncmp(l->pl_name, "New ", 4)) {
+	      strncpy(buf, l->pl_name + 4, 3);
+	  } else if (0 == strncmp(l->pl_name, "Planet ", 7)) {
+	      strncpy(buf, l->pl_name + 7, 3);
+	  } else
+	      strncpy(buf, l->pl_name, 3);
+
+	  /* moving planets */
+	  if (pl_update[l->pl_no].plu_update == 1) {
+	      odx = (pl_update[l->pl_no].plu_x - offsetx) * WINSIDE / gwidth;
+	      ody = (pl_update[l->pl_no].plu_y - offsety) * WINSIDE / gwidth;
+
+	      /* XFIX */
+	      W_ClearArea(mapw, odx - (mplanet_width / 2), ody - (mplanet_height / 2),
+			  mplanet_width, mplanet_height);
+
+	      W_WriteText(mapw, odx - (mplanet_width / 2), ody + (mplanet_height / 2),
+			  backColor, buf, 3, planetFont(l));
+
+	      pl_update[l->pl_no].plu_update = 0;
+	  }
+#if 0
+/* not necessary, pl_update is now set whenever a planet needs to be
+ * erased. -JR
+ */
+	  else {
+
+	      /* XFIX */
+	      W_ClearArea(mapw, dx - (mplanet_width / 2), dy - (mplanet_height / 2),
+			  mplanet_width, mplanet_height);
+	  }
+#endif
+	  color = ((paradise) && (l->pl_flags & (PLSTAR | PLWHOLE))) ?
+	      textColor : planetColor(l);
+#ifdef BEEPLITE
+	  if (UseLite && emph_planet_seq_n[l->pl_no] > 0 &&
+	      (F_beeplite_flags & LITE_PLANETS)) {
+	      int     seq_n = emph_planet_seq_n[l->pl_no] % emph_planet_seq_frames;
+
+	      if ((emph_planet_seq_n[l->pl_no] -= 1) > 0)
+		  W_OverlayBitmap(dx - (emph_planet_seq_width / 2),
+				  dy - (emph_planet_seq_height / 2),
+				  emph_planet_seq[seq_n],
+				  emph_planet_color[l->pl_no]);
+	      else
+		  W_ClearArea(mapw, dx - (emph_planet_seq_width / 2),
+			      dy - (emph_planet_seq_height / 2),
+			      emph_planet_seq_width, emph_planet_seq_height);
+	      W_WriteBitmap(dx - (mplanet_width / 2), dy - (mplanet_height / 2),
+			    planetmBitmap(l), color);
+	      l->pl_flags |= PLREDRAW;	/* Leave redraw on until done
+					     highlighting */
+	      pl_update[l->pl_no].plu_update = 1;
+	  } else
+#endif
+          if (!(PL_TYPE(*l) == PLWHOLE)) { /* non wormholes */
+	  W_WriteBitmap(dx - (mplanet_width / 2), dy - (mplanet_height / 2),
+			    planetmBitmap(l), color);
+	  W_WriteText(mapw, dx - (mplanet_width / 2), dy + (mplanet_height / 2),
+		      color, buf, ((strlen(buf) >= 3) ? 3 : strlen(buf)),
+		      planetFont(l));
+#ifdef SHOW_IND
+	  if (showIND && (l->pl_info & idx_to_mask(me->p_teami)) && (l->pl_owner == NOBODY) && l->pl_flags & PLPLANET)
+	  {
+	      W_MakeLine (mapw, dx + (mplanet_width / 2 - 1), dy + (mplanet_height / 2 - 1),
+			  dx - (mplanet_width / 2), dy - (mplanet_height / 2),
+			  W_White);
+	      W_MakeLine (mapw, dx - (mplanet_width / 2), dy + (mplanet_height / 2 - 1),
+			  dx + (mplanet_width / 2 - 1), dy - (mplanet_height / 2),
+			  W_White);
+	  }
+#endif
+	  } 
+#ifdef VISIBLE_WORMHOLES
+	  else { /* wormholes show when scouted [BDyess] */
+	    if(l->pl_info & idx_to_mask(me->p_teami)) { /* have info [BDyess]*/
+	      printf("l->pl_info == %d\n",l->pl_info);
+	      W_WriteBitmap(dx - (mplanet_width / 2), 
+	                    dy - (mplanet_height / 2),
+			    planetmBitmap(l), 
+			    color);
+	    }
+	  }
+#endif /*VISIBLE_WORMHOLES*/
+#ifdef HOCKEY
+    }
+#endif
+    /* Draw ships */
+    for (i = 0, j = &players[i]; i < nplayers; i++, j++) {
+	/*
+	   We draw the guy if redrawall, or we just erased him. Also, we
+	   redraw if we haven't drawn for 30 frames. (in case he was erased
+	   by other ships).
+	*/
+	if (lastUpdate[i] != 0 && (!redrawall) && lastUpdate[i] < 30)
+	    continue;
+	if (j->p_status != PALIVE)
+	    continue;
+	lastUpdate[i] = 0;
+	dx = (j->p_x - offsetx) * WINSIDE / gwidth;
+	dy = (j->p_y - offsety) * WINSIDE / gwidth;
+
+	if ((showLock & 1) && !(j->p_flags & PFCLOAK)) {
+	    if ((me->p_flags & PFPLOCK) && (me->p_playerl == j->p_no)) {
+		if (lockLine) {
+		    if ((last_lockx[0] != me_galx) || (last_locky[0] != me_galx) ||
+			(last_lockx[1] != dx) || (last_locky[1] != dy)) {
+			W_MakeTractLine(mapw, last_lockx[0], last_locky[0],
+				   last_lockx[1], last_locky[1], backColor);
+			last_lockx[0] = me_galx;
+			last_locky[0] = me_galy;
+			last_lockx[1] = dx;
+			last_locky[1] = dy;
+			last_lockx[2] = 1;
+			W_MakeTractLine(mapw, last_lockx[0], last_locky[0],
+				     last_lockx[1], last_locky[1], W_Green);
+
+		    }
+		}
+		W_WriteTriangle(mapw, dx, dy + 6, 4, 1, foreColor);
+		pl = 1;
+	    }
+	}
+	if (PtOutsideWin(dx, dy))
+	    continue;
+
+	if (blk_friendlycloak == 1) {
+	    if (j->p_flags & PFCLOAK) {
+		if (myPlayer(j))
+		    color = myColor;
+		else if (friendlyPlayer(j))
+		    color = playerColor(j);
+		else
+		    color = unColor;
+	    } else
+		color = playerColor(j);
+
+	    pl = 0;
+	    if (j->p_flags & PFCLOAK)
+		W_WriteText(mapw, dx - W_Textwidth * cloakcharslen / 2,
+		    dy - W_Textheight / 2, color, cloakchars, cloakcharslen,
+			    W_RegularFont);
+	    else
+		W_WriteText(mapw, dx - W_Textwidth,
+			    dy - W_Textheight / 2, color, j->p_mapchars, 2,
+			    shipFont(j));
+	} else {
+	    if (j->p_flags & PFCLOAK) {
+		W_WriteText(mapw, dx - W_Textwidth * cloakcharslen / 2,
+		  dy - W_Textheight / 2, unColor, cloakchars, cloakcharslen,
+			    W_RegularFont);
+	    } else {
+		W_WriteText(mapw, dx - W_Textwidth,
+		    dy - W_Textheight / 2, playerColor(j), j->p_mapchars, 2,
+			    shipFont(j));
+	    }
+	}
+
+#ifdef BEEPLITE
+	if (UseLite && emph_player_seq_n[i] > 0 &&
+	    (F_beeplite_flags & LITE_PLAYERS_MAP)) {
+	    int     seq_n = emph_player_seq_n[i] % emph_player_seq_frames;
+
+	    W_WriteBitmap(dx - (emph_player_seq_width / 2 - 1),
+			  dy - (emph_player_seq_height / 2 + 1),
+			  emph_player_seq[seq_n],
+			  emph_player_color[i]);
+	    emph_player_seq_n[i] -= 1;
+	    mclearzone[0][i] = dx - (emph_player_seq_width / 2 - 1);
+	    mclearzone[1][i] = dy - (emph_player_seq_height / 2 + 1);
+	    mclearzone[2][i] = emph_player_seq_width;
+	    mclearzone[3][i] = emph_player_seq_height;
+	    mclearzone[4][i] = j->p_x;
+	    mclearzone[5][i] = j->p_y;
+	    /*
+	       Force redraw for this guy no matter what. Even if stationary.
+	    */
+	    lastUpdate[i] = 30;
+	    /* Leave redraw on until done highlighting */
+	    redrawPlayer[i] = 1;
+	} else
+#endif
+	{
+	    if (j->p_flags & PFCLOAK) {
+		mclearzone[0][i] = dx - W_Textwidth * cloakcharslen / 2;
+		mclearzone[1][i] = dy - W_Textheight / 2;
+		mclearzone[2][i] = W_Textwidth * cloakcharslen;
+	    } else {
+		mclearzone[0][i] = dx - W_Textwidth;
+		mclearzone[1][i] = dy - W_Textheight / 2;
+		mclearzone[2][i] = W_Textwidth * 2;
+	    }
+	    if (pl)
+		mclearzone[3][i] = W_Textheight + 8;
+	    else
+		mclearzone[3][i] = W_Textheight;
+	    /* Set these so we can checkRedraw() next time */
+	    mclearzone[4][i] = j->p_x;
+	    mclearzone[5][i] = j->p_y;
+	    redrawPlayer[i] = 0;
+	}
+    }
+    /* draw viewBox if wanted [BDyess] */
+#define VIEWDIST SCALE * WINSIDE * WINSIDE / (gwidth * 2)
+#define REDRAWDIST SCALE * WINSIDE / 2
+    if (viewBox && allowViewBox) {
+	static int viewx = 0, viewy = 0;
+
+	dx = (me->p_x - offsetx) * WINSIDE / gwidth;
+	dy = (me->p_y - offsety) * WINSIDE / gwidth;
+	if (viewx != dx || viewy != dy || redrawall) {
+	    /* clear old dots - placed here for less flicker */
+	    W_DrawPoint(mapw, viewx + VIEWDIST, viewy + VIEWDIST, backColor);
+	    W_DrawPoint(mapw, viewx + VIEWDIST, viewy - VIEWDIST, backColor);
+	    W_DrawPoint(mapw, viewx - VIEWDIST, viewy + VIEWDIST, backColor);
+	    W_DrawPoint(mapw, viewx - VIEWDIST, viewy - VIEWDIST, backColor);
+	    /* redraw any planets they overwrote */
+	    viewx *= gwidth / WINSIDE + offsetx;	/* correct from view
+							   scale */
+	    viewy *= gwidth / WINSIDE + offsety;
+	    checkRedraw(viewx + REDRAWDIST, viewy + REDRAWDIST);
+	    checkRedraw(viewx + REDRAWDIST, viewy - REDRAWDIST);
+	    checkRedraw(viewx - REDRAWDIST, viewy + REDRAWDIST);
+	    checkRedraw(viewx - REDRAWDIST, viewy - REDRAWDIST);
+	    /* draw the new points */
+	    W_DrawPoint(mapw, dx + VIEWDIST, dy + VIEWDIST, W_White);
+	    W_DrawPoint(mapw, dx + VIEWDIST, dy - VIEWDIST, W_White);
+	    W_DrawPoint(mapw, dx - VIEWDIST, dy + VIEWDIST, W_White);
+	    W_DrawPoint(mapw, dx - VIEWDIST, dy - VIEWDIST, W_White);
+	    viewx = dx;		/* store the points for later */
+	    viewy = dy;		/* clearing */
+	}
+    }
+#undef VIEWDIST
+#undef REDRAWDIST
+
+    if (clearlmcount) {
+	W_WriteTriangle(mapw, clearlmark[0], clearlmark[1], 4, 0, backColor);
+	clearlmcount--;
+    }
+    if (showLock & 1) {
+	/* for now draw this everytime */
+	if ((me->p_flags & PFPLLOCK) && (me->p_status != POBSERVE)) {
+	    struct planet *l = &planets[me->p_planet];
+	    dx = (l->pl_x - offsetx) * WINSIDE / gwidth;
+	    dy = (l->pl_y - offsety) * WINSIDE / gwidth;
+
+	    if (lockLine) {
+		if ((last_lockx[0] != me_galx) || (last_locky[0] != me_galx) ||
+		    (last_lockx[1] != dx) || (last_locky[1] != dy)) {
+		    W_MakeTractLine(mapw, last_lockx[0], last_locky[0],
+				    last_lockx[1], last_locky[1], backColor);
+		    last_lockx[0] = me_galx;
+		    last_locky[0] = me_galy;
+		    last_lockx[1] = dx;
+		    last_locky[1] = dy;
+		    last_lockx[2] = 1;
+		    W_MakeTractLine(mapw, last_lockx[0], last_locky[0],
+				    last_lockx[1], last_locky[1], W_Green);
+		}
+	    }
+	    if (!PtOutsideWin(dx, dy)) {
+		W_WriteTriangle(mapw, dx, dy - (mplanet_height) / 2 - 4, 4, 0,
+				foreColor);
+		clearlmark[0] = dx;
+		clearlmark[1] = dy - (mplanet_height) / 2 - 4;
+		clearlmcount++;
+	    }
+	}
+    }
+    /* if lock line is drawn but no lock; erase lock line */
+    if (lockLine && ((me->p_flags & (PFPLLOCK | PFPLOCK)) == 0) && last_lockx[2]) {
+	W_MakeTractLine(mapw, last_lockx[0], last_locky[0], last_lockx[1],
+			last_locky[1], backColor);
+	last_lockx[2] = 0;
+    }
+    /* redraw warp beacon routes */
+
+    for (i = 0; i < ngthingies; i += 2) {
+	struct thingy *k = &thingies[i + nplayers * npthingies];
+	if (k[0].t_shape == SHP_WARP_BEACON &&
+	    k[1].t_shape == SHP_WARP_BEACON) {
+	    W_MakeLine(mapw, (k[0].t_x - offsetx) * WINSIDE / gwidth,
+		       (k[0].t_y - offsety) * WINSIDE / gwidth,
+		       (k[1].t_x - offsetx) * WINSIDE / gwidth,
+		       (k[1].t_y - offsety) * WINSIDE / gwidth,
+		       W_Grey);
+	}
+    }
+  }
+  redrawall = 0;
+}
+
+#define TWODIGIT_L(p, val) \
+{ \
+    if ((val)<10) { \
+		      (p)[0] = (val)+'0'; \
+		      (p)[1] = ' '; \
+    } else { \
+	       (p)[0] = (val)/10 + '0'; \
+	       (p)[1] = (val)%10 + '0'; \
+	   } \
+}
+
+#define TWODIGIT_R(p, val) \
+{ \
+    if ((val)<10) { \
+		      (p)[0] = ' '; \
+		      (p)[1] = (val)+'0'; \
+    } else { \
+	       (p)[0] = (val)/10 + '0'; \
+	       (p)[1] = (val)%10 + '0'; \
+	   } \
+}
+
+#define THREEDIGIT_C(p, val) \
+{ \
+    if ((val)<10) { \
+		    (p)[0] = ' '; (p)[1] = (val)+'0'; (p)[2] = ' '; \
+    } else if ((val)<100) { \
+			    (p)[0] = (val)/10 + '0'; \
+			    (p)[1] = (val)%10 + '0'; \
+			    (p)[2] = ' ';  \
+    } else { \
+	       (p)[0] = (val)/100 + '0'; \
+	       (p)[1] = ((val)/10 %10) + '0'; \
+	       (p)[2] = (val)%10 + '0'; \
+	   } \
+}
+
+#define THREEDIGIT_R(p, val) \
+{ \
+    if ((val)<10) { \
+		    (p)[0] = ' '; (p)[1] = ' '; (p)[2] = (val)+'0'; \
+    } else if ((val)<100) { \
+			    (p)[0] = ' ';  \
+			    (p)[1] = (val)/10 + '0'; \
+			    (p)[2] = (val)%10 + '0'; \
+    } else { \
+	       (p)[0] = (val)/100 + '0'; \
+	       (p)[1] = ((val)/10 %10) + '0'; \
+	       (p)[2] = (val)%10 + '0'; \
+	   } \
+}
+
+#define FOURDIGIT_R(p, val) \
+{ \
+    if ((val)<10) { \
+		      (p)[0] = ' '; \
+		      (p)[1] = ' '; \
+		      (p)[2] = ' '; \
+		      (p)[3] = (val)+'0'; \
+    } else if ((val)<100) { \
+			      (p)[0] = ' ';  \
+			      (p)[1] = ' ';  \
+			      (p)[2] = (val)/10 + '0'; \
+			      (p)[3] = (val)%10 + '0'; \
+    } else if ((val)<1000) { \
+			       (p)[0] = ' ';  \
+			       (p)[1] = (val)/100 + '0'; \
+			       (p)[2] = ((val)/10 %10) + '0'; \
+			       (p)[3] = (val)%10 + '0'; \
+    } else { \
+	       (p)[0] = (val)/1000 + '0'; \
+	       (p)[1] = ((val)/100 %10) + '0'; \
+	       (p)[2] = ((val)/10 %10) + '0'; \
+	       (p)[3] = (val)%10 + '0'; \
+	   } \
+}
+
+#define SIXDIGIT_R(p, val) \
+{ \
+    if ((val)<10) { \
+		      (p)[0] = ' '; \
+		      (p)[1] = ' '; \
+		      (p)[2] = ' '; \
+		      (p)[3] = ' '; \
+		      (p)[4] = ' '; \
+		      (p)[5] = (val)+'0'; \
+    } else if ((val)<100) { \
+			      (p)[0] = ' ';  \
+			      (p)[1] = ' ';  \
+			      (p)[2] = ' ';  \
+			      (p)[3] = ' ';  \
+			      (p)[4] = (val)/10 + '0'; \
+			      (p)[5] = (val)%10 + '0'; \
+    } else if ((val)<1000) { \
+			       (p)[0] = ' ';  \
+			       (p)[1] = ' ';  \
+			       (p)[2] = ' ';  \
+			       (p)[3] = (val)/100 + '0'; \
+			       (p)[4] = ((val)/10 %10) + '0'; \
+			       (p)[5] = (val)%10 + '0'; \
+    } else if ((val)<10000) { \
+				(p)[0] = ' ';  \
+				(p)[1] = ' ';  \
+				(p)[2] = ((val)/1000 %10) + '0';  \
+				(p)[3] = ((val)/100 %10) + '0'; \
+				(p)[4] = ((val)/10 %10) + '0'; \
+				(p)[5] = (val)%10 + '0'; \
+    } else if ((val)<100000) { \
+				 (p)[0] = ' ';  \
+				 (p)[1] = ((val)/10000 %10) + '0';  \
+				 (p)[2] = ((val)/1000 %10) + '0';  \
+				 (p)[3] = ((val)/100 %10) + '0'; \
+				 (p)[4] = ((val)/10 %10) + '0'; \
+				 (p)[5] = (val)%10 + '0'; \
+    } else { \
+	       (p)[0] = (val)/100000 + '0';  \
+	       (p)[1] = ((val)/10000 %10) + '0';  \
+	       (p)[2] = ((val)/1000 %10) + '0'; \
+	       (p)[3] = ((val)/100 %10) + '0'; \
+	       (p)[4] = ((val)/10 %10) + '0'; \
+	       (p)[5] = (val)%10 + '0'; \
+	   } \
+}
+
+#define SIXnTWOf_R(p, val) \
+{ \
+    (p)[3] = '.'; \
+    (p)[4] = ((int) (10*(val))) %10 + '0'; \
+    (p)[5] = ((int) (100*(val))) %10 + '0'; \
+    if ((val)<10) { \
+		      (p)[0] = ' '; \
+		      (p)[1] = ' '; \
+		      (p)[2] = ((int)(val))+'0'; \
+    } else if ((val)<100) { \
+			      (p)[0] = ' ';  \
+			      (p)[1] = ((int)(val))/10 + '0'; \
+			      (p)[2] = ((int)(val))%10 + '0'; \
+    } else { \
+	       (p)[0] = ((int)(val))/100 + '0'; \
+	       (p)[1] = (((int)(val))/10 %10) + '0'; \
+	       (p)[2] = ((int)(val))%10 + '0'; \
+	   } \
+}
+
+#if 0
+
+static void
+stline(flag)
+    int     flag;
+{
+    static char buf1[80];
+    static char buf2[80];
+    static char whichbuf = 0;
+    static int lastnewDashboard;
+    register char *buf, *oldbuf;
+    register char *s;
+    register int i, j;
+    int     k;
+/* if you don't do something like this, then switching in the options menu
+   is 'entertaining'  */
+    if (newDashboard != lastnewDashboard) {
+	lastnewDashboard = newDashboard;
+	redrawTstats();
+	return;
+    }
+/* use the new dashboard if we can */
+
+
+
+
+
+
+    if (newDashboard) {
+	db_redraw(flag);
+	return;
+    }
+    /* Instead of one sprintf, we do all this by hand for optimization */
+
+    if (flag)
+	whichbuf = 0;		/* We must completely refresh */
+
+    if (whichbuf != 2) {
+	buf = buf1;
+	oldbuf = buf2;
+    } else {
+	buf = buf2;
+	oldbuf = buf1;
+    }
+    buf[0] = (me->p_flags & PFSHIELD ? 'S' : ' ');
+    if (me->p_flags & PFGREEN)
+	buf[1] = 'G';
+    else if (me->p_flags & PFYELLOW)
+	buf[1] = 'Y';
+    else if (me->p_flags & PFRED)
+	buf[1] = 'R';
+    buf[2] = (me->p_flags & (PFPLLOCK | PFPLOCK) ? 'L' : ' ');
+    buf[3] = (me->p_flags & PFREPAIR ? 'R' : ' ');
+    buf[4] = (me->p_flags & PFBOMB ? 'B' : ' ');
+    buf[5] = (me->p_flags & PFORBIT ? 'O' : ' ');
+    buf[6] = (me->p_flags & PFDOCKOK ? 'D' : ' ');
+/*      buf[6] = (me->p_flags & PFDOCK ? 'D' : ' ');*/
+    buf[7] = (me->p_flags & PFCLOAK ? 'C' : ' ');
+    buf[8] = (me->p_flags & PFWEP ? 'W' : ' ');
+    buf[9] = (me->p_flags & PFENG ? 'E' : ' ');
+    if (me->p_flags & PFPRESS)
+	buf[10] = 'P';
+    else if (me->p_flags & PFTRACT)
+	buf[10] = 'T';
+    else
+	buf[10] = ' ';
+    if (me->p_flags & PFBEAMUP)
+	buf[11] = 'u';
+    else if (me->p_flags & PFBEAMDOWN)
+	buf[11] = 'd';
+    else
+	buf[11] = ' ';
+    if (!paradise)
+	buf[12] = (status->tourn) ? 't' : ' ';
+    else
+	buf[12] = (status2->tourn) ? 't' : ' ';
+
+    buf[13] = ' ';
+
+#if 1
+/* w/i indicator is a kludge - it just guesses based on the speed of
+   the ship */
+    sprintf(buf + 14, "%2d%c   %3d %3d  %1d  %6.2f %3d %6d  %4d %4d  ",
+	me->p_speed, (me->p_speed > me->p_ship->s_maxspeed + 2) ? 'w' : 'i',
+	    me->p_damage, me->p_shield, me->p_ntorp, me->p_kills,
+	    me->p_armies, me->p_fuel, me->p_wtemp, me->p_etemp);
+#else
+#if 0
+    TWODIGIT_L(&buf[14], me->p_speed);
+    buf[16] = 'i';
+    buf[17] = ' ';
+    buf[18] = ' ';
+    buf[19] = ' ';
+    THREEDIGIT_R(&buf[20], me->p_damage);
+    buf[23] = ' ';
+    THREEDIGIT_R(&buf[24], me->p_shield);
+    buf[27] = ' ';
+    TWODIGIT_R(&buf[28], me->p_ntorp);
+    buf[30] = ' ';
+    buf[31] = ' ';
+    SIXnTWOf_R(&buf[32], me->p_kills);
+    buf[38] = ' ';
+    THREEDIGIT_C(&buf[39], me->p_armies);
+    buf[42] = ' ';
+    SIXDIGIT_R(&buf[43], me->p_fuel);
+    buf[49] = ' ';
+    buf[50] = ' ';
+    FOURDIGIT_R(&buf[51], me->p_wtemp / 10);
+    buf[55] = ' ';
+    FOURDIGIT_R(&buf[56], me->p_etemp / 10);
+    buf[60] = ' ';
+    buf[61] = ' ';
+#else
+    buf[14] = '0' + ((me->p_speed % 100) / 10);
+    if (buf[14] == '0')
+	buf[14] = ' ';
+    buf[15] = '0' + (me->p_speed % 10);	/* speed */
+    buf[16] = ' ';
+    buf[17] = ' ';
+    buf[18] = '0' + (me->p_damage / 100);
+    if (buf[18] == '0')
+	buf[18] = ' ';
+    buf[19] = '0' + ((me->p_damage % 100) / 10);
+    if ((buf[19] == '0') && (me->p_damage < 100))
+	buf[19] = ' ';
+    buf[20] = '0' + (me->p_damage % 10);
+    buf[21] = ' ';
+    buf[22] = '0' + (me->p_shield / 100);
+    if (buf[22] == '0')
+	buf[22] = ' ';
+    buf[23] = '0' + ((me->p_shield % 100) / 10);
+    if ((buf[23] == '0') && (me->p_shield < 100))
+	buf[23] = ' ';
+    buf[24] = '0' + (me->p_shield % 10);
+    buf[25] = ' ';
+    buf[26] = ' ';
+    buf[27] = '0' + ((me->p_ntorp % 100) / 10);
+    if (buf[27] == '0')
+	buf[27] = ' ';
+    buf[28] = '0' + (me->p_ntorp % 10);
+    buf[29] = ' ';
+    buf[30] = ' ';
+    buf[31] = ' ';
+    buf[32] = ' ';
+    buf[33] = '0' + ((int) (me->p_kills / 10));
+    if (buf[33] == '0')
+	buf[33] = ' ';
+    buf[34] = '0' + (((int) me->p_kills) % 10);
+    buf[35] = '.';
+    buf[36] = '0' + (((int) (me->p_kills * 10)) % 10);
+    buf[37] = '0' + (((int) (me->p_kills * 100)) % 10);
+    buf[38] = ' ';
+    buf[39] = ' ';
+    buf[40] = ' ';
+    buf[41] = '0' + ((me->p_armies % 100) / 10);
+    if (buf[41] == '0')
+	buf[41] = ' ';
+    buf[42] = '0' + (me->p_armies % 10);
+    buf[43] = ' ';
+    buf[44] = ' ';
+    buf[45] = ' ';
+
+    buf[46] = '0' + (me->p_fuel / 100000);
+    if (buf[46] == '0')
+	buf[46] = ' ';
+    buf[47] = '0' + ((me->p_fuel % 100000) / 10000);
+    if ((buf[47] == '0') && (me->p_fuel < 100000))
+	buf[47] = ' ';
+    buf[48] = '0' + ((me->p_fuel % 10000) / 1000);
+    if ((buf[48] == '0') && (me->p_fuel < 10000))
+	buf[48] = ' ';
+    buf[49] = '0' + ((me->p_fuel % 1000) / 100);
+    if ((buf[49] == '0') && (me->p_fuel < 1000))
+	buf[49] = ' ';
+    buf[50] = '0' + ((me->p_fuel % 100) / 10);
+    if ((buf[50] == '0') && (me->p_fuel < 100))
+	buf[50] = ' ';
+    buf[51] = '0' + (me->p_fuel % 10);
+    buf[52] = ' ';
+    buf[53] = ' ';
+    buf[54] = ' ';
+
+    buf[55] = '0' + ((me->p_wtemp / 10) / 100);
+    if (buf[55] == '0')
+	buf[55] = ' ';
+    buf[56] = '0' + (((me->p_wtemp / 10) % 100) / 10);
+    if ((buf[56] == '0') && (me->p_wtemp < 1000))
+	buf[56] = ' ';
+    buf[57] = '0' + ((me->p_wtemp / 10) % 10);
+
+    buf[58] = ' ';
+    buf[59] = ' ';
+    buf[60] = ' ';
+    buf[61] = '0' + ((me->p_etemp / 10) / 1000);
+    if (buf[61] == '0')
+	buf[61] = ' ';
+    buf[62] = '0' + (((me->p_etemp / 10) % 1000) / 100);
+    if (buf[62] == '0' && me->p_etemp < 1000)
+	buf[62] = ' ';
+    buf[63] = '0' + (((me->p_etemp / 10) % 100) / 10);
+    if ((buf[63] == '0') && (me->p_etemp < 1000))
+	buf[63] = ' ';
+    buf[64] = '0' + ((me->p_etemp / 10) % 10);
+    buf[65] = ' ';
+#endif
+#endif
+
+    if (whichbuf == 0) {
+	/* Draw status line */
+	W_WriteText(tstatw, TSTATW_BASEX, 16, textColor, buf, 66, W_RegularFont);
+	whichbuf = 1;
+    } else {			/* Hacks to make it print only what is
+				   necessary */
+	whichbuf = 3 - whichbuf;
+	j = -1;
+	for (i = 0; i < 66; i++) {
+	    if (*(buf++) != *(oldbuf++)) {
+		/* Different string */
+		if (j == -1) {
+		    k = i;
+		    s = buf - 1;
+		}
+		j = 0;
+	    } else {
+		/* Same string */
+		if (j == -1)
+		    continue;
+		j++;
+		if (j == 20) {	/* Random number */
+		    W_WriteText(tstatw, TSTATW_BASEX + W_Textwidth * k, 16, textColor,
+				s, i - k - 19, W_RegularFont);
+		    j = -1;
+		}
+	    }
+	}
+	if (j != -1) {
+	    W_WriteText(tstatw, TSTATW_BASEX + W_Textwidth * k, 16, textColor, s, i - k - j,
+			W_RegularFont);
+	}
+    }
+}
+
+void
+redrawTstats()
+{
+    char    buf[100];
+    W_ClearWindow(tstatw);
+    /* use new dashboard if possible */
+    if (newDashboard) {
+	db_redraw(1);
+	return;
+    }
+    stline(1);			/* This is for refresh.  We redraw player
+				   stats too */
+    strcpy(buf, "Flags        Speed  Dam Shd Trp  Kills Ams   Fuel  Wtmp Etmp  Special"	/* "Flags        Warp
+											   Dam Shd Torps  Kills
+											   Armies   Fuel  Wtemp
+	       Etemp" */ );
+    W_WriteText(tstatw, TSTATW_BASEX, 5, textColor, buf, strlen(buf), W_RegularFont);
+    sprintf(buf,
+	    "Maximum:      %2d    %3d %3d  8         %3d %6d  %4d %4d ",
+	    me->p_ship->s_maxspeed, me->p_ship->s_maxdamage,
+	    me->p_ship->s_maxshield, me->p_ship->s_maxarmies,
+	    me->p_ship->s_maxfuel, me->p_ship->s_maxwpntemp / 10,
+	    me->p_ship->s_maxegntemp / 10);
+    W_WriteText(tstatw, TSTATW_BASEX, 27, textColor, buf, strlen(buf), W_RegularFont);
+}
+#endif