예제 #1
0
bool
getcodi(int *co, double *di)
{

	*co = getintpar("Course");

	/* course must be in the interval [0, 360] */
	if (*co < 0 || *co > 360)
		return (1);
	*di = getfltpar("Distance");

	/* distance must be in the interval [0, 15] */
	if (*di <= 0.0 || *di > 15.0)
		return (1);

	/* good return */
	return (0);
}
예제 #2
0
/*ARGSUSED*/
void
torped(int v __unused)
{
	int		ix, iy;
	double		x, y, dx, dy;
	double		angle;
	int		course, course2;
	int		k;
	double		bigger;
	double		sectsize;
	int		burst;
	int		n;

	if (Ship.cloaked) {
		printf("Federation regulations do not permit attack while "
		       "cloaked.\n");
		return;
	}
	if (check_out(TORPED))
		return;
	if (Ship.torped <= 0) {
		printf("All photon torpedos expended\n");
		return;
	}

	/* get the course */
	course = getintpar("Torpedo course");
	if (course < 0 || course > 360)
		return;
	burst = -1;

	/* need at least three torpedoes for a burst */
	if (Ship.torped < 3) {
		printf("No-burst mode selected\n");
		burst = 0;
	} else {
		/* see if the user wants one */
		if (!testnl()) {
			k = ungetc(getchar(), stdin);
			if (k >= '0' && k <= '9')
				burst = 1;
		}
	}
	if (burst < 0) {
		burst = getynpar("Do you want a burst");
	}
	if (burst) {
		burst = getintpar("burst angle");
		if (burst <= 0)
			return;
		if (burst > 15) {
			printf("Maximum burst angle is 15 degrees\n");
			return;
		}
	}
	sectsize = NSECTS;
	n = -1;
	if (burst) {
		n = 1;
		course -= burst;
	}
	for (; n && n <= 3; n++) {
		/* select a nice random course */
		course2 = course + randcourse(n);
		/* convert to radians */
		angle = course2 * 0.0174532925;
		dx = -cos(angle);
		dy =  sin(angle);
		bigger = fabs(dx);
		x = fabs(dy);
		if (x > bigger)
			bigger = x;
		dx /= bigger;
		dy /= bigger;
		x = Ship.sectx + 0.5;
		y = Ship.secty + 0.5;
		if (Ship.cond != DOCKED)
			Ship.torped -= 1;
		printf("Torpedo track");
		if (n > 0)
			printf(", torpedo number %d", n);
		printf(":\n%6.1f\t%4.1f\n", x, y);
		while (1) {
			ix = x += dx;
			iy = y += dy;
			if (x < 0.0 || x >= sectsize ||
			    y < 0.0 || y >= sectsize) {
				printf("Torpedo missed\n");
				break;
			}
			printf("%6.1f\t%4.1f\n", x, y);
			switch (Sect[ix][iy]) {
			  case EMPTY:
				continue;

			  case HOLE:
				printf("Torpedo disappears into a black "
				       "hole\n");
				break;

			  case KLINGON:
				for (k = 0; k < Etc.nkling; k++) {
					if (Etc.klingon[k].x != ix ||
					    Etc.klingon[k].y != iy)
						continue;
					Etc.klingon[k].power -= 500 + ranf(501);
					if (Etc.klingon[k].power > 0) {
						printf("*** Hit on Klingon at "
						       "%d,%d: extensive "
						       "damages\n",
							ix, iy);
						break;
					}
					killk(ix, iy);
					break;
				}
				break;

			  case STAR:
				nova(ix, iy);
				break;

			  case INHABIT:
				kills(ix, iy, -1);
				break;

			  case BASE:
				killb(Ship.quadx, Ship.quady);
				Game.killb += 1;
				break;

			  default:
				printf("Unknown object %c at %d,%d destroyed\n",
					Sect[ix][iy], ix, iy);
				Sect[ix][iy] = EMPTY;
				break;
			}
			break;
		}
		if (damaged(TORPED) || Quad[Ship.quadx][Ship.quady].stars < 0)
			break;
		course += burst;
	}
	Move.free = 0;
}
예제 #3
0
phaser()
{
	register int		i;
	int			j;
	register struct kling	*k;
	double			dx, dy;
	double			anglefactor, distfactor;
	register struct banks	*b;
	int			manual, flag, extra;
	int			hit;
	double			tot;
	int			n;
	int			hitreqd[NBANKS];
	struct banks		bank[NBANKS];
	struct cvntab		*ptr;

	if (Ship.cond == DOCKED)
		return(printf("Phasers cannot fire through starbase shields\n"));
	if (damaged(PHASER))
		return (out(PHASER));
	if (Ship.shldup)
		return (printf("Sulu: Captain, we cannot fire through shields.\n"));
	if (Ship.cloaked)
	{
		printf("Sulu: Captain, surely you must realize that we cannot fire\n");
		printf("  phasers with the cloaking device up.\n");
		return;
	}

	/* decide if we want manual or automatic mode */
	manual = 0;
	if (testnl())
	{
		if (damaged(COMPUTER))
		{
			printf(Device[COMPUTER].name);
			manual++;
		}
		else
			if (damaged(SRSCAN))
			{
				printf(Device[SRSCAN].name);
				manual++;
			}
		if (manual)
			printf(" damaged, manual mode selected\n");
	}

	if (!manual)
	{
		ptr = getcodpar("Manual or automatic", Matab);
		manual = (int) ptr->value;
	}
	if (!manual && damaged(COMPUTER))
	{
		printf("Computer damaged, manual selected\n");
		skiptonl(0);
		manual++;
	}

	/* initialize the bank[] array */
	flag = 1;
	for (i = 0; i < NBANKS; i++)
		bank[i].units = 0;
	if (manual)
	{
		/* collect manual mode statistics */
		while (flag)
		{
			printf("%d units available\n", Ship.energy);
			extra = 0;
			flag = 0;
			for (i = 0; i < NBANKS; i++)
			{
				b = &bank[i];
				printf("\nBank %d:\n", i);
				hit = getintpar("units");
				if (hit < 0)
					return;
				if (hit == 0)
					break;
				extra += hit;
				if (extra > Ship.energy)
				{
					printf("available energy exceeded.  ");
					skiptonl(0);
					flag++;
					break;
				}
				b->units = hit;
				hit = getintpar("course");
				if (hit < 0 || hit > 360)
					return;
				b->angle = hit * 0.0174532925;
				b->spread = getfltpar("spread");
				if (b->spread < 0 || b->spread > 1)
					return;
			}
			Ship.energy -= extra;
		}
		extra = 0;
	}
	else
	{
		/* automatic distribution of power */
		if (Etc.nkling <= 0)
			return (printf("Sulu: But there are no Klingons in this quadrant\n"));
		printf("Phasers locked on target.  ");
		while (flag)
		{
			printf("%d units available\n", Ship.energy);
			hit = getintpar("Units to fire");
			if (hit <= 0)
				return;
			if (hit > Ship.energy)
			{
				printf("available energy exceeded.  ");
				skiptonl(0);
				continue;
			}
			flag = 0;
			Ship.energy -= hit;
			extra = hit;
			n = Etc.nkling;
			if (n > NBANKS)
				n = NBANKS;
			tot = n * (n + 1) / 2;
			for (i = 0; i < n; i++)
			{
				k = &Etc.klingon[i];
				b = &bank[i];
				distfactor = k->dist;
				anglefactor = ALPHA * BETA * OMEGA / (distfactor * distfactor + EPSILON);
				anglefactor *= GAMMA;
				distfactor = k->power;
				distfactor /= anglefactor;
				hitreqd[i] = distfactor + 0.5;
				dx = Ship.sectx - k->x;
				dy = k->y - Ship.secty;
				b->angle = atan2(dy, dx);
				b->spread = 0.0;
				b->units = ((n - i) / tot) * extra;
#				ifdef xTRACE
				if (Trace)
				{
					printf("b%d hr%d u%d df%.2f af%.2f\n",
						i, hitreqd[i], b->units,
						distfactor, anglefactor);
				}
#				endif
				extra -= b->units;
				hit = b->units - hitreqd[i];
				if (hit > 0)
				{
					extra += hit;
					b->units -= hit;
				}
			}

			/* give out any extra energy we might have around */
			if (extra > 0)
			{
				for (i = 0; i < n; i++)
				{
					b = &bank[i];
					hit = hitreqd[i] - b->units;
					if (hit <= 0)
						continue;
					if (hit >= extra)
					{
						b->units += extra;
						extra = 0;
						break;
					}
					b->units = hitreqd[i];
					extra -= hit;
				}
				if (extra > 0)
					printf("%d units overkill\n", extra);
			}
		}
	}

#	ifdef xTRACE
	if (Trace)
	{
		for (i = 0; i < NBANKS; i++)
		{
			b = &bank[i];
			printf("b%d u%d", i, b->units);
			if (b->units > 0)
				printf(" a%.2f s%.2f\n", b->angle, b->spread);
			else
				printf("\n");
		}
	}
#	endif

	/* actually fire the shots */
	Move.free = 0;
	for (i = 0; i < NBANKS; i++)
	{
		b = &bank[i];
		if (b->units <= 0)
		{
			continue;
		}
		printf("\nPhaser bank %d fires:\n", i);
		n = Etc.nkling;
		k = Etc.klingon;
		for (j = 0; j < n; j++)
		{
			if (b->units <= 0)
				break;
			/*
			** The formula for hit is as follows:
			**
			**  zap = OMEGA * [(sigma + ALPHA) * (rho + BETA)]
			**	/ (dist ** 2 + EPSILON)]
			**	* [cos(delta * sigma) + GAMMA]
			**	* hit
			**
			** where sigma is the spread factor,
			** rho is a random number (0 -> 1),
			** GAMMA is a crud factor for angle (essentially
			**	cruds up the spread factor),
			** delta is the difference in radians between the
			**	angle you are shooting at and the actual
			**	angle of the klingon,
			** ALPHA scales down the significance of sigma,
			** BETA scales down the significance of rho,
			** OMEGA is the magic number which makes everything
			**	up to "* hit" between zero and one,
			** dist is the distance to the klingon
			** hit is the number of units in the bank, and
			** zap is the amount of the actual hit.
			**
			** Everything up through dist squared should maximize
			** at 1.0, so that the distance factor is never
			** greater than one.  Conveniently, cos() is
			** never greater than one, but the same restric-
			** tion applies.
			*/
			distfactor = BETA + franf();
			distfactor *= ALPHA + b->spread;
			distfactor *= OMEGA;
			anglefactor = k->dist;
			distfactor /= anglefactor * anglefactor + EPSILON;
			distfactor *= b->units;
			dx = Ship.sectx - k->x;
			dy = k->y - Ship.secty;
			anglefactor = atan2(dy, dx) - b->angle;
			anglefactor = cos((anglefactor * b->spread) + GAMMA);
			if (anglefactor < 0.0)
			{
				k++;
				continue;
			}
			hit = anglefactor * distfactor + 0.5;
			k->power -= hit;
			printf("%d unit hit on Klingon", hit);
			if (!damaged(SRSCAN))
				printf(" at %d,%d", k->x, k->y);
			printf("\n");
			b->units -= hit;
			if (k->power <= 0)
			{
				killk(k->x, k->y);
				continue;
			}
			k++;
		}
	}

	/* compute overkill */
	for (i = 0; i < NBANKS; i++)
		extra += bank[i].units;
	if (extra > 0)
		printf("\n%d units expended on empty space\n", extra);
}
예제 #4
0
파일: computer.c 프로젝트: dank101/386BSD
computer()
{
	int			ix, iy;
	register int		i, j;
	int			numout;
	int			tqx, tqy;
	struct cvntab		*r;
	int			cost;
	int			course;
	double			dist, time;
	double			warpfact;
	struct quad		*q;
	register struct event	*e;

	if (check_out(COMPUTER))
		return;
	while (1)
	{
		r = getcodpar("\nRequest", Cputab);
		switch ((int)r->value)
		{

		  case 1:			/* star chart */
			printf("Computer record of galaxy for all long range sensor scans\n\n");
			printf("  ");
			/* print top header */
			for (i = 0; i < NQUADS; i++)
				printf("-%d- ", i);
			printf("\n");
			for (i = 0; i < NQUADS; i++)
			{
				printf("%d ", i);
				for (j = 0; j < NQUADS; j++)
				{
					if (i == Ship.quadx && j == Ship.quady)
					{
						printf("$$$ ");
						continue;
					}
					q = &Quad[i][j];
					/* 1000 or 1001 is special case */
					if (q->scanned >= 1000)
						if (q->scanned > 1000)
							printf(".1. ");
						else
							printf("/// ");
					else
						if (q->scanned < 0)
							printf("... ");
						else
							printf("%3d ", q->scanned);
				}
				printf("%d\n", i);
			}
			printf("  ");
			/* print bottom footer */
			for (i = 0; i < NQUADS; i++)
				printf("-%d- ", i);
			printf("\n");
			break;

		  case 2:			/* trajectory */
			if (check_out(SRSCAN))
			{
				break;
			}
			if (Etc.nkling <= 0)
			{
				printf("No Klingons in this quadrant\n");
				break;
			}
			/* for each Klingon, give the course & distance */
			for (i = 0; i < Etc.nkling; i++)
			{
				printf("Klingon at %d,%d", Etc.klingon[i].x, Etc.klingon[i].y);
				course = kalc(Ship.quadx, Ship.quady, Etc.klingon[i].x, Etc.klingon[i].y, &dist);
				prkalc(course, dist);
			}
			break;

		  case 3:			/* course calculation */
			if (readdelim('/'))
			{
				tqx = Ship.quadx;
				tqy = Ship.quady;
			}
			else
			{
				ix = getintpar("Quadrant");
				if (ix < 0 || ix >= NSECTS)
					break;
				iy = getintpar("q-y");
				if (iy < 0 || iy >= NSECTS)
					break;
				tqx = ix;
				tqy = iy;
			}
			ix = getintpar("Sector");
			if (ix < 0 || ix >= NSECTS)
				break;
			iy = getintpar("s-y");
			if (iy < 0 || iy >= NSECTS)
				break;
			course = kalc(tqx, tqy, ix, iy, &dist);
			if (r->value2)
			{
				warp(-1, course, dist);
				break;
			}
			printf("%d,%d/%d,%d to %d,%d/%d,%d",
				Ship.quadx, Ship.quady, Ship.sectx, Ship.secty, tqx, tqy, ix, iy);
			prkalc(course, dist);
			break;

		  case 4:			/* score */
			score();
			break;

		  case 5:			/* phaser effectiveness */
			dist = getfltpar("range");
			if (dist < 0.0)
				break;
			dist *= 10.0;
			cost = pow(0.90, dist) * 98.0 + 0.5;
			printf("Phasers are %d%% effective at that range\n", cost);
			break;

		  case 6:			/* warp cost (time/energy) */
			dist = getfltpar("distance");
			if (dist < 0.0)
				break;
			warpfact = getfltpar("warp factor");
			if (warpfact <= 0.0)
				warpfact = Ship.warp;
			cost = (dist + 0.05) * warpfact * warpfact * warpfact;
			time = Param.warptime * dist / (warpfact * warpfact);
			printf("Warp %.2f distance %.2f cost %.2f stardates %d (%d w/ shlds up) units\n",
				warpfact, dist, time, cost, cost + cost);
			break;

		  case 7:			/* impulse cost */
			dist = getfltpar("distance");
			if (dist < 0.0)
				break;
			cost = 20 + 100 * dist;
			time = dist / 0.095;
			printf("Distance %.2f cost %.2f stardates %d units\n",
				dist, time, cost);
			break;

		  case 8:			/* distresslist */
			j = 1;
			printf("\n");
			/* scan the event list */
			for (i = 0; i < MAXEVENTS; i++)
			{
				e = &Event[i];
				/* ignore hidden entries */
				if (e->evcode & E_HIDDEN)
					continue;
				switch (e->evcode & E_EVENT)
				{

				  case E_KDESB:
					printf("Klingon is attacking starbase in quadrant %d,%d\n",
						e->x, e->y);
					j = 0;
					break;

				  case E_ENSLV:
				  case E_REPRO:
					printf("Starsystem %s in quadrant %d,%d is distressed\n",
						Systemname[e->systemname], e->x, e->y);
					j = 0;
					break;
				}
			}
			if (j)
				printf("No known distress calls are active\n");
			break;

		}

		/* skip to next semicolon or newline.  Semicolon
		 * means get new computer request; newline means
		 * exit computer mode. */
		while ((i = cgetc(0)) != ';')
		{
			if (i == '\0')
				exit(1);
			if (i == '\n')
			{
				ungetc(i, stdin);
				return;
			}
		}
	}
}