Beispiel #1
0
//------- Begin of function TalkMsg::msg_str --------//
//
// Return the text of this message.
//
// <int> viewingNationRecno = the recno of the nation viewing this message
// [int] dispReply 			 = whether display the reply if there is one
//										(default: 1)
// [int] dispSecondLine		 = whether should display the second line of the
//										message (default: 0)
//
char* TalkMsg::msg_str(int viewingNationRecno, int dispReply, int dispSecondLine)
{
	viewing_nation_recno = viewingNationRecno;
	should_disp_reply		= dispReply;
	disp_second_line		= dispSecondLine;

	//-------- compose the message str -------//

	switch(talk_id)
	{
		case TALK_PROPOSE_TRADE_TREATY:
			propose_treaty("accord commercial");
			break;

		case TALK_PROPOSE_FRIENDLY_TREATY:
			propose_treaty("pacte de non-agression");
			break;

		case TALK_PROPOSE_ALLIANCE_TREATY:
			propose_treaty("traité d'alliance");
			break;

		case TALK_END_TRADE_TREATY:
			end_treaty("accord commercial");
			break;

		case TALK_END_FRIENDLY_TREATY:
			end_treaty("pacte de non-agression");
			break;

		case TALK_END_ALLIANCE_TREATY:
			end_treaty("traité d'alliance");
			break;

		case TALK_REQUEST_MILITARY_AID:
			request_military_aid();
			break;

		case TALK_REQUEST_TRADE_EMBARGO:
			request_trade_embargo();
			break;

		case TALK_REQUEST_CEASE_WAR:
			request_cease_war();
			break;

		case TALK_REQUEST_DECLARE_WAR:
			request_declare_war();
			break;

		case TALK_REQUEST_BUY_FOOD:
			request_buy_food();
			break;

		case TALK_DECLARE_WAR:
			declare_war();
			break;

		case TALK_GIVE_TRIBUTE:
			give_tribute("tribut");
			break;

		case TALK_DEMAND_TRIBUTE:
			demand_tribute(0);		// 1-is tribute, not aid
			break;

		case TALK_GIVE_AID:
			give_tribute("aide");
			break;

		case TALK_DEMAND_AID:
			demand_tribute(1);		// 1-is aid, not tribute
			break;

		case TALK_GIVE_TECH:
			give_tech();
			break;

		case TALK_DEMAND_TECH:
			demand_tech();
			break;

		case TALK_REQUEST_SURRENDER:
			request_surrender();
			break;

		case TALK_SURRENDER:
			surrender();
			break;

		default:
			err_here();
	}

	return str;
}
Beispiel #2
0
struct Enemy *
get_nearest()
{
    int pcount = 0;
    register int i;
    register struct player *j;
    int intruder = 0;
    int tdist;
    double dx, dy;
    double vxa, vya, l;	/* Used for trap shooting */
    double vxt, vyt;
    double vxs, vys;
    double dp;

    /* Find an enemy */
    ebuf.e_info = me->p_no;
    ebuf.e_dist = GWIDTH + 1;

    pcount = 0;  /* number of human players in game */

    if (target >= 0) {
	j = &players[target];
	if (!(me->p_war & j->p_team))
	    declare_war(players[target].p_team, 0); /* make sure we're at war 7/31/91 TC */

	/* We have an enemy */
	/* Get his range */
	dx = j->p_x - me->p_x;
	dy = j->p_y - me->p_y;
	tdist = hypot(dx, dy);

	if (j->p_status != POUTFIT) { /* ignore target if outfitting */
	    ebuf.e_info = target;
	    ebuf.e_dist = tdist;
	    ebuf.e_flags &= ~(E_INTRUDER);
	}
	
	/* need a loop to find hostile ships */
	/* within tactical range */

	for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
	    if ((j->p_status != PALIVE) || (j == me) ||
		((j->p_flags & PFROBOT) && (!hostile)))
		continue;
	    else
		pcount++;	/* Other players in the game */
	    if ((j->p_war & me->p_team) ||
		(me->p_war & j->p_team)) {
		/* We have an enemy */
		/* Get his range */
		dx = j->p_x - me->p_x;
		dy = j->p_y - me->p_y;
		tdist = hypot(dx, dy);
		
		/* if target's teammate is too close, mark as nearest */

		if ((tdist < ebuf.e_dist) && (tdist < 15000)) {
		    ebuf.e_info = i;
		    ebuf.e_dist = tdist;
		    ebuf.e_flags &= ~(E_INTRUDER);
		}
	    }			/* end if */
	}			/* end for */
    }
    else {			/* no target */
	/* avoid dead slots, me, other robots (which aren't hostile) */
	for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
	    if ((j->p_status != PALIVE) || (j == me) ||
		((j->p_flags & PFROBOT) && (!hostile)) ||
                (j->p_flags & PFPRACTR))
		continue;
	    else
		pcount++;	/* Other players in the game */
	    if ((j->p_war & me->p_team) || 
		(me->p_war & j->p_team)) {
		/* We have an enemy */
		/* Get his range */
		dx = j->p_x - me->p_x;
		dy = j->p_y - me->p_y;
		tdist = hypot(dx, dy);
		
		/* Check to see if ship is in our space. */
		switch (me->p_team) {
		  case FED:
		    intruder = ((j->p_x < GWIDTH/2) && (j->p_y > GWIDTH/2));
		    break;
		  case ROM:
		    intruder = ((j->p_x < GWIDTH/2) && (j->p_y < GWIDTH/2));
		    break;
		  case KLI:
		    intruder = ((j->p_x > GWIDTH/2) && (j->p_y < GWIDTH/2));
		    break;
		  case ORI:
		    intruder = ((j->p_x > GWIDTH/2) && (j->p_y > GWIDTH/2));
		    break;
		}
		
		if (tdist < ebuf.e_dist) {
		    ebuf.e_info = i;
		    ebuf.e_dist = tdist;
		    if (intruder)
			ebuf.e_flags |= E_INTRUDER;
		    else
			ebuf.e_flags &= ~(E_INTRUDER);
		}
	    }			/* end if */
	}			/* end for */
    }				/* end else */
    if (pcount == 0) {
	return NOENEMY;    /* no players in game */
    } else if (ebuf.e_info == me->p_no) {
	return 0;			/* no hostile players in the game */
    } else {
	j = &players[ebuf.e_info];

	/* Get torpedo course to nearest enemy */
	ebuf.e_flags &= ~(E_TSHOT);

	vxa = (j->p_x - me->p_x);
	vya = (j->p_y - me->p_y);
	l = hypot(vxa, vya);	/* Normalize va */
	if (l!=0) {
	    vxa /= l;
	    vya /= l;
	}
	vxs = (Cos[j->p_dir] * j->p_speed) * WARP1;
	vys = (Sin[j->p_dir] * j->p_speed) * WARP1;
	dp = vxs * vxa + vys * vya;	/* Dot product of (va vs) */
	dx = vxs - dp * vxa;
	dy = vys - dp * vya;
	l = hypot(dx, dy);      /* Determine how much speed is required */
        dp = (float) (me->p_ship.s_torpspeed * WARP1);
        l = (dp * dp - l * l);
        if (l > 0) {
	    double he_x, he_y, area;

	    /* Only shoot if within distance */
	    he_x = j->p_x + Cos[j->p_dir] * j->p_speed * 50 * WARP1;
	    he_y = j->p_y + Sin[j->p_dir] * j->p_speed * 50 * WARP1;
	    area = 50 * me->p_ship.s_torpspeed * WARP1;
	    if (hypot(he_x - me->p_x, he_y - me->p_y) < area) {
		l=sqrt(l);
		vxt = l * vxa + dx;
		vyt = l * vya + dy;
		ebuf.e_flags |= E_TSHOT;
		ebuf.e_tcourse = getcourse((int) vxt + me->p_x, (int) vyt + me->p_y);
	    }
	}

	/* Get phaser shot status */
	if (ebuf.e_dist < 0.8 * phrange)
		ebuf.e_flags |= E_PSHOT;
	else
		ebuf.e_flags &= ~(E_PSHOT);

	/* Get tractor/pressor status */
	if (ebuf.e_dist < trrange)
		ebuf.e_flags |= E_TRACT;
	else
		ebuf.e_flags &= ~(E_TRACT);


	/* get his phaser range */
	ebuf.e_phrange = PHASEDIST * j->p_ship.s_phaserdamage / 100;

	/* get course info */
	ebuf.e_course = getcourse(j->p_x, j->p_y);
	ebuf.e_edir = j->p_dir;
	ebuf.e_hisflags = j->p_flags;
	ebuf.e_tractor = j->p_tractor;
	/*
	if (debug)
	    ERROR(1,( "Set course to enemy is %d (%d)\n",
		    (int)ebuf.e_course, 
		    (int) ebuf.e_course * 360 / 256));
	*/

	/* check to polymorph */

	if ((polymorphic) && (j->p_ship.s_type != me->p_ship.s_type) &&
	    (j->p_ship.s_type != ATT)) { /* don't polymorph to ATT 4/8/92 TC */
	    extern int config();
	    int old_shield;
	    int old_damage;
	    old_shield = me->p_ship.s_maxshield;
	    old_damage = me->p_ship.s_maxdamage;
	    
	    getship(&(me->p_ship), j->p_ship.s_type);
	    config();
	    if (me->p_speed > me->p_ship.s_maxspeed)
		me->p_speed = me->p_ship.s_maxspeed;
	    me->p_shield = (me->p_shield * (float)me->p_ship.s_maxshield)
		/(float)old_shield;
	    me->p_damage = (me->p_damage * (float)me->p_ship.s_maxdamage)
		/(float)old_damage;
	}

	return &ebuf;
    }
}
int 
enter(int tno, int disp, int pno, int s_type, int startplanet)
{
    static int lastteam = -1;	/* to hold team of last enter */
    static int lastrank = -1;	/* to hold rank of last enter */
    char    buf[80];		/* to sprintf into */
    char    buf2[80];		/* to sprintf into */
    char    addrbuf[10];	/* to hold address */

    if ((startplanet < 0) || (startplanet >= NUMPLANETS))
	startplanet = -1;

    (void) strncpy(me->p_name, pseudo, sizeof(me->p_name));	/* get name */
    me->p_name[sizeof(me->p_name) - 1] = '\0';	/* delimiet just in case */

    me->p_kills = 0.0;		/* have no kills yet */
    get_ship_for_player(me, s_type);	/* get the player's ship type */

    if (me->p_ship.s_nflags & SFNHASFIGHTERS)
	me->p_ship.s_missilestored = 0;

    me->p_docked = 0;		/* not docked to anyone */
    me->p_updates = 0;		/* start updating immediately */
    me->p_flags = PFSHIELD;
    if (allows_docking(me->p_ship))
	me->p_flags |= PFDOCKOK;/* enable docking */
    me->p_dir = 0;		/* direction angle of zero */
    me->p_desdir = 0;		/* desired direction of zero */
    me->p_speed = 0;		/* speed of zero */
    me->p_desspeed = 0;		/* desired speed of zero */
    me->p_subspeed = 0;		/* fractional part of speed zero */

/*  Gunboat docked to ships stuff */
    if ((me->p_ship.s_nflags & SFNMASSPRODUCED) &&
	(shipvals[shipPick].s_numports)) {
	int     i;

	me->p_team = (1 << tno);
	for (i = 0; i < MAXPLAYER; i++)
	    if ((players[i].p_ship.s_type == shipPick) &&
		(players[i].p_team == me->p_team) &&
		(players[i].p_status == PALIVE) &&	/* if all this stuff... */
		(players[i].p_flags & PFDOCKOK) &&
		(players[i].p_docked < players[i].p_ship.s_numports) &&
		(players[i].p_ship.s_missilestored)) {
		me->p_x = players[i].p_x;	/* ...dock em on */
		me->p_y = players[i].p_y;
		newdock(i);
		if (players[i].p_ship.s_missilestored != -1)
		   players[i].p_ship.s_missilestored--;
		if (players[i].p_flags & PFCLOAK) {
		   me->p_flags |= PFCLOAK;
		   me->p_cloakphase = players[i].p_cloakphase;
		} else me->p_cloakphase = 0;
		break;
	    }
    }
/* End Gunboat stuff */

    if ((tno == 4) || (tno == 5)) {	/* if player indep or a robot */
	me->p_team = 0;		/* he has no team */
    }
    else {			/* else player is normal player--find planet */
	me->p_team = (1 << tno);/* set players team number */

	/* forgive me father, for I have used short-circuiting to
	   emulate control flow */
	(startplanet >= 0	/* start planet already specified? */
	 || (((startplanet = me->p_lastrefit) >= 0	/* we've got a home
							   planet */
	      && (planets[startplanet].pl_flags & PLSHIPYARD)	/* and it's a yard */
	      &&(planets[startplanet].pl_owner == me->p_team))	/* and it's ours */
	     ||0 < (me->p_lastrefit = -1))	/* oops, no more home
						   shipyard, F */
	 ||(startplanet = find_start_planet(me->p_team, PLSHIPYARD)) != -1
	 || (startplanet = find_start_planet(me->p_team, PLREPAIR)) != -1
	 || (startplanet = find_start_planet(me->p_team, PLAGRI)) != -1
	 || (startplanet = find_start_planet(me->p_team, PLFUEL)) != -1
	 || (startplanet = find_start_planet(me->p_team, PLHOME)) != -1
	 || (startplanet = find_start_planet(me->p_team, 0)) != -1
	    );
    }
    if (startplanet == -1) {
	placeIndependent();
    }
    else {
	int i;
	double dx, dy;
	struct planet *l;

	/* we have a planet */
	/* use p_x and y as scratch registers */
	while(1) {
	    me->p_x = planets[startplanet].pl_x + (lrand48() % 10000) - 5000;
	    me->p_y = planets[startplanet].pl_y + (lrand48() % 10000) - 5000;
	    if (me->p_x < 0)	/* can't come in outside of borders */
		me->p_x = 0;	/* now can we?  */
	    if (me->p_y < 0)
		me->p_y = 0;
	    if (me->p_x >= GWIDTH)
		me->p_x = GWIDTH-1;
	    if (me->p_y >= GWIDTH)
		me->p_y = GWIDTH-1;
	    for(i = 0, l = &planets[0]; i < NUMPLANETS; i++, l++) {
		if(PL_TYPE(*l) == PLSTAR) {
		    dx = ABS(l->pl_x - me->p_x);
		    dy = ABS(l->pl_y - me->p_y);
		    if(dx * dx + dy * dy <
				MIN_DIST_FROM_STAR * MIN_DIST_FROM_STAR)
			break;
		}
	    }
	    if(i == NUMPLANETS)
		break;
	}
	/* legitimize p_x and p_y */
	move_player(me->p_no, me->p_x, me->p_y, 0);
    }
    me->p_ntorp = 0;		/* have not fired torps yete */
    if (!((me->p_ship.s_nflags & SFNMASSPRODUCED) &&
	(shipvals[shipPick].s_numports)))
       me->p_cloakphase = 0;	/* no cloaking phase--not cloaked */
    me->p_nplasmatorp = 0;	/* no plasma torps */
    me->p_swar = 0;		/* at war with nobody */
    me->p_armies = 0;		/* carrying no armies */
    tmpPick = 0;

    switch_special_weapon();

    if (!keeppeace)		/* if keep peace mode then */
	auto_peace();		/* set do automatic peace */
    me->p_hostile &= ~me->p_team;	/* hostile to all but own team */
    me->p_swar &= ~me->p_team;
    if ((lastteam != tno) || (lastrank != mystats->st_rank)) {
	if ((lastteam > 0) && (lastteam < NUMTEAM) && (lastteam != tno))
	    declare_war((1 << lastteam) | me->p_hostile);	/* if changing then
								   adjust war stat */
	lastteam = tno;		/* store team number in static */
	lastrank = mystats->st_rank;	/* store rank in static */
	sprintf(addrbuf, " %s->ALL", twoletters(me));
	if ((tno == 4) && (strcmp(me->p_monitor, "Nowhere") == 0)) {
	    time_t  curtime;	/* if a robot and independent */
	    struct tm *tmstruct;/* to hold time */
	    int     queuesize;	/* to hold queue size */
	    int     hour;	/* to hold hour */

	    time(&curtime);	/* get the time */
	    tmstruct = localtime(&curtime);	/* convert to local time */
	    if (!(hour = tmstruct->tm_hour % 12))	/* get the hour */
		hour = 12;
	    sprintf(buf, "It's %d:%02d%s, time to die.", hour, tmstruct->tm_min,
		    tmstruct->tm_hour >= 12 ? "pm" : "am");
	    if ((queuesize = status->count - status->wait) > 0) {
		/* lint: queuesize set but not used in function enter */
		sprintf(buf2, "  Approximate queue size: %d.", status->answer);
		strcat(buf, buf2);	/* get queue size if queue */
	    }
	    pmessage2(buf, 0, MALL, addrbuf, me->p_no);	/* display message */
	}
	else if (tno == 5) {	/* if a robot then */
	    if (players[disp].p_status != PFREE) {
		sprintf(buf2, "%s has been targeted for termination.",
			twoletters(&players[disp]));
		pmessage2(buf2, 0, MALL, addrbuf, me->p_no);
	    }
	}

	if (!status2->league)	/* no peanut messages in a league game */
	    peanut_gallery();	/* check for important people */

	if (me->p_stats.st_royal == 0)
	    sprintf(buf, "%s %.16s is now %2.2s (%.16s@%.32s)",
		    ranks[me->p_stats.st_rank].name, me->p_name,
		    twoletters(me), me->p_login, me->p_full_hostname);
	else
	    sprintf(buf, "%s %.16s is now %2.2s (%.16s@%.32s)",
		    royal[me->p_stats.st_royal].name, me->p_name,
		    twoletters(me), me->p_login, me->p_full_hostname);

	pmessage2(buf, 0, MALL | MJOIN, addrbuf, me->p_no);

	advertise_tourney_queue();

    }
    delay = 0;
    return startplanet;
}
Beispiel #4
0
void rmove()
{
    register struct player *j;
    register int i;
    register int burst;
    register int numHits, tDir;
    int		avDir;
    extern struct Enemy *get_nearest();
    struct Enemy *enemy_buf;
    struct player *enemy = NULL;
    static int	roboclock = 0;
    static int	avoid[2] = { -32, 32 };
    int no_cloak;
    char towhom[MSG_LEN];
    int timer;
    static int lastTorpped = 0; /* when we last fired a torp 4/13/92 TC */

    roboclock++;

    /* keep ghostbuster away */
    me->p_ghostbuster = 0;

    /* Check that I'm alive */
    if (me->p_status == PEXPLODE) {
        if (debug) ERROR(1,("Robot: Augh! exploding.\n"));
	return;
    }
    else if (me->p_status == PDEAD) {
	if (me->p_ntorp > 0)
               return;
	if (debug) ERROR(1,("Robot: done exploding and torps are gone.\n"));
	exitRobot();
	return;
    }


    timer=0;
    for (i = 0, j = &players[i]; i < (MAXPLAYER - TESTERS); i++, j++) {
	if ((j->p_status != PFREE) && !(j->p_flags & PFROBOT))
	    timer=1;
    }
    if (!timer && !sticky) {
	exitRobot();
	return;
    }

    /* if I'm a Terminator, quit if he quits, and quit if he dies and */
    /* I'm not "sticky" (-s) */

    if (target >= 0) {
	if (players[target].p_status == PFREE) { /* he went away */
	    me->p_status = PEXPLODE;	    
	    return;
	}
	if ((!sticky) && (players[target].p_status != PALIVE)) { /* he died */
	    me->p_status = PEXPLODE;
	    return;
	}
    }

    /* If it's been BOREDOM_TIME updates since we fired a torp, become
       hostile to all races, if we aren't already, and if we're not
       a practice robot (intended for guardian bots). 4/13/92 TC */

    if ((roboclock - lastTorpped > BOREDOM_TIME) && (!practice) && (!hostile) &&
        (me->p_team != 0 && !quiet)) {
        messAll(me->p_no,roboname,"I'm bored.");
        hostile++;
        declare_war(ALLTEAM, 0);
    }

    /* Our first priority is to phaser plasma torps in nearby vicinity... */
    /* If we fire, we aren't allowed to cloak... */
    no_cloak = phaser_plasmas();

    /* Find an enemy */

    enemy_buf = get_nearest();

    if ((enemy_buf != NULL) && (enemy_buf != NOENEMY)) {	/* Someone to kill */
	enemy = &players[enemy_buf->e_info];
	if (((random() % messfuse) == 0) &&
	    (hypot((double) me->p_x-enemy->p_x, (double) me->p_y-enemy->p_y) < 20000.0)) {
	    /* change 5/10/21 TC ...neut robots don't message */
	    messfuse = MESSFUSEVAL;
	    if (me->p_team != 0 && !quiet) {
		sprintf(towhom, " %s->%s",
			players[me->p_no].p_mapchars,
			players[enemy->p_no].p_mapchars);
		pmessage2(enemy->p_no, MINDIV, towhom, me->p_no, "%s",
			robo_message(enemy));
	    }
	    else if (target >= 0 && !quiet) {
		messAll(me->p_no,roboname,"%s",termie_message(enemy));
	    }
	}
	else
	    if (--messfuse == 0)
		messfuse = 1;
	timer = 0;
/*	if (debug)
	    ERROR(1,( "%d) noticed %d\n", me->p_no, enemy_buf->e_info));*/
    }
    else if (enemy_buf == NOENEMY) { /* no more players. wait 1 minute. */
	if (do_repair()) {
	    return;
	}
	go_home(0);
/*	if (debug)
	    ERROR(1,( "%d) No players in game.\n", me->p_no));*/
	return;
    }
    else if (enemy_buf == 0) {	 /* no one hostile */
/*	if (debug)
	    ERROR(1,( "%d) No hostile players in game.\n", me->p_no));*/
	if (do_repair()) {
	    return;
	}
	go_home(0);
	timer = 0;
	return;
    }

/* Note a bug in this algorithm:
** Once someone dies, he is forgotten.  This makes robots particularly easy
**  to kill on a suicide run, where you aim to where you think he will turn 
**  as you die.  Once dead, the robot will ignore you and all of your 
**  active torpedoes!
**/

/* Algorithm:
** We have an enemy.
** First priority: shoot at target in range.
** Second: Dodge torps and plasma torps.
** Third: Get away if we are damaged.
** Fourth: repair.
** Fifth: attack.
*/

/*
** If we are a practice robot, we will do all but the second.  One
** will be modified to shoot poorly and not use phasers.
**/
    /* Fire weapons!!! */
    /*
    ** get_nearest() has already determined if torpedoes and phasers
    ** will hit.  It has also determined the courses which torps and
    ** phasers should be fired.  If so we will go ahead and shoot here.
    ** We will lose repair and cloaking for the rest of this interrupt.
    ** if we fire here.
    */

    if (practice) {
	no_cloak = 1;
	if (enemy_buf->e_flags & E_TSHOT) {
/*	    if (debug)
		ERROR(1,( "%d) firing torps\n", me->p_no));*/
	    for (burst = 0; (burst < 3) && (me->p_ntorp < MAXTORP); burst++) {
		ntorp(enemy_buf->e_tcourse, TWOBBLE | TOWNERSAFE | TDETTEAMSAFE | TPRACTICE);
	    }
	}
    }
    else {
	if (enemy_buf->e_flags & E_TSHOT) {
/*	    if (debug)
		ERROR(1,( "%d) firing torps\n", me->p_no));*/
	    for (burst = 0; (burst < 2) && (me->p_ntorp < MAXTORP); burst++) {
		repair_off();
		if (! cloaker) cloak_off();
		ntorp(enemy_buf->e_tcourse, TWOBBLE | TOWNERSAFE | TDETTEAMSAFE);
		no_cloak++;
                lastTorpped = roboclock; /* record time of firing 4/13/92 TC */
	    }
	}
	if (enemy_buf->e_flags & E_PSHOT) {
/*	    if (debug)
		ERROR(1,( "%d) phaser firing\n", me->p_no));*/
	    no_cloak++;
	    repair_off();
	    if (! cloaker) cloak_off();
	    phaser(enemy_buf->e_course);
	}
    }

    /* auto pressor 7/27/91 TC */
    /* tractor/pressor rewritten on 5/1/92... glitches galore :-| TC */

    /* whoa, too close for comfort, or he's tractoring me, or
       headed in for me, or I'm hurt */

    /* a little tuning -- 0.8 on phrange and +/- 90 degrees in for pressor */

    /* pressor_player(-1); this didn't do anything before, so we'll let
       the pressors disengage by themselves 5/1/92 TC */
    if (enemy_buf->e_flags & E_TRACT) {	/* if pressorable */
	if (((enemy_buf->e_dist < 0.8 * enemy_buf->e_phrange) &&
	     (angdist(enemy_buf->e_edir, enemy_buf->e_course) > 64)) ||
	    (isTractoringMe(enemy_buf)) ||
	    (me->p_damage > 0)) {
	    if (!(enemy->p_flags & PFCLOAK)) {
		  if (debug)
		    ERROR(1,( "%d) pressoring %d\n", me->p_no,
			    enemy_buf->e_info));
		  pressor_player(enemy->p_no);
		  no_cloak++;
		  repair_off();
		  if (!cloaker) cloak_off();
	    }
	}
    }

    /* auto tractor 7/31/91 TC */

    /* tractor if not pressoring and... */

    /* tractor if: in range, not too close, and not headed +/- 90 degrees */
    /* of me, and I'm not hurt */
    
    if ((!(me->p_flags & PFPRESS)) &&
	(enemy_buf->e_flags & E_TRACT) &&
	(angdist(enemy_buf->e_edir, enemy_buf->e_course) < 64) &&
	(enemy_buf->e_dist > 0.7 * enemy_buf->e_phrange)) {
	if (!(me->p_flags & PFTRACT)) {
	    if (debug)
		ERROR(1,( "%d) tractoring %d\n", me->p_no,
			enemy_buf->e_info));
	    tractor_player(enemy->p_no);
	    no_cloak++;
	}
    }	
    else
	tractor_player(-1);	/* otherwise don't tractor */

    /* Avoid torps */
    /*
    ** This section of code allows robots to avoid torps.
    ** Within a specific range they will check to see if
    ** any of the 'closest' enemies torps will hit them.
    ** If so, they will evade for four updates.
    ** Evading is all they will do for this round, other than shooting.
    */

    if (!practice) {
	if ((enemy->p_ntorp < 5)) {
	    if ((enemy_buf->e_dist < 15000) || (avoidTime > 0)) {
		numHits = projectDamage(enemy->p_no, &avDir);
		if (debug) {
		    ERROR(1,( "%d hits expected from %d from dir = %d\n",
			    numHits, enemy->p_no, avDir));
		}
		if (numHits == 0) {
		    if (--avoidTime > 0) {	/* we may still be avoiding */
			if (angdist(me->p_desdir, me->p_dir) > 64)
			    me->p_desspeed = dogslow;
			else
			    me->p_desspeed = dogfast;
			return;
		    }
		} else {
		    /*
		     * Actually avoid Torps
		     */ 
		    avoidTime = AVOID_TIME;
		    tDir = avDir - me->p_dir;
		    /* put into 0->255 range */
		    tDir = NORMALIZE(tDir);
		    if (debug)
			ERROR(1,( "mydir = %d avDir = %d tDir = %d q = %d\n",
			    me->p_dir, avDir, tDir, tDir / 64));
		    switch (tDir / 64) {
		    case 0:
		    case 1:
			    set_course(NORMALIZE(avDir + 64));
			    break;
		    case 2:
		    case 3:
			    set_course(NORMALIZE(avDir - 64));
			    break;
		    }
		    if (!no_cloak)
			cloak_on();

		    if (angdist(me->p_desdir, me->p_dir) > 64)
			me->p_desspeed = dogslow;
		    else
			me->p_desspeed = dogfast;
			
		    shield_up();
		    detothers();	/* hmm */
		    if (debug)
			ERROR(1,( "evading to dir = %d\n", me->p_desdir));
		    return;
		}
	    }
	}

	/*
	** Trying another scheme.
	** Robot will keep track of the number of torps a player has
	** launched.  If they are greater than say four, the robot will
	** veer off immediately.  Seems more humanlike to me.
	*/

	else if (enemy_buf->e_dist < 15000) {
	    if (--avoidTime > 0) {	/* we may still be avoiding */
		if (angdist(me->p_desdir, me->p_dir) > 64)
		    me->p_desspeed = dogslow;
		else
		    me->p_desspeed = dogfast;
		return;
	    }
	    if (random() % 2) {
		me->p_desdir = NORMALIZE(enemy_buf->e_course - 64);
		avoidTime = AVOID_TIME;
	    }
	    else {
		me->p_desdir = NORMALIZE(enemy_buf->e_course + 64);
		avoidTime = AVOID_TIME;
	    }
	    if (angdist(me->p_desdir, me->p_dir) > 64)
		me->p_desspeed = dogslow;
	    else
		me->p_desspeed = dogfast;
	    shield_up();
	    return;
	}
    }
	    
    /* Run away */
    /*
    ** The robot has taken damage.  He will now attempt to run away from
    ** the closest player.  This obviously won't do him any good if there
    ** is another player in the direction he wants to go.
    ** Note that the robot will not run away if he dodged torps, above.
    ** The robot will lower his shields in hopes of repairing some damage.
    */

#define STARTDELTA 5000		/* ships appear +/- delta of home planet */

    if (me->p_damage > 0 && enemy_buf->e_dist < 13000) {
	if (me->p_etemp > 900)		/* 90% of 1000 */
	    me->p_desspeed = runslow;
	else
	    me->p_desspeed = runfast;
	if (!no_cloak)
	    cloak_on();
	repair_off();
	shield_down();
	set_course(enemy_buf->e_course - 128);
	if (debug)
	    ERROR(1,( "%d(%d)(%d/%d) running from %c%d %16s damage (%d/%d) dist %d\n",
		me->p_no,
		(int) me->p_kills,
		me->p_damage,
		me->p_shield,
		teamlet[enemy->p_team],
		enemy->p_no,
		enemy->p_login,
		enemy->p_damage,
		enemy->p_shield,
		enemy_buf->e_dist));
	return;
    }

    /* Repair if necessary (we are safe) */
    /*
    ** The robot is safely away from players.  It can now repair in peace.
    ** It will try to do so now.
    */

    if (do_repair()) {
	return;
    }

    /* Attack. */
    /*
    ** The robot has nothing to do.  It will check and see if the nearest
    ** enemy fits any of its criterion for attack.  If it does, the robot
    ** will speed in and deliver a punishing blow.  (Well, maybe)
    */

    if ((enemy_buf->e_flags & E_INTRUDER) || (enemy_buf->e_dist < 15000)
	|| (hostile)) {
	if ((!no_cloak) && (enemy_buf->e_dist < 10000))
	    cloak_on();
	shield_up();
/*	if (debug)
	    ERROR(1,( "%d(%d)(%d/%d) attacking %c%d %16s damage (%d/%d) dist %d\n",
		me->p_no,
		(int) me->p_kills,
		me->p_damage,
		me->p_shield,
		teamlet[enemy->p_team],
		enemy->p_no,
		enemy->p_login,
		enemy->p_damage,
		enemy->p_shield,
		enemy_buf->e_dist));*/

	if (enemy_buf->e_dist < 15000) {
	    set_course(enemy_buf->e_course + 
		    avoid[(roboclock / AVOID_CLICKS) % SIZEOF(avoid)]);
	    if (angdist(me->p_desdir, me->p_dir) > 64)
		set_speed(closeslow);
	    else
		set_speed(closefast);
	}
	else {
	    me->p_desdir = enemy_buf->e_course;
	    if (angdist(me->p_desdir, me->p_dir) > 64)
		set_speed(closeslow);
	    if (target >= 0)	/* 7/27/91 TC */
		set_speed(12);
	    else if (me->p_etemp > 900)		/* 90% of 1000 */
		set_speed(runslow);
	    else
		set_speed(runfast);
	}
    }
    else {
	go_home(enemy_buf);
    }
}