Wikihack
Advertisement

Below is the full text to src/worm.c from NetHack 3.4.3. To link to a particular line, write [[worm.c#line123]], for example.

Top of file[]

1.    /*	SCCS Id: @(#)worm.c	3.4	1995/01/28	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
5.    #include "hack.h"
6.    #include "lev.h"
7.    
8.    #define newseg()		(struct wseg *) alloc(sizeof(struct wseg))
9.    #define dealloc_seg(wseg)	free((genericptr_t) (wseg))
10.   
11.   /* worm segment structure */
12.   struct wseg {
13.       struct wseg *nseg;
14.       xchar  wx, wy;	/* the segment's position */
15.   };
16.   
17.   STATIC_DCL void FDECL(toss_wsegs, (struct wseg *,BOOLEAN_P));
18.   STATIC_DCL void FDECL(shrink_worm, (int));
19.   STATIC_DCL void FDECL(random_dir, (XCHAR_P,XCHAR_P,xchar *,xchar *));
20.   STATIC_DCL struct wseg *FDECL(create_worm_tail, (int));
21.   
22.   /*  Description of long worm implementation.
23.    *
24.    *  Each monst struct of the head of a tailed worm has a wormno set to
25.    *			1 <= wormno < MAX_NUM_WORMS
26.    *  If wormno == 0 this does not mean that the monster is not a worm,
27.    *  it just means that the monster does not have a long worm tail.
28.    *
29.    *  The actual segments of a worm are not full blown monst structs.
30.    *  They are small wseg structs, and their position in the levels.monsters[][]
31.    *  array is held by the monst struct of the head of the worm.  This makes
32.    *  things like probing and hit point bookkeeping much easier.
33.    *
34.    *  The segments of the long worms on a level are kept as an array of
35.    *  singly threaded linked lists.  The wormno variable is used as an index
36.    *  for these segment arrays.
37.    *
38.    *  wtails:	The first (starting struct) of a linked list.  This points
39.    *		to the tail (last) segment of the worm.
40.    *
41.    *  wheads:	The last (end) of a linked list of segments.  This points to
42.    *		the segment that is at the same position as the real monster
43.    *		(the head).  Note that the segment that wheads[wormno] points
44.    *		to, is not displayed.  It is simply there to keep track of
45.    *		where the head came from, so that worm movement and display are
46.    *		simplified later.
47.    *		Keeping the head segment of the worm at the end of the list
48.    *		of tail segments is an endless source of confusion, but it is
49.    *		necessary.
50.    *		From now on, we will use "start" and "end" to refer to the
51.    *		linked list and "head" and "tail" to refer to the worm.
52.    *
53.    *  One final worm array is:
54.    *
55.    *  wgrowtime:	This tells us when to add another segment to the worm.
56.    *
57.    *  When a worm is moved, we add a new segment at the head, and delete the
58.    *  segment at the tail (unless we want it to grow).  This new head segment is
59.    *  located in the same square as the actual head of the worm.  If we want
60.    *  to grow the worm, we don't delete the tail segment, and we give the worm
61.    *  extra hit points, which possibly go into its maximum.
62.    *
63.    *  Non-moving worms (worm_nomove) are assumed to be surrounded by their own
64.    *  tail, and, thus, shrink instead of grow (as their tails keep going while
65.    *  their heads are stopped short).  In this case, we delete the last tail
66.    *  segment, and remove hit points from the worm.
67.    */
68.   
69.   struct wseg *wheads[MAX_NUM_WORMS]   = DUMMY, *wtails[MAX_NUM_WORMS] = DUMMY;
70.   long	    wgrowtime[MAX_NUM_WORMS] = DUMMY;
71.   

get_wormno[]

72.   /*
73.    *  get_wormno()
74.    *
75.    *  Find an unused worm tail slot and return the index.  A zero means that
76.    *  there are no slots available.  This means that the worm head can exist,
77.    *  it just cannot ever grow a tail.
78.    *
79.    *  It, also, means that there is an optimisation to made.  The [0] positions
80.    *  of the arrays are never used.  Meaning, we really *could* have one more
81.    *  tailed worm on the level, or use a smaller array (using wormno - 1).
82.    *
83.    *  Implementation is left to the interested hacker.
84.    */
85.   int
86.   get_wormno()
87.   {
88.       register int new_wormno = 1;
89.   
90.       while (new_wormno < MAX_NUM_WORMS) {
91.   	if (!wheads[new_wormno])
92.   	    return new_wormno; /* found an empty wtails[] slot at new_wormno */
93.   	new_wormno++;
94.       }
95.   
96.       return(0);	/* level infested with worms */
97.   }
98.   

initworm[]

99.   /*
100.   *  initworm()
101.   *
102.   *  Use if (mon->wormno = get_wormno()) before calling this function!
103.   *
104.   *  Initialize the worm entry.  This will set up the worm grow time, and
105.   *  create and initialize the dummy segment for wheads[] and wtails[].
106.   *
107.   *  If the worm has no tail (ie get_wormno() fails) then this function need
108.   *  not be called.
109.   */
110.  void
111.  initworm(worm, wseg_count)
112.      struct monst *worm;
113.      int wseg_count;
114.  {
115.      register struct wseg *seg, *new_tail = create_worm_tail(wseg_count);
116.      register int wnum = worm->wormno;
117.  
118.  /*  if (!wnum) return;  bullet proofing */
119.  
120.      if (new_tail) {
121.  	wtails[wnum] = new_tail;
122.  	for (seg = new_tail; seg->nseg; seg = seg->nseg);
123.  	wheads[wnum] = seg;
124.      } else {
125.  	wtails[wnum] = wheads[wnum] = seg = newseg();
126.  	seg->nseg    = (struct wseg *) 0;
127.  	seg->wx      = worm->mx;
128.  	seg->wy      = worm->my;
129.      }
130.      wgrowtime[wnum] = 0L;
131.  }
132.  
133.  

toss_wsegs[]

134.  /*
135.   *  toss_wsegs()
136.   *
137.   *  Get rid of all worm segments on and following the given pointer curr.
138.   *  The display may or may not need to be updated as we free the segments.
139.   */
140.  STATIC_OVL
141.  void
142.  toss_wsegs(curr, display_update)
143.      register struct wseg *curr;
144.      register boolean display_update;
145.  {
146.      register struct wseg *seg;
147.  
148.      while (curr) {
149.  	seg = curr->nseg;
150.  
151.  	/* remove from level.monsters[][] */
152.  
153.  	/* need to check curr->wx for genocided while migrating_mon */
154.  	if (curr->wx) {
155.  	    remove_monster(curr->wx, curr->wy);
156.  
157.  	    /* update screen before deallocation */
158.  	    if (display_update) newsym(curr->wx,curr->wy);
159.  	}
160.  
161.  	/* free memory used by the segment */
162.  	dealloc_seg(curr);
163.  	curr = seg;
164.      }
165.  }
166.  
167.  

shrink_worm[]

168.  /*
169.   *  shrink_worm()
170.   *
171.   *  Remove the tail segment of the worm (the starting segment of the list).
172.   */
173.  STATIC_OVL
174.  void
175.  shrink_worm(wnum)
176.      int wnum;	/* worm number */
177.  {
178.      struct wseg *seg;
179.  
180.      if (wtails[wnum] == wheads[wnum]) return;	/* no tail */
181.  
182.      seg = wtails[wnum];
183.      wtails[wnum] = seg->nseg;
184.      seg->nseg = (struct wseg *) 0;
185.      toss_wsegs(seg, TRUE);
186.  }
187.  /*Hack*/

worm_move[]

188.  /*
189.   *  worm_move()
190.   *
191.   *  Check for mon->wormno before calling this function!
192.   *
193.   *  Move the worm.  Maybe grow.
194.   */
195.  void
196.  worm_move(worm)
197.      struct monst *worm;
198.  {
199.      register struct wseg *seg, *new_seg;	/* new segment */
200.      register int	 wnum = worm->wormno;	/* worm number */
201.  
202.  
203.  /*  if (!wnum) return;  bullet proofing */
204.  
205.      /*
206.       *  Place a segment at the old worm head.  The head has already moved.
207.       */
208.      seg = wheads[wnum];
209.      place_worm_seg(worm, seg->wx, seg->wy);
210.      newsym(seg->wx,seg->wy);		/* display the new segment */
211.  
212.      /*
213.       *  Create a new dummy segment head and place it at the end of the list.
214.       */
215.      new_seg       = newseg();
216.      new_seg->wx   = worm->mx;
217.      new_seg->wy   = worm->my;
218.      new_seg->nseg = (struct wseg *) 0;
219.      seg->nseg     = new_seg;		/* attach it to the end of the list */
220.      wheads[wnum]  = new_seg;		/* move the end pointer */
221.  
222.  
223.      if (wgrowtime[wnum] <= moves) {
224.  	if (!wgrowtime[wnum])
225.  	    wgrowtime[wnum] = moves + rnd(5);
226.  	else
227.  	    wgrowtime[wnum] += rn1(15, 3);
228.  	worm->mhp += 3;
229.  	if (worm->mhp > MHPMAX) worm->mhp = MHPMAX;
230.  	if (worm->mhp > worm->mhpmax) worm->mhpmax = worm->mhp;
231.      } else
232.  	/* The worm doesn't grow, so the last segment goes away. */
233.  	shrink_worm(wnum);
234.  }
235.  

worm_nomove[]

236.  /*
237.   *  worm_nomove()
238.   *
239.   *  Check for mon->wormno before calling this function!
240.   *
241.   *  The worm don't move so it should shrink.
242.   */
243.  void
244.  worm_nomove(worm)
245.      register struct monst *worm;
246.  {
247.      shrink_worm((int) worm->wormno);	/* shrink */
248.  
249.      if (worm->mhp > 3)
250.  	worm->mhp -= 3;		/* mhpmax not changed ! */
251.      else
252.  	worm->mhp = 1;
253.  }
254.  

wormgone[]

255.  /*
256.   *  wormgone()
257.   *
258.   *  Check for mon->wormno before calling this function!
259.   *
260.   *  Kill a worm tail.
261.   */
262.  void
263.  wormgone(worm)
264.      register struct monst *worm;
265.  {
266.      register int wnum = worm->wormno;
267.  
268.  /*  if (!wnum) return;  bullet proofing */
269.  
270.      worm->wormno = 0;
271.  
272.      /*  This will also remove the real monster (ie 'w') from the its
273.       *  position in level.monsters[][].
274.       */
275.      toss_wsegs(wtails[wnum], TRUE);
276.  
277.      wheads[wnum] = wtails[wnum] = (struct wseg *) 0;
278.  }
279.  

wormhitu[]

280.  /*
281.   *  wormhitu()
282.   *
283.   *  Check for mon->wormno before calling this function!
284.   *
285.   *  If the hero is near any part of the worm, the worm will try to attack.
286.   */
287.  void
288.  wormhitu(worm)
289.      register struct monst *worm;
290.  {
291.      register int wnum = worm->wormno;
292.      register struct wseg *seg;
293.  
294.  /*  if (!wnum) return;  bullet proofing */
295.  
296.  /*  This does not work right now because mattacku() thinks that the head is
297.   *  out of range of the player.  We might try to kludge, and bring the head
298.   *  within range for a tiny moment, but this needs a bit more looking at
299.   *  before we decide to do this.
300.   */
301.      for (seg = wtails[wnum]; seg; seg = seg->nseg)
302.  	if (distu(seg->wx, seg->wy) < 3)
303.  	    (void) mattacku(worm);
304.  }
305.  

cutworm[]

306.  /*  cutworm()
307.   *
308.   *  Check for mon->wormno before calling this function!
309.   *
310.   *  When hitting a worm (worm) at position x, y, with a weapon (weap),
311.   *  there is a chance that the worm will be cut in half, and a chance
312.   *  that both halves will survive.
313.   */
314.  void
315.  cutworm(worm, x, y, weap)
316.      struct monst *worm;
317.      xchar x,y;
318.      struct obj *weap;
319.  {
320.      register struct wseg  *curr, *new_tail;
321.      register struct monst *new_worm;
322.      int wnum = worm->wormno;
323.      int cut_chance, new_wnum;
324.  
325.      if (!wnum) return; /* bullet proofing */
326.  
327.      if (x == worm->mx && y == worm->my) return;		/* hit on head */
328.  
329.      /* cutting goes best with a bladed weapon */
330.      cut_chance = rnd(20);	/* Normally  1-16 does not cut */
331.  				/* Normally 17-20 does */
332.  
333.      if (weap && is_blade(weap))	/* With a blade 1- 6 does not cut */
334.  	cut_chance += 10;	/*		7-20 does */
335.  
336.      if (cut_chance < 17) return;	/* not good enough */
337.  
338.      /* Find the segment that was attacked. */
339.      curr = wtails[wnum];
340.  
341.      while ( (curr->wx != x) || (curr->wy != y) ) {
342.  	curr = curr->nseg;
343.  	if (!curr) {
344.  	    impossible("cutworm: no segment at (%d,%d)", (int) x, (int) y);
345.  	    return;
346.  	}
347.      }
348.  
349.      /* If this is the tail segment, then the worm just loses it. */
350.      if (curr == wtails[wnum]) {
351.  	shrink_worm(wnum);
352.  	return;
353.      }
354.  
355.      /*
356.       *  Split the worm.  The tail for the new worm is the old worm's tail.
357.       *  The tail for the old worm is the segment that follows "curr",
358.       *  and "curr" becomes the dummy segment under the new head.
359.       */
360.      new_tail = wtails[wnum];
361.      wtails[wnum] = curr->nseg;
362.      curr->nseg = (struct wseg *) 0;	/* split the worm */
363.  
364.      /*
365.       *  At this point, the old worm is correct.  Any new worm will have
366.       *  it's head at "curr" and its tail at "new_tail".
367.       */
368.  
369.      /* Sometimes the tail end dies. */
370.      if (rn2(3) || !(new_wnum = get_wormno())) {
371.  	if (flags.mon_moving)
372.  	    pline("Part of the tail of %s is cut off.", mon_nam(worm));
373.  	else
374.  	    You("cut part of the tail off of %s.", mon_nam(worm));
375.  	toss_wsegs(new_tail, TRUE);
376.  	if (worm->mhp > 1) worm->mhp /= 2;
377.  	return;
378.      }
379.  
380.      remove_monster(x, y);		/* clone_mon puts new head here */
381.      new_worm = clone_mon(worm, x, y);
382.      new_worm->wormno = new_wnum;	/* affix new worm number */
383.  
384.      /* Devalue the monster level of both halves of the worm. */
385.      worm->m_lev = ((unsigned)worm->m_lev <= 3) ?
386.  		   (unsigned)worm->m_lev : max((unsigned)worm->m_lev - 2, 3);
387.      new_worm->m_lev = worm->m_lev;
388.  
389.      /* Calculate the mhp on the new_worm for the (lower) monster level. */
390.      new_worm->mhpmax = new_worm->mhp = d((int)new_worm->m_lev, 8);
391.  
392.      /* Calculate the mhp on the old worm for the (lower) monster level. */
393.      if (worm->m_lev > 3) {
394.  	worm->mhpmax = d((int)worm->m_lev, 8);
395.  	if (worm->mhpmax < worm->mhp) worm->mhp = worm->mhpmax;
396.      }
397.  
398.      wtails[new_wnum] = new_tail;	/* We've got all the info right now */
399.      wheads[new_wnum] = curr;		/* so we can do this faster than    */
400.      wgrowtime[new_wnum] = 0L;		/* trying to call initworm().       */
401.  
402.      /* Place the new monster at all the segment locations. */
403.      place_wsegs(new_worm);
404.  
405.      if (flags.mon_moving)
406.  	pline("%s is cut in half.", Monnam(worm));
407.      else
408.  	You("cut %s in half.", mon_nam(worm));
409.  }
410.  
411.  

see_wsegs[]

412.  /*
413.   *  see_wsegs()
414.   *
415.   *  Refresh all of the segments of the given worm.  This is only called
416.   *  from see_monster() in display.c or when a monster goes minvis.  It
417.   *  is located here for modularity.
418.   */
419.  void
420.  see_wsegs(worm)
421.      struct monst *worm;
422.  {
423.      struct wseg *curr = wtails[worm->wormno];
424.  
425.  /*  if (!mtmp->wormno) return;  bullet proofing */
426.  
427.      while (curr != wheads[worm->wormno]) {
428.  	newsym(curr->wx,curr->wy);
429.  	curr = curr->nseg;
430.      }
431.  }
432.  

detect_wsegs[]

433.  /*
434.   *  detect_wsegs()
435.   *
436.   *  Display all of the segments of the given worm for detection.
437.   */
438.  void
439.  detect_wsegs(worm, use_detection_glyph)
440.      struct monst *worm;
441.      boolean use_detection_glyph;
442.  {
443.      int num;
444.      struct wseg *curr = wtails[worm->wormno];
445.  
446.  /*  if (!mtmp->wormno) return;  bullet proofing */
447.  
448.      while (curr != wheads[worm->wormno]) {
449.  	num = use_detection_glyph ?
450.  		detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)) :
451.  		monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL));
452.  	show_glyph(curr->wx,curr->wy,num);
453.  	curr = curr->nseg;
454.      }
455.  }
456.  
457.  

save_worm[]

458.  /*
459.   *  save_worm()
460.   *
461.   *  Save the worm information for later use.  The count is the number
462.   *  of segments, including the dummy.  Called from save.c.
463.   */
464.  void
465.  save_worm(fd, mode)
466.      int fd, mode;
467.  {
468.      int i;
469.      int count;
470.      struct wseg *curr, *temp;
471.  
472.      if (perform_bwrite(mode)) {
473.  	for (i = 1; i < MAX_NUM_WORMS; i++) {
474.  	    for (count = 0, curr = wtails[i]; curr; curr = curr->nseg) count++;
475.  	    /* Save number of segments */
476.  	    bwrite(fd, (genericptr_t) &count, sizeof(int));
477.  	    /* Save segment locations of the monster. */
478.  	    if (count) {
479.  		for (curr = wtails[i]; curr; curr = curr->nseg) {
480.  		    bwrite(fd, (genericptr_t) &(curr->wx), sizeof(xchar));
481.  		    bwrite(fd, (genericptr_t) &(curr->wy), sizeof(xchar));
482.  		}
483.  	    }
484.  	}
485.  	bwrite(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
486.      }
487.  
488.      if (release_data(mode)) {
489.  	/* Free the segments only.  savemonchn() will take care of the
490.  	 * monsters. */
491.  	for (i = 1; i < MAX_NUM_WORMS; i++) {
492.  	    if (!(curr = wtails[i])) continue;
493.  
494.  	    while (curr) {
495.  		temp = curr->nseg;
496.  		dealloc_seg(curr);		/* free the segment */
497.  		curr = temp;
498.  	    }
499.  	    wheads[i] = wtails[i] = (struct wseg *) 0;
500.  	}
501.      }
502.  
503.  }
504.  

rest_worm[]

505.  /*
506.   *  rest_worm()
507.   *
508.   *  Restore the worm information from the save file.  Called from restore.c
509.   */
510.  void
511.  rest_worm(fd)
512.      int fd;
513.  {
514.      int i, j, count;
515.      struct wseg *curr, *temp;
516.  
517.      for (i = 1; i < MAX_NUM_WORMS; i++) {
518.  	mread(fd, (genericptr_t) &count, sizeof(int));
519.  	if (!count) continue;	/* none */
520.  
521.  	/* Get the segments. */
522.  	for (curr = (struct wseg *) 0, j = 0; j < count; j++) {
523.  	    temp = newseg();
524.  	    temp->nseg = (struct wseg *) 0;
525.  	    mread(fd, (genericptr_t) &(temp->wx), sizeof(xchar));
526.  	    mread(fd, (genericptr_t) &(temp->wy), sizeof(xchar));
527.  	    if (curr)
528.  		curr->nseg = temp;
529.  	    else
530.  		wtails[i] = temp;
531.  	    curr = temp;
532.  	}
533.  	wheads[i] = curr;
534.      }
535.      mread(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
536.  }
537.  

place_wsegs[]

538.  /*
539.   *  place_wsegs()
540.   *
541.   *  Place the segments of the given worm.  Called from restore.c
542.   */
543.  void
544.  place_wsegs(worm)
545.      struct monst *worm;
546.  {
547.      struct wseg *curr = wtails[worm->wormno];
548.  
549.  /*  if (!mtmp->wormno) return;  bullet proofing */
550.  
551.      while (curr != wheads[worm->wormno]) {
552.  	place_worm_seg(worm,curr->wx,curr->wy);
553.  	curr = curr->nseg;
554.      }
555.  }
556.  

remove_worm[]

557.  /*
558.   *  remove_worm()
559.   *
560.   *  This function is equivalent to the remove_monster #define in
561.   *  rm.h, only it will take the worm *and* tail out of the levels array.
562.   *  It does not get rid of (dealloc) the worm tail structures, and it does
563.   *  not remove the mon from the fmon chain.
564.   */
565.  void
566.  remove_worm(worm)
567.      register struct monst *worm;
568.  {
569.      register struct wseg *curr = wtails[worm->wormno];
570.  
571.  /*  if (!mtmp->wormno) return;  bullet proofing */
572.  
573.      while (curr) {
574.  	remove_monster(curr->wx, curr->wy);
575.  	newsym(curr->wx, curr->wy);
576.  	curr = curr->nseg;
577.      }
578.  }
579.  

place_worm_tail_randomly[]

580.  /*
581.   *  place_worm_tail_randomly()
582.   *
583.   *  Place a worm tail somewhere on a level behind the head.
584.   *  This routine essentially reverses the order of the wsegs from head
585.   *  to tail while placing them.
586.   *  x, and y are most likely the worm->mx, and worm->my, but don't *need* to
587.   *  be, if somehow the head is disjoint from the tail.
588.   */
589.  void
590.  place_worm_tail_randomly(worm, x, y)
591.      struct monst *worm;
592.      xchar x, y;
593.  {
594.      int wnum = worm->wormno;
595.      struct wseg *curr = wtails[wnum];
596.      struct wseg *new_tail;
597.      register xchar ox = x, oy = y;
598.  
599.  /*  if (!wnum) return;  bullet proofing */
600.  
601.      if (wnum && (!wtails[wnum] || !wheads[wnum]) ) {
602.  	impossible("place_worm_tail_randomly: wormno is set without a tail!");
603.  	return;
604.      }
605.  
606.      wheads[wnum] = new_tail = curr;
607.      curr = curr->nseg;
608.      new_tail->nseg = (struct wseg *) 0;
609.      new_tail->wx = x;
610.      new_tail->wy = y;
611.  
612.      while(curr)  {
613.  	xchar nx, ny;
614.  	char tryct = 0;
615.  
616.  	/* pick a random direction from x, y and search for goodpos() */
617.  
618.  	do {
619.  	    random_dir(ox, oy, &nx, &ny);
620.  	} while (!goodpos(nx, ny, worm, 0) && (tryct++ < 50));
621.  
622.  	if (tryct < 50)  {
623.  	    place_worm_seg(worm, nx, ny);
624.  	    curr->wx = ox = nx;
625.  	    curr->wy = oy = ny;
626.  	    wtails[wnum] = curr;
627.  	    curr = curr->nseg;
628.  	    wtails[wnum]->nseg = new_tail;
629.  	    new_tail = wtails[wnum];
630.  	    newsym(nx, ny);
631.  	} else {			/* Oops.  Truncate because there was */
632.  	    toss_wsegs(curr, FALSE);    /* no place for the rest of it */
633.  	    curr = (struct wseg *) 0;
634.  	}
635.      }
636.  }
637.  

random_dir[]

638.  /*
639.   * Given a coordinate x, y.
640.   * return in *nx, *ny, the coordinates of one of the <= 8 squares adjoining.
641.   *
642.   * This function, and the loop it serves, could be eliminated by coding
643.   * enexto() with a search radius.
644.   */
645.  STATIC_OVL
646.  void
647.  random_dir(x, y, nx, ny)
648.      register xchar   x,   y;
649.      register xchar *nx, *ny;
650.  {
651.      *nx = x;
652.      *ny = y;
653.  
654.      *nx += (x > 1 ?			/* extreme left ? */
655.  		(x < COLNO ?		 /* extreme right ? */
656.  			(rn2(3) - 1)	  /* neither so +1, 0, or -1 */
657.  		:	-rn2(2))	 /* 0, or -1 */
658.  	   :	rn2(2));		/* 0, or 1 */
659.  
660.      *ny += (*nx == x ?			/* same kind of thing with y */
661.  		(y > 1 ?
662.  		    (y < ROWNO ?
663.  			(rn2(2) ?
664.  			    1
665.  			:   -1)
666.  		    :	-1)
667.  		:   1)
668.  	    :	(y > 1 ?
669.  		    (y < ROWNO ?
670.  			(rn2(3) - 1)
671.  		    :	-rn2(2))
672.  		:   rn2(2)));
673.  }
674.  

count_wsegs[]

675.  /*  count_wsegs()
676.   *
677.   *  returns
678.   *  the number of visible segments that a worm has.
679.   */
680.  
681.  int
682.  count_wsegs(mtmp)
683.      struct monst *mtmp;
684.  {
685.      register int i=0;
686.      register struct wseg *curr = (wtails[mtmp->wormno])->nseg;
687.  
688.  /*  if (!mtmp->wormno) return 0;  bullet proofing */
689.  
690.      while (curr) {
691.  	i++;
692.  	curr = curr->nseg;
693.      }
694.  
695.      return i;
696.  }
697.  

create_worm_tail[]

698.  /*  create_worm_tail()
699.   *
700.   *  will create a worm tail chain of (num_segs + 1) and return a pointer to it.
701.   */
702.  STATIC_OVL
703.  struct wseg *
704.  create_worm_tail(num_segs)
705.      int num_segs;
706.  {
707.      register int i=0;
708.      register struct wseg *new_tail, *curr;
709.  
710.      if (!num_segs) return (struct wseg *)0;
711.  
712.      new_tail = curr = newseg();
713.      curr->nseg = (struct wseg *)0;
714.      curr->wx = 0;
715.      curr->wy = 0;
716.  
717.      while (i < num_segs) {
718.  	curr->nseg = newseg();
719.  	curr = curr->nseg;
720.  	curr->nseg = (struct wseg *)0;
721.  	curr->wx = 0;
722.  	curr->wy = 0;
723.  	i++;
724.      }
725.  
726.      return (new_tail);
727.  }
728.  

worm_known[]

729.  /*  worm_known()
730.   *
731.   *  Is any segment of this worm in viewing range?  Note: caller must check
732.   *  invisibility and telepathy (which should only show the head anyway).
733.   *  Mostly used in the canseemon() macro.
734.   */
735.  boolean
736.  worm_known(worm)
737.  struct monst *worm;
738.  {
739.      struct wseg *curr = wtails[worm->wormno];
740.  
741.      while (curr) {
742.  	if(cansee(curr->wx,curr->wy)) return TRUE;
743.  	curr = curr->nseg;
744.      }
745.      return FALSE;
746.  }
747.  
748.  /*worm.c*/
Advertisement