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