|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T e
Length: 13518 (0x34ce)
Types: TextFile
Names: »enemycom.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Trek73/src/enemycom.c«
#ident "@(#) TREK73 $Header: enemycom.c,v 1.1 87/10/09 11:05:38 okamoto Exp $"
/*
* $Source: /ccc/okamoto/src/trek/src/RCS/enemycom.c,v $
*
* $Header: enemycom.c,v 1.1 87/10/09 11:05:38 okamoto Exp $
*
* $Log: enemycom.c,v $
* Revision 1.1 87/10/09 11:05:38 11:05:38 okamoto (Jeff Okamoto)
* Initial revision
*
*/
/*
* TREK73: enemycom.c
*
* Enemy strategy sub-routines
*
* e_attack, e_checkarms, e_checkprobe, e_cloak_off, e_cloak_on,
* e_closetorps, e_destruct, e_evade, e_jettison, e_launchprobe,
* e_loadtubes, e_lockphasers, e_locktubes, e_phasers, e_pursue,
* e_runaway, e_torpedo
*
*/
#include "externs.h"
/*
* This routine turns the ship at speed towards its target
*/
int
e_attack(sp, fed)
struct ship *sp;
struct ship *fed;
{
float speed;
float tmpf;
tmpf = fabs(fed->warp);
if (fabs(sp->warp) >= tmpf + 2.0 || (is_dead(sp, S_WARP)))
return 0;
if ((speed = tmpf + randm(2) + 2.0) > sp->max_speed)
speed = sp->max_speed;
(void) e_pursue(sp, fed, speed);
if (cansee(sp) && syswork(fed, S_SENSOR))
printf("%s: %s attacking.\n", helmsman, sp->name);
return 1;
}
/*
* Returns the number of currently loaded, undamaged weapons
*/
int
e_checkarms(sp)
struct ship *sp;
{
register int i;
register int arms;
arms = 0;
for (i=0; i<sp->num_phasers; i++)
if (!(sp->phasers[i].status & P_DAMAGED) &&
(sp->phasers[i].load >= 0))
arms++;
for (i=0; i<sp->num_tubes; i++)
if (!(sp->tubes[i].status & T_DAMAGED) &&
(sp->tubes[i].load >= 0))
arms++;
#ifdef TRACE
if (trace)
printf("*** Checkarms: Returning %d\n", arms);
#endif
return arms;
}
/*
* returns 1 if evasive action being taken (to avoid probe)
*/
int
e_checkprobe(sp)
struct ship *sp;
{
register struct list *lp;
register int range;
register struct torpedo *tp;
/*
* If we are cloaked, do not bother with this.
* Since probes cannot detect us when cloaked.
*/
if (cantsee(sp))
return 0;
for (lp = &head; lp != tail; lp = lp->fwd) {
if (lp->type != I_PROBE)
continue;
tp = lp->data.tp;
range = rangefind(sp->x, tp->x, sp->y, tp->y);
#ifdef TRACE
if (trace)
printf("*** Checkprobe: Range = %d\n", range);
#endif
if (range < 2000) {
(void) e_evade(sp, tp->x, tp->y, I_PROBE);
return 1;
}
}
return 0;
}
/*
* Returns 1 if cloaking device was turned off
*/
int
e_cloak_off(sp, fed)
struct ship *sp;
struct ship *fed;
{
if (sp->cloaking != C_ON)
return 0;
sp->cloaking = C_OFF;
sp->cloak_delay = 4;
if (syswork(sp, S_SENSOR)) {
printf("%s: The %s has reappeared on our sensors %d\n",
science, sp->name, rangefind(sp->x, sp->position.x,
sp->y, sp->position.y));
puts(" megameters from its projected position.");
}
fed = fed; /* LINT */
return 1;
}
/*
* Returns 1 if cloaking device was turned on
*/
int
e_cloak_on(sp, fed)
struct ship *sp;
struct ship *fed;
{
if ((sp->cloak_delay > 0) || (sp->cloaking != C_OFF))
return 0;
sp->cloaking = C_ON;
sp->position.x = sp->x;
sp->position.y = sp->y;
sp->position.warp = sp->warp;
sp->position.course = sp->course;
if (syswork(fed, S_SENSOR))
printf("%s: The %s has disappeared from our sensors.\n",
science, sp->name);
fed = fed; /* LINT */
return 1;
}
/*
* Returns 1 if firing phasers at or evading nearby torpedoes
*/
int
e_closetorps(sp, fed)
struct ship *sp;
struct ship *fed;
{
register struct list *lp;
register int range;
register struct torpedo *tp;
struct torpedo *bad;
/*
* If we are cloaked, forget about this.
* Since prox fuses won't affect us under cloak
*/
if (cantsee(sp))
return 0;
bad = NULL;
for (lp = &head; lp != tail; lp = lp->fwd) {
if (lp->type != I_TORPEDO)
continue;
tp = lp->data.tp;
if (tp->from != fed)
continue;
range = rangefind(sp->x, tp->x, sp->y, tp->y);
#ifdef TRACE
if (trace)
printf("*** Checktorp: Range = %d\n", range);
#endif
if (range < 1200) {
bad = tp;
/*
* fire phasers - hope they're pointing in
* the right direction!
*/
if (e_phasers(sp, (struct ship *) NULL))
return 1;
}
}
/*
* we can't get a phaser shot off.
* try and evade (although hopeless)
*/
if (bad != NULL) {
#ifdef TRACE
if (trace)
printf("*** Checktorp: Cannot fire phasers! Evade!\n");
#endif
(void) e_evade(sp, tp->x, tp->y, I_TORPEDO);
return 1;
}
return 0;
}
/*
* goodbye, cruel world (Returns 1 if self-destruct was initiated)
*/
int
e_destruct(sp, fed)
struct ship *sp, *fed;
{
if (sp->delay < 5.0)
return 0;
sp->delay = 5.0;
(void) e_cloak_off(sp, fed);
sp->cloaking = C_NONE;
if (syswork(fed, S_SENSOR)) {
printf("%s: The %s is overloading what remains of it's\n",
science, sp->name);
puts(" antimatter pods -- obviously a suicidal gesture.");
puts(" Estimate detonation in five seconds.");
}
return 1;
}
/*
* Advance to the rear! (Always returns 1)
*/
int
e_evade(sp, x, y, type)
struct ship *sp;
int x;
int y;
int type; /* Currently unused */
{
register float newcourse;
float bear;
bear = bearing(sp->x, x, sp->y, y);
if (cansee(sp) && syswork(shiplist[0], S_SENSOR))
printf("%s taking evasive action!\n", sp->name);
switch (randm(3)) {
case 1:
newcourse = rectify(bear - 90.0);
break;
case 2:
newcourse = rectify(bear + 90.0);
break;
case 3:
newcourse = rectify(bear + 180.0);
break;
default:
printf("error in evade()\n");
break;
}
sp->target = NULL;
sp->newcourse = newcourse;
sp->newwarp = 2 + randm((int)(sp->max_speed - 3));
if (is_dead(sp, S_WARP))
sp->newwarp = 1.0;
#ifdef TRACE
if (trace) {
printf("*** Evade: Newcourse = %3.0f\n", newcourse);
printf("*** Evade: Newwarp = %.2f\n", sp->newwarp);
}
#endif
type = type; /* LINT */
return 1;
}
/*
* Returns 1 if engineering was jettisoned
*/
int
e_jettison(sp, fed)
struct ship *sp, *fed;
{
register struct list *lp;
register struct torpedo *tp;
if (is_dead(sp, S_ENG))
return 0;
(void) e_cloak_off(sp, fed);
if (syswork(shiplist[0], S_SENSOR)) {
printf("%s: Sensors indicate debris being left by\n", science);
printf(" the %s. Insufficient mass . . .\n", sp->name);
}
lp = newitem(I_ENG);
tp = lp->data.tp = MKNODE(struct torpedo, *, 1);
if (tp == (struct torpedo *)NULL) {
fprintf(stderr, "e_jettison: malloc failed\n");
exit(2);
}
tp->id = new_slot();
/*
* ship slows to warp 1.0 when jettisonning engineering
*/
tp->newspeed = 0.0;
tp->speed = sp->warp;
tp->target = NULL;
tp->course = sp->course;
tp->x = sp->x;
tp->y = sp->y;
tp->prox = 0;
tp->timedelay = 10.;
tp->fuel = sp->energy;
tp->type = TP_ENGINEERING;
sp->energy = sp->pods = 0;
sp->regen = 0.0;
tp->from = sp;
if (sp->newwarp < -1.0)
sp->newwarp = -0.99;
if (sp->newwarp > 1.0)
sp->newwarp = 0.99;
sp->max_speed = 1.0;
sp->status[S_ENG] = 100; /* List as destroyed */
sp->status[S_WARP] = 100;
sp->cloaking = C_NONE;
sp->t_blind_left = sp->t_blind_right = sp->p_blind_left =
sp->p_blind_right = 180;
return 1;
}
/*
* Returns 1 if a probe was launched
*/
int
e_launchprobe(sp, fed)
struct ship *sp;
struct ship *fed;
{
register int i;
register struct list *lp;
register struct torpedo *tp;
if (!syswork(sp, S_PROBE) || sp->energy <= 10 || cantsee(sp))
return 0;
/*
* fed ship has to be going slow before we'll launch
* a probe at it.
*/
if (fabs(fed->warp) > 1.0)
return 0;
lp = newitem(I_PROBE);
tp = lp->data.tp = MKNODE(struct torpedo, *, 1);
if (tp == (struct torpedo *)NULL) {
fprintf(stderr, "e_launchprobe: malloc failed\n");
exit(2);
}
tp->from = sp;
tp->speed = sp->warp;
tp->newspeed = 3.0;
tp->target = fed;
tp->course = bearing(sp->x, fed->x, sp->y, fed->y);
tp->x = sp->x;
tp->y = sp->y;
tp->prox = 200 + randm(200);
tp->timedelay = 15.;
tp->id = new_slot();
if ((i = randm(15) + 10) > sp->energy)
i = sp->energy;
tp->fuel = i;
tp->type = TP_PROBE;
sp->energy -= i;
sp->pods -= i;
printf("%s launching probe #%d\n", sp->name, tp->id);
return 1;
}
/*
* Returns the number of tubes that were loaded
*/
int
e_loadtubes(sp)
struct ship *sp;
{
register int i;
register int j;
register int loaded;
register int below;
below = 10;
loaded = 0;
for (i=0; i<sp->num_tubes; i++) {
if (sp->energy <= below)
break;
if (sp->tubes[i].status & T_DAMAGED)
continue;
j = min(sp->energy, 10 - sp->tubes[i].load);
if (j == 0)
continue;
sp->energy -= j;
sp->pods -= j;
sp->tubes[i].load += j;
loaded++;
}
#ifdef TRACE
if (trace)
printf("*** Load tubes: Loaded %d tubes\n", loaded);
#endif
return loaded;
}
/*
* Returns the number of phasers that were locked
*/
int
e_lockphasers(sp, fed)
struct ship *sp;
struct ship *fed;
{
register int i;
register int banks;
banks = 0;
for (i=0; i<sp->num_phasers; i++) {
if (sp->phasers[i].status & P_DAMAGED)
continue;
if (sp->phasers[i].target != NULL)
continue;
sp->phasers[i].target = fed;
banks++;
}
#ifdef TRACE
if (trace)
printf("*** Lock phasers: Locked %d phasers\n", banks);
#endif
return banks;
}
/*
* Returns number of tubes locked
*/
int
e_locktubes(sp, fed)
struct ship *sp;
struct ship *fed;
{
register int i;
register int tubes;
tubes = 0;
for (i=0; i<sp->num_tubes; i++) {
if (sp->tubes[i].status & T_DAMAGED)
continue;
if (sp->tubes[i].target != NULL)
continue;
sp->tubes[i].target = fed;
tubes++;
}
#ifdef TRACE
if (trace)
printf("*** Lock tubes: Locked %d tubes\n", tubes);
#endif
return tubes;
}
/*
* returns the number of banks we're going to fire
* it also sets them up to fire.
*/
int
e_phasers(sp, fed)
struct ship *sp;
struct ship *fed;
{
register int i;
register int banks;
register int hit;
register int howmany;
float bear;
banks = 0;
howmany = randm(sp->num_phasers / 2) + sp->num_phasers / 2;
sp->p_spread = 10 + randm(12);
for (i=0; i<sp->num_phasers; i++) {
if ((sp->phasers[i].status & P_DAMAGED) ||
(sp->phasers[i].load == 0))
continue;
if (fed != NULL) {
if (sp->phasers[i].target == NULL)
continue;
bear = bearing(sp->x, fed->x, sp->y, fed->y);
hit = phaser_hit(sp, fed->x, fed->y, &sp->phasers[i], bear);
if (hit <= 0)
continue;
}
banks++;
sp->phasers[i].status |= P_FIRING;
if (banks >= howmany)
break;
}
return banks;
}
/*
* This routine will turn the ship, slowing down if necessary to
* facilitate the turn. (Always returns 1)
*/
int
e_pursue(sp, fed, speed)
struct ship *sp;
struct ship *fed;
float speed;
{
float bear;
float coursediff;
bear = bearing(sp->x, fed->x, sp->y, fed->y);
/*
* do a quick turn if our speed is > max_warp - 2 and
* (thus) we are never going to bear on the fed ship
* speed = max_warp / 2 is a magic cookie. Feel free to change.
*/
coursediff = rectify(sp->course - bear);
if (coursediff > 180.0)
coursediff -= 360.0;
if (speed >= sp->max_speed - 2 && fabs(coursediff) > 10)
speed = (int)(sp->max_speed / 2);
sp->target = fed;
sp->newcourse = bear;
sp->newwarp = speed;
if (speed > 1 && is_dead(sp, S_WARP))
sp->newwarp = 0.99;
#ifdef TRACE
if (trace) {
printf("*** Pursue: Newcourse = %.2f\n", sp->newcourse);
printf("*** Pursue: Newwarp = %.2f\n", sp->newwarp);
}
#endif
return 1;
}
/*
* This routine has the enemy ship turn its strongest shield towards
* the enemy and then accelerate to 2/3 maximum speed. (Always
* returns 1)
*/
int
e_runaway(sp, fed)
struct ship *sp;
struct ship *fed;
{
register double bear;
register int strong;
register double strength;
register double temp;
register int sign;
register float course;
register int i;
bear = bearing(sp->x, fed->x, sp->y, fed->y);
/*
* Find the strongest shield
*/
strong = 0;
strength = 0.;
for (i=0; i< SHIELDS; i++) {
temp = sp->shields[i].eff * sp->shields[i].drain *
(i == 0 ? SHIELD1 : 1.);
if (temp > strength) {
strong = i;
strength = temp;
}
}
switch (strong) {
case 0: course = bear;
sign = -1;
break;
case 1: course = rectify(bear - 90);
sign = 1;
break;
case 2: course = rectify(bear + 180);
sign = 1;
break;
case 3: course = rectify(bear + 90);
sign = 1;
break;
}
sp->target = NULL;
sp->newcourse = course;
sp->newwarp = 2 / 3 * sp->max_speed * sign;
if (sp->newwarp > 1.0 && is_dead(sp, S_WARP))
sp->newwarp = 0.99;
if (cansee(sp) && syswork(fed, S_SENSOR))
printf("%s: The %s is retreating.\n", helmsman, sp->name);
#ifdef TRACE
if (trace) {
printf("*** Runaway: Newcourse = %.2f\n", sp->newcourse);
printf("*** Runaway: Newwarp = %.2f\n", sp->newwarp);
}
#endif
return 1;
}
/*
* Returns the number of tubes we're going to fire
* Also sets them up to fire
*/
int
e_torpedo(sp)
struct ship *sp;
{
register int i;
register int tubes;
register int howmany;
register struct ship *sp1;
register int range;
/*
* don't shoot if someone might be in the way
* (i.e. proximity fuse will go off right as the
* torps leave the tubes!)
*/
for (i=1; i <= shipnum; i++) {
sp1 = shiplist[i];
/* This must check for dead ships too! */
if (sp1 == sp)
continue;
range = rangefind(sp->x, sp1->x, sp->y, sp1->y);
if (range <= 400)
return 0;
}
tubes = 0;
/* This is not and should not be dependent on the
number of tubes one has */
howmany = randm(2) + 1;
for (i=0; i<sp->num_tubes; i++) {
if ((sp->tubes[i].status & T_DAMAGED)
|| (sp->tubes[i].load == 0))
continue;
if (sp->tubes[i].target == NULL)
continue;
tubes++;
sp->tubes[i].status |= T_FIRING;
if (tubes >= howmany)
break;
}
return tubes;
}