printfs have been banished. All outputnow goes through prout/proutn/prouts.
[super-star-trek.git] / ai.c
1 #include "sst.h"\r
2 \r
3 static int tryexit(int lookx, int looky, int ienm, int loccom, int irun) {\r
4         int iqx, iqy, l;\r
5 \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
12         if (irun == 0) {\r
13                 /* avoid intruding on another commander's territory */\r
14                 if (ienm == IHC) {\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
19                 }\r
20                 /* don't leave if over 1000 units of energy */\r
21                 if (game.kpower[loccom] > 1000.) return 0;\r
22         }\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                 proutn("***");\r
28                 cramen(ienm);\r
29                 proutn(" escapes to");\r
30                 cramlc(1, iqx, iqy);\r
31                 prout(" (and regains strength).");\r
32         }\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
39         klhere--;\r
40         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
45         if (ienm==IHS) {\r
46                 ishere=0;\r
47                 iscate=0;\r
48                 ientesc=0;\r
49                 isatb=0;\r
50                 game.future[FSCMOVE]=0.2777+game.state.date;\r
51                 game.future[FSCDBAS]=1e30;\r
52                 game.state.isx=iqx;\r
53                 game.state.isy=iqy;\r
54         }\r
55         else {\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
60                                 break;\r
61                         }\r
62                 }\r
63                 comhere = 0;\r
64         }\r
65         return 1; /* success */\r
66 }\r
67 \r
68 \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
71         int irun = 0;\r
72         int krawlx, krawly;\r
73         int success;\r
74         int attempts;\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
78                                   (comhere + ishere);\r
79         double dist1, forces;\r
80 \r
81         dist1 = game.kdist[loccom];\r
82         mdist = dist1 + 0.5; /* Nearest integer distance */\r
83 \r
84         /* If SC, check with spy to see if should hi-tail it */\r
85         if (ienm==IHS &&\r
86                 (game.kpower[loccom] <= 500.0 || (condit==IHDOCKED && game.damage[DPHOTON]==0))) {\r
87                 irun = 1;\r
88                 motion = -10;\r
89         }\r
90         else {\r
91                 /* decide whether to advance, retreat, or hold position */\r
92 /* Algorithm:\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
96 \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
100 \r
101          Attacker Initial energy levels (nominal):\r
102                   Klingon   Romulan   Commander   Super-Commander\r
103          Novice    400        700        1200        \r
104          Fair      425        750        1250\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
109 \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
113 \r
114   *  If Enterprise is not docked, an agressive action is taken if enemy\r
115      forces are 1000 greater than Enterprise.\r
116 \r
117          Agressive action on average cuts the distance between the ship and\r
118          the enemy to 1/4 the original.\r
119 \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
123 \r
124          If docked, is reduced by roughly 1.75*skill, generally forcing a\r
125          retreat, especially at high skill levels.\r
126 \r
127   *  Motion is limited to skill level, except for SC hi-tailing it out.\r
128   */\r
129 \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
134                                 forces += 300.0;\r
135                         else\r
136                                 forces -= 0.2*(energy - 2500.0);\r
137                         if (game.damage[DPHOTON] != 0) /* photon torpedoes damaged */\r
138                                 forces += 300.0;\r
139                         else\r
140                                 forces -= 50.0*torps;\r
141                 }\r
142                 else {\r
143                         /* phasers and photon tubes both out! */\r
144                         forces += 1000.0;\r
145                 }\r
146                 motion = 0;\r
147                 if (forces <= 1000.0 && condit != IHDOCKED) /* Typical situation */\r
148                         motion = ((forces+200.0*Rand())/150.0) - 5.0;\r
149                 else {\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
154                 }\r
155 #ifdef DEBUG\r
156                 if (idebug) {\r
157                         proutn("MOTION = ");\r
158                         cramf(motion, 1, 2);\r
159             proutn("  FORCES = ");\r
160                         cramf(forces, 1, 2);\r
161                         skip(1);\r
162                 }\r
163 #endif\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
168         }\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
174 #ifdef DEBUG\r
175         if (idebug) {\r
176                 prout("NSTEPS = %d", nsteps);\r
177         }\r
178 #endif\r
179         /* Compute preferred values of delta X and Y */\r
180         mx = sectx - comx;\r
181         my = secty - comy;\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
186         nextx = comx;\r
187         nexty = comy;\r
188         game.quad[comx][comy] = IHDOT;\r
189         /* main move loop */\r
190         for (ll = 1; ll <= nsteps; ll++) {\r
191 #ifdef DEBUG\r
192                 if (idebug) {\r
193                         prout("%d", ll);\r
194                 }\r
195 #endif\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
201                 success = 0;\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
206                                         return;\r
207                                 if (krawlx == mx || my == 0) break;\r
208                                 lookx = nextx + krawlx;\r
209                                 krawlx = -krawlx;\r
210                         }\r
211                         else if (looky < 1 || looky > 10) {\r
212                                 if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))\r
213                                         return;\r
214                                 if (krawly == my || mx == 0) break;\r
215                                 looky = nexty + krawly;\r
216                                 krawly = -krawly;\r
217                         }\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
223                                         return;\r
224                                 }\r
225                                 if (krawlx != mx && my != 0) {\r
226                                         lookx = nextx + krawlx;\r
227                                         krawlx = -krawlx;\r
228                                 }\r
229                                 else if (krawly != my && mx != 0) {\r
230                                         looky = nexty + krawly;\r
231                                         krawly = -krawly;\r
232                                 }\r
233                                 else break; /* we have failed */\r
234                         }\r
235                         else success = 1;\r
236                 }\r
237                 if (success) {\r
238                         nextx = lookx;\r
239                         nexty = looky;\r
240 #ifdef DEBUG\r
241                         if (idebug) {\r
242                                 cramlc(0, nextx, nexty);\r
243                                 skip(1);\r
244                         }\r
245 #endif\r
246                 }\r
247                 else break; /* done early */\r
248         }\r
249         /* Put commander in place within same quadrant */\r
250         game.quad[nextx][nexty] = ienm;\r
251         if (nextx != comx || nexty != comy) {\r
252                 /* it moved */\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
258                         proutn("***");\r
259                         cramen(ienm);\r
260                         if (game.kdist[loccom] < dist1) proutn(" advances to");\r
261                         else proutn(" retreats to");\r
262                         cramlc(2, nextx, nexty);\r
263                         skip(1);\r
264                 }\r
265         }\r
266 }\r
267 \r
268 void movcom(void) {\r
269         int ix, iy, i;\r
270 \r
271 #ifdef DEBUG\r
272         if (idebug) prout("MOVCOM");\r
273 #endif\r
274 \r
275         /* Figure out which Klingon is the commander (or Supercommander)\r
276            and do move */\r
277         if (comhere) for (i = 1; i <= nenhere; i++) {\r
278                 ix = game.kx[i];\r
279                 iy = game.ky[i];\r
280                 if (game.quad[ix][iy] == IHC) {\r
281                         movebaddy(ix, iy, i, IHC);\r
282                         break;\r
283                 }\r
284         }\r
285         if (ishere) for (i = 1; i <= nenhere; i++) {\r
286                 ix = game.kx[i];\r
287                 iy = game.ky[i];\r
288                 if (game.quad[ix][iy] == IHS) {\r
289                         movebaddy(ix, iy, i, IHS);\r
290                         break;\r
291                 }\r
292         }\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
297                 ix = game.kx[i];\r
298                 iy = game.ky[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
301         }\r
302 \r
303         sortkl();\r
304 }\r
305 \r
306 static int checkdest(int iqx, int iqy, int flag, int *ipage) {\r
307         int i, j;\r
308 \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
312         if (flag) {\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
316         }\r
317 \r
318         /* do the move */\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
323         if (iscate) {\r
324                 /* SC has scooted, Remove him from current quadrant */\r
325                 iscate=0;\r
326                 isatb=0;\r
327                 ishere=0;\r
328                 ientesc=0;\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
338                 klhere--;\r
339                 nenhere--;\r
340                 if (condit!=IHDOCKED) newcnd();\r
341                 sortkl();\r
342         }\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
352                                 *ipage = 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
358                         }\r
359                         break;\r
360                 }\r
361         }\r
362         return 0; /* looks good! */\r
363 }\r
364                         \r
365                 \r
366         \r
367 \r
368 \r
369 void scom(int *ipage) {\r
370         int i, i2, j, ideltax, ideltay, ibqx, ibqy, sx, sy, ifindit, iwhichb;\r
371         int iqx, iqy;\r
372         int basetbl[6];\r
373         double bdist[6];\r
374         int flag;\r
375 #ifdef DEBUG\r
376         if (idebug) prout("SCOM");\r
377 #endif\r
378 \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
390                 }\r
391         }\r
392         else {\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
397                         return;\r
398                 }\r
399                 sx = game.state.isx;\r
400                 sy = game.state.isy;\r
401                 for (i = 1; i <= game.state.rembase; i++) {\r
402                         basetbl[i] = 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
406                 }\r
407                 if (game.state.rembase > 1) {\r
408                         /* sort into nearest first order */\r
409                         int iswitch;\r
410                         do {\r
411                                 iswitch = 0;\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
417                                                 bdist[i+1] = t;\r
418                                                 basetbl[i] = basetbl[i+1];\r
419                                                 basetbl[i+1] =ti;\r
420                                                 iswitch = 1;\r
421                                         }\r
422                                 }\r
423                         } while (iswitch);\r
424                 }\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
428 \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
440                                                 ifindit = 2;\r
441                                                 iwhichb = i;\r
442                                                 break;\r
443                                 }\r
444                         }\r
445                         if (j > game.state.remcom) { /* no commander -- use this one */\r
446                                 ifindit = 1;\r
447                                 iwhichb = i;\r
448                                 break;\r
449                         }\r
450                 }\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
457         }\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
463 \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
476                                 }\r
477                         }\r
478                         else {\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
483                                 }\r
484                         }\r
485                 }\r
486                 else {\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
493                         }\r
494                 }\r
495         }\r
496         /* check for a base */\r
497         if (game.state.rembase == 0) {\r
498                 game.future[FSCMOVE] = 1e30;\r
499         }\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
506                         iseenit = 0;\r
507                         isatb=1;\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
512                         iseenit = 1;\r
513                         if (*ipage == 0)  pause(1);\r
514                         *ipage=1;\r
515                         proutn("Lt. Uhura-  \"Captain, the starbase in");\r
516                         cramlc(1, game.state.isx, game.state.isy);\r
517                         skip(1);\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
521                         prout(" .\"");\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
525                         resting = 0;\r
526                         Time = 0.0; /* actually finished */\r
527                         return;\r
528                 }\r
529         }\r
530         /* Check for intelligence report */\r
531         if (\r
532 #ifdef DEBUG\r
533                 idebug==0 &&\r
534 #endif\r
535                 (Rand() > 0.2 ||\r
536                  (game.damage[DRADIO] > 0.0 && condit != IHDOCKED) ||\r
537                  game.starch[game.state.isx][game.state.isy] > 0))\r
538                 return;\r
539         if (*ipage==0) pause(1);\r
540         *ipage = 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
544         prout(".\"");\r
545         return;\r
546 }\r
547 \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
552 \r
553         if (ithx == 1 && ithy == 1) {\r
554                 idx = 1; idy = 10;\r
555         }\r
556         else if (ithx == 1 && ithy == 10) {\r
557                 idx = 10; idy = 10;\r
558         }\r
559         else if (ithx == 10 && ithy == 10) {\r
560                 idx = 10; idy = 1;\r
561         }\r
562         else if (ithx == 10 && ithy == 1) {\r
563                 idx = 1; idy = 1;\r
564         }\r
565         else {\r
566                 /* something is wrong! */\r
567                 ithere = 0;\r
568                 return;\r
569         }\r
570 \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
574 \r
575         if (ithx != idx) {\r
576                 /* move in x axis */\r
577                 im = fabs((double)idx - ithx)/((double)idx - ithx);\r
578                 while (ithx != idx) {\r
579                         ithx += im;\r
580                         if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;\r
581                 }\r
582         }\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
587                         ithy += im;\r
588                         if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;\r
589                 }\r
590         }\r
591         game.quad[ithx][ithy] = IHT;\r
592 \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
599         }\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
606         return;\r
607 }\r