Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
7142 siemargl 1
#include "sst.h"
2
 
3
static int tryexit(int lookx, int looky, int ienm, int loccom, int irun) {
4
	int iqx, iqy, l;
5
 
6
	iqx = quadx+(lookx+9)/10 - 1;
7
	iqy = quady+(looky+9)/10 - 1;
8
	if (iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
9
		d.galaxy[iqx][iqy] > 899)
10
		return 0; /* no can do -- neg energy, supernovae, or >8 Klingons */
11
	if (ienm == IHR) return 0; /* Romulans cannot escape! */
12
	if (irun == 0) {
13
		/* avoid intruding on another commander's territory */
14
		if (ienm == IHC) {
15
			for (l = 1; l <= d.remcom; l++)
16
				if (d.cx[l]==iqx && d.cy[l]==iqy) return 0;
17
			/* refuse to leave if currently attacking starbase */
18
			if (batx==quadx && baty==quady) return 0;
19
		}
20
		/* don't leave if over 1000 units of energy */
21
		if (kpower[loccom] > 1000.) return 0;
22
	}
23
	/* print escape message and move out of quadrant.
24
	   We know this if either short or long range sensors are working */
25
	if (damage[DSRSENS] == 0.0 || damage[DLRSENS] == 0.0 ||
26
		condit == IHDOCKED) {
27
		proutn("***");
28
		cramen(ienm);
29
		proutn(" escapes to");
30
		cramlc(1, iqx, iqy);
31
		prout(" (and regains strength).");
32
	}
33
	/* handle local matters related to escape */
34
	kx[loccom] = kx[nenhere];
35
	ky[loccom] = ky[nenhere];
36
	kavgd[loccom] = kavgd[nenhere];
37
	kpower[loccom] = kpower[nenhere];
38
	kdist[loccom] = kdist[nenhere];
39
	klhere--;
40
	nenhere--;
41
	if (condit != IHDOCKED) newcnd();
42
	/* Handle global matters related to escape */
43
	d.galaxy[quadx][quady] -= 100;
44
	d.galaxy[iqx][iqy] += 100;
45
	if (ienm==IHS) {
46
		ishere=0;
47
		iscate=0;
48
		ientesc=0;
49
		isatb=0;
50
		future[FSCMOVE]=0.2777+d.date;
51
		future[FSCDBAS]=1e30;
52
		d.isx=iqx;
53
		d.isy=iqy;
54
	}
55
	else {
56
		for (l=1; l<=d.remcom; l++) {
57
			if (d.cx[l]==quadx && d.cy[l]==quady) {
58
				d.cx[l]=iqx;
59
				d.cy[l]=iqy;
60
				break;
61
			}
62
		}
63
		comhere = 0;
64
	}
65
	return 1; /* success */
66
}
67
 
68
 
69
static void movebaddy(int comx, int comy, int loccom, int ienm) {
70
	int motion, mdist, nsteps, mx, my, nextx, nexty, lookx, looky, ll;
71
	int irun = 0;
72
	int krawlx, krawly;
73
	int success;
74
	int attempts;
75
	/* This should probably be just comhere + ishere */
76
	int nbaddys = skill > SGOOD ?
77
				  (int)((comhere*2 + ishere*2+klhere*1.23+irhere*1.5)/2.0):
78
				  (comhere + ishere);
79
	double dist1, forces;
80
 
81
	dist1 = kdist[loccom];
82
	mdist = dist1 + 0.5; /* Nearest integer distance */
83
 
84
	/* If SC, check with spy to see if should hi-tail it */
85
	if (ienm==IHS &&
86
		(kpower[loccom] <= 500.0 || (condit==IHDOCKED && damage[DPHOTON]==0))) {
87
		irun = 1;
88
		motion = -10;
89
	}
90
	else {
91
		/* decide whether to advance, retreat, or hold position */
92
/* Algorithm:
93
   * Enterprise has "force" based on condition of phaser and photon torpedoes.
94
     If both are operating full strength, force is 1000. If both are damaged,
95
	 force is -1000. Having shields down subtracts an additional 1000.
96
 
97
   * Enemy has forces equal to the energy of the attacker plus
98
     100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
99
	 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
100
 
101
	 Attacker Initial energy levels (nominal):
102
	          Klingon   Romulan   Commander   Super-Commander
103
	 Novice    400        700        1200
104
	 Fair      425        750        1250
105
	 Good      450        800        1300        1750
106
	 Expert    475        850        1350        1875
107
	 Emeritus  500        900        1400        2000
108
     VARIANCE   75        200         200         200
109
 
110
	 Enemy vessels only move prior to their attack. In Novice - Good games
111
	 only commanders move. In Expert games, all enemy vessels move if there
112
	 is a commander present. In Emeritus games all enemy vessels move.
113
 
114
  *  If Enterprise is not docked, an agressive action is taken if enemy
115
     forces are 1000 greater than Enterprise.
116
 
117
	 Agressive action on average cuts the distance between the ship and
118
	 the enemy to 1/4 the original.
119
 
120
  *  At lower energy advantage, movement units are proportional to the
121
     advantage with a 650 advantage being to hold ground, 800 to move forward
122
	 1, 950 for two, 150 for back 4, etc. Variance of 100.
123
 
124
	 If docked, is reduced by roughly 1.75*skill, generally forcing a
125
	 retreat, especially at high skill levels.
126
 
127
  *  Motion is limited to skill level, except for SC hi-tailing it out.
128
  */
129
 
130
		forces = kpower[loccom]+100.0*nenhere+400*(nbaddys-1);
131
		if (shldup==0) forces += 1000; /* Good for enemy if shield is down! */
132
		if (damage[DPHASER] == 0.0 || damage[DPHOTON] == 0.0) {
133
			if (damage[DPHASER] != 0) /* phasers damaged */
134
				forces += 300.0;
135
			else
136
				forces -= 0.2*(energy - 2500.0);
137
			if (damage[DPHOTON] != 0) /* photon torpedoes damaged */
138
				forces += 300.0;
139
			else
140
				forces -= 50.0*torps;
141
		}
142
		else {
143
			/* phasers and photon tubes both out! */
144
			forces += 1000.0;
145
		}
146
		motion = 0;
147
		if (forces <= 1000.0 && condit != IHDOCKED) /* Typical situation */
148
			motion = ((forces+200.0*Rand())/150.0) - 5.0;
149
		else {
150
			if (forces > 1000.0) /* Very strong -- move in for kill */
151
				motion = (1.0-square(Rand()))*dist1 + 1.0;
152
			if (condit==IHDOCKED) /* protected by base -- back off ! */
153
				motion -= skill*(2.0-square(Rand()));
154
		}
155
#ifdef DEBUG
156
		if (idebug) {
157
			proutn("MOTION = ");
158
			cramf(motion, 1, 2);
159
            proutn("  FORCES = ");
160
			cramf(forces, 1, 2);
161
			skip(1);
162
		}
163
#endif
164
		/* don't move if no motion */
165
		if (motion==0) return;
166
		/* Limit motion according to skill */
167
		if (abs(motion) > skill) motion = (motion < 0) ? -skill : skill;
168
	}
169
	/* calcuate preferred number of steps */
170
	nsteps = motion < 0 ? -motion : motion;
171
	if (motion > 0 && nsteps > mdist) nsteps = mdist; /* don't overshoot */
172
	if (nsteps > 10) nsteps = 10; /* This shouldn't be necessary */
173
	if (nsteps < 1) nsteps = 1; /* This shouldn't be necessary */
174
#ifdef DEBUG
175
	if (idebug) {
176
		proutn("NSTEPS = ");
177
		crami(nsteps, 1);
178
		skip(1);
179
	}
180
#endif
181
	/* Compute preferred values of delta X and Y */
182
	mx = sectx - comx;
183
	my = secty - comy;
184
	if (2.0 * abs(mx) < abs(my)) mx = 0;
185
	if (2.0 * abs(my) < abs(sectx-comx)) my = 0;
186
	if (mx != 0) mx = mx*motion < 0 ? -1 : 1;
187
	if (my != 0) my = my*motion < 0 ? -1 : 1;
188
	nextx = comx;
189
	nexty = comy;
190
	quad[comx][comy] = IHDOT;
191
	/* main move loop */
192
	for (ll = 1; ll <= nsteps; ll++) {
193
#ifdef DEBUG
194
		if (idebug) {
195
			crami(ll,2);
196
			skip(1);
197
		}
198
#endif
199
		/* Check if preferred position available */
200
		lookx = nextx + mx;
201
		looky = nexty + my;
202
		krawlx = mx < 0 ? 1 : -1;
203
		krawly = my < 0 ? 1 : -1;
204
		success = 0;
205
		attempts = 0; /* Settle mysterious hang problem */
206
		while (attempts++ < 20 && !success) {
207
			if (lookx < 1 || lookx > 10) {
208
				if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
209
					return;
210
				if (krawlx == mx || my == 0) break;
211
				lookx = nextx + krawlx;
212
				krawlx = -krawlx;
213
			}
214
			else if (looky < 1 || looky > 10) {
215
				if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
216
					return;
217
				if (krawly == my || mx == 0) break;
218
				looky = nexty + krawly;
219
				krawly = -krawly;
220
			}
221
			else if (quad[lookx][looky] != IHDOT) {
222
				/* See if we should ram ship */
223
				if (quad[lookx][looky] == ship &&
224
					(ienm == IHC || ienm == IHS)) {
225
					ram(1, ienm, comx, comy);
226
					return;
227
				}
228
				if (krawlx != mx && my != 0) {
229
					lookx = nextx + krawlx;
230
					krawlx = -krawlx;
231
				}
232
				else if (krawly != my && mx != 0) {
233
					looky = nexty + krawly;
234
					krawly = -krawly;
235
				}
236
				else break; /* we have failed */
237
			}
238
			else success = 1;
239
		}
240
		if (success) {
241
			nextx = lookx;
242
			nexty = looky;
243
#ifdef DEBUG
244
			if (idebug) {
245
				cramlc(0, nextx, nexty);
246
				skip(1);
247
			}
248
#endif
249
		}
250
		else break; /* done early */
251
	}
252
	/* Put commander in place within same quadrant */
253
	quad[nextx][nexty] = ienm;
254
	if (nextx != comx || nexty != comy) {
255
		/* it moved */
256
		kx[loccom] = nextx;
257
		ky[loccom] = nexty;
258
		kdist[loccom] = kavgd[loccom] =
259
					sqrt(square(sectx-nextx)+square(secty-nexty));
260
		if (damage[DSRSENS] == 0 || condit == IHDOCKED) {
261
			proutn("***");
262
			cramen(ienm);
263
			if (kdist[loccom] < dist1) proutn(" advances to");
264
			else proutn(" retreats to");
265
			cramlc(2, nextx, nexty);
266
			skip(1);
267
		}
268
	}
269
}
270
 
271
void movcom(void) {
272
	int ix, iy, i;
273
 
274
#ifdef DEBUG
275
	if (idebug) prout("MOVCOM");
276
#endif
277
 
278
	/* Figure out which Klingon is the commander (or Supercommander)
279
	   and do move */
280
	if (comhere) for (i = 1; i <= nenhere; i++) {
281
		ix = kx[i];
282
		iy = ky[i];
283
		if (quad[ix][iy] == IHC) {
284
			movebaddy(ix, iy, i, IHC);
285
			break;
286
		}
287
	}
288
	if (ishere) for (i = 1; i <= nenhere; i++) {
289
		ix = kx[i];
290
		iy = ky[i];
291
		if (quad[ix][iy] == IHS) {
292
			movebaddy(ix, iy, i, IHS);
293
			break;
294
		}
295
	}
296
	/* if skill level is high, move other Klingons and Romulans too!
297
	   Move these last so they can base their actions on what the
298
       commander(s) do. */
299
	if (skill > SGOOD) for (i = 1; i <= nenhere; i++) {
300
		ix = kx[i];
301
		iy = ky[i];
302
		if (quad[ix][iy] == IHK || quad[ix][iy] == IHR)
303
			movebaddy(ix, iy, i, quad[ix][iy]);
304
	}
305
 
306
	sortkl();
307
}
308
 
309
static int checkdest(int iqx, int iqy, int flag, int *ipage) {
310
	int i, j;
311
 
312
	if ((iqx==quadx && iqy==quady) ||
313
		iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
314
		d.galaxy[iqx][iqy] > 899) return 1;
315
	if (flag) {
316
		/* Avoid quadrants with bases if we want to avoid Enterprise */
317
		for (i = 1; i <= d.rembase; i++)
318
			if (d.baseqx[i]==iqx && d.baseqy[i]==iqy) return 1;
319
	}
320
 
321
	/* do the move */
322
	d.galaxy[d.isx][d.isy] -= 100;
323
	d.isx = iqx;
324
	d.isy = iqy;
325
	d.galaxy[d.isx][d.isy] += 100;
326
	if (iscate) {
327
		/* SC has scooted, Remove him from current quadrant */
328
		iscate=0;
329
		isatb=0;
330
		ishere=0;
331
		ientesc=0;
332
		future[FSCDBAS]=1e30;
333
		for (i = 1; i <= nenhere; i++)
334
			if (quad[kx[i]][ky[i]] == IHS) break;
335
		quad[kx[i]][ky[i]] = IHDOT;
336
		kx[i] = kx[nenhere];
337
		ky[i] = ky[nenhere];
338
		kdist[i] = kdist[nenhere];
339
		kavgd[i] = kavgd[nenhere];
340
		kpower[i] = kpower[nenhere];
341
		klhere--;
342
		nenhere--;
343
		if (condit!=IHDOCKED) newcnd();
344
		sortkl();
345
	}
346
	/* check for a helpful planet */
347
	for (i = 1; i <= inplan; i++) {
348
		if (d.plnets[i].x==d.isx && d.plnets[i].y==d.isy &&
349
			d.plnets[i].crystals == 1) {
350
			/* destroy the planet */
351
			d.plnets[i] = nulplanet;
352
			d.newstuf[d.isx][d.isy] -= 1;
353
			if (REPORTS) {
354
				if (*ipage==0) pause(1);
355
				*ipage = 1;
356
				prout("Lt. Uhura-  \"Captain, Starfleet Intelligence reports");
357
				proutn("   a planet in");
358
				cramlc(1, d.isx, d.isy);
359
				prout(" has been destroyed");
360
				prout("   by the Super-commander.\"");
361
			}
362
			break;
363
		}
364
	}
365
	return 0; /* looks good! */
366
}
367
 
368
 
369
 
370
 
371
 
372
void scom(int *ipage) {
373
	int i, i2, j, ideltax, ideltay, ibqx, ibqy, sx, sy, ifindit, iwhichb;
374
	int iqx, iqy;
375
	int basetbl[6];
376
	double bdist[6];
377
	int flag;
378
#ifdef DEBUG
379
	if (idebug) prout("SCOM");
380
#endif
381
 
382
	/* Decide on being active or passive */
383
	flag = ((d.killc+d.killk)/(d.date+0.01-indate) < 0.1*skill*(skill+1.0) ||
384
			(d.date-indate) < 3.0);
385
	if (iscate==0 && flag) {
386
		/* compute move away from Enterprise */
387
		ideltax = d.isx-quadx;
388
		ideltay = d.isy-quady;
389
		if (sqrt(ideltax*(double)ideltax+ideltay*(double)ideltay) > 2.0) {
390
			/* circulate in space */
391
			ideltax = d.isy-quady;
392
			ideltay = quadx-d.isx;
393
		}
394
	}
395
	else {
396
		/* compute distances to starbases */
397
		if (d.rembase <= 0) {
398
			/* nothing left to do */
399
			future[FSCMOVE] = 1e30;
400
			return;
401
		}
402
		sx = d.isx;
403
		sy = d.isy;
404
		for (i = 1; i <= d.rembase; i++) {
405
			basetbl[i] = i;
406
			ibqx = d.baseqx[i];
407
			ibqy = d.baseqy[i];
408
			bdist[i] = sqrt(square(ibqx-sx) + square(ibqy-sy));
409
		}
410
		if (d.rembase > 1) {
411
			/* sort into nearest first order */
412
			int iswitch;
413
			do {
414
				iswitch = 0;
415
				for (i=1; i < d.rembase-1; i++) {
416
					if (bdist[i] > bdist[i+1]) {
417
						int ti = basetbl[i];
418
						double t = bdist[i];
419
						bdist[i] = bdist[i+1];
420
						bdist[i+1] = t;
421
						basetbl[i] = basetbl[i+1];
422
						basetbl[i+1] =ti;
423
						iswitch = 1;
424
					}
425
				}
426
			} while (iswitch);
427
		}
428
		/* look for nearest base without a commander, no Enterprise, and
429
		   without too many Klingons, and not already under attack. */
430
		ifindit = iwhichb = 0;
431
 
432
		for (i2 = 1; i2 <= d.rembase; i2++) {
433
			i = basetbl[i2];	/* bug in original had it not finding nearest*/
434
			ibqx = d.baseqx[i];
435
			ibqy = d.baseqy[i];
436
			if ((ibqx == quadx && ibqy == quady) ||
437
				(ibqx == batx && ibqy == baty) ||
438
				d.galaxy[ibqx][ibqy] > 899) continue;
439
			/* if there is a commander, an no other base is appropriate,
440
			   we will take the one with the commander */
441
			for (j = 1; j <= d.remcom; j++) {
442
				if (ibqx==d.cx[j] && ibqy==d.cy[j] && ifindit!= 2) {
443
						ifindit = 2;
444
						iwhichb = i;
445
						break;
446
				}
447
			}
448
			if (j > d.remcom) { /* no commander -- use this one */
449
				ifindit = 1;
450
				iwhichb = i;
451
				break;
452
			}
453
		}
454
		if (ifindit==0) return; /* Nothing suitable -- wait until next time*/
455
		ibqx = d.baseqx[iwhichb];
456
		ibqy = d.baseqy[iwhichb];
457
		/* decide how to move toward base */
458
		ideltax = ibqx - d.isx;
459
		ideltay = ibqy - d.isy;
460
	}
461
	/* Maximum movement is 1 quadrant in either or both axis */
462
	if (ideltax > 1) ideltax = 1;
463
	if (ideltax < -1) ideltax = -1;
464
	if (ideltay > 1) ideltay = 1;
465
	if (ideltay < -1) ideltay = -1;
466
 
467
	/* try moving in both x and y directions */
468
	iqx = d.isx + ideltax;
469
	iqy = d.isy + ideltax;
470
	if (checkdest(iqx, iqy, flag, ipage)) {
471
		/* failed -- try some other maneuvers */
472
		if (ideltax==0 || ideltay==0) {
473
			/* attempt angle move */
474
			if (ideltax != 0) {
475
				iqy = d.isy + 1;
476
				if (checkdest(iqx, iqy, flag, ipage)) {
477
					iqy = d.isy - 1;
478
					checkdest(iqx, iqy, flag, ipage);
479
				}
480
			}
481
			else {
482
				iqx = d.isx + 1;
483
				if (checkdest(iqx, iqy, flag, ipage)) {
484
					iqx = d.isx - 1;
485
					checkdest(iqx, iqy, flag, ipage);
486
				}
487
			}
488
		}
489
		else {
490
			/* try moving just in x or y */
491
			iqy = d.isy;
492
			if (checkdest(iqx, iqy, flag, ipage)) {
493
				iqy = d.isy + ideltay;
494
				iqx = d.isx;
495
				checkdest(iqx, iqy, flag, ipage);
496
			}
497
		}
498
	}
499
	/* check for a base */
500
	if (d.rembase == 0) {
501
		future[FSCMOVE] = 1e30;
502
	}
503
	else for (i=1; i<=d.rembase; i++) {
504
		ibqx = d.baseqx[i];
505
		ibqy = d.baseqy[i];
506
		if (ibqx==d.isx && ibqy == d.isy && d.isx != batx && d.isy != baty) {
507
			/* attack the base */
508
			if (flag) return; /* no, don't attack base! */
509
			iseenit = 0;
510
			isatb=1;
511
			future[FSCDBAS] = d.date + 1.0 +2.0*Rand();
512
			if (batx != 0) future[FSCDBAS] += future[FCDBAS]-d.date;
513
			if (!REPORTS)
514
				return; /* no warning */
515
			iseenit = 1;
516
			if (*ipage == 0)  pause(1);
517
			*ipage=1;
518
			proutn("Lt. Uhura-  \"Captain, the starbase in");
519
			cramlc(1, d.isx, d.isy);
520
			skip(1);
521
			prout("   reports that it is under attack from the Klingon Super-commander.");
522
			proutn("   It can survive until stardate ");
523
			cramf(future[FSCDBAS], 0, 1);
524
			prout(" .\"");
525
			if (resting==0) return;
526
			prout("Mr. Spock-  \"Captain, shall we cancel the rest period?\"");
527
			if (ja()==0) return;
528
			resting = 0;
529
			Time = 0.0; /* actually finished */
530
			return;
531
		}
532
	}
533
	/* Check for intelligence report */
534
	if (
535
#ifdef DEBUG
536
		idebug==0 &&
537
#endif
538
		(Rand() > 0.2 ||
539
		 (!REPORTS) ||
540
		 starch[d.isx][d.isy] > 0))
541
		return;
542
	if (*ipage==0) pause(1);
543
	*ipage = 1;
544
	prout("Lt. Uhura-  \"Captain, Starfleet Intelligence reports");
545
	proutn("   the Super-commander is in");
546
	cramlc(1, d.isx, d.isy);
547
	prout(".\"");
548
	return;
549
}
550
 
551
void movetho(void) {
552
	int idx, idy, im, i, dum, my;
553
	/* Move the Tholean */
554
	if (ithere==0 || justin == 1) return;
555
 
556
	if (ithx == 1 && ithy == 1) {
557
		idx = 1; idy = 10;
558
	}
559
	else if (ithx == 1 && ithy == 10) {
560
		idx = 10; idy = 10;
561
	}
562
	else if (ithx == 10 && ithy == 10) {
563
		idx = 10; idy = 1;
564
	}
565
	else if (ithx == 10 && ithy == 1) {
566
		idx = 1; idy = 1;
567
	}
568
	else {
569
		/* something is wrong! */
570
		ithere = 0;
571
		return;
572
	}
573
 
574
	/* Do nothing if we are blocked */
575
	if (quad[idx][idy]!= IHDOT && quad[idx][idy]!= IHWEB) return;
576
	quad[ithx][ithy] = IHWEB;
577
 
578
	if (ithx != idx) {
579
		/* move in x axis */
580
		im = fabs((double)idx - ithx)/((double)idx - ithx);
581
		while (ithx != idx) {
582
			ithx += im;
583
			if (quad[ithx][ithy]==IHDOT) quad[ithx][ithy] = IHWEB;
584
		}
585
	}
586
	else if (ithy != idy) {
587
		/* move in y axis */
588
		im = fabs((double)idy - ithy)/((double)idy - ithy);
589
		while (ithy != idy) {
590
			ithy += im;
591
			if (quad[ithx][ithy]==IHDOT) quad[ithx][ithy] = IHWEB;
592
		}
593
	}
594
	quad[ithx][ithy] = IHT;
595
 
596
	/* check to see if all holes plugged */
597
	for (i = 1; i < 11; i++) {
598
		if (quad[1][i]!=IHWEB && quad[1][i]!=IHT) return;
599
		if (quad[10][i]!=IHWEB && quad[10][i]!=IHT) return;
600
		if (quad[i][1]!=IHWEB && quad[i][1]!=IHT) return;
601
		if (quad[i][10]!=IHWEB && quad[i][10]!=IHT) return;
602
	}
603
	/* All plugged up -- Tholian splits */
604
	quad[ithx][ithy]=IHWEB;
605
	dropin(IHBLANK, &dum, &my);
606
	crmena(1,IHT, 2, ithx, ithy);
607
	prout(" completes web.");
608
	ithere = ithx = ithy = 0;
609
	return;
610
}