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
27 crmena(1, ienm, 2, game.kx[loccom], game.ky[loccom]);
\r
28 proutn(" escapes to %s (and regains strength).",
\r
29 cramlc(quadrant, iqx, iqy));
\r
31 /* handle local matters related to escape */
\r
32 game.quad[game.kx[loccom]][game.ky[loccom]] = IHDOT;
\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 /* main move loop */
\r
185 for (ll = 1; ll <= nsteps; ll++) {
\r
191 /* Check if preferred position available */
\r
192 lookx = nextx + mx;
\r
193 looky = nexty + my;
\r
194 krawlx = mx < 0 ? 1 : -1;
\r
195 krawly = my < 0 ? 1 : -1;
\r
197 attempts = 0; /* Settle mysterious hang problem */
\r
198 while (attempts++ < 20 && !success) {
\r
199 if (lookx < 1 || lookx > 10) {
\r
200 if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
\r
202 if (krawlx == mx || my == 0) break;
\r
203 lookx = nextx + krawlx;
\r
206 else if (looky < 1 || looky > 10) {
\r
207 if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
\r
209 if (krawly == my || mx == 0) break;
\r
210 looky = nexty + krawly;
\r
213 else if (game.quad[lookx][looky] != IHDOT) {
\r
214 /* See if we should ram ship */
\r
215 if (game.quad[lookx][looky] == ship &&
\r
216 (ienm == IHC || ienm == IHS)) {
\r
217 ram(1, ienm, comx, comy);
\r
220 if (krawlx != mx && my != 0) {
\r
221 lookx = nextx + krawlx;
\r
224 else if (krawly != my && mx != 0) {
\r
225 looky = nexty + krawly;
\r
228 else break; /* we have failed */
\r
237 prout(cramlc(neither, nextx, nexty));
\r
241 else break; /* done early */
\r
243 /* Put commander in place within same quadrant */
\r
244 game.quad[comx][comy] = IHDOT;
\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
256 cramlc(2, comx, comy);
\r
257 if (game.kdist[loccom] < dist1) proutn(" advances to");
\r
258 else proutn(" retreats to ");
\r
259 prout(cramlc(sector, nextx, nexty));
\r
264 void movcom(void) {
\r
268 if (idebug) prout("MOVCOM");
\r
271 /* Figure out which Klingon is the commander (or Supercommander)
\r
273 if (comhere) for (i = 1; i <= nenhere; i++) {
\r
276 if (game.quad[ix][iy] == IHC) {
\r
277 movebaddy(ix, iy, i, IHC);
\r
281 if (ishere) for (i = 1; i <= nenhere; i++) {
\r
284 if (game.quad[ix][iy] == IHS) {
\r
285 movebaddy(ix, iy, i, IHS);
\r
289 /* if skill level is high, move other Klingons and Romulans too!
\r
290 Move these last so they can base their actions on what the
\r
291 commander(s) do. */
\r
292 if (skill > 3) for (i = 1; i <= nenhere; i++) {
\r
295 if (game.quad[ix][iy] == IHK || game.quad[ix][iy] == IHR)
\r
296 movebaddy(ix, iy, i, game.quad[ix][iy]);
\r
302 static int movescom(int iqx, int iqy, int flag, int *ipage) {
\r
305 if ((iqx==quadx && iqy==quady) ||
\r
306 iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
\r
307 game.state.galaxy[iqx][iqy] > 899) return 1;
\r
309 /* Avoid quadrants with bases if we want to avoid Enterprise */
\r
310 for (i = 1; i <= game.state.rembase; i++)
\r
311 if (game.state.baseqx[i]==iqx && game.state.baseqy[i]==iqy) return 1;
\r
313 if (justin && !iscate) return 1;
\r
315 game.state.galaxy[game.state.isx][game.state.isy] -= 100;
\r
316 game.state.isx = iqx;
\r
317 game.state.isy = iqy;
\r
318 game.state.galaxy[game.state.isx][game.state.isy] += 100;
\r
320 /* SC has scooted, Remove him from current quadrant */
\r
325 game.future[FSCDBAS]=1e30;
\r
326 for (i = 1; i <= nenhere; i++)
\r
327 if (game.quad[game.kx[i]][game.ky[i]] == IHS) break;
\r
328 game.quad[game.kx[i]][game.ky[i]] = IHDOT;
\r
329 game.kx[i] = game.kx[nenhere];
\r
330 game.ky[i] = game.ky[nenhere];
\r
331 game.kdist[i] = game.kdist[nenhere];
\r
332 game.kavgd[i] = game.kavgd[nenhere];
\r
333 game.kpower[i] = game.kpower[nenhere];
\r
336 if (condit!=IHDOCKED) newcnd();
\r
339 /* check for a helpful planet */
\r
340 for (i = 0; i < inplan; i++) {
\r
341 if (game.state.plnets[i].x==game.state.isx && game.state.plnets[i].y==game.state.isy &&
\r
342 game.state.plnets[i].crystals == 1) {
\r
343 /* destroy the planet */
\r
344 DESTROY(&game.state.plnets[i]);
\r
345 game.state.newstuf[game.state.isx][game.state.isy] -= 1;
\r
346 if (game.damage[DRADIO] == 0.0 || condit == IHDOCKED) {
\r
347 if (*ipage==0) pause_game(1);
\r
349 prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports");
\r
350 proutn(" a planet in ");
\r
351 proutn(cramlc(quadrant, game.state.isx, game.state.isy));
\r
352 prout(" has been destroyed");
\r
353 prout(" by the Super-commander.\"");
\r
358 return 0; /* looks good! */
\r
365 void scom(int *ipage) {
\r
366 int i, i2, j, ideltax, ideltay, ibqx, ibqy, sx, sy, ifindit, iwhichb;
\r
372 if (idebug) prout("SCOM");
\r
375 /* Decide on being active or passive */
\r
376 flag = ((game.state.killc+game.state.killk)/(game.state.date+0.01-indate) < 0.1*skill*(skill+1.0) ||
\r
377 (game.state.date-indate) < 3.0);
\r
378 if (iscate==0 && flag) {
\r
379 /* compute move away from Enterprise */
\r
380 ideltax = game.state.isx-quadx;
\r
381 ideltay = game.state.isy-quady;
\r
382 if (sqrt(ideltax*(double)ideltax+ideltay*(double)ideltay) > 2.0) {
\r
383 /* circulate in space */
\r
384 ideltax = game.state.isy-quady;
\r
385 ideltay = quadx-game.state.isx;
\r
389 /* compute distances to starbases */
\r
390 if (game.state.rembase <= 0) {
\r
391 /* nothing left to do */
\r
392 game.future[FSCMOVE] = 1e30;
\r
395 sx = game.state.isx;
\r
396 sy = game.state.isy;
\r
397 for (i = 1; i <= game.state.rembase; i++) {
\r
399 ibqx = game.state.baseqx[i];
\r
400 ibqy = game.state.baseqy[i];
\r
401 bdist[i] = sqrt(square(ibqx-sx) + square(ibqy-sy));
\r
403 if (game.state.rembase > 1) {
\r
404 /* sort into nearest first order */
\r
408 for (i=1; i < game.state.rembase-1; i++) {
\r
409 if (bdist[i] > bdist[i+1]) {
\r
410 int ti = basetbl[i];
\r
411 double t = bdist[i];
\r
412 bdist[i] = bdist[i+1];
\r
414 basetbl[i] = basetbl[i+1];
\r
421 /* look for nearest base without a commander, no Enterprise, and
\r
422 without too many Klingons, and not already under attack. */
\r
423 ifindit = iwhichb = 0;
\r
425 for (i2 = 1; i2 <= game.state.rembase; i2++) {
\r
426 i = basetbl[i2]; /* bug in original had it not finding nearest*/
\r
427 ibqx = game.state.baseqx[i];
\r
428 ibqy = game.state.baseqy[i];
\r
429 if ((ibqx == quadx && ibqy == quady) ||
\r
430 (ibqx == batx && ibqy == baty) ||
\r
431 game.state.galaxy[ibqx][ibqy] > 899) continue;
\r
432 /* if there is a commander, an no other base is appropriate,
\r
433 we will take the one with the commander */
\r
434 for (j = 1; j <= game.state.remcom; j++) {
\r
435 if (ibqx==game.state.cx[j] && ibqy==game.state.cy[j] && ifindit!= 2) {
\r
441 if (j > game.state.remcom) { /* no commander -- use this one */
\r
447 if (ifindit==0) return; /* Nothing suitable -- wait until next time*/
\r
448 ibqx = game.state.baseqx[iwhichb];
\r
449 ibqy = game.state.baseqy[iwhichb];
\r
450 /* decide how to move toward base */
\r
451 ideltax = ibqx - game.state.isx;
\r
452 ideltay = ibqy - game.state.isy;
\r
454 /* Maximum movement is 1 quadrant in either or both axis */
\r
455 if (ideltax > 1) ideltax = 1;
\r
456 if (ideltax < -1) ideltax = -1;
\r
457 if (ideltay > 1) ideltay = 1;
\r
458 if (ideltay < -1) ideltay = -1;
\r
460 /* try moving in both x and y directions */
\r
461 iqx = game.state.isx + ideltax;
\r
462 iqy = game.state.isy + ideltax;
\r
463 if (movescom(iqx, iqy, flag, ipage)) {
\r
464 /* failed -- try some other maneuvers */
\r
465 if (ideltax==0 || ideltay==0) {
\r
466 /* attempt angle move */
\r
467 if (ideltax != 0) {
\r
468 iqy = game.state.isy + 1;
\r
469 if (movescom(iqx, iqy, flag, ipage)) {
\r
470 iqy = game.state.isy - 1;
\r
471 movescom(iqx, iqy, flag, ipage);
\r
475 iqx = game.state.isx + 1;
\r
476 if (movescom(iqx, iqy, flag, ipage)) {
\r
477 iqx = game.state.isx - 1;
\r
478 movescom(iqx, iqy, flag, ipage);
\r
483 /* try moving just in x or y */
\r
484 iqy = game.state.isy;
\r
485 if (movescom(iqx, iqy, flag, ipage)) {
\r
486 iqy = game.state.isy + ideltay;
\r
487 iqx = game.state.isx;
\r
488 movescom(iqx, iqy, flag, ipage);
\r
492 /* check for a base */
\r
493 if (game.state.rembase == 0) {
\r
494 game.future[FSCMOVE] = 1e30;
\r
496 else for (i=1; i<=game.state.rembase; i++) {
\r
497 ibqx = game.state.baseqx[i];
\r
498 ibqy = game.state.baseqy[i];
\r
499 if (ibqx==game.state.isx && ibqy == game.state.isy && game.state.isx != batx && game.state.isy != baty) {
\r
500 /* attack the base */
\r
501 if (flag) return; /* no, don't attack base! */
\r
504 game.future[FSCDBAS] = game.state.date + 1.0 +2.0*Rand();
\r
505 if (game.future[FCDBAS] < 1e30) game.future[FSCDBAS] +=
\r
506 game.future[FCDBAS]-game.state.date;
\r
507 if (game.damage[DRADIO] > 0 && condit != IHDOCKED)
\r
508 return; /* no warning */
\r
510 if (*ipage == 0) pause_game(1);
\r
512 proutn("Lt. Uhura- \"Captain, the starbase in ");
\r
513 proutn(cramlc(quadrant, game.state.isx, game.state.isy));
\r
515 prout(" reports that it is under attack from the Klingon Super-commander.");
\r
516 proutn(" It can survive until stardate %d.\"",
\r
517 (int)game.future[FSCDBAS]);
\r
518 if (resting==0) return;
\r
519 prout("Mr. Spock- \"Captain, shall we cancel the rest period?\"");
\r
520 if (ja()==0) return;
\r
522 Time = 0.0; /* actually finished */
\r
526 /* Check for intelligence report */
\r
532 (game.damage[DRADIO] > 0.0 && condit != IHDOCKED) ||
\r
533 game.starch[game.state.isx][game.state.isy] > 0))
\r
535 if (*ipage==0) pause_game(1);
\r
537 prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports");
\r
538 proutn(" the Super-commander is in ");
\r
539 proutn(cramlc(quadrant, game.state.isx, game.state. isy));
\r
544 void movetho(void) {
\r
545 int idx, idy, im, i, dum, my;
\r
546 /* Move the Tholian */
\r
547 if (ithere==0 || justin == 1) return;
\r
549 if (ithx == 1 && ithy == 1) {
\r
552 else if (ithx == 1 && ithy == 10) {
\r
553 idx = 10; idy = 10;
\r
555 else if (ithx == 10 && ithy == 10) {
\r
558 else if (ithx == 10 && ithy == 1) {
\r
562 /* something is wrong! */
\r
567 /* Do nothing if we are blocked */
\r
568 if (game.quad[idx][idy]!= IHDOT && game.quad[idx][idy]!= IHWEB) return;
\r
569 game.quad[ithx][ithy] = IHWEB;
\r
572 /* move in x axis */
\r
573 im = fabs((double)idx - ithx)/((double)idx - ithx);
\r
574 while (ithx != idx) {
\r
576 if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;
\r
579 else if (ithy != idy) {
\r
580 /* move in y axis */
\r
581 im = fabs((double)idy - ithy)/((double)idy - ithy);
\r
582 while (ithy != idy) {
\r
584 if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;
\r
587 game.quad[ithx][ithy] = IHT;
\r
588 game.kx[nenhere]=ithx;
\r
589 game.ky[nenhere]=ithy;
\r
591 /* check to see if all holes plugged */
\r
592 for (i = 1; i < 11; i++) {
\r
593 if (game.quad[1][i]!=IHWEB && game.quad[1][i]!=IHT) return;
\r
594 if (game.quad[10][i]!=IHWEB && game.quad[10][i]!=IHT) return;
\r
595 if (game.quad[i][1]!=IHWEB && game.quad[i][1]!=IHT) return;
\r
596 if (game.quad[i][10]!=IHWEB && game.quad[i][10]!=IHT) return;
\r
598 /* All plugged up -- Tholian splits */
\r
599 game.quad[ithx][ithy]=IHWEB;
\r
600 dropin(IHBLANK, &dum, &my);
\r
601 crmena(1,IHT, 2, ithx, ithy);
\r
602 prout(" completes web.");
\r
603 ithere = ithx = ithy = 0;
\r