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 prout("NSTEPS = %d", nsteps);
\r
179 /* Compute preferred values of delta X and Y */
\r
182 if (2.0 * abs(mx) < abs(my)) mx = 0;
\r
183 if (2.0 * abs(my) < abs(sectx-comx)) my = 0;
\r
184 if (mx != 0) mx = mx*motion < 0 ? -1 : 1;
\r
185 if (my != 0) my = my*motion < 0 ? -1 : 1;
\r
188 game.quad[comx][comy] = IHDOT;
\r
189 /* main move loop */
\r
190 for (ll = 1; ll <= nsteps; ll++) {
\r
196 /* Check if preferred position available */
\r
197 lookx = nextx + mx;
\r
198 looky = nexty + my;
\r
199 krawlx = mx < 0 ? 1 : -1;
\r
200 krawly = my < 0 ? 1 : -1;
\r
202 attempts = 0; /* Settle mysterious hang problem */
\r
203 while (attempts++ < 20 && !success) {
\r
204 if (lookx < 1 || lookx > 10) {
\r
205 if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
\r
207 if (krawlx == mx || my == 0) break;
\r
208 lookx = nextx + krawlx;
\r
211 else if (looky < 1 || looky > 10) {
\r
212 if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
\r
214 if (krawly == my || mx == 0) break;
\r
215 looky = nexty + krawly;
\r
218 else if (game.quad[lookx][looky] != IHDOT) {
\r
219 /* See if we should ram ship */
\r
220 if (game.quad[lookx][looky] == ship &&
\r
221 (ienm == IHC || ienm == IHS)) {
\r
222 ram(1, ienm, comx, comy);
\r
225 if (krawlx != mx && my != 0) {
\r
226 lookx = nextx + krawlx;
\r
229 else if (krawly != my && mx != 0) {
\r
230 looky = nexty + krawly;
\r
233 else break; /* we have failed */
\r
242 cramlc(0, nextx, nexty);
\r
247 else break; /* done early */
\r
249 /* Put commander in place within same quadrant */
\r
250 game.quad[nextx][nexty] = ienm;
\r
251 if (nextx != comx || nexty != comy) {
\r
253 game.kx[loccom] = nextx;
\r
254 game.ky[loccom] = nexty;
\r
255 game.kdist[loccom] = game.kavgd[loccom] =
\r
256 sqrt(square(sectx-nextx)+square(secty-nexty));
\r
257 if (game.damage[DSRSENS] == 0 || condit == IHDOCKED) {
\r
260 if (game.kdist[loccom] < dist1) proutn(" advances to");
\r
261 else proutn(" retreats to");
\r
262 cramlc(2, nextx, nexty);
\r
268 void movcom(void) {
\r
272 if (idebug) prout("MOVCOM");
\r
275 /* Figure out which Klingon is the commander (or Supercommander)
\r
277 if (comhere) for (i = 1; i <= nenhere; i++) {
\r
280 if (game.quad[ix][iy] == IHC) {
\r
281 movebaddy(ix, iy, i, IHC);
\r
285 if (ishere) for (i = 1; i <= nenhere; i++) {
\r
288 if (game.quad[ix][iy] == IHS) {
\r
289 movebaddy(ix, iy, i, IHS);
\r
293 /* if skill level is high, move other Klingons and Romulans too!
\r
294 Move these last so they can base their actions on what the
\r
295 commander(s) do. */
\r
296 if (skill > 3) for (i = 1; i <= nenhere; i++) {
\r
299 if (game.quad[ix][iy] == IHK || game.quad[ix][iy] == IHR)
\r
300 movebaddy(ix, iy, i, game.quad[ix][iy]);
\r
306 static int checkdest(int iqx, int iqy, int flag, int *ipage) {
\r
309 if ((iqx==quadx && iqy==quady) ||
\r
310 iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
\r
311 game.state.galaxy[iqx][iqy] > 899) return 1;
\r
313 /* Avoid quadrants with bases if we want to avoid Enterprise */
\r
314 for (i = 1; i <= game.state.rembase; i++)
\r
315 if (game.state.baseqx[i]==iqx && game.state.baseqy[i]==iqy) return 1;
\r
319 game.state.galaxy[game.state.isx][game.state.isy] -= 100;
\r
320 game.state.isx = iqx;
\r
321 game.state.isy = iqy;
\r
322 game.state.galaxy[game.state.isx][game.state.isy] += 100;
\r
324 /* SC has scooted, Remove him from current quadrant */
\r
329 game.future[FSCDBAS]=1e30;
\r
330 for (i = 1; i <= nenhere; i++)
\r
331 if (game.quad[game.kx[i]][game.ky[i]] == IHS) break;
\r
332 game.quad[game.kx[i]][game.ky[i]] = IHDOT;
\r
333 game.kx[i] = game.kx[nenhere];
\r
334 game.ky[i] = game.ky[nenhere];
\r
335 game.kdist[i] = game.kdist[nenhere];
\r
336 game.kavgd[i] = game.kavgd[nenhere];
\r
337 game.kpower[i] = game.kpower[nenhere];
\r
340 if (condit!=IHDOCKED) newcnd();
\r
343 /* check for a helpful planet */
\r
344 for (i = 0; i < inplan; i++) {
\r
345 if (game.state.plnets[i].x==game.state.isx && game.state.plnets[i].y==game.state.isy &&
\r
346 game.state.plnets[i].crystals == 1) {
\r
347 /* destroy the planet */
\r
348 DESTROY(&game.state.plnets[i]);
\r
349 game.state.newstuf[game.state.isx][game.state.isy] -= 1;
\r
350 if (game.damage[DRADIO] == 0.0 || condit == IHDOCKED) {
\r
351 if (*ipage==0) pause(1);
\r
353 prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports");
\r
354 proutn(" a planet in");
\r
355 cramlc(1, game.state.isx, game.state.isy);
\r
356 prout(" has been destroyed");
\r
357 prout(" by the Super-commander.\"");
\r
362 return 0; /* looks good! */
\r
369 void scom(int *ipage) {
\r
370 int i, i2, j, ideltax, ideltay, ibqx, ibqy, sx, sy, ifindit, iwhichb;
\r
376 if (idebug) prout("SCOM");
\r
379 /* Decide on being active or passive */
\r
380 flag = ((game.state.killc+game.state.killk)/(game.state.date+0.01-indate) < 0.1*skill*(skill+1.0) ||
\r
381 (game.state.date-indate) < 3.0);
\r
382 if (iscate==0 && flag) {
\r
383 /* compute move away from Enterprise */
\r
384 ideltax = game.state.isx-quadx;
\r
385 ideltay = game.state.isy-quady;
\r
386 if (sqrt(ideltax*(double)ideltax+ideltay*(double)ideltay) > 2.0) {
\r
387 /* circulate in space */
\r
388 ideltax = game.state.isy-quady;
\r
389 ideltay = quadx-game.state.isx;
\r
393 /* compute distances to starbases */
\r
394 if (game.state.rembase <= 0) {
\r
395 /* nothing left to do */
\r
396 game.future[FSCMOVE] = 1e30;
\r
399 sx = game.state.isx;
\r
400 sy = game.state.isy;
\r
401 for (i = 1; i <= game.state.rembase; i++) {
\r
403 ibqx = game.state.baseqx[i];
\r
404 ibqy = game.state.baseqy[i];
\r
405 bdist[i] = sqrt(square(ibqx-sx) + square(ibqy-sy));
\r
407 if (game.state.rembase > 1) {
\r
408 /* sort into nearest first order */
\r
412 for (i=1; i < game.state.rembase-1; i++) {
\r
413 if (bdist[i] > bdist[i+1]) {
\r
414 int ti = basetbl[i];
\r
415 double t = bdist[i];
\r
416 bdist[i] = bdist[i+1];
\r
418 basetbl[i] = basetbl[i+1];
\r
425 /* look for nearest base without a commander, no Enterprise, and
\r
426 without too many Klingons, and not already under attack. */
\r
427 ifindit = iwhichb = 0;
\r
429 for (i2 = 1; i2 <= game.state.rembase; i2++) {
\r
430 i = basetbl[i2]; /* bug in original had it not finding nearest*/
\r
431 ibqx = game.state.baseqx[i];
\r
432 ibqy = game.state.baseqy[i];
\r
433 if ((ibqx == quadx && ibqy == quady) ||
\r
434 (ibqx == batx && ibqy == baty) ||
\r
435 game.state.galaxy[ibqx][ibqy] > 899) continue;
\r
436 /* if there is a commander, an no other base is appropriate,
\r
437 we will take the one with the commander */
\r
438 for (j = 1; j <= game.state.remcom; j++) {
\r
439 if (ibqx==game.state.cx[j] && ibqy==game.state.cy[j] && ifindit!= 2) {
\r
445 if (j > game.state.remcom) { /* no commander -- use this one */
\r
451 if (ifindit==0) return; /* Nothing suitable -- wait until next time*/
\r
452 ibqx = game.state.baseqx[iwhichb];
\r
453 ibqy = game.state.baseqy[iwhichb];
\r
454 /* decide how to move toward base */
\r
455 ideltax = ibqx - game.state.isx;
\r
456 ideltay = ibqy - game.state.isy;
\r
458 /* Maximum movement is 1 quadrant in either or both axis */
\r
459 if (ideltax > 1) ideltax = 1;
\r
460 if (ideltax < -1) ideltax = -1;
\r
461 if (ideltay > 1) ideltay = 1;
\r
462 if (ideltay < -1) ideltay = -1;
\r
464 /* try moving in both x and y directions */
\r
465 iqx = game.state.isx + ideltax;
\r
466 iqy = game.state.isy + ideltax;
\r
467 if (checkdest(iqx, iqy, flag, ipage)) {
\r
468 /* failed -- try some other maneuvers */
\r
469 if (ideltax==0 || ideltay==0) {
\r
470 /* attempt angle move */
\r
471 if (ideltax != 0) {
\r
472 iqy = game.state.isy + 1;
\r
473 if (checkdest(iqx, iqy, flag, ipage)) {
\r
474 iqy = game.state.isy - 1;
\r
475 checkdest(iqx, iqy, flag, ipage);
\r
479 iqx = game.state.isx + 1;
\r
480 if (checkdest(iqx, iqy, flag, ipage)) {
\r
481 iqx = game.state.isx - 1;
\r
482 checkdest(iqx, iqy, flag, ipage);
\r
487 /* try moving just in x or y */
\r
488 iqy = game.state.isy;
\r
489 if (checkdest(iqx, iqy, flag, ipage)) {
\r
490 iqy = game.state.isy + ideltay;
\r
491 iqx = game.state.isx;
\r
492 checkdest(iqx, iqy, flag, ipage);
\r
496 /* check for a base */
\r
497 if (game.state.rembase == 0) {
\r
498 game.future[FSCMOVE] = 1e30;
\r
500 else for (i=1; i<=game.state.rembase; i++) {
\r
501 ibqx = game.state.baseqx[i];
\r
502 ibqy = game.state.baseqy[i];
\r
503 if (ibqx==game.state.isx && ibqy == game.state.isy && game.state.isx != batx && game.state.isy != baty) {
\r
504 /* attack the base */
\r
505 if (flag) return; /* no, don't attack base! */
\r
508 game.future[FSCDBAS] = game.state.date + 1.0 +2.0*Rand();
\r
509 if (batx != 0) game.future[FSCDBAS] += game.future[FCDBAS]-game.state.date;
\r
510 if (game.damage[DRADIO] > 0 && condit != IHDOCKED)
\r
511 return; /* no warning */
\r
513 if (*ipage == 0) pause(1);
\r
515 proutn("Lt. Uhura- \"Captain, the starbase in");
\r
516 cramlc(1, game.state.isx, game.state.isy);
\r
518 prout(" reports that it is under attack from the Klingon Super-commander.");
\r
519 proutn(" It can survive until stardate ");
\r
520 cramf(game.future[FSCDBAS], 0, 1);
\r
522 if (resting==0) return;
\r
523 prout("Mr. Spock- \"Captain, shall we cancel the rest period?\"");
\r
524 if (ja()==0) return;
\r
526 Time = 0.0; /* actually finished */
\r
530 /* Check for intelligence report */
\r
536 (game.damage[DRADIO] > 0.0 && condit != IHDOCKED) ||
\r
537 game.starch[game.state.isx][game.state.isy] > 0))
\r
539 if (*ipage==0) pause(1);
\r
541 prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports");
\r
542 proutn(" the Super-commander is in");
\r
543 cramlc(1, game.state.isx, game.state. isy);
\r
548 void movetho(void) {
\r
549 int idx, idy, im, i, dum, my;
\r
550 /* Move the Tholian */
\r
551 if (ithere==0 || justin == 1) return;
\r
553 if (ithx == 1 && ithy == 1) {
\r
556 else if (ithx == 1 && ithy == 10) {
\r
557 idx = 10; idy = 10;
\r
559 else if (ithx == 10 && ithy == 10) {
\r
562 else if (ithx == 10 && ithy == 1) {
\r
566 /* something is wrong! */
\r
571 /* Do nothing if we are blocked */
\r
572 if (game.quad[idx][idy]!= IHDOT && game.quad[idx][idy]!= IHWEB) return;
\r
573 game.quad[ithx][ithy] = IHWEB;
\r
576 /* move in x axis */
\r
577 im = fabs((double)idx - ithx)/((double)idx - ithx);
\r
578 while (ithx != idx) {
\r
580 if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;
\r
583 else if (ithy != idy) {
\r
584 /* move in y axis */
\r
585 im = fabs((double)idy - ithy)/((double)idy - ithy);
\r
586 while (ithy != idy) {
\r
588 if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;
\r
591 game.quad[ithx][ithy] = IHT;
\r
593 /* check to see if all holes plugged */
\r
594 for (i = 1; i < 11; i++) {
\r
595 if (game.quad[1][i]!=IHWEB && game.quad[1][i]!=IHT) return;
\r
596 if (game.quad[10][i]!=IHWEB && game.quad[10][i]!=IHT) return;
\r
597 if (game.quad[i][1]!=IHWEB && game.quad[i][1]!=IHT) return;
\r
598 if (game.quad[i][10]!=IHWEB && game.quad[i][10]!=IHT) return;
\r
600 /* All plugged up -- Tholian splits */
\r
601 game.quad[ithx][ithy]=IHWEB;
\r
602 dropin(IHBLANK, &dum, &my);
\r
603 crmena(1,IHT, 2, ithx, ithy);
\r
604 prout(" completes web.");
\r
605 ithere = ithx = ithy = 0;
\r