Get rid of all DOS-generated CRs.
[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+9)/10 - 1;
7         iqy = quady+(looky+9)/10 - 1;
8         if (iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
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                 proutn(" 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 = -10;
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 > 10) nsteps = 10; /* 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 > 10) {
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 > 10) {
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");
256                         cramlc(2, comx, comy);
257                         if (game.kdist[loccom] < dist1) proutn(" advances to");
258                         else proutn(" retreats to ");
259                         prout(cramlc(sector, nextx, nexty));
260                 }
261         }
262 }
263
264 void movcom(void) {
265         int ix, iy, i;
266
267 #ifdef DEBUG
268         if (idebug) prout("MOVCOM");
269 #endif
270
271         /* Figure out which Klingon is the commander (or Supercommander)
272            and do move */
273         if (comhere) for (i = 1; i <= nenhere; i++) {
274                 ix = game.kx[i];
275                 iy = game.ky[i];
276                 if (game.quad[ix][iy] == IHC) {
277                         movebaddy(ix, iy, i, IHC);
278                         break;
279                 }
280         }
281         if (ishere) for (i = 1; i <= nenhere; i++) {
282                 ix = game.kx[i];
283                 iy = game.ky[i];
284                 if (game.quad[ix][iy] == IHS) {
285                         movebaddy(ix, iy, i, IHS);
286                         break;
287                 }
288         }
289         /* if skill level is high, move other Klingons and Romulans too!
290            Move these last so they can base their actions on what the
291        commander(s) do. */
292         if (skill > 3) for (i = 1; i <= nenhere; i++) {
293                 ix = game.kx[i];
294                 iy = game.ky[i];
295                 if (game.quad[ix][iy] == IHK || game.quad[ix][iy] == IHR)
296                         movebaddy(ix, iy, i, game.quad[ix][iy]);
297         }
298
299         sortkl();
300 }
301
302 static int movescom(int iqx, int iqy, int flag, int *ipage) {
303         int i;
304
305         if ((iqx==quadx && iqy==quady) ||
306                 iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
307                 game.state.galaxy[iqx][iqy] > 899) return 1;
308         if (flag) {
309                 /* Avoid quadrants with bases if we want to avoid Enterprise */
310                 for (i = 1; i <= game.state.rembase; i++)
311                         if (game.state.baseqx[i]==iqx && game.state.baseqy[i]==iqy) return 1;
312         }
313         if (justin && !iscate) return 1;
314         /* do the move */
315         game.state.galaxy[game.state.isx][game.state.isy] -= 100;
316         game.state.isx = iqx;
317         game.state.isy = iqy;
318         game.state.galaxy[game.state.isx][game.state.isy] += 100;
319         if (ishere) {
320                 /* SC has scooted, Remove him from current quadrant */
321                 iscate=0;
322                 isatb=0;
323                 ishere=0;
324                 ientesc=0;
325                 game.future[FSCDBAS]=1e30;
326                 for (i = 1; i <= nenhere; i++) 
327                         if (game.quad[game.kx[i]][game.ky[i]] == IHS) break;
328                 game.quad[game.kx[i]][game.ky[i]] = IHDOT;
329                 game.kx[i] = game.kx[nenhere];
330                 game.ky[i] = game.ky[nenhere];
331                 game.kdist[i] = game.kdist[nenhere];
332                 game.kavgd[i] = game.kavgd[nenhere];
333                 game.kpower[i] = game.kpower[nenhere];
334                 klhere--;
335                 nenhere--;
336                 if (condit!=IHDOCKED) newcnd();
337                 sortkl();
338         }
339         /* check for a helpful planet */
340         for (i = 0; i < inplan; i++) {
341                 if (game.state.plnets[i].x==game.state.isx && game.state.plnets[i].y==game.state.isy &&
342                         game.state.plnets[i].crystals == 1) {
343                         /* destroy the planet */
344                         DESTROY(&game.state.plnets[i]);
345                         game.state.newstuf[game.state.isx][game.state.isy] -= 1;
346                         if (game.damage[DRADIO] == 0.0 || condit == IHDOCKED) {
347                                 if (*ipage==0) pause_game(1);
348                                 *ipage = 1;
349                                 prout("Lt. Uhura-  \"Captain, Starfleet Intelligence reports");
350                                 proutn("   a planet in ");
351                                 proutn(cramlc(quadrant, game.state.isx, game.state.isy));
352                                 prout(" has been destroyed");
353                                 prout("   by the Super-commander.\"");
354                         }
355                         break;
356                 }
357         }
358         return 0; /* looks good! */
359 }
360                         
361                 
362         
363
364
365 void scom(int *ipage) {
366         int i, i2, j, ideltax, ideltay, ibqx, ibqy, sx, sy, ifindit, iwhichb;
367         int iqx, iqy;
368         int basetbl[6];
369         double bdist[6];
370         int flag;
371 #ifdef DEBUG
372         if (idebug) prout("SCOM");
373 #endif
374
375         /* Decide on being active or passive */
376         flag = ((game.state.killc+game.state.killk)/(game.state.date+0.01-indate) < 0.1*skill*(skill+1.0) ||
377                         (game.state.date-indate) < 3.0);
378         if (iscate==0 && flag) {
379                 /* compute move away from Enterprise */
380                 ideltax = game.state.isx-quadx;
381                 ideltay = game.state.isy-quady;
382                 if (sqrt(ideltax*(double)ideltax+ideltay*(double)ideltay) > 2.0) {
383                         /* circulate in space */
384                         ideltax = game.state.isy-quady;
385                         ideltay = quadx-game.state.isx;
386                 }
387         }
388         else {
389                 /* compute distances to starbases */
390                 if (game.state.rembase <= 0) {
391                         /* nothing left to do */
392                         game.future[FSCMOVE] = 1e30;
393                         return;
394                 }
395                 sx = game.state.isx;
396                 sy = game.state.isy;
397                 for (i = 1; i <= game.state.rembase; i++) {
398                         basetbl[i] = i;
399                         ibqx = game.state.baseqx[i];
400                         ibqy = game.state.baseqy[i];
401                         bdist[i] = sqrt(square(ibqx-sx) + square(ibqy-sy));
402                 }
403                 if (game.state.rembase > 1) {
404                         /* sort into nearest first order */
405                         int iswitch;
406                         do {
407                                 iswitch = 0;
408                                 for (i=1; i < game.state.rembase-1; i++) {
409                                         if (bdist[i] > bdist[i+1]) {
410                                                 int ti = basetbl[i];
411                                                 double t = bdist[i];
412                                                 bdist[i] = bdist[i+1];
413                                                 bdist[i+1] = t;
414                                                 basetbl[i] = basetbl[i+1];
415                                                 basetbl[i+1] =ti;
416                                                 iswitch = 1;
417                                         }
418                                 }
419                         } while (iswitch);
420                 }
421                 /* look for nearest base without a commander, no Enterprise, and
422                    without too many Klingons, and not already under attack. */
423                 ifindit = iwhichb = 0;
424
425                 for (i2 = 1; i2 <= game.state.rembase; i2++) {
426                         i = basetbl[i2];        /* bug in original had it not finding nearest*/
427                         ibqx = game.state.baseqx[i];
428                         ibqy = game.state.baseqy[i];
429                         if ((ibqx == quadx && ibqy == quady) ||
430                                 (ibqx == batx && ibqy == baty) ||
431                                 game.state.galaxy[ibqx][ibqy] > 899) continue;
432                         /* if there is a commander, an no other base is appropriate,
433                            we will take the one with the commander */
434                         for (j = 1; j <= game.state.remcom; j++) {
435                                 if (ibqx==game.state.cx[j] && ibqy==game.state.cy[j] && ifindit!= 2) {
436                                                 ifindit = 2;
437                                                 iwhichb = i;
438                                                 break;
439                                 }
440                         }
441                         if (j > game.state.remcom) { /* no commander -- use this one */
442                                 ifindit = 1;
443                                 iwhichb = i;
444                                 break;
445                         }
446                 }
447                 if (ifindit==0) return; /* Nothing suitable -- wait until next time*/
448                 ibqx = game.state.baseqx[iwhichb];
449                 ibqy = game.state.baseqy[iwhichb];
450                 /* decide how to move toward base */
451                 ideltax = ibqx - game.state.isx;
452                 ideltay = ibqy - game.state.isy;
453         }
454         /* Maximum movement is 1 quadrant in either or both axis */
455         if (ideltax > 1) ideltax = 1;
456         if (ideltax < -1) ideltax = -1;
457         if (ideltay > 1) ideltay = 1;
458         if (ideltay < -1) ideltay = -1;
459
460         /* try moving in both x and y directions */
461         iqx = game.state.isx + ideltax;
462         iqy = game.state.isy + ideltax;
463         if (movescom(iqx, iqy, flag, ipage)) {
464                 /* failed -- try some other maneuvers */
465                 if (ideltax==0 || ideltay==0) {
466                         /* attempt angle move */
467                         if (ideltax != 0) {
468                                 iqy = game.state.isy + 1;
469                                 if (movescom(iqx, iqy, flag, ipage)) {
470                                         iqy = game.state.isy - 1;
471                                         movescom(iqx, iqy, flag, ipage);
472                                 }
473                         }
474                         else {
475                                 iqx = game.state.isx + 1;
476                                 if (movescom(iqx, iqy, flag, ipage)) {
477                                         iqx = game.state.isx - 1;
478                                         movescom(iqx, iqy, flag, ipage);
479                                 }
480                         }
481                 }
482                 else {
483                         /* try moving just in x or y */
484                         iqy = game.state.isy;
485                         if (movescom(iqx, iqy, flag, ipage)) {
486                                 iqy = game.state.isy + ideltay;
487                                 iqx = game.state.isx;
488                                 movescom(iqx, iqy, flag, ipage);
489                         }
490                 }
491         }
492         /* check for a base */
493         if (game.state.rembase == 0) {
494                 game.future[FSCMOVE] = 1e30;
495         }
496         else for (i=1; i<=game.state.rembase; i++) {
497                 ibqx = game.state.baseqx[i];
498                 ibqy = game.state.baseqy[i];
499                 if (ibqx==game.state.isx && ibqy == game.state.isy && game.state.isx != batx && game.state.isy != baty) {
500                         /* attack the base */
501                         if (flag) return; /* no, don't attack base! */
502                         iseenit = 0;
503                         isatb=1;
504                         game.future[FSCDBAS] = game.state.date + 1.0 +2.0*Rand();
505                         if (game.future[FCDBAS] < 1e30) game.future[FSCDBAS] +=
506                                 game.future[FCDBAS]-game.state.date;
507                         if (game.damage[DRADIO] > 0 && condit != IHDOCKED)
508                                 return; /* no warning */
509                         iseenit = 1;
510                         if (*ipage == 0)  pause_game(1);
511                         *ipage=1;
512                         proutn("Lt. Uhura-  \"Captain, the starbase in ");
513                         proutn(cramlc(quadrant, game.state.isx, game.state.isy));
514                         skip(1);
515                         prout("   reports that it is under attack from the Klingon Super-commander.");
516                         proutn("   It can survive until stardate %d.\"",
517                                (int)game.future[FSCDBAS]);
518                         if (resting==0) return;
519                         prout("Mr. Spock-  \"Captain, shall we cancel the rest period?\"");
520                         if (ja()==0) return;
521                         resting = 0;
522                         Time = 0.0; /* actually finished */
523                         return;
524                 }
525         }
526         /* Check for intelligence report */
527         if (
528 #ifdef DEBUG
529                 idebug==0 &&
530 #endif
531                 (Rand() > 0.2 ||
532                  (game.damage[DRADIO] > 0.0 && condit != IHDOCKED) ||
533                  game.starch[game.state.isx][game.state.isy] > 0))
534                 return;
535         if (*ipage==0) pause_game(1);
536         *ipage = 1;
537         prout("Lt. Uhura-  \"Captain, Starfleet Intelligence reports");
538         proutn("   the Super-commander is in ");
539         proutn(cramlc(quadrant, game.state.isx, game.state. isy));
540         prout(".\"");
541         return;
542 }
543
544 void movetho(void) {
545         int idx, idy, im, i, dum, my;
546         /* Move the Tholian */
547         if (ithere==0 || justin == 1) return;
548
549         if (ithx == 1 && ithy == 1) {
550                 idx = 1; idy = 10;
551         }
552         else if (ithx == 1 && ithy == 10) {
553                 idx = 10; idy = 10;
554         }
555         else if (ithx == 10 && ithy == 10) {
556                 idx = 10; idy = 1;
557         }
558         else if (ithx == 10 && ithy == 1) {
559                 idx = 1; idy = 1;
560         }
561         else {
562                 /* something is wrong! */
563                 ithere = 0;
564                 return;
565         }
566
567         /* Do nothing if we are blocked */
568         if (game.quad[idx][idy]!= IHDOT && game.quad[idx][idy]!= IHWEB) return;
569         game.quad[ithx][ithy] = IHWEB;
570
571         if (ithx != idx) {
572                 /* move in x axis */
573                 im = fabs((double)idx - ithx)/((double)idx - ithx);
574                 while (ithx != idx) {
575                         ithx += im;
576                         if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;
577                 }
578         }
579         else if (ithy != idy) {
580                 /* move in y axis */
581                 im = fabs((double)idy - ithy)/((double)idy - ithy);
582                 while (ithy != idy) {
583                         ithy += im;
584                         if (game.quad[ithx][ithy]==IHDOT) game.quad[ithx][ithy] = IHWEB;
585                 }
586         }
587         game.quad[ithx][ithy] = IHT;
588         game.kx[nenhere]=ithx;
589         game.ky[nenhere]=ithy;
590
591         /* check to see if all holes plugged */
592         for (i = 1; i < 11; i++) {
593                 if (game.quad[1][i]!=IHWEB && game.quad[1][i]!=IHT) return;
594                 if (game.quad[10][i]!=IHWEB && game.quad[10][i]!=IHT) return;
595                 if (game.quad[i][1]!=IHWEB && game.quad[i][1]!=IHT) return;
596                 if (game.quad[i][10]!=IHWEB && game.quad[i][10]!=IHT) return;
597         }
598         /* All plugged up -- Tholian splits */
599         game.quad[ithx][ithy]=IHWEB;
600         dropin(IHBLANK, &dum, &my);
601         crmena(1,IHT, 2, ithx, ithy);
602         prout(" completes web.");
603         ithere = ithx = ithy = 0;
604         nenhere--;
605         return;
606 }