/*
 * bzkill.c
 * aka: Mr Smith.
 *   -- v0.9 (not stable enuff for my likez, but it workz)
 *   -- code by z3r0 c00l and 8o88yD1g1t4L
 *
 * dedictated to Xtra .. u gm camping skirt ..
 * released after being kiked @bzflag.secretplace.us, thanks C++ 
 * [yeah yeah .. u were just doin' ur job, u bested ;-)]
 *
 *
 *
 *
 * so u doan feel bad bout copying this proggy (GNU GPL);
 *
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 *
 * with the addition that u doan need to contact me with the mods ;-)
 *
 *
 *
 *
 * --
 * bzflag [bzflag.org] is multiplayer 3D tank battle game, a bugfest
 * and a cheaters heaven. bzflag listens on at least two tcp ports, one
 * port feeding us the bzfs [bzflag server] version and reconnect port,
 * and the other one where the real fun begins. force feeding these ports
 * with some magic fairy powder can make bzfs go insane and eat itself.
 * --
 * for these trix-n-more .. see bzdeath.c by the russian code molester.
 *
 *
 * if ur flvr ov mayhem is sltly more sufistikated, then bzkill.c is 4
 * u. by entering the gaam as a reel usr, u will launch endless hrs ov
 * havoc by stalking ur prey.  Mr Smith has majical Matrix-like powers ..
 * he alwyz no'z where hiz victim is and wich way hez facing. Mr Smith has
 * an unkwencheble thirst for shooting vctmz in the bck .. respawning where
 * they respawn .. dying when they dy .. re-aliasing is the vctmz only
 * hope .. unless .. maybe u want to lock onto his playerid? (its all in
 * the pkt payload numb-nuts; http://www.bzflag.org/developers/protocol.php).
 *
 *
 * consider ths the 1st reel wurking bot for bzf (2weekz of l8 nitez 2 c0d3).
 *
 *
 * shoutz to the russian code molester .. ur mummas at my place, cum
 * pick her lazy ass up. [yes, those horz at neworder.box.sk put ur
 * file in their "latest vulnerabilities" section] ... ud corz more DoS
 * damage if u created a UDP session (c0d3 belo) and flooded it instead ..
 * they've c0d3d around ur antiks in g2.
 *
 *
 * hak the planet.
 *
*/

/*
 * not reely into this c-crap but want to compile it to run it?
 *
 * sh# gcc bzkill.c -o ./bzkill -lm -lpthread -O2 -Wall -fno-strict-aliasing
 * sh# strip bzkill
 * sh# ./bzkill
 *
 *
 * have a cookie.
 *
*/
 

#include <stdio.h>
#include <math.h>
#include <tgmath.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <time.h>



// If Linus could only c ths->list of #definz ;-))
#if 0
#define DEBUGbzcnct(format, args...) printf("bzcnct: " format, ## args)
#define DEBUGbzudpr(format, args...) printf("bzudpr: " format, ## args)
#define DEBUGbzudps(format, args...) printf("bzudps: " format, ## args)
#define DEBUGbznter(format, args...) printf("bznter: " format, ## args)
#define DEBUGbzrlay(format, args...) printf("bzrlay: " format, ## args)
#define DEBUGbzlpng(format, args...) printf("bzlpng: " format, ## args)
#define DEBUGbzpngr(format, args...) printf("bzpngr: " format, ## args)
#define DEBUGbzlive(format, args...) printf("bzlive: " format, ## args)
#define DEBUGbzupdt(format, args...) printf("bzupdt: " format, ## args)
#define DEBUGbzshot(format, args...) printf("bzshot: " format, ## args)
#define DEBUGbztprt(format, args...) printf("bztprt: " format, ## args)
#define DEBUGbzqery(format, args...) printf("bzqery: " format, ## args)
#define DEBUGgetPacket(format, args...) printf("getPacket: " format, ## args)
#define DEBUGgetmsg(format, args...) printf("getMsg: " format, ## args)
#define DEBUGbzexit(format, args...) printf("bzexit: " format, ## args)
#else
#define DEBUGbzcnct(format, args...)
#define DEBUGbzudpr(format, args...)
#define DEBUGbzudps(format, args...)
#define DEBUGbznter(format, args...)
#define DEBUGbzrlay(format, args...)
#define DEBUGbzlpng(format, args...)
#define DEBUGbzpngr(format, args...)
#define DEBUGbzlive(format, args...)
#define DEBUGbzupdt(format, args...)
#define DEBUGbzshot(format, args...)
#define DEBUGbztprt(format, args...)
#define DEBUGbzqery(format, args...)
#define DEBUGgetPacket(format, args...)
#define DEBUGgetmsg(format, args...)
#define DEBUGbzexit(format, args...)
#endif



// The Best Of Collection: Protocol.h 

// multicast message codes
#define MsgPlayerUpdate		0x7075
#define MsgGMUpdate		0x676d
#define MsgAudio		0x6175
#define MsgVideo		0x7669

// server message codes
#define	MsgAccept		0x6163
#define	MsgAlive		0x616c
#define	MsgAddPlayer		0x6170
#define	MsgAcquireRadio		0x6172
#define	MsgCaptureFlag		0x6366
#define	MsgDropFlag		0x6466
#define	MsgEnter		0x656e
#define	MsgExit			0x6578
#define	MsgFlagUpdate		0x6675
#define	MsgGrabFlag		0x6766
#define	MsgGetWorld		0x6777
#define	MsgIdAck		0x6964
#define	MsgKilled		0x6b6c
#define	MsgMessage		0x6d67
#define	MsgNetworkRelay		0x6e72
#define	MsgQueryGame		0x7167
#define	MsgQueryPlayers		0x7170
#define	MsgReject		0x726a
#define	MsgRemovePlayer		0x7270
#define	MsgReleaseRadio		0x7272
#define	MsgShotBegin		0x7362
#define	MsgScore		0x7363
#define	MsgScoreOver		0x736f
#define	MsgShotEnd		0x7365
#define	MsgSuperKill		0x736b
#define	MsgTimeUpdate		0x746f
#define	MsgTeleport		0x7470
#define	MsgSetTTL		0x7474
#define	MsgTeamUpdate		0x7475
#define	MsgWantWHash		0x7768

// world database codes
// the world is not enuff - irrlvnt
#define WorldCodeBase		0x6261
#define WorldCodeBox		0x6278
#define WorldCodeEnd		0x6564
#define WorldCodeLink		0x6c6e
#define WorldCodePyramid	0x7079
#define WorldCodeStyle		0x7374
#define WorldCodeTeleporter	0x7465
#define WorldCodeWall		0x776c

// ping packet sizes, codes and structure
#define PingCodeOldReply	0x0101
#define PingCodeOldRequest	0x0202
#define PingCodeReply		0x0303
#define PingCodeRequest		0x0404

// radio flags
#define RadioToAll		0x0001

// rejection codes
#define RejectBadRequest	0x0001
#define RejectBadTeam		0x0002
#define RejectBadType		0x0003
#define RejectNoRogues		0x0004
#define RejectTeamFull		0x0005
#define RejectServerFull	0x0006

// request for additional UDP link
#define MsgUDPLinkRequest	0x6f66
#define MsgUDPLinkEstablished	0x6f67
#define MsgUDPLinkUpdate	0x6f68
#define MsgClientVersion	0x6f6a

// server control message
#define MsgServerControl	0x6f69

// lag ping sent by server to client and reply from client
#define MsgLagPing		0x7069



// And then there's global.h ...

// Flags ..
#define NullFlag		0
#define NoFlag			0

// team flags:
#define RedFlag			1
#define GreenFlag		2
#define BlueFlag		3
#define PurpleFlag		4

// the good super flags:
#define VelocityFlag		5
#define QuickTurnFlag		6
#define OscOverthrusterFlag	7
#define RapidFireFlag		8
#define MachineGunFlag		9
#define GuidedMissileFlag	10
#define LaserFlag		11
#define RicochetFlag		12
#define SuperBulletFlag		13
#define InvisibleBulletFlag	14
#define StealthFlag		15
#define TinyFlag		16
#define NarrowFlag		17
#define ShieldFlag		18
#define SteamrollerFlag		19
#define ShockWaveFlag		20
#define PhantomZoneFlag		21
#define GenocideFlag		22
#define JumpingFlag		23
#define IdentifyFlag		24
#define CloakingFlag		25

// the bad super flags
#define ColorblindnessFlag	26
#define ObesityFlag		27
#define LeftTurnOnlyFlag	28
#define RightTurnOnlyFlag	29
#define MomentumFlag		30
#define BlindnessFlag		31
#define JammingFlag		32
#define WideAngleFlag		33



// And then there's flag.h

// Flag Status
#define FlagNoExist		0
#define FlagOnGround		1
#define FlagOnTank		2
#define FlagInAir		3
#define FlagComing		4
#define FlagGoing		5

// Flag Type
#define FlagNormal		0
#define FlagUnstable		1
#define FlagSticky		2


// Also see ServerLink.cxx ..
#define INTERNALVERSION		0x17a0
#define	UDPPktHdr		0xfeed


// And some other file ...

// Player Status
#define DeadStatus		0x0000
#define Alive			0x0001
#define Paused			0x0002
#define Exploding		0x0004
#define Teleporting		0x0008
#define FlagActive		0x0010
#define CrossingWall		0x0020
#define Falling			0x0040



// Home grown defs ... 

// Teams
#define team_rogue 		0
#define team_red		1
#define team_green		2
#define team_blue		3
#define team_purple		4

// Player Types
#define plyr_tank		0
#define plyr_jafo		1
#define plyr_robo		2

// Lookup Types
#define byident			0
#define byalias			1

#define shotspeed		50


// Yo cucumber licker - search for any reference of PI_4 and ze_azimuth
// and replace the old code... happy hackin
#define PI			3.14159265358979323846
#define PI_2			1.57079632679489661923
#define PI_4			0.78539816339744830962


#define BUFSIZE 16192
#define TIMEOUT 10
#define	ADV(_b, _t)	((void*)(((char*)(_b)) + sizeof(_t)))


pthread_mutex_t mutex_addplyr		= PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_getmsg		= PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_haltpayload	= PTHREAD_MUTEX_INITIALIZER;
pthread_t thr_pid[5] = { 0 };
int	term = 0;


int  _connect(char*, int, int, int);
void die(char*);
void banner();
void usage();


// Player Defaults
char *	usr_victm		= "Xtra";
char *	usr_alias		= "Mr Smith.";
char *	usr_email		= "mememememe, me2";
int	usr_team		= team_rogue;
int	usr_plyr		= plyr_tank;
int	dflt_port		= 5155;
int	dflt_smith		= 1;


// Socket Info
int ctrl_pt;
int data_pt;
int urcv_pt;
int usnd_pt;
int ctrl_fd;
int data_fd;
int urcv_fd;
int usnd_fd;
uint32_t srvr_ad;
struct sockaddr urcv_ad;
struct sockaddr usnd_ad;

// Critical Buffers
char *	tcp_buf_msg;
char *	tcp_buf_pri;
char *	tcp_pri_ptr;
char *	tcp_msg_ptr;
char *	udp_buf_msg;
char *	udp_buf_pri;
char *	udp_pri_ptr;
char *	udp_msg_ptr;

int team_num;
int plyr_num;


char	dman[32];
char	dhost[128];
char	dport[16];
int	dteam;
char	dalias[32];
char	demail[128];
int	ismith;

int	len_dman   = 32;
int	len_dhost  = 128;
int	len_dport  = 16;
int	len_dalias = 32;
int	len_demail = 128;
int	len_orig_dalias;

int	firstMsgMessage;
int	rejectcode;
int	smith_count;


// const char sMsgBuf[MaxPacketLen];
// char sMsgBuf[1024];


/*
 * N0t3 th1s (yes, u)
 * 
 *   if u ever haz problemz uzing this proggy then
 *   make the playerid var/field look like a reel 
 *   client .. it iz the only thng that makez uz
 *   look out ov place on the gaam srvr ... cept
 *   may-b the lastRecvPacketNo in the sh0t ..
 */
char playerid[9] = "xxxxxxxx\0";




int plyr_live	= 0;
char plyr_vry1[5] = "NULL";

struct player {
	char	id[32];
	int	status;
	char	alias[32];
	char	email[128];
	int	type;
	int	team;
	float	px;
	float	py;
	float	pz;
	float	fx;
	float	fy;
	float	fz;
	float	azimuth;
	float	angular_velocity;
	int	tport_from;
	int	tport_to;
	uint	last_playerupdate;
	uint	last_tport;
	struct	player *next;
};
struct player *player_ptr;


struct team {
	int	plyrs_cur;
	int	plyrs_max;
	int	score_win;
	int	score_los;
	int	score_cur;
	struct	team *next;
};
struct team *team_ptr;




// TIME FUNCTIONS
// unused -- intended to make the player updatz okkur *only* when the plyr
// state changed ... thr iz a small sleep in the payload loop .. if you rmoov
// this sleep (or shrink it too far) thn Mr Smith will DoS the gaam server 
// with updatz .... (thinking of u code molester, u dribbler) 

//---- time -----------------------------------------------------------------
/*
Long_t TUnixSystem::UnixNow()
{
   // Get current time in milliseconds since 0:00 Jan 1 1995.

   static time_t jan95 = 0;
   if (!jan95) {
      struct tm tp;
      tp.tm_year  = 95;
      tp.tm_mon   = 0;
      tp.tm_mday  = 1;
      tp.tm_hour  = 0;
      tp.tm_min   = 0;
      tp.tm_sec   = 0;
      tp.tm_isdst = -1;

      jan95 = mktime(&tp);
      if ((int)jan95 == -1) {
         ::SysError("TUnixSystem::UnixNow", "error converting 950001 0:00 to time_t");
         return 0;
      }
   }

   struct timeval t;
   gettimeofday(&t, 0);
   return (t.tv_sec-(Long_t)jan95)*1000 + t.tv_usec/1000;
}



// sendClientVersion();
void
sendClientVersion()
{
	char msg[2];
	void* buf = msg;
	buf = nboPackUShort(buf, INTERNALVERSION);
	send(MsgClientVersion, sizeof(msg), msg);
}


*/




// ENCODE/DECODE FUNCTIONS


void*
nboPackUShort(void* b, uint16_t v)
{
	const uint16_t x = (uint16_t)htons(v);
	memcpy(b, &x, sizeof(uint16_t));
	return ADV(b, uint16_t);
}

void*
nboPackFloat(void* b, float v)
{
	uint32_t x = htonl(*((uint32_t*)&v));
	const float y = *((float*)&x);
	memcpy(b, &y, sizeof(float));
	return ADV(b, float);
}

void*
nboPackString(void* b, const void* m, int len)
{
	if (!m || len == 0) return b;
	memcpy(b, m, len);
	return (void*)((char*)b + len);
}

uint16_t
getUnpackUShort(void* b)
{
	uint16_t v;
	uint16_t x;
	memcpy(&x, b, sizeof(uint16_t));
	v = (uint16_t)ntohs(x);
	return v;
}

float
getUnpackFloat(void* b)
{
	float v;
	uint32_t x;
	uint32_t y;
	memcpy(&x, b, sizeof(uint32_t));
	y = (uint32_t)ntohl(x);
	v = *((float*)&y);
	return v;
}




// SOCKET FUNCTIONS


int
_connect(char *host, int port, int sockopt, int proto) {
	struct	hostent *he;
	struct	sockaddr_in remote_addr;
	int	sockfd;
	int	flag;

	if((he = gethostbyname(host)) == NULL)
		return -1;

	remote_addr.sin_family = AF_INET;
	remote_addr.sin_addr = *((struct in_addr *)he->h_addr);
	remote_addr.sin_port = htons(port);
	memset(&(remote_addr.sin_zero), 0x00, 8);

	// for udp connection, store server spec
	srvr_ad = remote_addr.sin_addr.s_addr;

	switch(proto) {

		case IPPROTO_UDP:
			if((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
				return -1;
			printf("_connect: have udp socket.\n");
			break;
			;;
			

		case IPPROTO_TCP:
			if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
				return -1;
			printf("_connect: have tcp socket.\n");
			if(sockopt == 1) {
				flag = 1;
  				if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) < 0 )
					return -1;
			}
			break;
			;;

		default:
			return -1;
			break;
			;;

	}

	if(connect(sockfd, (struct sockaddr *)&remote_addr, 
			sizeof(struct sockaddr)) == -1)
		return -1;

	return sockfd;
}


int
bzudpr(void) {
	char *		msg;
	char *		buf;
	int		tcplen;
	uint16_t	code;

	struct sockaddr_in serv_addr;
	uint32_t	addr_len = sizeof(serv_addr);


	DEBUGbzudpr("binding UDP listener\n");

	if ((urcv_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		printf("bzudpr: socket() failed, no udp receiver ..\n");
		return -1;
	}

	for (urcv_pt=17200; urcv_pt < 65000; urcv_pt++) {
		memset((unsigned char *)&serv_addr, 0, sizeof(serv_addr));
		serv_addr.sin_family = AF_INET;
		serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
		serv_addr.sin_port = htons(urcv_pt);
		if (bind(urcv_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == 0) {
			break;
		}
	}

	if (getsockname(urcv_fd, (struct sockaddr*)&serv_addr, (socklen_t*) &addr_len) < 0) {
		close(urcv_fd);
		urcv_fd = 0;
		printf("bzudpr: getsockname() failed, no udp receiver ..\n");
		return -1;
	}

	// store pervasive data
	urcv_pt = ntohs(serv_addr.sin_port);
	memcpy((char *)&urcv_ad,(char *)&serv_addr, sizeof(serv_addr));


	DEBUGbzudpr("sending MsgUDPLinkRequest\n");

	code = MsgUDPLinkRequest;
	tcplen = 6;

	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bzudpr: malloc failed, no udp receiver ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);

	buf = msg;
	buf = nboPackUShort(buf, (uint16_t)2);
	buf = nboPackUShort(buf, code);
	buf = nboPackUShort(buf, (uint16_t)urcv_pt);

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bzudpr: send() failed, no udp receiver ..\n");
		return -1;
	}
	free(msg);

	return 0;
}


int
bzudps(void) {
	char *		msg;
	char *		buf;
	int		tcplen;
	uint16_t	code;

	struct sockaddr_in serv_addr;
	struct sockaddr_in xist_addr;
	uint32_t	addr_len = sizeof(serv_addr);


	DEBUGbzudps("finding UDP server\n");

	if (getsockname(data_fd, (struct sockaddr*)&xist_addr, (socklen_t*) &addr_len) < 0) {
		printf("bzudps: getsockname() failed, no udp sender ..\n");
		return -1;
	}

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = srvr_ad;
	serv_addr.sin_port = htons(usnd_pt);

	// store pervasive data
	memcpy((char *)&usnd_ad,(char *)&serv_addr, sizeof(serv_addr));
	usnd_fd = urcv_fd;


	DEBUGbzudpr("sending MsgUDPLinkEstablished\n");

	code = MsgUDPLinkEstablished;
	tcplen = 6;

	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bzudps: malloc failed, no udp sender ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);

	buf = msg;
	buf = nboPackUShort(buf, (uint16_t)2);
	buf = nboPackUShort(buf, code);
	buf = nboPackUShort(buf, (uint16_t)0);

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bzudps: send() failed, no udp sender ..\n");
		return -1;
	}
	free(msg);

	return 0;
}




// BZFLAG FUNCTIONS


int
bzcnct(char * host, int port) {
	char	buf[BUFSIZE];
	char	bzsign[8];


	memset(buf, 0, BUFSIZE);

	DEBUGbzcnct("connecting to %s:%s ..\n", host, port);
	if((ctrl_fd = _connect(host, port, 0, IPPROTO_TCP)) == -1) {
		printf("bzcnct: unable to connect to control port.\n");
		return -1;
	}
 
	DEBUGbzcnct("main: connection established.\n");
	if(recv(ctrl_fd, buf, 16, 0) <= 0) {
		close(ctrl_fd);
		printf("bzcnct: recv() failed\n");
		return -1;
	}

	DEBUGbzcnct("control channel ascii: %s\n", buf);

	sprintf(bzsign, "%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
	if(!strcmp(bzsign, "BZFS")) {
		DEBUGbzcnct("bzfs signature confirmed\n");
		printf("bzcnct: server signature [%c%c%c%c %c.%c%c%c]\n",
		buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
	} else {
		close(ctrl_fd);
		printf("bzcnct: bzfs signature mismatch (NOT bzflag server)\n");
		return -1;
	}

	if(strlen(buf) >= 10) {
		data_pt = (((int) buf[strlen(buf) - 2]) << 8) | buf[strlen(buf) - 1];
	} else {
		close(ctrl_fd);
		printf("bzcnct: server did not send reconnect port\n");
		return -1;
	}

	if(data_pt >= 64 * 1024 || data_pt <= 0) {
		close(ctrl_fd);
		printf("bzcnct: server sent illegal data port.\n");
		return -1;
	}

	DEBUGbzcnct("data port is %d\n", data_pt);
	DEBUGbzcnct("connecting to %s:%d ..\n", host, data_pt);

	if((data_fd = _connect(host, data_pt, 1, IPPROTO_TCP)) == -1) {
		close(ctrl_fd);
		printf("bzcnct: unable to connect to data port.\n");
		return -1;
	}

	return 0;
}

int
bznter(uint16_t type, uint16_t team, const char* palias, const char* pemail)
{
	char *		msg;
	char *		buf;
	int		buflen, tcplen;
	uint16_t	code;


	code = (int)MsgEnter;

	buflen = 12 + sizeof(dalias) + sizeof(demail);
	tcplen = sizeof(uint16_t) + sizeof(uint16_t) + strlen(playerid) +
			sizeof(uint16_t) + sizeof(uint16_t) + sizeof(dalias) +
			sizeof(demail);

	DEBUGbznter("total length = %d\n", buflen);


	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bznter: malloc failed, no nter ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);
	buf = msg;
	buf = nboPackUShort(buf, (uint16_t)buflen);
	buf = nboPackUShort(buf, code);

	/*
	hostaddr = (int32_t)gethostbyname(host);
	memcpy(buf, &hostaddr, sizeof(int32_t));
	buf += sizeof(int32_t);
	memcpy(buf, &port, sizeof(int16_t));
	buf += sizeof(int16_t);
	*/

	buf = nboPackString(buf, playerid, strlen(playerid));
	buf = nboPackUShort(buf, (uint16_t)type);
	buf = nboPackUShort(buf, (uint16_t)team);
	buf = nboPackString(buf, dalias, sizeof(dalias));
	buf = nboPackString(buf, demail, sizeof(demail));

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bznter: send() failed, no nter ..\n");
		return -1;
	}
	free(msg);

	DEBUGbznter("sent ..\n");
	DEBUGbznter("        len = [%d], %d\n", buflen, sizeof(uint16_t));
	DEBUGbznter("       code = [%x], %d\n", code, sizeof(uint16_t));
	DEBUGbznter("   playerid = [%s], %d\n", playerid, strlen(playerid));
	DEBUGbznter("       type = [%u], %d\n", type, sizeof(uint16_t));
	DEBUGbznter("       team = [%u], %d\n", dteam, sizeof(uint16_t));
	DEBUGbznter("       name = [%s], %d\n", dalias, sizeof(dalias));
	DEBUGbznter("      email = [%s], %d\n", demail, sizeof(demail));
	DEBUGbznter("   -------------------\n");
	DEBUGbznter("     tcplen = [%d]\n", tcplen);


	return 0;

}


int
bzrlay(void) {
	char *		msg;
	char *		buf;
	int		tcplen;
	uint16_t	code;


	DEBUGbzrlay("sending MsgNetworkRelay\n");

	code = MsgNetworkRelay;
	tcplen = 4;

	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bzrlay: malloc failed, no exit ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);

	buf = msg;
	buf = nboPackUShort(buf, (uint16_t)0);
	buf = nboPackUShort(buf, code);

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bzrlay: send() failed, no exit ..\n");
		return -1;
	}
	free(msg);

	return 0;
}


int
bzlpng(int sequence) {
	char *		msg;
	char *		buf;
	int		tcplen;
	uint16_t	code;


	DEBUGbzlpng("sending MsgLagPing\n");

	code = MsgLagPing;
	tcplen = 6;

	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bzlpng: malloc failed, no exit ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);

	buf = msg;
	buf = nboPackUShort(buf, (uint16_t)2);
	buf = nboPackUShort(buf, code);
	buf = nboPackUShort(buf, sequence);

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bzlpng: send() failed, no lag ping ..\n");
		return -1;
	}
	free(msg);

	return 0;
}

int
bzpngr(void) {
	char *		msg;
	char *		buf;
	int		tcplen;
	uint16_t	code;


	DEBUGbzpngr("sending PingCodeRequest\n");

	code = PingCodeRequest;
	tcplen = 6;

	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bzpngr: malloc failed, no exit ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);

	buf = msg;
	buf = nboPackUShort(buf, (uint16_t)2);
	buf = nboPackUShort(buf, code);
	buf = nboPackUShort(buf, (uint16_t)0);

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bzpngr: send() failed, no ping request ..\n");
		// return -1;
	}
	free(msg);

	return 0;
}

int
bzlive(float px, float py, float pz, float fx, float fy, float fz) {
	char *		msg;
	char *		buf;
	int		tcplen;
	uint16_t	code;


	DEBUGbzlive("sending MsgNetworkRelay\n");

	code = MsgAlive;
	tcplen = 28;

	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bzlive: malloc failed, no exit ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);

	buf = msg;
	buf = nboPackUShort(buf, (uint16_t) 0x0018);
	buf = nboPackUShort(buf, code);
	buf = nboPackFloat(buf, px);
	buf = nboPackFloat(buf, py);
	buf = nboPackFloat(buf, pz);
	buf = nboPackFloat(buf, fx);
	buf = nboPackFloat(buf, fy);
	buf = nboPackFloat(buf, fz);

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bzlive: send() failed, no exit ..\n");
		return -1;
	}
	free(msg);

	return 0;
}

int
bzupdt(int status, float px, float py, float pz, float fx, float fy, float fz, float az, float av) {
	char *		msg;
	char *		buf;
	int		tcplen;
	uint16_t	code;


	DEBUGbzupdt("sending MsgPlayerUpdate\n");

	code = MsgPlayerUpdate;
	tcplen = 46;

	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bzupdt: malloc failed, no exit ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);

	buf = msg;
	buf = nboPackUShort(buf, (uint16_t) 0x002a);
	buf = nboPackUShort(buf, code);
	buf = nboPackString(buf, playerid, strlen(playerid));
	buf = nboPackUShort(buf, status);
	buf = nboPackFloat(buf, px);
	buf = nboPackFloat(buf, py);
	buf = nboPackFloat(buf, pz);
	buf = nboPackFloat(buf, fx);
	buf = nboPackFloat(buf, fy);
	buf = nboPackFloat(buf, fz);
	// azimuth
	buf = nboPackFloat(buf, az);
	// angular velocity
	buf = nboPackFloat(buf, av);

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bzupdt: send() failed, no update ..\n");
		return -1;
	}
	free(msg);

	return 0;
}


int
bzshot(int type, float px, float py, float pz, float fx, float fy, float fz) {
	char *		msg;
	char *		buf;
	int		pktlen;
	uint16_t	code;

	DEBUGbzshot("sending MsgShotBegin\n");

	code = MsgShotBegin;
	pktlen = 48;

	if(usnd_fd != 0)
		pktlen += 10;

	if((msg = (char *)malloc(pktlen)) == NULL) {
		printf("bzshot: malloc failed, no exit ..\n");
		return -1;
	}
	memset(msg, 0, pktlen);

	buf = msg;

	if(usnd_fd != 0) {
		// buf = (unsigned char *)nboPackUShort(buf, 0xfeed);
		// buf = (unsigned char *)nboPackUShort(buf, lastRecvPacketNo);
		// buf = (unsigned char *)nboPackUShort(buf, moving->length);
		// buf = (unsigned char *)nboPackUShort(buf, moving->seqno);

		buf = nboPackUShort(buf, UDPPktHdr);
		buf = nboPackUShort(buf, (uint16_t) 0x0000);
		buf = nboPackUShort(buf, (uint16_t)(pktlen - 2));
		buf = nboPackUShort(buf, (uint16_t) 0x0000);

	}

	buf = nboPackUShort(buf, (uint16_t) 0x002c);
	buf = nboPackUShort(buf, code);
	buf = nboPackString(buf, playerid, strlen(playerid));
	buf = nboPackUShort(buf, (uint16_t) 0x0000);
	buf = nboPackFloat(buf, px);
	buf = nboPackFloat(buf, py);
	buf = nboPackFloat(buf, pz);
	buf = nboPackFloat(buf, fx);
	buf = nboPackFloat(buf, fy);
	buf = nboPackFloat(buf, fz);
	buf = nboPackFloat(buf, (float)0.0);
	buf = nboPackUShort(buf, type);
	buf = nboPackFloat(buf, (float)3.5);

	if(usnd_fd != 0)
		buf = nboPackUShort(buf, (uint16_t) 0xffff);

	buf = msg;
	if(usnd_fd != 0) {
		if(sendto(usnd_fd, buf, pktlen, 0, &usnd_ad, sizeof(usnd_ad)) != pktlen) {
			printf("bzshot: sendto() failed, no shot ..\n");
			return -1;
		}
	} else {
		if(send(data_fd, buf, pktlen, 0) != pktlen) {
			printf("bzshot: send() failed, no shot ..\n");
			return -1;
		}
	}
	free(msg);

	return 0;
}


int
bztprt(int tport_from, int tport_to) {
	char *		msg;
	char *		buf;
	int		tcplen;
	uint16_t	code;


	DEBUGbztprt("sending MsgTeleport\n");

	code = MsgTeleport;
	tcplen = 8;

	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bztprt: malloc failed, no exit ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);

	buf = msg;
	buf = nboPackUShort(buf, (uint16_t)4);
	buf = nboPackUShort(buf, code);
	buf = nboPackUShort(buf, tport_from);
	buf = nboPackUShort(buf, tport_to);

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bztprt: send() failed, no teleport ..\n");
		return -1;
	}
	free(msg);

	return 0;
}


int
bzqery() {
	char *		msg;
	char *		buf;
	int		tcplen;
	uint16_t	code;


	DEBUGbzqery("sending MsgQueryPlayers\n");

	code = MsgQueryPlayers;
	tcplen = 4;

	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bzqery: malloc failed, no exit ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);

	buf = msg;
	buf = nboPackUShort(buf, (uint16_t)0);
	buf = nboPackUShort(buf, code);

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bzqery: send() failed, no exit ..\n");
		return -1;
	}
	free(msg);

	return 0;
}


int
bzvry1() {
	uint16_t	code;
	struct player * Player;

	char buf[8] = "\0\0\0\0\0\0\0\0";

	code = 0;
        Player = player_ptr;
	while (Player->next != NULL) {
		Player = Player->next;
	}

	memcpy(&Player->id, &buf, 8);
	sprintf(Player->alias, "%s", plyr_vry1);
	Player->type = plyr_tank;
	Player->team = team_rogue;
	Player->next = (struct player *) malloc(sizeof(struct player));

	return 0;
}


int
bzplyr(char * buf) {
	uint16_t	code;
	struct player * Player;
	

	code = 0;
        Player = player_ptr;
	while (Player->next != NULL) {
		Player = Player->next;
	}
	memset(&Player->id, 0, 9);
	memcpy(&Player->id, &buf[4], 8);

	sprintf(Player->alias, "%s", (unsigned char *)buf + 20);
	Player->type = getUnpackUShort((unsigned char *)buf + 12);
	Player->team = getUnpackUShort((unsigned char *)buf + 14);
	Player->tport_from = 0;
	Player->tport_to = 0;
	Player->last_playerupdate = 0;
	Player->last_tport = 0;

	// printf("decode: added player [%s]\n", Player->alias);
	Player->next = (struct player *) malloc(sizeof(struct player));
	// Player = Player->next;


	return 0;

}

int
bzteam(char * buf) {
	uint16_t	code;
	

	code = 0;
	printf("decode: found team ");
	switch(getUnpackUShort((unsigned char *)buf + 4)) {
		case team_rogue:
			printf("Rogue   ");
			break;
			;;
		case team_red:
			printf("Red     ");
			break;
			;;
		case team_green:
			printf("Green   ");
			break;
			;;
		case team_blue:
			printf("Blue    ");
			break;
			;;
		case team_purple:
			printf("Purple  ");
			break;
			;;
	}
	printf("Players [%d/%d]  Wins/Losses [%d/%d]  Score = %d\n",
		getUnpackUShort((unsigned char *)buf + 8),
		getUnpackUShort((unsigned char *)buf + 6),
		getUnpackUShort((unsigned char *)buf + 10),
		getUnpackUShort((unsigned char *)buf + 12),
		getUnpackUShort((unsigned char *)buf + 10) -
		getUnpackUShort((unsigned char *)buf + 12));


	return 0;

}


struct player*
msg_getplayer(char * buf, int opt) {
	struct player * Player;
	struct player * ptr;
	
	ptr = NULL;
        Player = player_ptr;
	while (Player->next != NULL) {
		if(opt == byident) {
			if(!strcmp(buf, Player->id)) {
				ptr = Player;
				break;
			}
		} else if(opt == byalias) {
			if(!strcmp(buf, Player->alias)) {
				ptr = Player;
				break;
			}
		}
		Player = Player->next;
	}

	return ptr;
}


struct player*
pay_getplayer(char * buf, int opt) {
	struct player * Player;
	struct player * ptr;
	
	ptr = NULL;
        Player = player_ptr;
	while (Player->next != NULL) {
		if(opt == byident) {
			if(!strcmp(buf, Player->id)) {
				ptr = Player;
				break;
			}
		} else if(opt == byalias) {
			if(!strcmp(buf, Player->alias)) {
				ptr = Player;
				break;
			}
		}
		Player = Player->next;
	}

	return ptr;
}


int
printPlayerStatus(int status)
{
	char comma[2] = "\0\0";

	if(status == DeadStatus) {
		printf("%s dead", comma);
		return status;
	}

	if(status & Alive) {
		printf("%s alive", comma);
		*comma = ',';
	}

	if(status & Paused) {
		printf("%s paused", comma);
		*comma = ',';
	}

	if(status & Exploding) {
		printf("%s exploding", comma);
		*comma = ',';
	}

	if(status & Teleporting) {
		printf("%s teleporting", comma);
		*comma = ',';
	}

	if(status & FlagActive) {
		printf("%s flag empowered", comma);
		*comma = ',';
	}

	if(status & CrossingWall) {
		printf("%s passing through a wall", comma);
		*comma = ',';
	}

	if(status & Falling) {
		printf("%s falling", comma);
		*comma = ',';
	}

	if(status > ((Falling * 2) - 1))
		printf(" **unregistered** ");

	return status;

}


int
printPlayerType(int type)
{

	switch(type) {

		case plyr_tank:
			printf("a Tank");
			break;
			;;

		case plyr_jafo:
			printf("Just Another Fucking Observer");
			break;
			;;

		case plyr_robo:
			printf("a Robot");
			break;
			;;

		default:
			printf("an **unregistered** type");
			break;
			;;
	}

	return type;
}


int
printFlagStatus(int flag)
{

	switch(flag) {

		case FlagNoExist:
			printf("is not active");
			break;
			;;

		case FlagOnGround:
			printf("is sitting on the ground");
			break;
			;;

		case FlagOnTank:
			printf("is on a player's tank");
			break;
			;;

		case FlagInAir:
			printf("is in the air and will fall back down");
			break;
			;;

		case FlagComing:
			printf("just appeared and is falling to the ground");
			break;
			;;

		case FlagGoing:
			printf("was thrown in the air and is disappearing");
			break;
			;;

		default:
			printf(" **unregistered** ");
			break;
			;;
	}


	return(flag);
}


int
printFlagType(int flag)
{

	switch(flag) {
		case FlagNoExist:
			printf("is normal/permanent");
			break;
			;;

		case FlagUnstable:
			printf("disappears after use");
			break;
			;;

		case FlagSticky:
			printf("can't be dropped normally");
			break;
			;;

		default:
			printf(" **unregistered** ");
			break;
			;;
	}

	return(flag);
}


int
printFlagId(int flag)
{


	switch(flag) {

		case NullFlag:
			printf("no");
			break;
			;;

		/*
		case NoFlag:
			printf("null");
			break;
			;;
		*/

		case RedFlag:
			printf("red team");
			break;
			;;

		case GreenFlag:
			printf("green team");
			break;
			;;

		case BlueFlag:
			printf("blue team");
			break;
			;;

		case PurpleFlag:
			printf("purple team");
			break;
			;;

		case VelocityFlag:
			printf("high speed");
			break;
			;;

		case QuickTurnFlag:
			printf("quick turm");
			break;
			;;

		case OscOverthrusterFlag:
			printf("oscillation overthruster");
			break;
			;;

		case RapidFireFlag:
			printf("rapid fire");
			break;
			;;

		case MachineGunFlag:
			printf("machine gun");
			break;
			;;

		case GuidedMissileFlag:
			printf("guided missiles");
			break;
			;;

		case LaserFlag:
			printf("laser");
			break;
			;;

		case RicochetFlag:
			printf("ricochet");
			break;
			;;

		case SuperBulletFlag:
			printf("super bullet");
			break;
			;;

		case InvisibleBulletFlag:
			printf("invisible bullet");
			break;
			;;

		case StealthFlag:
			printf("stealth");
			break;
			;;

		case TinyFlag:
			printf("tiny");
			break;
			;;

		case NarrowFlag:
			printf("narrow");
			break;
			;;

		case ShieldFlag:
			printf("shield");
			break;
			;;

		case SteamrollerFlag:
			printf("steam roller");
			break;
			;;

		case ShockWaveFlag:
			printf("shock wave");
			break;
			;;

		case PhantomZoneFlag:
			printf("phantom zone");
			break;
			;;

		case GenocideFlag:
			printf("genocide");
			break;
			;;

		case JumpingFlag:
			printf("jumping");
			break;
			;;

		case IdentifyFlag:
			printf("identity");
			break;
			;;

		case CloakingFlag:
			printf("cloaking");
			break;
			;;

		case ColorblindnessFlag:
			printf("color blindness");
			break;
			;;

		case ObesityFlag:
			printf("obesity");
			break;
			;;

		case LeftTurnOnlyFlag:
			printf("left turn only");
			break;
			;;

		case RightTurnOnlyFlag:
			printf("right turn only");
			break;
			;;

		case MomentumFlag:
			printf("momentum");
			break;
			;;

		case BlindnessFlag:
			printf("blindness");
			break;
			;;

		case JammingFlag:
			printf("jamming");
			break;
			;;

		case WideAngleFlag:
			printf("wide angle");
			break;
			;;

		default:
			printf(" **unregistered** ");
			break;
			;;
	}


	return(flag);

}


int
getTCPPacket(char * buf, int len)
{
	int	act;


	act = 0;
	if(len == 0)
		len = BUFSIZE;

	memset(buf, 0, len);

	act = recv(data_fd, buf, len, 0);
	if(act > 0)
		DEBUGgetPacket("TCP: recv() = [%d]\n", act);

	return act;
}


int
getUDPPacket(char * buf, int len)
{
	int	act;
	int	recvlen;


	act = 0;
	recvlen = sizeof(urcv_ad);
	if(len == 0)
		len = BUFSIZE;

	memset(buf, 0, len);

	act = recvfrom(urcv_fd, buf, len, 0, &urcv_ad, (socklen_t*)&recvlen);
	if(act > 0)
		DEBUGgetPacket("UDP: recv() = [%d]\n", act);

	return act;
}


int
getTCPMsg(char * buf_pri, char * pri_ptr, char * buf_msg, char * msg_ptr, int pkt_len)
{
	int msg_len;
	int msg_remain;
	int msg_code;
	int pkt_remain;
	int out_len;



	DEBUGgetmsg("getTCPMsg: entered\n");

	msg_len = 0;
	msg_code = 0;
	pkt_remain = buf_pri + pkt_len - pri_ptr;

	if(msg_ptr != buf_msg) {
		DEBUGgetmsg("getTCPMsg: dirty buf_msg\n");
		msg_len = getUnpackUShort((unsigned char *)buf_msg) + 4;
		msg_remain = msg_len - (msg_ptr - buf_msg);

	} else {
		DEBUGgetmsg("getTCPMsg: clean buf_msg\n");
		memset(buf_msg, 0, BUFSIZE);
		DEBUGgetmsg("getTCPMsg: buf_pri = [%02x], pri_ptr = [%02x]\n", buf_pri, pri_ptr);
		DEBUGgetmsg("getTCPMsg: buf_msg = [%02x], msg_ptr = [%02x]\n", buf_msg, msg_ptr);

		msg_len = getUnpackUShort((unsigned char *)pri_ptr) + 4;
		DEBUGgetmsg("msg_len = [%d]\n", msg_len);
		msg_remain = msg_len;

	}


	if(pkt_remain < msg_remain) {
		DEBUGgetmsg("getTCPMsg: pkt_remain < msg_remain [%d]\n", msg_remain - pkt_remain);
		memcpy(msg_ptr, pri_ptr, pkt_remain);
		out_len = -pkt_remain;

	} else if(pkt_remain > msg_remain) {
		DEBUGgetmsg("getTCPMsg: msg_remain < pkt_remain [%d]\n", pkt_remain - msg_remain);
		memcpy(msg_ptr, pri_ptr, msg_remain);
		out_len = msg_remain;

	} else {
		memcpy(msg_ptr, pri_ptr, msg_remain);
		out_len = msg_remain;

	}

	DEBUGgetmsg("getTCPMsg: Lengths ...  out_len = [%d]\n", out_len);
	DEBUGgetmsg("getTCPMsg: finishing\n");

	// Success
	msg_code = getUnpackUShort((unsigned char *)buf_msg+2);

	DEBUGgetmsg("getTCPMsg: msg_code = [%x]\n", msg_code);
	return out_len;
}


int
getUDPMsg(char * buf_pri, char * pri_ptr, char * buf_msg, char * msg_ptr, int pkt_len)
{
	int msg_len;
	int msg_remain;
	int msg_code;
	int msg_feed;
	int pkt_remain;
	int out_len;



	DEBUGgetmsg("getUDPMsg: entered\n");

	msg_len = 0;
	msg_code = 0;
	pkt_remain = buf_pri + pkt_len - pri_ptr;

	if(msg_ptr != buf_msg) {
		DEBUGgetmsg("getUDPMsg: dirty buf_msg\n");
		msg_len = getUnpackUShort((unsigned char *)buf_msg) + 4;
		msg_remain = msg_len - (msg_ptr - buf_msg);

	} else {
		DEBUGgetmsg("getUDPMsg: clean buf_msg\n");
		memset(buf_msg, 0, BUFSIZE);
		DEBUGgetmsg("getUDPMsg: buf_pri = [%02x], pri_ptr = [%02x]\n", buf_pri, pri_ptr);
		DEBUGgetmsg("getUDPMsg: buf_msg = [%02x], msg_ptr = [%02x]\n", buf_msg, msg_ptr);
		if(pri_ptr == buf_pri) {
			DEBUGgetmsg("getUDPMsg: ... beginning of the packet.\n");
			msg_feed = getUnpackUShort((unsigned char *)pri_ptr);
			if(msg_feed != UDPPktHdr) {
				printf("getUDPMsg: feed error, invalid header\n");
				return -1;
			}
			msg_len = getUnpackUShort((unsigned char *)pri_ptr+8) + 4 + 8;

		} else {
			DEBUGgetmsg("getUDPMsg: ... not the beginning of the packet.\n");
			msg_len = getUnpackUShort((unsigned char *)pri_ptr+4) + 4 + 4;

		}

		msg_remain = msg_len;

		// try to avoid another loop because of the terminating char
		if(pkt_remain - msg_remain == 2) {
			if(getUnpackUShort((unsigned char *)pri_ptr + msg_len) == 0xffff) {
				msg_len += 2;
			}
		}

		DEBUGgetmsg("msg_len = [%d]\n", msg_len);
		msg_remain = msg_len;

	}


	if(pkt_remain < msg_remain) {
		DEBUGgetmsg("getUDPMsg: pkt_remain < msg_remain [%d]\n", msg_remain - pkt_remain);
		memcpy(msg_ptr, pri_ptr, pkt_remain);
		out_len = -pkt_remain;

	} else if(pkt_remain > msg_remain) {
		DEBUGgetmsg("getUDPMsg: msg_remain < pkt_remain [%d]\n", pkt_remain - msg_remain);
		memcpy(msg_ptr, pri_ptr, msg_remain);
		out_len = msg_remain;

	} else {
		memcpy(msg_ptr, pri_ptr, msg_remain);
		out_len = msg_remain;
		// out_len = -0;

	}

	DEBUGgetmsg("getUDPMsg: Lengths ...  out_len = [%d]\n", out_len);
	DEBUGgetmsg("getUDPMsg: finishing\n");

	return out_len;
}


int
bzexit(void) {
	char *		msg;
	char *		buf;
	int		tcplen;
	uint16_t	code;


	DEBUGbzexit("sending MsgExit\n");

	code = MsgExit;
	tcplen = 4;

	if((msg = (char *)malloc(tcplen)) == NULL) {
		printf("bzexit: malloc failed, no exit ..\n");
		return -1;
	}
	memset(msg, 0, tcplen);

	buf = msg;
	buf = nboPackUShort(buf, (uint16_t)0);
	buf = nboPackUShort(buf, code);

	printf("main: exiting game ..\n");

	buf = msg;
	if(send(data_fd, buf, tcplen, 0) != tcplen) {
		printf("bzexit: send() failed, no exit ..\n");
		return -1;
	}
	free(msg);


	printf("main: done. \n");

	return 0;
}




// PROGRAM


void
die(char *text) {
	fprintf(stderr, "error: %s\n", text);
	exit(1);
}


void
banner(void) {
	printf("\n");
	printf("bz  , ,  -,-  ,    ,  \n");
	printf("   /.'   /   /    /   \n");
	printf("  / |  _/_  /__  /__     by z3r0 c00l and 8o88yD1g1t4L\n");
	printf("\n");
	return;
}


void
usage(void) {
	printf("\n\n");
	banner();
	printf("\n\n");
	printf("usage: ./bzkill {user}@host{:port} {<team> {<alias> {<email> (<ismith>}}}}\n");
	printf("dflts: ./bzkill %s@host:%d %d \"%s\" \"%s\" %d\n", usr_victm, dflt_port, usr_team, usr_alias, usr_email, dflt_smith);
	printf("\n\n");
	exit(1);
}


void
code_check(int code, char * msg_ptr) {
	int	len, i, j;
	struct player * Player;
	struct player * lst_plyr;


	Player = player_ptr;

	printf("msgl: --[code]---[%x]\n", code);
	switch(code) {
		case 0:
			printf("msgl: --> caught by the zero catcher ?\n");
			break;
			;;


		case MsgAccept:
			printf("msgl: MsgAccept [%x]=[%s];\n",
			getUnpackUShort((unsigned char *)msg_ptr+6),
					msg_ptr+6);
			break;
			;;


		case MsgAcquireRadio:
			printf("msgl: MsgAcquireRadio [%x]=[%s];\n",
			getUnpackUShort((unsigned char *)msg_ptr+6),
					msg_ptr+6);
			break;
			;;


		case MsgAddPlayer:
			printf("msgl: MsgAddPlayer;\n");
			pthread_mutex_lock(&mutex_addplyr);
			bzplyr(msg_ptr);
			pthread_mutex_unlock(&mutex_addplyr);
			printf("msgl: MsgAddPlayer: ");
			Player = player_ptr;
			if((Player = msg_getplayer(msg_ptr+4, byident)) != NULL)
				printf(" alias=[%s], joined as ", Player->alias);
			else
				printf(" unknown, joined as ");

			printPlayerType(getUnpackFloat((unsigned char *)msg_ptr + 12));
			printf(".\n");

			break;
			;;
		
	
		case MsgAlive:
			printf("msgl: MsgAlive:   ");
			if((Player = msg_getplayer(msg_ptr+4, byident)) != NULL)
				printf("     alias=[%s]\n", Player->alias);
			else
				printf("     alias=[unknown]; not known locally.\n");
			break;
			;;


		case MsgDropFlag:
			printf("msgl: MsgDropFlag:     ");
			if((Player = msg_getplayer(msg_ptr+20, byident)) == NULL)
				printf("unknown ");
			else
				printf("[%s] ", Player->alias);

			printf("dropped the ");
			printFlagId(getUnpackUShort((unsigned char *)msg_ptr + 14));
			printf(" flag, at x=%2.2f, y=%2.2f, z=%2.2f\n",
				getUnpackFloat((unsigned char *)msg_ptr + 28),
				getUnpackFloat((unsigned char *)msg_ptr + 32),
				getUnpackFloat((unsigned char *)msg_ptr + 36));

			break;
			;;


		case MsgFlagUpdate:
			printf("msgl: MsgFlagUpdate:   flag no. [%x], the ",
				getUnpackUShort((unsigned char *)msg_ptr + 4));
			printFlagId(getUnpackUShort((unsigned char *)msg_ptr + 6));
			printf(" flag ");
			printFlagStatus(getUnpackUShort((unsigned char *)msg_ptr + 8));
			printf(" and ");
			printFlagType(getUnpackUShort((unsigned char *)msg_ptr + 10));
			printf(", at x=%2.2f, y=%2.2f, z=%2.2f\n",
				getUnpackFloat((unsigned char *)msg_ptr + 28),
				getUnpackFloat((unsigned char *)msg_ptr + 32),
				getUnpackFloat((unsigned char *)msg_ptr + 36));

			break;
			;;


		case MsgGMUpdate:
			printf("msgl: MsgGMUpdate:     ");
			printf("missile [%u], ", getUnpackUShort((unsigned char *)msg_ptr + 12));
			if((Player = msg_getplayer(msg_ptr+4, byident)) != NULL)
				printf("fired by [%s], ", Player->alias);
			else
				printf("fired by unknown, ");

			if((Player = msg_getplayer(msg_ptr+42, byident)) != NULL)
				printf("aimed at [%s], ", Player->alias);
			else
				printf("aimed at unknown, ");

			printf("is at x=%2.2f, y=%2.2f, z=%2.2f\n",
				getUnpackFloat((unsigned char *)msg_ptr + 14),
				getUnpackFloat((unsigned char *)msg_ptr + 18),
				getUnpackFloat((unsigned char *)msg_ptr + 22));

			break;
			;;


		case MsgGrabFlag:
			printf("msgl: MsgGrabFlag:     ");
			if((Player = msg_getplayer(msg_ptr+20, byident)) == NULL)
				printf("unknown ");
			else
				printf("[%s] ", Player->alias);

			printf("grabbed the ");
			printFlagId(getUnpackUShort((unsigned char *)msg_ptr + 14));
			printf(" flag, at x=%2.2f, y=%2.2f, z=%2.2f\n",
				getUnpackFloat((unsigned char *)msg_ptr + 28),
				getUnpackFloat((unsigned char *)msg_ptr + 32),
				getUnpackFloat((unsigned char *)msg_ptr + 36));

			break;
			;;


		case MsgKilled:
			printf("msgl: MsgKilled:       ");
			if((Player = msg_getplayer(msg_ptr+4, byident)) == NULL)
				printf("unknown killed by ");
			else
				printf("[%s] killed by ", Player->alias);

			if((Player = msg_getplayer(msg_ptr+12, byident)) == NULL)
				printf("unknown\n");
			else
				printf("[%s]\n", Player->alias);
			break;
			;;


		case MsgLagPing:
			printf("msgl: MsgLagPing;\n");
			bzlpng(getUnpackUShort((unsigned char *)msg_ptr+4));
			break;
			;;


		case MsgMessage:
			printf("msgl: MsgMessage:    :: ");
			if(firstMsgMessage == 0) firstMsgMessage++;
			if((Player = msg_getplayer(msg_ptr+4, byident)) == NULL)
				printf("unknown --> ");
			else
				printf("[%s] --> ", Player->alias);

			if((Player = msg_getplayer(msg_ptr+12, byident)) == NULL) {
					printf("unknown ");
			} else {
				if(strcmp(Player->alias, plyr_vry1))
					printf("[%s] ", Player->alias);
			}

			switch(getUnpackUShort((unsigned char *)msg_ptr + 20)) {
				case team_rogue:
					printf("All         ");
					break;
					;;
				case team_red:
					printf("Red Team    ");
					break;
					;;
				case team_green:
					printf("Green Team  ");
					break;
					;;
				case team_blue:
					printf("Blue Team   ");
					break;
					;;
				case team_purple:
					printf("Purple Team ");
					break;
					;;
			}

			printf(" ::\n");
			printf("msgl: MsgMessage:    :: [%s] ::\n", msg_ptr+22 );
			break;
			;;
			

		case MsgNetworkRelay:
			printf("msgl: MsgNetworkRelay;\n");
  			if(bzudpr() < 0) {
				printf("msgl: failed to register UDP receiver.\n");
				pthread_exit(NULL);
			}
			printf("msgl: MsgNetworkRelay: UDP receiver registered at [%u].\n", urcv_pt);
			break;
			;;


		case MsgPlayerUpdate:
			if((Player = msg_getplayer(msg_ptr+4, byident)) == NULL) {
				printf("msgl: MsgPlayerUpdate: player update for non-existant player.\n");
				/*
				Player = player_ptr;
				while (Player->next != NULL) {
					Player = Player->next;
				}
				Player->next = (struct player *) malloc(sizeof(struct player));
				sprintf(Player->id, "%c%c%c%c%c%c%c%c",
						msg_ptr[4], msg_ptr[5], msg_ptr[6], msg_ptr[7],
						msg_ptr[8], msg_ptr[9], msg_ptr[10], msg_ptr[11]);
				memset(Player->alias, 0, 32);
				printf("msgl: MsgPlayerUpdate: added struct for unidentified player\n");
				*/
			} else {
				Player->status = getUnpackUShort((unsigned char *)msg_ptr + 12);
				Player->px = getUnpackFloat((unsigned char *)msg_ptr + 14);
				Player->py = getUnpackFloat((unsigned char *)msg_ptr + 18);
				Player->pz = getUnpackFloat((unsigned char *)msg_ptr + 22);
				Player->fx = getUnpackFloat((unsigned char *)msg_ptr + 26);
				Player->fy = getUnpackFloat((unsigned char *)msg_ptr + 30);
				Player->fz = getUnpackFloat((unsigned char *)msg_ptr + 34);
				Player->azimuth = getUnpackFloat((unsigned char *)msg_ptr + 38);
				Player->angular_velocity = getUnpackFloat((unsigned char *)msg_ptr + 42);
				// Player->last_playerupdate = microtime();
				// if(Player == msg_getplayer(dman, byalias)) {
					printf("msgl: MsgPlayerUpdate: alias=[%s] player is", Player->alias);
					printPlayerStatus(Player->status);
					printf(" at pos x=%2.2f, y=%2.2f, z=%2.2f; ", Player->px, Player->py, Player->pz);
					// printf(" at vel x=%2.2f, y=%2.2f, z=%2.2f; ", Player->fx, Player->fy, Player->fz);
					printf(" at azimuth=%2.2f;\n", Player->azimuth);
				// }
			}
			break;
			;;


		case MsgQueryPlayers:
			printf("msgl: MsgQueryPlayers;\n");
			break;
			;;


		case MsgReject:
			printf("msgl: MsgReject; ");
			rejectcode = getUnpackUShort((unsigned char *)msg_ptr + 4);
			switch(rejectcode) {
				case RejectBadRequest:
					printf("msgl: RejectBadRequest: bogus data in MsgEnter.\n");
					break;
					;;
				case RejectBadTeam:
					printf("msgl: RejectBadTeam: invalid team id.\n");
					break;
					;;
				case RejectBadType:
					printf("msgl: RejectBadType:  invalid client type .\n");
					break;
					;;
				case RejectNoRogues:
					printf("msgl: RejectNoRogues: rogue team requested but rogues not allowed.\n");
					break;
					;;
				case RejectTeamFull:
					printf("msgl: RejectTeamFull: no more players allowed on team.\n");
					break;
					;;
				case RejectServerFull:
					printf("msgl: RejectServerFull: no more players allowed on any team.\n");
					break;
					;;
				default:
					printf("msgl: unknown error code [%x]\n", getUnpackUShort((unsigned char *)msg_ptr + 4));
					break;
					;;
			}
			/*
			if(bzexit() < 0) {
				printf("failed to exit game cleanly.\n");
				pthread_exit(NULL);
			}
			*/
			term = 1;
			printf("msgl: exited game.\n");
			break;
			;;


		case MsgRemovePlayer:
			printf("msgl: MsgRemovePlayer: ");
			if((Player = msg_getplayer(msg_ptr+4, byident)) != NULL) {
				printf(" player [%s] has left the game.\n", Player->alias);

				lst_plyr = player_ptr;
				Player = player_ptr;
				while (Player->next != NULL) {
					if(!strcmp(msg_ptr+4, Player->id)) {
						lst_plyr->next = Player->next;
						free(Player);
						break;
					}
					lst_plyr = Player;
					Player = Player->next;
				}

			} else {
				printf(" attempted to remove a non-existant player(?)\n");

			}
			break;
			;;


		case MsgScore:
			printf("msgl: MsgScore:        ");
			if((Player = msg_getplayer(msg_ptr+4, byident)) == NULL)
				printf("unknown score; ");
			else
				printf("[%s] score; ", Player->alias);

			printf("wins = [%d], losses = [%d], total = [%d]\n",
				getUnpackUShort((unsigned char *)msg_ptr + 12),
				getUnpackUShort((unsigned char *)msg_ptr + 14),
				getUnpackUShort((unsigned char *)msg_ptr + 12) -
				getUnpackUShort((unsigned char *)msg_ptr + 14));
			break;
			;;


		case MsgShotBegin:
			printf("msgl: MsgShotBegin:    ");
			printf("shot [%u], fired by ", getUnpackUShort(msg_ptr + 12));
			if((Player = msg_getplayer(msg_ptr+4, byident)) == NULL)
				printf("unknown, ");
			else
				printf("[%s], ", Player->alias);

			printf("with ");
			printFlagId(getUnpackUShort(msg_ptr + 42));
			printf(" flag, at x=%2.2f, y=%2.2f, z=%2.2f\n",
				getUnpackFloat((unsigned char *)msg_ptr + 14),
				getUnpackFloat((unsigned char *)msg_ptr + 18),
				getUnpackFloat((unsigned char *)msg_ptr + 22));

			break;
			;;
	
			
		case MsgShotEnd:
			printf("msgl: MsgShotEnd:      shot fired by ");
			printf("shot [%u], fired by ", getUnpackUShort(msg_ptr + 12));
			if((Player = msg_getplayer(msg_ptr+4, byident)) == NULL)
				printf("unknown, ");
			else
				printf("[%s], ", Player->alias);

			if(getUnpackUShort(msg_ptr + 10) == 1)
				printf("ended with an exlposion!\n");
			else
				printf("ended.\n");

			break;
			;;


		case MsgSuperKill:
			printf("msgl: MsgSuperKill\n");
			/*
  			if(bzexit() < 0) {
				printf("failed to exit game cleanly.\n");
				pthread_exit(NULL);
			}
			*/
			term = 1;
			printf("msgl: MsgSuperKill .. completed successfully.\n");
			break;
			;;

			
		case MsgTeamUpdate:
			printf("msgl: MsgTeamUpdate;\n");
			bzteam(msg_ptr);
			break;
			;;

			
		case MsgTeleport:
			printf("msgl: MsgTeleport: ");
			if((Player = msg_getplayer(msg_ptr+4, byident)) != NULL) {
				Player->tport_from = getUnpackUShort((unsigned char *)msg_ptr + 12),
				Player->tport_to = getUnpackUShort((unsigned char *)msg_ptr + 14),
				printf("[%s], teleported from [%u] to [%u]\n", Player->alias,
					Player->tport_from, Player->tport_to);
			} else {
				printf("unknown, teleported from [%u] to [%u]\n", 
					getUnpackUShort((unsigned char *)msg_ptr + 12),
					getUnpackUShort((unsigned char *)msg_ptr + 14));
			}
			break;
			;;


		case MsgTimeUpdate:
			printf("msgl: MsgTimeUpdate: ");
			printf("[%u] seconds remaining.\n", 
				getUnpackUShort((unsigned char *)msg_ptr + 4));
			if(getUnpackUShort((unsigned char *)msg_ptr + 4) == 0) {
				printf("msgl: MsgTimeUpdate: time is zero.\n");
				term = 1;
			}
			break;
			;;

			
		case MsgUDPLinkEstablished:
			printf("msgl: MsgUDPLinkEstablished: ??\n");
			break;
			;;


		case MsgUDPLinkRequest:
			printf("msgl: MsgUDPLinkRequest: port ");
			usnd_pt = getUnpackUShort((unsigned char *)msg_ptr + 4),
			printf("[%u], ", usnd_pt);
			if(bzudps() < 0)
				printf("failed.\n");
			else
				printf("succeeded.\n");
			break;
			;;


		default:
			printf("msgl: unknown message -c [%x]\n", code);
			printf("msgl: ------------------ [%x]\n", code);
			// len = 1024;
			len = getUnpackUShort((unsigned char *)msg_ptr),
			printf("msgl: ");
			for(i = 0, j = 1; i < len; i++, j++) {
				if(msg_ptr[i] < 64 || msg_ptr[i] > 126) {
    					printf(".");
				} else {
    					printf("%c", msg_ptr[i]);
				}
				if(j == 31) {
					j = 0;
					printf("\nmsgl: ");
				}
			}
			printf("\n\n\n");
			break;
			;;

	}

	return;
}


void
messagingTCP(void) {
	int	processed;
	int	pktlen;
	uint16_t code;


	// Run Neo ..

	firstMsgMessage = 0;
	pthread_mutex_lock(&mutex_haltpayload);

	while(term == 0) {
		if((pktlen = getTCPPacket(tcp_buf_pri, 0)) <= 0)
			continue;
		
		tcp_pri_ptr = tcp_buf_pri;

		printf("mTCP: --[packet]----------------------------------------------------------------\n");

		pthread_mutex_lock(&mutex_getmsg);
		while((processed = getTCPMsg(tcp_buf_pri, tcp_pri_ptr, tcp_buf_msg, tcp_msg_ptr, pktlen)) && term == 0) {

			if(processed <= 0) {
				processed = 0 - processed;
				tcp_msg_ptr += processed;
				break;
			}

			tcp_pri_ptr += processed;
			tcp_msg_ptr = tcp_buf_msg;

			code = 0;
			code = getUnpackUShort((unsigned char *)tcp_msg_ptr+2);
			code_check(code, tcp_msg_ptr);
		}
		pthread_mutex_unlock(&mutex_getmsg);

		if(firstMsgMessage == 1) {
			firstMsgMessage++;
			pthread_mutex_unlock(&mutex_haltpayload);
		}
	}
	printf("mTCP: term must be true?\n");

	// watch that initial MsgReject ... agent names may out psyc here ..
	if(firstMsgMessage == 0)
		pthread_mutex_unlock(&mutex_haltpayload);

	pthread_cancel(thr_pid[2]);
	pthread_cancel(thr_pid[1]);

	pthread_exit((void *)rejectcode);

}


void
messagingUDP(void) {
	int	processed;
	int	pktlen;
	uint16_t code;
	uint16_t feed;

	code	= 0;

	// Run Neo ..

	while(term == 0) {
		if((pktlen = getUDPPacket(udp_buf_pri, 0)) <= 0)
			continue;
		
		udp_pri_ptr = udp_buf_pri;

		printf("mUDP: --[packet]----------------------------------------------------------------\n");

		pthread_mutex_lock(&mutex_getmsg);
		while((processed = getUDPMsg(udp_buf_pri, udp_pri_ptr, udp_buf_msg, udp_msg_ptr, pktlen)) && term == 0) {

			if(processed <= 0) {
				processed = 0 - processed;
				udp_msg_ptr += processed;
				break;
			}

			udp_pri_ptr += processed;
			udp_msg_ptr = udp_buf_msg;

			feed = 0;
			feed = getUnpackUShort((unsigned char *)udp_msg_ptr);
			if(feed == UDPPktHdr) {
				code = getUnpackUShort((unsigned char *)udp_msg_ptr+10);
				code_check(code, udp_msg_ptr+8);
			} else {
				code = getUnpackUShort((unsigned char *)udp_msg_ptr+6);
				code_check(code, udp_msg_ptr+4);
			}
		}
		pthread_mutex_unlock(&mutex_getmsg);
	}
	printf("mUDP: term must be true?\n");

	pthread_cancel(thr_pid[1]);
	pthread_cancel(thr_pid[0]);

	pthread_exit((void *)-2);
}


int
payload(void) {

	// int	last_agent;
	// int	used_agent;
	int	this_agent;
	char	s_agent[32];
	char *	p_s_agent;
	char	s_alias[32];
	char	a_alias[32];
	int	a_alias_len;

	float	mag;
	float	dst;
	float	max_dst;
	float	ze_azimuth;

	int	our_status;
	float	our_px;
	float	our_py;
	float	our_pz;
	float	our_fx;
	float	our_fy;
	float	our_fz;
	float	our_azimuth;
	float	our_angular_velocity;

	int	old_status;
	float	old_px;
	float	old_py;
	float	old_pz;
	float	old_azimuth;

        float   shot_px;
        float   shot_py;
        float   shot_pz;
        float   shot_fx;
        float   shot_fy;
        float   shot_fz;

	struct player * Player;



	dst		= 10;
	max_dst		= 1.5 * dst;


	// whingy compilers ...

	old_status	= 0;
	old_px		= 0.0;
	old_py		= 0.0;
	old_pz		= 0.0;
	old_azimuth	= 0.0;

	smith_count	= 0;


	// arbitrary .. thread catchup
	usleep(25);

  	if(bznter(usr_plyr, dteam, dalias, demail) < 0) {
		printf("pyld: failed to enter game.\n");
		pthread_exit(NULL);
	}
	printf("pyld: entered game.\n");


	// new mutex for Smith^Smith.

	// wait until the users are known to us ... 
	pthread_mutex_lock(&mutex_haltpayload);
	pthread_mutex_unlock(&mutex_haltpayload);

	printf("pyld: payload released!\n");

	pthread_testcancel();

	// find me too ...
	if(ismith != 0) {
		// used_agent = 0;
		a_alias_len = strlen(dalias) - strlen("[00]");
		memset(&a_alias, 0, 32);
		memcpy(&a_alias, &dalias, a_alias_len);
        	Player = player_ptr;
        	while (Player->next != NULL) {
			memset(&s_alias, 0, 32);
			memcpy(&s_alias, &Player->alias, a_alias_len);
			printf("pyld: scanning Player->alias = [%s] ...: ", Player->alias);
			// is this player an agent?
			if(!strcmp(a_alias, s_alias)) {
				// is this player us?
				memset(&s_agent, 0, 32);
				memcpy(&s_agent, &Player->alias, strlen(Player->alias));
				p_s_agent = s_agent;
				p_s_agent+= strlen(Player->alias) - 3;
				memset(&s_alias, 0, 3);
				memcpy(&s_alias, p_s_agent, 2);
				this_agent = atoi(s_alias);
				smith_count++;
				if(memcmp(playerid, Player->id, 8)) {
					printf("agent; agent id [%02x]\n", this_agent);
				} else {
					printf("me; agent id [%02x]\n", this_agent);
				}
			} else {
				printf("copper-top .. \n");
			}
                	Player = Player->next;
		}
		// turns out u cant join the server if ur alias is alrdy in use .. weenies ..
		/*
		if(used_agent == 1) {
			pthread_cancel(thr_pid[1]);
			pthread_cancel(thr_pid[0]);

			pthread_exit((void *)&last_agent);
		}
		*/
		printf("pyld: working as agent [%d]\n", ismith);
	} else {
		printf("pyld: working alone .. for now.\n");
	}


	while(term == 0) {

		usleep(50);

		// the pinger could almost be unutha thread ... 0ms is fast .. but ..
		bzpngr();

		// term = 1;

		if((Player = pay_getplayer(dman, byalias)) != NULL) {
			pthread_testcancel();

			// Neutralise the threat
			printf("pyld: target [%s] acquired ..\n", Player->alias);

			// Try not to DoS the gaam srvr with plyr updates
			if(Player->px != old_px || Player->py != old_py || Player->pz != old_pz
				|| Player->azimuth != old_azimuth || Player->status != old_status ) {

				// did we teleport? -- this is kludgy
				if(Player->px > old_px + max_dst || Player->px < old_px - max_dst ||
				   Player->py > old_py + max_dst || Player->py < old_py - max_dst ||
				   Player->pz > old_pz + max_dst || Player->pz < old_pz - max_dst ) {

					if(Player->tport_from != 0 && Player->tport_to !=0 ) {
						printf("pyld: target [%s] teleported from [%u] to [%u] ..\n",
							Player->alias, Player->tport_from, Player->tport_to);
						bztprt(Player->tport_from, Player->tport_to);
					}


				}

				// plyr_live++;
				printf("pyld: target [%s] out of sync ..\n", Player->alias);

				mag			= 0;

				our_status		= Player->status;
				our_px			= Player->px;
				our_py			= Player->py;
				our_pz			= Player->pz;
				our_fx			= Player->fx;
				our_fy			= Player->fy;
				our_fz			= Player->fz;
				our_azimuth		= Player->azimuth;
				our_angular_velocity	= Player->angular_velocity;

				old_status		= Player->status;
				old_px			= Player->px;
				old_py			= Player->py;
				old_pz			= Player->pz;
				old_azimuth		= Player->azimuth;

				shot_px			= 0;
				shot_py			= 0;
				shot_pz			= 0;
				shot_fx			= 0;
				shot_fy			= 0;
				shot_fz			= 0;


				// Crdt where crdt is dyu; the nxt 50 lines
				// r the reel smartz ... c0d3d by 8o88yD1g1t4L

				// ------- z3r0 c00l broke the previous code --------
				
				ze_azimuth = (Player->azimuth + ((ismith - 1)*PI_4));
				while (ze_azimuth >= 2*PI)
					ze_azimuth -= 2*PI;

				if ((ze_azimuth <= PI_2) || (ze_azimuth >= 1.5*PI)){
       					if (ze_azimuth <= PI_2)
						mag = PI_2 - ze_azimuth;
       					else
						mag = ze_azimuth - (1.5*PI);
					our_px = Player->px - (mag * dst);
				}

				if ((PI_2 < ze_azimuth) && (ze_azimuth < 1.5*PI)){
       					mag = ze_azimuth - PI_2;
       					if (mag > PI_2)
						mag -= PI_2;
       					our_px = Player->px + (mag * dst);
				}

				if ((0 <= ze_azimuth) && (ze_azimuth <= PI)){
					mag = ze_azimuth;
        				if (mag > PI_2)
                				mag -= PI_2;
        				our_py = Player->py - (mag * dst);
				}

				if ((PI < ze_azimuth) && (ze_azimuth < 2*PI)){
       					mag = ze_azimuth - PI;
       					if (mag > PI_2)
						mag -= PI_2;
					our_py = Player->py + (mag * dst);
				}

				our_azimuth = ze_azimuth;


				// Ze shot from ze weapon

                                shot_px = (our_px + Player->px)/2;
                                shot_py = (our_py + Player->py)/2;
                                shot_pz = our_pz + 1;

                                if (our_azimuth <= PI_2) {
                                        shot_fx = shotspeed * cos(our_azimuth);
                                        shot_fy = shotspeed * sin(our_azimuth);
                                }
                                if ((PI_2 < our_azimuth) && (our_azimuth <= PI)) {
                                        shot_fx = 0 - (shotspeed * sin(our_azimuth-PI_2));
                                        shot_fy = shotspeed * cos(our_azimuth-PI_2);
                                }
                                if ((PI < our_azimuth) && (our_azimuth <= 1.5*PI)) {
                                        shot_fx = 0 - (shotspeed * cos(our_azimuth-PI));
                                        shot_fy = 0 - (shotspeed * sin(our_azimuth-PI));
                                }
                                if (1.5*PI < our_azimuth) {
                                        shot_fx = shotspeed * sin(our_azimuth-(1.5*PI));
                                        shot_fy = 0 - (shotspeed * cos(our_azimuth-(1.5*PI)));
                                }
                                shot_fz = (float)0.0;


				// ------- z3r0 c00l broke the following code --------

				if(plyr_live == 0) {

					printf("pyld: installing local tank ..\n");

					plyr_live = 1;

  					if(bzlive(our_px, our_py, our_pz, our_fx, our_fy, our_fz) < 0) {
						printf("failed to make local tank live.\n");
						pthread_exit(NULL);
					}
					printf("pyld: local tank lives at x=%2.2f, y=%2.2f, z=%2.2f\n", our_px, our_py, our_pz);

					// usleep(200);
					// usleep(100);
					// sleep(1);

				}

				pthread_testcancel();
  				bzupdt(our_status, our_px, our_py, our_pz, our_fx, our_fy, our_fz,
								our_azimuth, our_angular_velocity);
				printf("pyld: local tank updated; x=%2.2f, y=%2.2f, z=%2.2f, az=%2.2f\n",
								our_px, our_py, our_pz, our_azimuth);
				printf("pyld: local tank updated;");
				printPlayerStatus(our_status);
				printf("\n");

				// usleep(200);
				// sleep(1);

                                // if(bzshot(NoFlag, shot_px, shot_py, shot_pz, shot_fx, shot_fy, shot_fz) < 0) 
                                if(bzshot(LaserFlag, shot_px, shot_py, shot_pz, shot_fx, shot_fy, shot_fz) < 0) 
                                        printf("pyld: failed to send shot.\n");
                                printf("pyld: local tank shot sent from x=%2.2f, y=%2.2f, z=%2.2f\n",
					shot_px, shot_py, shot_pz);
				printf("pyld:                   at vel; x=%2.2f, y=%2.2f, z=%2.2f\n",
                                        shot_fx, shot_fy, shot_fz);

				// usleep(100);

			}
		}
		pthread_testcancel();
	}

	pthread_exit(NULL);

}


int
main(int argc, char **argv) {

	char *	srcpos;
	char *	dstpos;
	int	pthrdptr;
	int	iplayerid;
	int	thrnum;
	int	retval;
	int *	p_retval;
	void *	p_p_retval;
	char *	p_dalias;
	int	char_count;


	if(argc < 2) usage();


	// User Params

	memset(&dman, 0, sizeof(dman));
	memset(&dhost, 0, sizeof(dhost));
	memset(&dport, 0, sizeof(dport));
	memset(&dalias, 0, sizeof(dalias));
	memset(&demail, 0, sizeof(demail));

  	srcpos = argv[1];

	dstpos = dman;
	char_count = len_dman;
	while( *srcpos != '\0' && *srcpos != '@' ) {
		if(char_count > 0) {
			*dstpos = *srcpos;
			dstpos++;
			char_count--;
		}
		srcpos++;
	}
	if(*srcpos == '\0') {
		fprintf(stderr, "\nerror: no host part found (missing an \"@\") in [%s].\n", argv[1]);
		usage();
	}
	srcpos++;

	dstpos = dhost;
	char_count = len_dhost;
	while( *srcpos != '\0' && *srcpos != ':') {
		if(char_count > 0) {
			*dstpos = *srcpos;
			dstpos++;
			char_count--;
		}
		srcpos++;
	}
	if(*srcpos == ':') {
		srcpos++;
		dstpos = dport;
		char_count = len_dport;
		while( *srcpos != '\0' ) {
			if(char_count > 0) {
				*dstpos = *srcpos;
				dstpos++;
				char_count--;
			}
			srcpos++;
		}
	} else {
		sprintf(dport, "%u", dflt_port);
	}

  	srcpos = argv[1];
	if(!atoi(dport)) {
		fprintf(stderr, "\nerror: invalid port [%s].\n", dport);
		usage();
	}

	if(!strlen(dman)) { 
		memcpy(&dman, usr_victm, strlen(usr_victm));
	}

	if(argc >= 3)
		dteam = atoi(argv[2]);
	else
		dteam = usr_team;

	if(argc >= 4)
		memcpy(&dalias, argv[3], strlen(argv[3]));
	else
		memcpy(&dalias, usr_alias, strlen(usr_alias));

	if(argc >= 5)
		memcpy(&demail, argv[4], strlen(argv[4]));
	else
		memcpy(&demail, usr_email, strlen(usr_email));

	if(argc >= 6) {
		if((ismith = atoi(argv[5])) > 8)
			ismith = 1;
	} else {
		ismith = dflt_smith;
	}



	// Randomize Player ID

	srand((uint)time(0));
	iplayerid = 1+(int) (16777215.0*rand()/(RAND_MAX+1.0));
	sprintf(playerid, "%08x", iplayerid);


	// Get it out to the hero

	banner();



	// Loading the Matrix

	// TCP
	if((tcp_buf_pri = (char *)malloc(BUFSIZE)) == NULL) {
		die("main: malloc failed, no primary buf ..\n");
	}
	printf("main: packet buffer allocated.\n");
	memset(tcp_buf_pri, 0, BUFSIZE);

	if((tcp_buf_msg = (char *)malloc(BUFSIZE)) == NULL) {
		die("main: malloc failed, no message buf ..\n");
	}
	printf("main: message buffer allocated.\n");
	memset(tcp_buf_msg, 0, BUFSIZE);

	tcp_pri_ptr = tcp_buf_pri;
	tcp_msg_ptr = tcp_buf_msg;


	// UDP
	if((udp_buf_pri = (char *)malloc(BUFSIZE)) == NULL) {
		die("main: malloc failed, no primary buf ..\n");
	}
	printf("main: packet buffer allocated.\n");
	memset(udp_buf_pri, 0, BUFSIZE);

	if((udp_buf_msg = (char *)malloc(BUFSIZE)) == NULL) {
		die("main: malloc failed, no message buf ..\n");
	}
	printf("main: message buffer allocated.\n");
	memset(udp_buf_msg, 0, BUFSIZE);

	udp_pri_ptr = udp_buf_pri;
	udp_msg_ptr = udp_buf_msg;



	// Everyone Player

	player_ptr = (struct player *) malloc(sizeof(struct player));
  	if(bzvry1() < 0) {
		printf("main: failed to add the everyone player.\n");
	}


	len_orig_dalias = strlen(dalias);

	while(ismith < 9) {

		// Sort out agent clustering ..

		if(ismith != 0) {
			p_dalias = (char *)&dalias + len_orig_dalias;
			sprintf(p_dalias, " [%02x]", ismith);
		}


		printf("kill [%s] on [%s] at [%d]\n", dman, dhost, atoi(dport));
		printf("as [%s] (%s) on team [%d] with id [%s].\n\n", dalias, demail, dteam, playerid);

		// Enter the Matrix

		firstMsgMessage = 0;

  		if(bzcnct(dhost, atoi(dport)) < 0) {
			die("failed to connect to server.\n");
		}
		printf("main: connection established.\n");
  		close(ctrl_fd);


		// no need for ths .. turnz out the bzf guyz cudnt maake it wurk either ;-)
		/*
  		if(bzrlay() < 0) {
			close(ctrl_fd);
			close(data_fd);
			die("failed to disable multicast.\n");
		}
		printf("main: disabled multicast.\n");
		*/


		// Choose Neo ...
		term = 0;
		pthrdptr = 0;
		pthread_create(&(thr_pid[0]), NULL, (void *)&messagingTCP, (void *)pthrdptr);
		pthread_create(&(thr_pid[1]), NULL, (void *)&messagingUDP, (void *)pthrdptr);
		pthread_create(&(thr_pid[2]), NULL, (void *)&payload, (void *)pthrdptr);


		for(thrnum = 0; thrnum < 3; thrnum++) {
			retval = 0;
			p_retval = &retval;
			p_p_retval = &p_retval;
			pthread_join(thr_pid[thrnum], (void **)p_retval);
			if(p_retval != NULL) {
				printf("main: thread number [%d], returned [%d]\n", thrnum, retval);
				if(ismith != 0) {
					if(thrnum == 0 && retval == 1)
						ismith++;
				}
			} else {
				printf("main: thread number [%d], returned null\n", thrnum);
			}
		}

		printf("main: humpty is together again .. \n");

		close(data_fd);
		close(urcv_fd);

		printf("main: sockets are closed .. \n");
	}

	free(tcp_buf_pri);
	free(tcp_buf_msg);
	free(udp_buf_pri);
	free(udp_buf_msg);

	printf("main: memory is freed .. \n");

	exit(0);
}

// there is no spoon.


