OSDN Git Service

update year to 2020
[jnethack/source.git] / src / worm.c
1 /* NetHack 3.6  worm.c  $NHDT-Date: 1561340880 2019/06/24 01:48:00 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.30 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2009. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 #include "hack.h"
12 #include "lev.h"
13
14 #define newseg() (struct wseg *) alloc(sizeof (struct wseg))
15 #define dealloc_seg(wseg) free((genericptr_t) (wseg))
16
17 /* worm segment structure */
18 struct wseg {
19     struct wseg *nseg;
20     xchar wx, wy; /* the segment's position */
21 };
22
23 STATIC_DCL void FDECL(toss_wsegs, (struct wseg *, BOOLEAN_P));
24 STATIC_DCL void FDECL(shrink_worm, (int));
25 STATIC_DCL void FDECL(random_dir, (XCHAR_P, XCHAR_P, xchar *, xchar *));
26 STATIC_DCL struct wseg *FDECL(create_worm_tail, (int));
27
28 /*  Description of long worm implementation.
29  *
30  *  Each monst struct of the head of a tailed worm has a wormno set to
31  *                      1 <= wormno < MAX_NUM_WORMS
32  *  If wormno == 0 this does not mean that the monster is not a worm,
33  *  it just means that the monster does not have a long worm tail.
34  *
35  *  The actual segments of a worm are not full blown monst structs.
36  *  They are small wseg structs, and their position in the levels.monsters[][]
37  *  array is held by the monst struct of the head of the worm.  This makes
38  *  things like probing and hit point bookkeeping much easier.
39  *
40  *  The segments of the long worms on a level are kept as an array of
41  *  singly threaded linked lists.  The wormno variable is used as an index
42  *  for these segment arrays.
43  *
44  *  wtails:     The first (starting struct) of a linked list.  This points
45  *              to the tail (last) segment of the worm.
46  *
47  *  wheads:     The last (end) of a linked list of segments.  This points to
48  *              the segment that is at the same position as the real monster
49  *              (the head).  Note that the segment that wheads[wormno] points
50  *              to, is not displayed.  It is simply there to keep track of
51  *              where the head came from, so that worm movement and display
52  *              are simplified later.
53  *              Keeping the head segment of the worm at the end of the list
54  *              of tail segments is an endless source of confusion, but it is
55  *              necessary.
56  *              From now on, we will use "start" and "end" to refer to the
57  *              linked list and "head" and "tail" to refer to the worm.
58  *
59  *  One final worm array is:
60  *
61  *  wgrowtime:  This tells us when to add another segment to the worm.
62  *
63  *  When a worm is moved, we add a new segment at the head, and delete the
64  *  segment at the tail (unless we want it to grow).  This new head segment is
65  *  located in the same square as the actual head of the worm.  If we want
66  *  to grow the worm, we don't delete the tail segment, and we give the worm
67  *  extra hit points, which possibly go into its maximum.
68  *
69  *  Non-moving worms (worm_nomove) are assumed to be surrounded by their own
70  *  tail, and, thus, shrink instead of grow (as their tails keep going while
71  *  their heads are stopped short).  In this case, we delete the last tail
72  *  segment, and remove hit points from the worm.
73  */
74
75 struct wseg *wheads[MAX_NUM_WORMS] = DUMMY, *wtails[MAX_NUM_WORMS] = DUMMY;
76 long wgrowtime[MAX_NUM_WORMS] = DUMMY;
77
78 /*
79  *  get_wormno()
80  *
81  *  Find an unused worm tail slot and return the index.  A zero means that
82  *  there are no slots available.  This means that the worm head can exist,
83  *  it just cannot ever grow a tail.
84  *
85  *  It, also, means that there is an optimisation to made.  The [0] positions
86  *  of the arrays are never used.  Meaning, we really *could* have one more
87  *  tailed worm on the level, or use a smaller array (using wormno - 1).
88  *
89  *  Implementation is left to the interested hacker.
90  */
91 int
92 get_wormno()
93 {
94     register int new_wormno = 1;
95
96     while (new_wormno < MAX_NUM_WORMS) {
97         if (!wheads[new_wormno])
98             return new_wormno; /* found empty wtails[] slot at new_wormno */
99         new_wormno++;
100     }
101     return 0; /* level infested with worms */
102 }
103
104 /*
105  *  initworm()
106  *
107  *  Use if (mon->wormno = get_wormno()) before calling this function!
108  *
109  *  Initialize the worm entry.  This will set up the worm grow time, and
110  *  create and initialize the dummy segment for wheads[] and wtails[].
111  *
112  *  If the worm has no tail (ie get_wormno() fails) then this function need
113  *  not be called.
114  */
115 void
116 initworm(worm, wseg_count)
117 struct monst *worm;
118 int wseg_count;
119 {
120     register struct wseg *seg, *new_tail = create_worm_tail(wseg_count);
121     register int wnum = worm->wormno;
122
123     /*  if (!wnum) return;  bullet proofing */
124
125     if (new_tail) {
126         wtails[wnum] = new_tail;
127         for (seg = new_tail; seg->nseg; seg = seg->nseg)
128             ;
129         wheads[wnum] = seg;
130     } else {
131         wtails[wnum] = wheads[wnum] = seg = newseg();
132         seg->nseg = (struct wseg *) 0;
133         seg->wx = worm->mx;
134         seg->wy = worm->my;
135     }
136     wgrowtime[wnum] = 0L;
137 }
138
139 /*
140  *  toss_wsegs()
141  *
142  *  Get rid of all worm segments on and following the given pointer curr.
143  *  The display may or may not need to be updated as we free the segments.
144  */
145 STATIC_OVL
146 void
147 toss_wsegs(curr, display_update)
148 register struct wseg *curr;
149 register boolean display_update;
150 {
151     register struct wseg *seg;
152
153     while (curr) {
154         seg = curr->nseg;
155
156         /* remove from level.monsters[][] */
157
158         /* need to check curr->wx for genocided while migrating_mon */
159         if (curr->wx) {
160             remove_monster(curr->wx, curr->wy);
161
162             /* update screen before deallocation */
163             if (display_update)
164                 newsym(curr->wx, curr->wy);
165         }
166
167         /* free memory used by the segment */
168         dealloc_seg(curr);
169         curr = seg;
170     }
171 }
172
173 /*
174  *  shrink_worm()
175  *
176  *  Remove the tail segment of the worm (the starting segment of the list).
177  */
178 STATIC_OVL
179 void
180 shrink_worm(wnum)
181 int wnum; /* worm number */
182 {
183     struct wseg *seg;
184
185     if (wtails[wnum] == wheads[wnum])
186         return; /* no tail */
187
188     seg = wtails[wnum];
189     wtails[wnum] = seg->nseg;
190     seg->nseg = (struct wseg *) 0;
191     toss_wsegs(seg, TRUE);
192 }
193
194 /*
195  *  worm_move()
196  *
197  *  Check for mon->wormno before calling this function!
198  *
199  *  Move the worm.  Maybe grow.
200  */
201 void
202 worm_move(worm)
203 struct monst *worm;
204 {
205     register struct wseg *seg, *new_seg; /* new segment */
206     register int wnum = worm->wormno;    /* worm number */
207
208     /*  if (!wnum) return;  bullet proofing */
209
210     /*
211      *  Place a segment at the old worm head.  The head has already moved.
212      */
213     seg = wheads[wnum];
214     place_worm_seg(worm, seg->wx, seg->wy);
215     newsym(seg->wx, seg->wy); /* display the new segment */
216
217     /*
218      *  Create a new dummy segment head and place it at the end of the list.
219      */
220     new_seg = newseg();
221     new_seg->wx = worm->mx;
222     new_seg->wy = worm->my;
223     new_seg->nseg = (struct wseg *) 0;
224     seg->nseg = new_seg;    /* attach it to the end of the list */
225     wheads[wnum] = new_seg; /* move the end pointer */
226
227     if (wgrowtime[wnum] <= moves) {
228         if (!wgrowtime[wnum])
229             wgrowtime[wnum] = moves + rnd(5);
230         else
231             wgrowtime[wnum] += rn1(15, 3);
232         worm->mhp += 3;
233         if (worm->mhp > MHPMAX)
234             worm->mhp = MHPMAX;
235         if (worm->mhp > worm->mhpmax)
236             worm->mhpmax = worm->mhp;
237     } else
238         /* The worm doesn't grow, so the last segment goes away. */
239         shrink_worm(wnum);
240 }
241
242 /*
243  *  worm_nomove()
244  *
245  *  Check for mon->wormno before calling this function!
246  *
247  *  The worm don't move so it should shrink.
248  */
249 void
250 worm_nomove(worm)
251 register struct monst *worm;
252 {
253     shrink_worm((int) worm->wormno); /* shrink */
254
255     if (worm->mhp > 3)
256         worm->mhp -= 3; /* mhpmax not changed ! */
257     else
258         worm->mhp = 1;
259 }
260
261 /*
262  *  wormgone()
263  *
264  *  Check for mon->wormno before calling this function!
265  *
266  *  Kill a worm tail.
267  */
268 void
269 wormgone(worm)
270 register struct monst *worm;
271 {
272     register int wnum = worm->wormno;
273
274     /*  if (!wnum) return;  bullet proofing */
275
276     worm->wormno = 0;
277
278     /*  This will also remove the real monster (ie 'w') from the its
279      *  position in level.monsters[][].
280      */
281     toss_wsegs(wtails[wnum], TRUE);
282
283     wheads[wnum] = wtails[wnum] = (struct wseg *) 0;
284 }
285
286 /*
287  *  wormhitu()
288  *
289  *  Check for mon->wormno before calling this function!
290  *
291  *  If the hero is near any part of the worm, the worm will try to attack.
292  */
293 void
294 wormhitu(worm)
295 register struct monst *worm;
296 {
297     register int wnum = worm->wormno;
298     register struct wseg *seg;
299
300     /*  if (!wnum) return;  bullet proofing */
301
302     /*  This does not work right now because mattacku() thinks that the head
303      *  is out of range of the player.  We might try to kludge, and bring
304      *  the head within range for a tiny moment, but this needs a bit more
305      *  looking at before we decide to do this.
306      */
307     for (seg = wtails[wnum]; seg; seg = seg->nseg)
308         if (distu(seg->wx, seg->wy) < 3)
309             if (mattacku(worm))
310                 return; /* your passive ability killed the worm */
311 }
312
313 /*  cutworm()
314  *
315  *  Check for mon->wormno before calling this function!
316  *
317  *  When hitting a worm (worm) at position x, y, with a weapon (weap),
318  *  there is a chance that the worm will be cut in half, and a chance
319  *  that both halves will survive.
320  */
321 void
322 cutworm(worm, x, y, cuttier)
323 struct monst *worm;
324 xchar x, y;
325 boolean cuttier; /* hit is by wielded blade or axe or by thrown axe */
326 {
327     register struct wseg *curr, *new_tail;
328     register struct monst *new_worm;
329     int wnum = worm->wormno;
330     int cut_chance, new_wnum;
331
332     if (!wnum)
333         return; /* bullet proofing */
334
335     if (x == worm->mx && y == worm->my)
336         return; /* hit on head */
337
338     /* cutting goes best with a cuttier weapon */
339     cut_chance = rnd(20); /* Normally     1-16 does not cut, 17-20 does, */
340     if (cuttier)
341         cut_chance += 10; /* with a blade 1- 6 does not cut,  7-20 does. */
342
343     if (cut_chance < 17)
344         return; /* not good enough */
345
346     /* Find the segment that was attacked. */
347     curr = wtails[wnum];
348
349     while ((curr->wx != x) || (curr->wy != y)) {
350         curr = curr->nseg;
351         if (!curr) {
352             impossible("cutworm: no segment at (%d,%d)", (int) x, (int) y);
353             return;
354         }
355     }
356
357     /* If this is the tail segment, then the worm just loses it. */
358     if (curr == wtails[wnum]) {
359         shrink_worm(wnum);
360         return;
361     }
362
363     /*
364      *  Split the worm.  The tail for the new worm is the old worm's tail.
365      *  The tail for the old worm is the segment that follows "curr",
366      *  and "curr" becomes the dummy segment under the new head.
367      */
368     new_tail = wtails[wnum];
369     wtails[wnum] = curr->nseg;
370     curr->nseg = (struct wseg *) 0; /* split the worm */
371
372     /*
373      *  At this point, the old worm is correct.  Any new worm will have
374      *  it's head at "curr" and its tail at "new_tail".  The old worm
375      *  must be at least level 3 in order to produce a new worm.
376      */
377     new_worm = 0;
378     new_wnum = (worm->m_lev >= 3 && !rn2(3)) ? get_wormno() : 0;
379     if (new_wnum) {
380         remove_monster(x, y); /* clone_mon puts new head here */
381         /* clone_mon() will fail if enough long worms have been
382            created to have them be marked as extinct or if the hit
383            that cut the current one has dropped it down to 1 HP */
384         new_worm = clone_mon(worm, x, y);
385     }
386
387     /* Sometimes the tail end dies. */
388     if (!new_worm) {
389         place_worm_seg(worm, x, y); /* place the "head" segment back */
390         if (context.mon_moving) {
391             if (canspotmon(worm))
392 #if 0 /*JP:T*/
393                 pline("Part of %s tail has been cut off.",
394                       s_suffix(mon_nam(worm)));
395 #else
396                 pline("%s\82Ì\90K\94ö\82Ì\88ê\95\94\95ª\82ª\90Ø\82è\97\8e\82Æ\82³\82ê\82½\81D",
397                       mon_nam(worm));
398 #endif
399         } else
400 /*JP
401             You("cut part of the tail off of %s.", mon_nam(worm));
402 */
403             You("%s\82Ì\90K\94ö\82Ì\88ê\95\94\95ª\82ð\90Ø\82Á\82½\81D", mon_nam(worm));
404         toss_wsegs(new_tail, TRUE);
405         if (worm->mhp > 1)
406             worm->mhp /= 2;
407         return;
408     }
409
410     new_worm->wormno = new_wnum; /* affix new worm number */
411     new_worm->mcloned = 0;       /* treat second worm as a normal monster */
412
413     /* Devalue the monster level of both halves of the worm.
414        Note: m_lev is always at least 3 in order to get this far. */
415     worm->m_lev = max((unsigned) worm->m_lev - 2, 3);
416     new_worm->m_lev = worm->m_lev;
417
418     /* Calculate the lower-level mhp; use <N>d8 for long worms.
419        Can't use newmonhp() here because it would reset m_lev. */
420     new_worm->mhpmax = new_worm->mhp = d((int) new_worm->m_lev, 8);
421     worm->mhpmax = d((int) worm->m_lev, 8); /* new maxHP for old worm */
422     if (worm->mhpmax < worm->mhp)
423         worm->mhp = worm->mhpmax;
424
425     wtails[new_wnum] = new_tail; /* We've got all the info right now */
426     wheads[new_wnum] = curr;     /* so we can do this faster than    */
427     wgrowtime[new_wnum] = 0L;    /* trying to call initworm().       */
428
429     /* Place the new monster at all the segment locations. */
430     place_wsegs(new_worm, worm);
431
432     if (context.mon_moving)
433 /*JP
434         pline("%s is cut in half.", Monnam(worm));
435 */
436         pline("%s\82Í\90^\82Á\82Õ\82½\82Â\82É\82³\82ê\82½\81D", Monnam(worm));
437     else
438 /*JP
439         You("cut %s in half.", mon_nam(worm));
440 */
441         You("%s\82ð\90^\82Á\82Õ\82½\82Â\82É\82µ\82½\81D", mon_nam(worm));
442 }
443
444 /*
445  *  see_wsegs()
446  *
447  *  Refresh all of the segments of the given worm.  This is only called
448  *  from see_monster() in display.c or when a monster goes minvis.  It
449  *  is located here for modularity.
450  */
451 void
452 see_wsegs(worm)
453 struct monst *worm;
454 {
455     struct wseg *curr = wtails[worm->wormno];
456
457     /*  if (!mtmp->wormno) return;  bullet proofing */
458
459     while (curr != wheads[worm->wormno]) {
460         newsym(curr->wx, curr->wy);
461         curr = curr->nseg;
462     }
463 }
464
465 /*
466  *  detect_wsegs()
467  *
468  *  Display all of the segments of the given worm for detection.
469  */
470 void
471 detect_wsegs(worm, use_detection_glyph)
472 struct monst *worm;
473 boolean use_detection_glyph;
474 {
475     int num;
476     struct wseg *curr = wtails[worm->wormno];
477
478     /*  if (!mtmp->wormno) return;  bullet proofing */
479     int what_tail = what_mon(PM_LONG_WORM_TAIL, newsym_rn2);
480
481     while (curr != wheads[worm->wormno]) {
482         num = use_detection_glyph
483             ? detected_monnum_to_glyph(what_tail)
484             : (worm->mtame
485                ? petnum_to_glyph(what_tail)
486                : monnum_to_glyph(what_tail));
487         show_glyph(curr->wx, curr->wy, num);
488         curr = curr->nseg;
489     }
490 }
491
492 /*
493  *  save_worm()
494  *
495  *  Save the worm information for later use.  The count is the number
496  *  of segments, including the dummy.  Called from save.c.
497  */
498 void
499 save_worm(fd, mode)
500 int fd, mode;
501 {
502     int i;
503     int count;
504     struct wseg *curr, *temp;
505
506     if (perform_bwrite(mode)) {
507         for (i = 1; i < MAX_NUM_WORMS; i++) {
508             for (count = 0, curr = wtails[i]; curr; curr = curr->nseg)
509                 count++;
510             /* Save number of segments */
511             bwrite(fd, (genericptr_t) &count, sizeof(int));
512             /* Save segment locations of the monster. */
513             if (count) {
514                 for (curr = wtails[i]; curr; curr = curr->nseg) {
515                     bwrite(fd, (genericptr_t) & (curr->wx), sizeof(xchar));
516                     bwrite(fd, (genericptr_t) & (curr->wy), sizeof(xchar));
517                 }
518             }
519         }
520         bwrite(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
521     }
522
523     if (release_data(mode)) {
524         /* Free the segments only.  savemonchn() will take care of the
525          * monsters. */
526         for (i = 1; i < MAX_NUM_WORMS; i++) {
527             if (!(curr = wtails[i]))
528                 continue;
529
530             while (curr) {
531                 temp = curr->nseg;
532                 dealloc_seg(curr); /* free the segment */
533                 curr = temp;
534             }
535             wheads[i] = wtails[i] = (struct wseg *) 0;
536         }
537     }
538 }
539
540 /*
541  *  rest_worm()
542  *
543  *  Restore the worm information from the save file.  Called from restore.c
544  */
545 void
546 rest_worm(fd)
547 int fd;
548 {
549     int i, j, count;
550     struct wseg *curr, *temp;
551
552     for (i = 1; i < MAX_NUM_WORMS; i++) {
553         mread(fd, (genericptr_t) &count, sizeof(int));
554         if (!count)
555             continue; /* none */
556
557         /* Get the segments. */
558         for (curr = (struct wseg *) 0, j = 0; j < count; j++) {
559             temp = newseg();
560             temp->nseg = (struct wseg *) 0;
561             mread(fd, (genericptr_t) & (temp->wx), sizeof(xchar));
562             mread(fd, (genericptr_t) & (temp->wy), sizeof(xchar));
563             if (curr)
564                 curr->nseg = temp;
565             else
566                 wtails[i] = temp;
567             curr = temp;
568         }
569         wheads[i] = curr;
570     }
571     mread(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
572 }
573
574 /*
575  *  place_wsegs()
576  *
577  *  Place the segments of the given worm.  Called from restore.c
578  *  If oldworm is not NULL, assumes the oldworm segments are on map
579  *  in the same location as worm segments
580  */
581 void
582 place_wsegs(worm, oldworm)
583 struct monst *worm, *oldworm;
584 {
585     struct wseg *curr = wtails[worm->wormno];
586
587     /*  if (!mtmp->wormno) return;  bullet proofing */
588
589     while (curr != wheads[worm->wormno]) {
590         xchar x = curr->wx;
591         xchar y = curr->wy;
592
593         if (oldworm) {
594             if (m_at(x,y) == oldworm)
595                 remove_monster(x, y);
596             else
597                 impossible("placing worm seg <%i,%i> over another mon", x, y);
598         }
599         place_worm_seg(worm, x, y);
600         curr = curr->nseg;
601     }
602 }
603
604 void
605 sanity_check_worm(worm)
606 struct monst *worm;
607 {
608     struct wseg *curr;
609
610     if (!worm)
611         panic("no worm!");
612     if (!worm->wormno)
613         panic("not a worm?!");
614
615     curr = wtails[worm->wormno];
616
617     while (curr != wheads[worm->wormno]) {
618         if (curr->wx) {
619             if (!isok(curr->wx, curr->wy))
620                 panic("worm seg not isok");
621             if (level.monsters[curr->wx][curr->wy] != worm)
622                 panic("worm not at seg location");
623         }
624         curr = curr->nseg;
625     }
626 }
627
628 /*
629  *  remove_worm()
630  *
631  *  This function is equivalent to the remove_monster #define in
632  *  rm.h, only it will take the worm *and* tail out of the levels array.
633  *  It does not get rid of (dealloc) the worm tail structures, and it does
634  *  not remove the mon from the fmon chain.
635  */
636 void
637 remove_worm(worm)
638 register struct monst *worm;
639 {
640     register struct wseg *curr = wtails[worm->wormno];
641
642     /*  if (!mtmp->wormno) return;  bullet proofing */
643
644     while (curr) {
645         if (curr->wx) {
646             remove_monster(curr->wx, curr->wy);
647             newsym(curr->wx, curr->wy);
648             curr->wx = 0;
649         }
650         curr = curr->nseg;
651     }
652 }
653
654 /*
655  *  place_worm_tail_randomly()
656  *
657  *  Place a worm tail somewhere on a level behind the head.
658  *  This routine essentially reverses the order of the wsegs from head
659  *  to tail while placing them.
660  *  x, and y are most likely the worm->mx, and worm->my, but don't *need* to
661  *  be, if somehow the head is disjoint from the tail.
662  */
663 void
664 place_worm_tail_randomly(worm, x, y)
665 struct monst *worm;
666 xchar x, y;
667 {
668     int wnum = worm->wormno;
669     struct wseg *curr = wtails[wnum];
670     struct wseg *new_tail;
671     register xchar ox = x, oy = y;
672
673     /*  if (!wnum) return;  bullet proofing */
674
675     if (wnum && (!wtails[wnum] || !wheads[wnum])) {
676         impossible("place_worm_tail_randomly: wormno is set without a tail!");
677         return;
678     }
679
680     wheads[wnum] = new_tail = curr;
681     curr = curr->nseg;
682     new_tail->nseg = (struct wseg *) 0;
683     new_tail->wx = x;
684     new_tail->wy = y;
685
686     while (curr) {
687         xchar nx, ny;
688         char tryct = 0;
689
690         /* pick a random direction from x, y and search for goodpos() */
691         do {
692             random_dir(ox, oy, &nx, &ny);
693         } while (!goodpos(nx, ny, worm, 0) && (tryct++ < 50));
694
695         if (tryct < 50) {
696             place_worm_seg(worm, nx, ny);
697             curr->wx = ox = nx;
698             curr->wy = oy = ny;
699             wtails[wnum] = curr;
700             curr = curr->nseg;
701             wtails[wnum]->nseg = new_tail;
702             new_tail = wtails[wnum];
703             newsym(nx, ny);
704         } else {                     /* Oops.  Truncate because there was */
705             toss_wsegs(curr, FALSE); /* no place for the rest of it */
706             curr = (struct wseg *) 0;
707         }
708     }
709 }
710
711 /*
712  * Given a coordinate x, y.
713  * return in *nx, *ny, the coordinates of one of the <= 8 squares adjoining.
714  *
715  * This function, and the loop it serves, could be eliminated by coding
716  * enexto() with a search radius.
717  */
718 STATIC_OVL
719 void
720 random_dir(x, y, nx, ny)
721 xchar x, y;
722 xchar *nx, *ny;
723 {
724     *nx = x + (x > 1                /* extreme left ? */
725                ? (x < COLNO - 1     /* extreme right ? */
726                   ? (rn2(3) - 1)    /* neither so +1, 0, or -1 */
727                   : -rn2(2))        /* right edge, use -1 or 0 */
728                : rn2(2));           /* left edge, use 0 or 1 */
729     if (*nx != x) /* if x has changed, do same thing with y */
730         *ny = y + (y > 0             /* y==0 is ok (x==0 is not) */
731                    ? (y < ROWNO - 1
732                       ? (rn2(3) - 1)
733                       : -rn2(2))
734                    : rn2(2));
735     else /* when x has remained the same, force y to change */
736         *ny = y + (y > 0
737                    ? (y < ROWNO - 1
738                       ? (rn2(2) ? 1 : -1)   /* not at edge, so +1 or -1 */
739                       : -1)                 /* bottom, use -1 */
740                    : 1);                    /* top, use +1 */
741 }
742
743 /* for size_monst(cmd.c) to support #stats */
744 int
745 size_wseg(worm)
746 struct monst *worm;
747 {
748     return (int) (count_wsegs(worm) * sizeof (struct wseg));
749 }
750
751 /*  count_wsegs()
752  *  returns the number of segments that a worm has.
753  */
754 int
755 count_wsegs(mtmp)
756 struct monst *mtmp;
757 {
758     register int i = 0;
759     register struct wseg *curr;
760
761     if (mtmp->wormno) {
762         for (curr = wtails[mtmp->wormno]->nseg; curr; curr = curr->nseg)
763             i++;
764     }
765     return i;
766 }
767
768 /*  create_worm_tail()
769  *  will create a worm tail chain of (num_segs + 1) and return pointer to it.
770  */
771 STATIC_OVL
772 struct wseg *
773 create_worm_tail(num_segs)
774 int num_segs;
775 {
776     register int i = 0;
777     register struct wseg *new_tail, *curr;
778
779     if (!num_segs)
780         return (struct wseg *) 0;
781
782     new_tail = curr = newseg();
783     curr->nseg = (struct wseg *) 0;
784     curr->wx = 0;
785     curr->wy = 0;
786
787     while (i < num_segs) {
788         curr->nseg = newseg();
789         curr = curr->nseg;
790         curr->nseg = (struct wseg *) 0;
791         curr->wx = 0;
792         curr->wy = 0;
793         i++;
794     }
795
796     return new_tail;
797 }
798
799 /*  worm_known()
800  *  Is any segment of this worm in viewing range?  Note: caller must check
801  *  invisibility and telepathy (which should only show the head anyway).
802  *  Mostly used in the canseemon() macro.
803  */
804 boolean
805 worm_known(worm)
806 struct monst *worm;
807 {
808     struct wseg *curr = wtails[worm->wormno];
809
810     while (curr) {
811         if (cansee(curr->wx, curr->wy))
812             return TRUE;
813         curr = curr->nseg;
814     }
815     return FALSE;
816 }
817
818 /* would moving from <x1,y1> to <x2,y2> involve passing between two
819    consecutive segments of the same worm? */
820 boolean
821 worm_cross(x1, y1, x2, y2)
822 int x1, y1, x2, y2;
823 {
824     struct monst *worm;
825     struct wseg *curr, *wnxt;
826
827     /*
828      * With digits representing relative sequence number of the segments,
829      * returns true when testing between @ and ? (passes through worm's
830      * body), false between @ and ! (stays on same side of worm).
831      *  .w1?..
832      *  ..@2..
833      *  .65!3.
834      *  ...4..
835      */
836
837     if (distmin(x1, y1, x2, y2) != 1) {
838         impossible("worm_cross checking for non-adjacent location?");
839         return FALSE;
840     }
841     /* attempting to pass between worm segs is only relevant for diagonal */
842     if (x1 == x2 || y1 == y2)
843         return FALSE;
844
845     /* is the same monster at <x1,y2> and at <x2,y1>? */
846     worm = m_at(x1, y2);
847     if (!worm || m_at(x2, y1) != worm)
848         return FALSE;
849
850     /* same monster is at both adjacent spots, so must be a worm; we need
851        to figure out if the two spots are occupied by consecutive segments */
852     for (curr = wtails[worm->wormno]; curr; curr = wnxt) {
853         wnxt = curr->nseg;
854         if (!wnxt)
855             break; /* no next segment; can't continue */
856
857         /* we don't know which of <x1,y2> or <x2,y1> we'll hit first, but
858            whichever it is, they're consecutive iff next seg is the other */
859         if (curr->wx == x1 && curr->wy == y2)
860             return (boolean) (wnxt->wx == x2 && wnxt->wy == y1);
861         if (curr->wx == x2 && curr->wy == y1)
862             return (boolean) (wnxt->wx == x1 && wnxt->wy == y2);
863     }
864     /* should never reach here... */
865     return FALSE;
866 }
867
868 /* construct an index number for a worm tail segment */
869 int
870 wseg_at(worm, x, y)
871 struct monst *worm;
872 int x, y;
873 {
874     int res = 0;
875
876     if (worm && worm->wormno && m_at(x, y) == worm) {
877         struct wseg *curr;
878         int i, n;
879         xchar wx = (xchar) x, wy = (xchar) y;
880
881         for (i = 0, curr = wtails[worm->wormno]; curr; curr = curr->nseg) {
882             if (curr->wx == wx && curr->wy == wy)
883                 break;
884             ++i;
885         }
886         for (n = i; curr; curr = curr->nseg)
887             ++n;
888         res = n - i;
889     }
890     return res;
891 }
892
893 /*worm.c*/