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