3 static int tryexit(int lookx, int looky, int ienm, int loccom, int irun) {
\r
6 iqx = quadx+(lookx+9)/10 - 1;
\r
7 iqy = quady+(looky+9)/10 - 1;
\r
8 if (iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
\r
9 game.state.galaxy[iqx][iqy] > 899)
\r
10 return 0; /* no can do -- neg energy, supernovae, or >8 Klingons */
\r
11 if (ienm == IHR) return 0; /* Romulans cannot escape! */
\r
13 /* avoid intruding on another commander's territory */
\r
15 for (l = 1; l <= game.state.remcom; l++)
\r
16 if (game.state.cx[l]==iqx && game.state.cy[l]==iqy) return 0;
\r
17 /* refuse to leave if currently attacking starbase */
\r
18 if (batx==quadx && baty==quady) return 0;
\r
20 /* don't leave if over 1000 units of energy */
\r
21 if (game.kpower[loccom] > 1000.) return 0;
\r
23 /* print escape message and move out of quadrant.
\r
24 We know this if either short or long range sensors are working */
\r
25 if (game.damage[DSRSENS] == 0.0 || game.damage[DLRSENS] == 0.0 ||
\r
26 condit == IHDOCKED) {
\r
29 proutn(" escapes to");
\r
30 cramlc(1, iqx, iqy);
\r
31 prout(" (and regains strength).");
\r
33 /* handle local matters related to escape */
\r
34 game.kx[loccom] = game.kx[nenhere];
\r
35 game.ky[loccom] = game.ky[nenhere];
\r
36 game.kavgd[loccom] = game.kavgd[nenhere];
\r
37 game.kpower[loccom] = game.kpower[nenhere];
\r
38 game.kdist[loccom] = game.kdist[nenhere];
\r
41 if (condit != IHDOCKED) newcnd();
\r
42 /* Handle global matters related to escape */
\r
43 game.state.galaxy[quadx][quady] -= 100;
\r
44 game.state.galaxy[iqx][iqy] += 100;
\r
50 game.future[FSCMOVE]=0.2777+game.state.date;
\r
51 game.future[FSCDBAS]=1e30;
\r
56 for (l=1; l<=game.state.remcom; l++) {
\r
57 if (game.state.cx[l]==quadx && game.state.cy[l]==quady) {
\r
58 game.state.cx[l]=iqx;
\r
59 game.state.cy[l]=iqy;
\r
65 return 1; /* success */
\r
69 static void movebaddy(int comx, int comy, int loccom, int ienm) {
\r
70 int motion, mdist, nsteps, mx, my, nextx, nexty, lookx, looky, ll;
\r
75 /* This should probably be just comhere + ishere */
\r
76 int nbaddys = skill > 3 ?
\r
77 (int)((comhere*2 + ishere*2+klhere*1.23+irhere*1.5)/2.0):
\r
79 double dist1, forces;
\r
81 dist1 = game.kdist[loccom];
\r
82 mdist = dist1 + 0.5; /* Nearest integer distance */
\r
84 /* If SC, check with spy to see if should hi-tail it */
\r
86 (game.kpower[loccom] <= 500.0 || (condit==IHDOCKED && game.damage[DPHOTON]==0))) {
\r
91 /* decide whether to advance, retreat, or hold position */
\r
93 * Enterprise has "force" based on condition of phaser and photon torpedoes.
\r
94 If both are operating full strength, force is 1000. If both are damaged,
\r
95 force is -1000. Having shields down subtracts an additional 1000.
\r
97 * Enemy has forces equal to the energy of the attacker plus
\r
98 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
\r
99 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
\r
101 Attacker Initial energy levels (nominal):
\r
102 Klingon Romulan Commander Super-Commander
\r
103 Novice 400 700 1200
\r
105 Good 450 800 1300 1750
\r
106 Expert 475 850 1350 1875
\r
107 Emeritus 500 900 1400 2000
\r
108 VARIANCE 75 200 200 200
\r
110 Enemy vessels only move prior to their attack. In Novice - Good games
\r
111 only commanders move. In Expert games, all enemy vessels move if there
\r
112 is a commander present. In Emeritus games all enemy vessels move.
\r
114 * If Enterprise is not docked, an agressive action is taken if enemy
\r
115 forces are 1000 greater than Enterprise.
\r
117 Agressive action on average cuts the distance between the ship and
\r
118 the enemy to 1/4 the original.
\r
120 * At lower energy advantage, movement units are proportional to the
\r
121 advantage with a 650 advantage being to hold ground, 800 to move forward
\r
122 1, 950 for two, 150 for back 4, etc. Variance of 100.
\r
124 If docked, is reduced by roughly 1.75*skill, generally forcing a
\r
125 retreat, especially at high skill levels.
\r
127 * Motion is limited to skill level, except for SC hi-tailing it out.
\r
130 forces = game.kpower[loccom]+100.0*nenhere+400*(nbaddys-1);
\r
131 if (shldup==0) forces += 1000; /* Good for enemy if shield is down! */
\r
132 if (game.damage[DPHASER] == 0.0 || game.damage[DPHOTON] == 0.0) {
\r
133 if (game.damage[DPHASER] != 0) /* phasers damaged */
\r
136 forces -= 0.2*(energy - 2500.0);
\r
137 if (game.damage[DPHOTON] != 0) /* photon torpedoes damaged */
\r
140 forces -= 50.0*torps;
\r
143 /* phasers and photon tubes both out! */
\r
147 if (forces <= 1000.0 && condit != IHDOCKED) /* Typical situation */
\r
148 motion = ((forces+200.0*Rand())/150.0) - 5.0;
\r
150 if (forces > 1000.0) /* Very strong -- move in for kill */
\r
151 motion = (1.0-square(Rand()))*dist1 + 1.0;
\r
152 if (condit==IHDOCKED) /* protected by base -- back off ! */
\r
153 motion -= skill*(2.0-square(Rand()));
\r
157 proutn("MOTION = ");
\r
158 cramf(motion, 1, 2);
\r
159 proutn(" FORCES = ");
\r
160 cramf(forces, 1, 2);
\r
164 /* don't move if no motion */
\r
165 if (motion==0) return;
\r
166 /* Limit motion according to skill */
\r
167 if (abs(motion) > skill) motion = (motion < 0) ? -skill : skill;
\r
169 /* calcuate preferred number of steps */
\r
170 nsteps = motion < 0 ? -motion : motion;
\r
171 if (motion > 0 && nsteps > mdist) nsteps = mdist; /* don't overshoot */
\r
172 if (nsteps > 10) nsteps = 10; /* This shouldn't be necessary */
\r
173 if (nsteps < 1) nsteps = 1; /* This shouldn't be necessary */
\r
176 proutn("NSTEPS = ");
\r
181 /* Compute preferred values of delta X and Y */
\r
184 if (2.0 * abs(mx) < abs(my)) mx = 0;
\r
185 if (2.0 * abs(my) < abs(sectx-comx)) my = 0;
\r
186 if (mx != 0) mx = mx*motion < 0 ? -1 : 1;
\r
187 if (my != 0) my = my*motion < 0 ? -1 : 1;
\r
190 game.quad[comx][comy] = IHDOT;
\r
191 /* main move loop */
\r
192 for (ll = 1; ll <= nsteps; ll++) {
\r
199 /* Check if preferred position available */
\r
200 lookx = nextx + mx;
\r
201 looky = nexty + my;
\r
202 krawlx = mx < 0 ? 1 : -1;
\r
203 krawly = my < 0 ? 1 : -1;
\r
205 attempts = 0; /* Settle mysterious hang problem */
\r
206 while (attempts++ < 20 && !success) {
\r
207 if (lookx < 1 || lookx > 10) {
\r
208 if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
\r
210 if (krawlx == mx || my == 0) break;
\r
211 lookx = nextx + krawlx;
\r
214 else if (looky < 1 || looky > 10) {
\r
215 if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
\r
217 if (krawly == my || mx == 0) break;
\r
218 looky = nexty + krawly;
\r
221 else if (game.quad[lookx][looky] != IHDOT) {
\r
222 /* See if we should ram ship */
\r
223 if (game.quad[lookx][looky] == ship &&
\r
224 (ienm == IHC || ienm == IHS)) {
\r
225 ram(1, ienm, comx, comy);
\r
228 if (krawlx != mx && my != 0) {
\r
229 lookx = nextx + krawlx;
\r
232 else if (krawly != my && mx != 0) {
\r
233 looky = nexty + krawly;
\r
236 else break; /* we have failed */
\r
245 cramlc(0, nextx, nexty);
\r
250 else break; /* done early */
\r
252 /* Put commander in place within same quadrant */
\r
253 game.quad[nextx][nexty] = ienm;
\r
254 if (nextx != comx || nexty != comy) {
\r
256 game.kx[loccom] = nextx;
\r
257 game.ky[loccom] = nexty;
\r
258 game.kdist[loccom] = game.kavgd[loccom] =
\r
259 sqrt(square(sectx-nextx)+square(secty-nexty));
\r
260 if (game.damage[DSRSENS] == 0 || condit == IHDOCKED) {
\r
263 if (game.kdist[loccom] < dist1) proutn(" advances to");
\r
264 else proutn(" retreats to");
\r
265 cramlc(2, nextx, nexty);
\r
271 void movcom(void) {
\r
275 if (idebug) prout("MOVCOM");
\r
278 /* Figure out which Klingon is the commander (or Supercommander)
\r
280 if (comhere) for (i = 1; i <= nenhere; i++) {
\r
283 if (game.quad[ix][iy] == IHC) {
\r
284 movebaddy(ix, iy, i, IHC);
\r
288 if (ishere) for (i = 1; i <= nenhere; i++) {
\r
291 if (game.quad[ix][iy] == IHS) {
\r
292 movebaddy(ix, iy, i, IHS);
\r
296 /* if skill level is high, move other Klingons and Romulans too!
\r
297 Move these last so they can base their actions on what the
\r
298 commander(s) do. */
\r
299 if (skill > 3) for (i = 1; i <= nenhere; i++) {
\r
302 if (game.quad[ix][iy] == IHK || game.quad[ix][iy] == IHR)
\r
303 movebaddy(ix, iy, i, game.quad[ix][iy]);
\r
309 static int checkdest(int iqx, int iqy, int flag, int *ipage) {
\r
312 if ((iqx==quadx && iqy==quady) ||
\r
313 iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
\r
314 game.state.galaxy[iqx][iqy] > 899) return 1;
\r
316 /* Avoid quadrants with bases if we want to avoid Enterprise */
\r
317 for (i = 1; i <= game.state.rembase; i++)
\r
318 if (game.state.baseqx[i]==iqx && game.state.baseqy[i]==iqy) return 1;
\r
322 game.state.galaxy[game.state.isx][game.state.isy] -= 100;
\r
323 game.state.isx = iqx;
\r
324 game.state.isy = iqy;
\r
325 game.state.galaxy[game.state.isx][game.state.isy] += 100;
\r
327 /* SC has scooted, Remove him from current quadrant */
\r
332 game.future[FSCDBAS]=1e30;
\r
333 for (i = 1; i <= nenhere; i++)
\r
334 if (game.quad[game.kx[i]][game.ky[i]] == IHS) break;
\r
335 game.quad[game.kx[i]][game.ky[i]] = IHDOT;
\r
336 game.kx[i] = game.kx[nenhere];
\r
337 game.ky[i] = game.ky[nenhere];
\r
338 game.kdist[i] = game.kdist[nenhere];
\r
339 game.kavgd[i] = game.kavgd[nenhere];
\r
340 game.kpower[i] = game.kpower[nenhere];
\r
343 if (condit!=IHDOCKED) newcnd();
\r
346 /* check for a helpful planet */
\r
347 for (i = 1; i <= inplan; i++) {
\r
348 if (game.state.plnets[i].x==game.state.isx && game.state.plnets[i].y==game.state.isy &&
\r
349 game.state.plnets[i].crystals == 1) {
\r
350 /* destroy the planet */
\r
351 game.state.plnets[i] = nulplanet;
\r
352 game.state.newstuf[game.state.isx][game.state.isy] -= 1;
\r
353 if (game.damage[DRADIO] == 0.0 || condit == IHDOCKED) {
\r
354 if (*ipage==0) pause(1);
\r
356 prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports");
\r
357 proutn(" a planet in");
\r
358 cramlc(1, game.state.isx, game.state.isy);
\r
359 prout(" has been destroyed");
\r
360 prout(" by the Super-commander.\"");
\r
365 return 0; /* looks good! */
\r
372 void scom(int *ipage) {
\r
373 int i, i2, j, ideltax, ideltay, ibqx, ibqy, sx, sy, ifindit, iwhichb;
\r
379 if (idebug) prout("SCOM");
\r
382 /* Decide on being active or passive */
\r
383 flag = ((game.state.killc+game.state.killk)/(game.state.date+0.01-indate) < 0.1*skill*(skill+1.0) ||
\r
384 (game.state.date-indate) < 3.0);
\r
385 if (iscate==0 && flag) {
\r
386 /* compute move away from Enterprise */
\r
387 ideltax = game.state.isx-quadx;
\r
388 ideltay = game.state.isy-quady;
\r
389 if (sqrt(ideltax*(double)ideltax+ideltay*(double)ideltay) > 2.0) {
\r
390 /* circulate in space */
\r
391 ideltax = game.state.isy-quady;
\r
392 ideltay = quadx-game.state.isx;
\r
396 /* compute distances to starbases */
\r
397 if (game.state.rembase <= 0) {
\r
398 /* nothing left to do */
\r
399 game.future[FSCMOVE] = 1e30;
\r
402 sx = game.state.isx;
\r
403 sy = game.state.isy;
\r
404 for (i = 1; i <= game.state.rembase; i++) {
\r
406 ibqx = game.state.baseqx[i];
\r
407 ibqy = game.state.baseqy[i];
\r
408 bdist[i] = sqrt(square(ibqx-sx) + square(ibqy-sy));
\r
410 if (game.state.rembase > 1) {
\r
411 /* sort into nearest first order */
\r
415 for (i=1; i < game.state.rembase-1; i++) {
\r
416 if (bdist[i] > bdist[i+1]) {
\r
417 int ti = basetbl[i];
\r
418 double t = bdist[i];
\r
419 bdist[i] = bdist[i+1];
\r
421 basetbl[i] = basetbl[i+1];
\r
428 /* look for nearest base without a commander, no Enterprise, and
\r
429 without too many Klingons, and not already under attack. */
\r
430 ifindit = iwhichb = 0;
\r
432 for (i2 = 1; i2 <= game.state.rembase; i2++) {
\r
433 i = basetbl[i2]; /* bug in original had it not finding nearest*/
\r
434 ibqx = game.state.baseqx[i];
\r
435 ibqy = game.state.baseqy[i];
\r
436 if ((ibqx == quadx && ibqy == quady) ||
\r
437 (ibqx == batx && ibqy == baty) ||
\r
438 game.state.galaxy[ibqx][ibqy] > 899) continue;
\r
439 /* if there is a commander, an no other base is appropriate,
\r
440 we will take the one with the commander */
\r
441 for (j = 1; j <= game.state.remcom; j++) {
\r
442 if (ibqx==game.state.cx[j] && ibqy==game.state.cy[j] && ifindit!= 2) {
\r
448 if (j > game.state.remcom) { /* no commander -- use this one */
\r
454 if (ifindit==0) return; /* Nothing suitable -- wait until next time*/
\r
455 ibqx = game.state.baseqx[iwhichb];
\r
456 ibqy = game.state.baseqy[iwhichb];
\r
457 /* decide how to move toward base */
\r
458 ideltax = ibqx - game.state.isx;
\r
459 ideltay = ibqy - game.state.isy;
\r
461 /* Maximum movement is 1 quadrant in either or both axis */
\r
462 if (ideltax > 1) ideltax = 1;
\r
463 if (ideltax < -1) ideltax = -1;
\r
464 if (ideltay > 1) ideltay = 1;
\r
465 if (ideltay < -1) ideltay = -1;
\r
467 /* try moving in both x and y directions */
\r
468 iqx = game.state.isx + ideltax;
\r
469 iqy = game.state.isy + ideltax;
\r
470 if (checkdest(iqx, iqy, flag, ipage)) {
\r
471 /* failed -- try some other maneuvers */
\r
472 if (ideltax==0 || ideltay==0) {
\r
473 /* attempt angle move */
\r
474 if (ideltax != 0) {
\r
475 iqy = game.state.isy + 1;
\r
476 if (checkdest(iqx, iqy, flag, ipage)) {
\r
477 iqy = game.state.isy - 1;
\r
478 checkdest(iqx, iqy, flag, ipage);
\r
482 iqx = game.state.isx + 1;
\r
483 if (checkdest(iqx, iqy, flag, ipage)) {
\r
484 iqx = game.state.isx - 1;
\r
485 checkdest(iqx, iqy, flag, ipage);
\r
490 /* try moving just in x or y */
\r
491 iqy = game.state.isy;
\r
492 if (checkdest(iqx, iqy, flag, ipage)) {
\r
493 iqy = game.state.isy + ideltay;
\r
494 iqx = game.state.isx;
\r
495 checkdest(iqx, iqy, flag, ipage);
\r
499 /* check for a base */
\r
500 if (game.state.rembase == 0) {
\r
501 game.future[FSCMOVE] = 1e30;
\r
503 else for (i=1; i<=game.state.rembase; i++) {
\r
504 ibqx = game.state.baseqx[i];
\r
505 ibqy = game.state.baseqy[i];
\r
506 if (ibqx==game.state.isx && ibqy == game.state.isy && game.state.isx != batx && game.state.isy != baty) {
\r
507 /* attack the base */
\r
508 if (flag) return; /* no, don't attack base! */
\r
511 game.future[FSCDBAS] = game.state.date + 1.0 +2.0*Rand();
\r
512 if (batx != 0) game.future[FSCDBAS] += game.future[FCDBAS]-game.state.date;
\r
513 if (game.damage[DRADIO] > 0 && condit != IHDOCKED)
\r
514 return; /* no warning */
\r
516 if (*ipage == 0) pause(1);
\r
518 proutn("Lt. Uhura- \"Captain, the starbase in");
\r
519 cramlc(1, game.state.isx, game.state.isy);
\r
521 prout(" reports that it is under attack from the Klingon Super-commander.");
\r
522 proutn(" It can survive until stardate ");
\r
523 cramf(game.future[FSCDBAS], 0, 1);
\r
525 if (resting==0) return;
\r
526 prout("Mr. Spock- \"Captain, shall we cancel the rest period?\"");
\r
527 if (ja()==0) return;
\r
529 Time = 0.0; /* actually finished */
\r
533 /* Check for intelligence report */
\r
539 (game.damage[DRADIO] > 0.0 && condit != IHDOCKED) ||
\r
540 game.starch[game.state.isx][game.state.isy] > 0))
\r
542 if (*ipage==0) pause(1);
\r
544 prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports");
\r
545 proutn(" the Super-commander is in");
\r
546 cramlc(1, game.state.isx, game.state. isy);
\r
551 void movetho(void) {
\r
552 int idx, idy, im, i, dum, my;
\r
553 /* Move the Tholian */
\r
554 if (ithere==0 || justin == 1) return;
\r
556 if (ithx == 1 && ithy == 1) {
\r
559 else if (ithx == 1 && ithy == 10) {
\r
560 idx = 10; idy = 10;
\r
562 else if (ithx == 10 && ithy == 10) {
\r
565 else if (ithx == 10 && ithy == 1) {
\r
569 /* something is wrong! */
\r
574 /* Do nothing if we are blocked */
\r
575 if (game.quad[idx][idy]!= IHDOT && game.quad[idx][idy]!= IHWEB) return;
\r
576 game.quad[ithx][ithy] = IHWEB;
\r
579 /* move in x axis */
\r
580 im = fabs((double)idx - ithx)/((double)idx - ithx);
\r
581 while (ithx != idx) {
\r
583 if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;
\r
586 else if (ithy != idy) {
\r
587 /* move in y axis */
\r
588 im = fabs((double)idy - ithy)/((double)idy - ithy);
\r
589 while (ithy != idy) {
\r
591 if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;
\r
594 game.quad[ithx][ithy] = IHT;
\r
596 /* check to see if all holes plugged */
\r
597 for (i = 1; i < 11; i++) {
\r
598 if (game.quad[1][i]!=IHWEB && game.quad[1][i]!=IHT) return;
\r
599 if (game.quad[10][i]!=IHWEB && game.quad[10][i]!=IHT) return;
\r
600 if (game.quad[i][1]!=IHWEB && game.quad[i][1]!=IHT) return;
\r
601 if (game.quad[i][10]!=IHWEB && game.quad[i][10]!=IHT) return;
\r
603 /* All plugged up -- Tholian splits */
\r
604 game.quad[ithx][ithy]=IHWEB;
\r
605 dropin(IHBLANK, &dum, &my);
\r
606 crmena(1,IHT, 2, ithx, ithy);
\r
607 prout(" completes web.");
\r
608 ithere = ithx = ithy = 0;
\r