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 %s (and regains strength).",
\r
30 cramlc(quadrant, iqx, iqy));
\r
32 /* handle local matters related to escape */
\r
33 game.kx[loccom] = game.kx[nenhere];
\r
34 game.ky[loccom] = game.ky[nenhere];
\r
35 game.kavgd[loccom] = game.kavgd[nenhere];
\r
36 game.kpower[loccom] = game.kpower[nenhere];
\r
37 game.kdist[loccom] = game.kdist[nenhere];
\r
40 if (condit != IHDOCKED) newcnd();
\r
41 /* Handle global matters related to escape */
\r
42 game.state.galaxy[quadx][quady] -= 100;
\r
43 game.state.galaxy[iqx][iqy] += 100;
\r
49 game.future[FSCMOVE]=0.2777+game.state.date;
\r
50 game.future[FSCDBAS]=1e30;
\r
55 for (l=1; l<=game.state.remcom; l++) {
\r
56 if (game.state.cx[l]==quadx && game.state.cy[l]==quady) {
\r
57 game.state.cx[l]=iqx;
\r
58 game.state.cy[l]=iqy;
\r
64 return 1; /* success */
\r
68 static void movebaddy(int comx, int comy, int loccom, int ienm) {
\r
69 int motion, mdist, nsteps, mx, my, nextx, nexty, lookx, looky, ll;
\r
74 /* This should probably be just comhere + ishere */
\r
75 int nbaddys = skill > 3 ?
\r
76 (int)((comhere*2 + ishere*2+klhere*1.23+irhere*1.5)/2.0):
\r
78 double dist1, forces;
\r
80 dist1 = game.kdist[loccom];
\r
81 mdist = dist1 + 0.5; /* Nearest integer distance */
\r
83 /* If SC, check with spy to see if should hi-tail it */
\r
85 (game.kpower[loccom] <= 500.0 || (condit==IHDOCKED && game.damage[DPHOTON]==0))) {
\r
90 /* decide whether to advance, retreat, or hold position */
\r
92 * Enterprise has "force" based on condition of phaser and photon torpedoes.
\r
93 If both are operating full strength, force is 1000. If both are damaged,
\r
94 force is -1000. Having shields down subtracts an additional 1000.
\r
96 * Enemy has forces equal to the energy of the attacker plus
\r
97 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
\r
98 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
\r
100 Attacker Initial energy levels (nominal):
\r
101 Klingon Romulan Commander Super-Commander
\r
102 Novice 400 700 1200
\r
104 Good 450 800 1300 1750
\r
105 Expert 475 850 1350 1875
\r
106 Emeritus 500 900 1400 2000
\r
107 VARIANCE 75 200 200 200
\r
109 Enemy vessels only move prior to their attack. In Novice - Good games
\r
110 only commanders move. In Expert games, all enemy vessels move if there
\r
111 is a commander present. In Emeritus games all enemy vessels move.
\r
113 * If Enterprise is not docked, an agressive action is taken if enemy
\r
114 forces are 1000 greater than Enterprise.
\r
116 Agressive action on average cuts the distance between the ship and
\r
117 the enemy to 1/4 the original.
\r
119 * At lower energy advantage, movement units are proportional to the
\r
120 advantage with a 650 advantage being to hold ground, 800 to move forward
\r
121 1, 950 for two, 150 for back 4, etc. Variance of 100.
\r
123 If docked, is reduced by roughly 1.75*skill, generally forcing a
\r
124 retreat, especially at high skill levels.
\r
126 * Motion is limited to skill level, except for SC hi-tailing it out.
\r
129 forces = game.kpower[loccom]+100.0*nenhere+400*(nbaddys-1);
\r
130 if (shldup==0) forces += 1000; /* Good for enemy if shield is down! */
\r
131 if (game.damage[DPHASER] == 0.0 || game.damage[DPHOTON] == 0.0) {
\r
132 if (game.damage[DPHASER] != 0) /* phasers damaged */
\r
135 forces -= 0.2*(energy - 2500.0);
\r
136 if (game.damage[DPHOTON] != 0) /* photon torpedoes damaged */
\r
139 forces -= 50.0*torps;
\r
142 /* phasers and photon tubes both out! */
\r
146 if (forces <= 1000.0 && condit != IHDOCKED) /* Typical situation */
\r
147 motion = ((forces+200.0*Rand())/150.0) - 5.0;
\r
149 if (forces > 1000.0) /* Very strong -- move in for kill */
\r
150 motion = (1.0-square(Rand()))*dist1 + 1.0;
\r
151 if (condit==IHDOCKED) /* protected by base -- back off ! */
\r
152 motion -= skill*(2.0-square(Rand()));
\r
156 proutn("MOTION = %1.2f", motion);
\r
157 proutn(" FORCES = %1,2f", forces);
\r
160 /* don't move if no motion */
\r
161 if (motion==0) return;
\r
162 /* Limit motion according to skill */
\r
163 if (abs(motion) > skill) motion = (motion < 0) ? -skill : skill;
\r
165 /* calcuate preferred number of steps */
\r
166 nsteps = motion < 0 ? -motion : motion;
\r
167 if (motion > 0 && nsteps > mdist) nsteps = mdist; /* don't overshoot */
\r
168 if (nsteps > 10) nsteps = 10; /* This shouldn't be necessary */
\r
169 if (nsteps < 1) nsteps = 1; /* This shouldn't be necessary */
\r
172 prout("NSTEPS = %d", nsteps);
\r
175 /* Compute preferred values of delta X and Y */
\r
178 if (2.0 * abs(mx) < abs(my)) mx = 0;
\r
179 if (2.0 * abs(my) < abs(sectx-comx)) my = 0;
\r
180 if (mx != 0) mx = mx*motion < 0 ? -1 : 1;
\r
181 if (my != 0) my = my*motion < 0 ? -1 : 1;
\r
184 game.quad[comx][comy] = IHDOT;
\r
185 /* main move loop */
\r
186 for (ll = 1; ll <= nsteps; ll++) {
\r
192 /* Check if preferred position available */
\r
193 lookx = nextx + mx;
\r
194 looky = nexty + my;
\r
195 krawlx = mx < 0 ? 1 : -1;
\r
196 krawly = my < 0 ? 1 : -1;
\r
198 attempts = 0; /* Settle mysterious hang problem */
\r
199 while (attempts++ < 20 && !success) {
\r
200 if (lookx < 1 || lookx > 10) {
\r
201 if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
\r
203 if (krawlx == mx || my == 0) break;
\r
204 lookx = nextx + krawlx;
\r
207 else if (looky < 1 || looky > 10) {
\r
208 if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
\r
210 if (krawly == my || mx == 0) break;
\r
211 looky = nexty + krawly;
\r
214 else if (game.quad[lookx][looky] != IHDOT) {
\r
215 /* See if we should ram ship */
\r
216 if (game.quad[lookx][looky] == ship &&
\r
217 (ienm == IHC || ienm == IHS)) {
\r
218 ram(1, ienm, comx, comy);
\r
221 if (krawlx != mx && my != 0) {
\r
222 lookx = nextx + krawlx;
\r
225 else if (krawly != my && mx != 0) {
\r
226 looky = nexty + krawly;
\r
229 else break; /* we have failed */
\r
238 prout(cramlc(neither, nextx, nexty));
\r
242 else break; /* done early */
\r
244 /* Put commander in place within same quadrant */
\r
245 game.quad[nextx][nexty] = ienm;
\r
246 if (nextx != comx || nexty != comy) {
\r
248 game.kx[loccom] = nextx;
\r
249 game.ky[loccom] = nexty;
\r
250 game.kdist[loccom] = game.kavgd[loccom] =
\r
251 sqrt(square(sectx-nextx)+square(secty-nexty));
\r
252 if (game.damage[DSRSENS] == 0 || condit == IHDOCKED) {
\r
255 if (game.kdist[loccom] < dist1) proutn(" advances to");
\r
256 else proutn(" retreats to ");
\r
257 prout(cramlc(sector, nextx, nexty));
\r
262 void movcom(void) {
\r
266 if (idebug) prout("MOVCOM");
\r
269 /* Figure out which Klingon is the commander (or Supercommander)
\r
271 if (comhere) for (i = 1; i <= nenhere; i++) {
\r
274 if (game.quad[ix][iy] == IHC) {
\r
275 movebaddy(ix, iy, i, IHC);
\r
279 if (ishere) for (i = 1; i <= nenhere; i++) {
\r
282 if (game.quad[ix][iy] == IHS) {
\r
283 movebaddy(ix, iy, i, IHS);
\r
287 /* if skill level is high, move other Klingons and Romulans too!
\r
288 Move these last so they can base their actions on what the
\r
289 commander(s) do. */
\r
290 if (skill > 3) for (i = 1; i <= nenhere; i++) {
\r
293 if (game.quad[ix][iy] == IHK || game.quad[ix][iy] == IHR)
\r
294 movebaddy(ix, iy, i, game.quad[ix][iy]);
\r
300 static int checkdest(int iqx, int iqy, int flag, int *ipage) {
\r
303 if ((iqx==quadx && iqy==quady) ||
\r
304 iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
\r
305 game.state.galaxy[iqx][iqy] > 899) return 1;
\r
307 /* Avoid quadrants with bases if we want to avoid Enterprise */
\r
308 for (i = 1; i <= game.state.rembase; i++)
\r
309 if (game.state.baseqx[i]==iqx && game.state.baseqy[i]==iqy) return 1;
\r
313 game.state.galaxy[game.state.isx][game.state.isy] -= 100;
\r
314 game.state.isx = iqx;
\r
315 game.state.isy = iqy;
\r
316 game.state.galaxy[game.state.isx][game.state.isy] += 100;
\r
318 /* SC has scooted, Remove him from current quadrant */
\r
323 game.future[FSCDBAS]=1e30;
\r
324 for (i = 1; i <= nenhere; i++)
\r
325 if (game.quad[game.kx[i]][game.ky[i]] == IHS) break;
\r
326 game.quad[game.kx[i]][game.ky[i]] = IHDOT;
\r
327 game.kx[i] = game.kx[nenhere];
\r
328 game.ky[i] = game.ky[nenhere];
\r
329 game.kdist[i] = game.kdist[nenhere];
\r
330 game.kavgd[i] = game.kavgd[nenhere];
\r
331 game.kpower[i] = game.kpower[nenhere];
\r
334 if (condit!=IHDOCKED) newcnd();
\r
337 /* check for a helpful planet */
\r
338 for (i = 0; i < inplan; i++) {
\r
339 if (game.state.plnets[i].x==game.state.isx && game.state.plnets[i].y==game.state.isy &&
\r
340 game.state.plnets[i].crystals == 1) {
\r
341 /* destroy the planet */
\r
342 DESTROY(&game.state.plnets[i]);
\r
343 game.state.newstuf[game.state.isx][game.state.isy] -= 1;
\r
344 if (game.damage[DRADIO] == 0.0 || condit == IHDOCKED) {
\r
345 if (*ipage==0) pause(1);
\r
347 prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports");
\r
348 proutn(" a planet in ");
\r
349 proutn(cramlc(quadrant, game.state.isx, game.state.isy));
\r
350 prout(" has been destroyed");
\r
351 prout(" by the Super-commander.\"");
\r
356 return 0; /* looks good! */
\r
363 void scom(int *ipage) {
\r
364 int i, i2, j, ideltax, ideltay, ibqx, ibqy, sx, sy, ifindit, iwhichb;
\r
370 if (idebug) prout("SCOM");
\r
373 /* Decide on being active or passive */
\r
374 flag = ((game.state.killc+game.state.killk)/(game.state.date+0.01-indate) < 0.1*skill*(skill+1.0) ||
\r
375 (game.state.date-indate) < 3.0);
\r
376 if (iscate==0 && flag) {
\r
377 /* compute move away from Enterprise */
\r
378 ideltax = game.state.isx-quadx;
\r
379 ideltay = game.state.isy-quady;
\r
380 if (sqrt(ideltax*(double)ideltax+ideltay*(double)ideltay) > 2.0) {
\r
381 /* circulate in space */
\r
382 ideltax = game.state.isy-quady;
\r
383 ideltay = quadx-game.state.isx;
\r
387 /* compute distances to starbases */
\r
388 if (game.state.rembase <= 0) {
\r
389 /* nothing left to do */
\r
390 game.future[FSCMOVE] = 1e30;
\r
393 sx = game.state.isx;
\r
394 sy = game.state.isy;
\r
395 for (i = 1; i <= game.state.rembase; i++) {
\r
397 ibqx = game.state.baseqx[i];
\r
398 ibqy = game.state.baseqy[i];
\r
399 bdist[i] = sqrt(square(ibqx-sx) + square(ibqy-sy));
\r
401 if (game.state.rembase > 1) {
\r
402 /* sort into nearest first order */
\r
406 for (i=1; i < game.state.rembase-1; i++) {
\r
407 if (bdist[i] > bdist[i+1]) {
\r
408 int ti = basetbl[i];
\r
409 double t = bdist[i];
\r
410 bdist[i] = bdist[i+1];
\r
412 basetbl[i] = basetbl[i+1];
\r
419 /* look for nearest base without a commander, no Enterprise, and
\r
420 without too many Klingons, and not already under attack. */
\r
421 ifindit = iwhichb = 0;
\r
423 for (i2 = 1; i2 <= game.state.rembase; i2++) {
\r
424 i = basetbl[i2]; /* bug in original had it not finding nearest*/
\r
425 ibqx = game.state.baseqx[i];
\r
426 ibqy = game.state.baseqy[i];
\r
427 if ((ibqx == quadx && ibqy == quady) ||
\r
428 (ibqx == batx && ibqy == baty) ||
\r
429 game.state.galaxy[ibqx][ibqy] > 899) continue;
\r
430 /* if there is a commander, an no other base is appropriate,
\r
431 we will take the one with the commander */
\r
432 for (j = 1; j <= game.state.remcom; j++) {
\r
433 if (ibqx==game.state.cx[j] && ibqy==game.state.cy[j] && ifindit!= 2) {
\r
439 if (j > game.state.remcom) { /* no commander -- use this one */
\r
445 if (ifindit==0) return; /* Nothing suitable -- wait until next time*/
\r
446 ibqx = game.state.baseqx[iwhichb];
\r
447 ibqy = game.state.baseqy[iwhichb];
\r
448 /* decide how to move toward base */
\r
449 ideltax = ibqx - game.state.isx;
\r
450 ideltay = ibqy - game.state.isy;
\r
452 /* Maximum movement is 1 quadrant in either or both axis */
\r
453 if (ideltax > 1) ideltax = 1;
\r
454 if (ideltax < -1) ideltax = -1;
\r
455 if (ideltay > 1) ideltay = 1;
\r
456 if (ideltay < -1) ideltay = -1;
\r
458 /* try moving in both x and y directions */
\r
459 iqx = game.state.isx + ideltax;
\r
460 iqy = game.state.isy + ideltax;
\r
461 if (checkdest(iqx, iqy, flag, ipage)) {
\r
462 /* failed -- try some other maneuvers */
\r
463 if (ideltax==0 || ideltay==0) {
\r
464 /* attempt angle move */
\r
465 if (ideltax != 0) {
\r
466 iqy = game.state.isy + 1;
\r
467 if (checkdest(iqx, iqy, flag, ipage)) {
\r
468 iqy = game.state.isy - 1;
\r
469 checkdest(iqx, iqy, flag, ipage);
\r
473 iqx = game.state.isx + 1;
\r
474 if (checkdest(iqx, iqy, flag, ipage)) {
\r
475 iqx = game.state.isx - 1;
\r
476 checkdest(iqx, iqy, flag, ipage);
\r
481 /* try moving just in x or y */
\r
482 iqy = game.state.isy;
\r
483 if (checkdest(iqx, iqy, flag, ipage)) {
\r
484 iqy = game.state.isy + ideltay;
\r
485 iqx = game.state.isx;
\r
486 checkdest(iqx, iqy, flag, ipage);
\r
490 /* check for a base */
\r
491 if (game.state.rembase == 0) {
\r
492 game.future[FSCMOVE] = 1e30;
\r
494 else for (i=1; i<=game.state.rembase; i++) {
\r
495 ibqx = game.state.baseqx[i];
\r
496 ibqy = game.state.baseqy[i];
\r
497 if (ibqx==game.state.isx && ibqy == game.state.isy && game.state.isx != batx && game.state.isy != baty) {
\r
498 /* attack the base */
\r
499 if (flag) return; /* no, don't attack base! */
\r
502 game.future[FSCDBAS] = game.state.date + 1.0 +2.0*Rand();
\r
503 if (batx != 0) game.future[FSCDBAS] += game.future[FCDBAS]-game.state.date;
\r
504 if (game.damage[DRADIO] > 0 && condit != IHDOCKED)
\r
505 return; /* no warning */
\r
507 if (*ipage == 0) pause(1);
\r
509 proutn("Lt. Uhura- \"Captain, the starbase in ");
\r
510 proutn(cramlc(quadrant, game.state.isx, game.state.isy));
\r
512 prout(" reports that it is under attack from the Klingon Super-commander.");
\r
513 proutn(" It can survive until stardate %d.\"",
\r
514 (int)game.future[FSCDBAS]);
\r
515 if (resting==0) return;
\r
516 prout("Mr. Spock- \"Captain, shall we cancel the rest period?\"");
\r
517 if (ja()==0) return;
\r
519 Time = 0.0; /* actually finished */
\r
523 /* Check for intelligence report */
\r
529 (game.damage[DRADIO] > 0.0 && condit != IHDOCKED) ||
\r
530 game.starch[game.state.isx][game.state.isy] > 0))
\r
532 if (*ipage==0) pause(1);
\r
534 prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports");
\r
535 proutn(" the Super-commander is in ");
\r
536 proutn(cramlc(quadrant, game.state.isx, game.state. isy));
\r
541 void movetho(void) {
\r
542 int idx, idy, im, i, dum, my;
\r
543 /* Move the Tholian */
\r
544 if (ithere==0 || justin == 1) return;
\r
546 if (ithx == 1 && ithy == 1) {
\r
549 else if (ithx == 1 && ithy == 10) {
\r
550 idx = 10; idy = 10;
\r
552 else if (ithx == 10 && ithy == 10) {
\r
555 else if (ithx == 10 && ithy == 1) {
\r
559 /* something is wrong! */
\r
564 /* Do nothing if we are blocked */
\r
565 if (game.quad[idx][idy]!= IHDOT && game.quad[idx][idy]!= IHWEB) return;
\r
566 game.quad[ithx][ithy] = IHWEB;
\r
569 /* move in x axis */
\r
570 im = fabs((double)idx - ithx)/((double)idx - ithx);
\r
571 while (ithx != idx) {
\r
573 if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;
\r
576 else if (ithy != idy) {
\r
577 /* move in y axis */
\r
578 im = fabs((double)idy - ithy)/((double)idy - ithy);
\r
579 while (ithy != idy) {
\r
581 if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;
\r
584 game.quad[ithx][ithy] = IHT;
\r
586 /* check to see if all holes plugged */
\r
587 for (i = 1; i < 11; i++) {
\r
588 if (game.quad[1][i]!=IHWEB && game.quad[1][i]!=IHT) return;
\r
589 if (game.quad[10][i]!=IHWEB && game.quad[10][i]!=IHT) return;
\r
590 if (game.quad[i][1]!=IHWEB && game.quad[i][1]!=IHT) return;
\r
591 if (game.quad[i][10]!=IHWEB && game.quad[i][10]!=IHT) return;
\r
593 /* All plugged up -- Tholian splits */
\r
594 game.quad[ithx][ithy]=IHWEB;
\r
595 dropin(IHBLANK, &dum, &my);
\r
596 crmena(1,IHT, 2, ithx, ithy);
\r
597 prout(" completes web.");
\r
598 ithere = ithx = ithy = 0;
\r