/* * TREK73: subs.c * * Miscellaneous Subroutines * * ship_name, newitem, delitem, rangefind, bearing, phaser_hit, * torpedo_hit, damage, antimatter_hit, recitfy */ #include "defines.h" #include "structs.h" #include #include extern struct ship *shiplist[]; extern char science[]; struct ship *ship_name(name, start) char *name; int start; { extern int shipnum; register int i; register int j; register int len; if (islower(*name)) { *name = toupper(*name); } j = shipnum; len = strlen(name); for (i=start; i<=j; i++) { if (shiplist[i]->name[0] == NULL) continue; if (strncmp(name, shiplist[i]->name, len) == 0) return shiplist[i]; } printf("%s: I am unable to find the %s\n", science, name); return NULL; } struct list *newitem(item) int item; { extern struct list head; extern struct list *tail; register struct list *new; register struct list *newtail; /* * if there's no "tail" node, make one (only happens at init) */ if (tail == NULL) { new = MKNODE(struct list, *, 1); new->back = &head; new->fwd = NULL; new->data.tp = NULL; head.fwd = new; tail = new; } new = tail; /* * now make the new tail node */ newtail = MKNODE(struct list, *, 1); newtail->back = new; newtail->fwd = NULL; newtail->data.tp = NULL; newtail->type = 0; tail = newtail; /* * link the old tail node to the new one */ new->type = item; new->fwd = newtail; return new; } int delitem(item) struct list *item; { extern struct list *tail; extern struct list head; register struct list *bp; register struct list *fp; bp = item->back; fp = item->fwd; if (item->data.tp != NULL) free((char *) item->data.tp); /* * re-arrange pointers on both the next and the previous * nodes; if no forward pointer, we were the tail so make * the bp the new tail node. */ if (fp != NULL) { bp->fwd = fp; fp->back = bp; } else { tail = bp; bp->fwd = NULL; } free((char *) item); } int rangefind(x1, x2, y1, y2) int x1; int x2; int y1; int y2; { extern double sqrt(); extern double atan(); register int i; register int x, y; double d1, d2; x = x2 - x1; y = y2 - y1; /* * Both x and y must be cast as double else overflow * may occur. */ d1 = (double) x * (double) x + (double) y * (double) y; d2 = sqrt(d1); i = d2; return i; } /* * This routine finds the bearing of (x2,y2) from (x1,y1) */ int bearing(x1, x2, y1, y2) int x1; int x2; int y1; int y2; { extern double atan(); float x; float y; register int bear; double d1; double d2; x = x2 - x1; y = y2 - y1; if (x == 0.0) bear = 90; else { d1 = y/x; d2 = atan(d1) * 57.2958; bear = d2; } if (x < 0.0 || y < 0.0) { bear += 180; if (x >= 0.0) bear += 180; } return bear; } int phaser_hit(sp, x, y, bank, true_bear) struct ship *sp; int x; int y; struct phaser *bank; int true_bear; { extern double sqrt(); register int hit; int i; int spread; int bear; double d1; double d2; hit = 0; i = rangefind(sp->x, x, sp->y, y); if (i < 1000) { bear = bearing(sp->x, x, sp->y, y); spread = rectify(true_bear - bear); /* * Check if a target is within the phaser spread */ if (spread > sp->p_spread && 360-spread > sp->p_spread) return 0; d1 = 1.0 - (float)i/1000.0; d2 = (float)bank->load * sqrt(d1) * sp->p_percent / 100; d2 = (float)bank->load * d2 * 45.0/(float)sp->p_spread * sp->p_percent / 100; hit = d2/10.0; } return hit; } int torpedo_hit(fuel, x, y, tx, ty) int fuel; int x; int y; int tx; int ty; { extern double sqrt(); register int hit; int i; double d1; double d2; float f1; float f2; hit = 0; i = rangefind(x, tx, y, ty); f1 = fuel * 5.0; f2 = f1 * 10.0; if (i < f2) { d1 = 1.0 - (float)i/f2; d2 = (float)f1 * sqrt(d1); hit = d2; } return hit; } damage(hit, ep, s, dam) int hit; struct ship *ep; int s; struct damage *dam; { register int i; register int j; register int k; float f1; float f2; struct ship *fed; fed = shiplist[0]; printf("hit %d on %s's shield %d\n", hit, ep->name, s); s--; /* * Note that if the shield is at 100% efficiency, no * damage at all will be taken */ f1 = hit * (1.0 - ep->shields[s].eff * ep->shields[s].drain); if (f1 < 0) return 0; ep->eff += f1/dam->eff; ep->pods -= f1/dam->fuel; ep->energy -= f1/dam->fuel; ep->regen -= f1/dam->regen; if (ep->regen < 0.0) ep->regen = 0.0; if (ep->pods < 0.0) ep->pods = 0.0; if (ep->energy < 0.0) ep->energy = 0.0; if (ep->pods < ep->energy) ep->energy = ep->pods; f2 = dam->shield * 100; if (s == 0) f2 *= 1.5; ep->shields[s].eff -= max(hit/f2, 0); if (ep->shields[s].eff < 0.0) ep->shields[s].eff = 0.0; j = f1 * dam->crew; if (j > 0) ep->crew -= max(randm(j), 0); if (ep->crew < 0) ep->crew = 0; j = f1/dam->weapon; for(i=0; iphasers[k].status & P_DAMAGED) continue; ep->phasers[k].status |= P_DAMAGED; /* * Reroute the energy * back to the engines */ ep->energy = min(ep->pods, ep->energy + ep->phasers[k].load); ep->phasers[k].load = 0; ep->phasers[k].drain = 0; k++; if (ep == fed) printf(" phaser %d damaged.\n", k); } else { k -= 5; if (ep->tubes[k].status & T_DAMAGED) continue; /* * If tubes are damaged, reroute the pods * back to the engines */ ep->pods += ep->tubes[k].load; ep->energy += ep->tubes[k].load; ep->tubes[k].load = 0; ep->tubes[k].status |= T_DAMAGED; k++; if (ep == fed) printf(" tube %d damaged\n", k); } } for (i=0; i<4; i++) { if (ep->status & 1<stats[i].roll) < f1) { ep->status |= 1<stats[i].mesg); } } #ifdef HISTORICAL /* * Historically, if more than 43 points of damage were done * to the ship, it would destroy itself. This led to much * abuse of probes and thus has been enclosed inside of * an #ifdef */ if (f1 > 43) ep->delay = 1; #endif return 0; } antimatter_hit(ptr, x, y, fuel) char *ptr; int x; int y; int fuel; { extern struct list head; extern struct list *tail; extern struct damage a_damage; register struct list *lp; register int hit; int tarx, tary; int s; int bear; struct torpedo *tp; struct ship *sp; for (lp = &head; lp != tail; lp = lp->fwd) { if (lp->type == 0) continue; sp = NULL; tp = NULL; if (lp->type == I_SHIP) { sp = lp->data.sp; tarx = sp->x; tary = sp->y; } else { tp = lp->data.tp; tarx = tp->x; tary = tp->y; } if (sp == (struct ship *) ptr || tp == (struct torpedo *) ptr) continue; hit = torpedo_hit(fuel, x, y, tarx, tary); if (hit <= 0) continue; if (sp) { /* * Determine which shield is hit */ bear = rectify(bearing(tarx, x, tary, y) - sp->course); if (bear < 45 || bear > 315) s = 1; else if (bear < 135) s = 2; else if (bear < 225) s = 3; else s = 4; damage(hit, sp, s, &a_damage); } else { if (tp->timedelay <= 2) continue; tp->timedelay = 2; switch (lp->type) { case I_TORPEDO: printf("hit on torpedo %d\n", tp->id); break; case I_PROBE: printf("hit on probe %d\n", tp->id); break; case I_ENG: printf("hit on %s engineering\n", tp->from->name); break; } } } } int rectify(x) int x; { register int ret; ret = x; if (ret < 0) ret += 360; else if (ret > 360) ret -= 360; return ret; }