FANDOM


Below is the full text to worm.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/worm.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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.    
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.   
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.   
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.  
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.  
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.  
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.  
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.  
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.  
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.  
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.   *  [ALI] Return true if worm is cut.
315.   */
316.  int
317.  cutworm(worm, x, y, weap)
318.      struct monst *worm;
319.      xchar x,y;
320.      struct obj *weap;
321.  {
322.      register struct wseg  *curr, *new_tail;
323.      register struct monst *new_worm;
324.      int wnum = worm->wormno;
325.      int cut_chance, new_wnum;
326.  
327.      if (!wnum) return 0; /* bullet proofing */
328.  
329.      if (x == worm->mx && y == worm->my) return 0;	/* hit on head */
330.  
331.      /* cutting goes best with a bladed weapon */
332.      cut_chance = rnd(20);	/* Normally  1-16 does not cut */
333.  				/* Normally 17-20 does */
334.  
335.      if (weap && is_blade(weap))	/* With a blade 1- 6 does not cut */
336.  	cut_chance += 10;	/*		7-20 does */
337.  
338.      if (cut_chance < 17) return 0;	/* not good enough */
339.  
340.      /* Find the segment that was attacked. */
341.      curr = wtails[wnum];
342.  
343.      while ( (curr->wx != x) || (curr->wy != y) ) {
344.  	curr = curr->nseg;
345.  	if (!curr) {
346.  	    impossible("cutworm:  no segment at (%d,%d)", (int) x, (int) y);
347.  	    return 0;
348.  	}
349.      }
350.  
351.      /* If this is the tail segment, then the worm just loses it. */
352.      if (curr == wtails[wnum]) {
353.  	shrink_worm(wnum);
354.  	return 1;
355.      }
356.  
357.      /*
358.       *  Split the worm.  The tail for the new worm is the old worm's tail.
359.       *  The tail for the old worm is the segment that follows "curr",
360.       *  and "curr" becomes the dummy segment under the new head.
361.       */
362.      new_tail = wtails[wnum];
363.      wtails[wnum] = curr->nseg;
364.      curr->nseg = (struct wseg *) 0;	/* split the worm */
365.  
366.      /*
367.       *  At this point, the old worm is correct.  Any new worm will have
368.       *  it's head at "curr" and its tail at "new_tail".
369.       */
370.  
371.      /* Sometimes the tail end dies. */
372.      if (rn2(3) || !(new_wnum = get_wormno())) {
373.  	if (flags.mon_moving)
374.  	    pline("Part of the tail of %s is cut off.", mon_nam(worm));
375.  	else
376.  	    You("cut part of the tail off of %s.", mon_nam(worm));
377.  	toss_wsegs(new_tail, TRUE);
378.  	if (worm->mhp > 1) worm->mhp /= 2;
379.  	return 1;
380.      }
381.  
382.      remove_monster(x, y);		/* clone_mon puts new head here */
383.      new_worm = clone_mon(worm, x, y);
384.      new_worm->wormno = new_wnum;	/* affix new worm number */
385.  
386.      /* Devalue the monster level of both halves of the worm. */
387.      worm->m_lev = ((unsigned)worm->m_lev <= 3) ?
388.  		   (unsigned)worm->m_lev : max((unsigned)worm->m_lev - 2, 3);
389.      new_worm->m_lev = worm->m_lev;
390.  
391.      /* Calculate the mhp on the new_worm for the (lower) monster level. */
392.      new_worm->mhpmax = new_worm->mhp = d((int)new_worm->m_lev, 8);
393.  
394.      /* Calculate the mhp on the old worm for the (lower) monster level. */
395.      if (worm->m_lev > 3) {
396.  	worm->mhpmax = d((int)worm->m_lev, 8);
397.  	if (worm->mhpmax < worm->mhp) worm->mhp = worm->mhpmax;
398.      }
399.  
400.      wtails[new_wnum] = new_tail;	/* We've got all the info right now */
401.      wheads[new_wnum] = curr;		/* so we can do this faster than    */
402.      wgrowtime[new_wnum] = 0L;		/* trying to call initworm().       */
403.  
404.      /* Place the new monster at all the segment locations. */
405.      place_wsegs(new_worm);
406.  
407.      if (flags.mon_moving)
408.  	pline("%s is cut in half.", Monnam(worm));
409.      else
410.  	You("cut %s in half.", mon_nam(worm));
411.  
412.      return 1;
413.  }
414.  
415.  
416.  /*
417.   *  see_wsegs()
418.   *
419.   *  Refresh all of the segments of the given worm.  This is only called
420.   *  from see_monster() in display.c or when a monster goes minvis.  It
421.   *  is located here for modularity.
422.   */
423.  void
424.  see_wsegs(worm)
425.      struct monst *worm;
426.  {
427.      struct wseg *curr = wtails[worm->wormno];
428.  
429.  /*  if (!mtmp->wormno) return;  bullet proofing */
430.  
431.      while (curr != wheads[worm->wormno]) {
432.  	newsym(curr->wx,curr->wy);
433.  	curr = curr->nseg;
434.      }
435.  }
436.  
437.  /*
438.   *  detect_wsegs()
439.   *
440.   *  Display all of the segments of the given worm for detection.
441.   */
442.  void
443.  detect_wsegs(worm, use_detection_glyph)
444.      struct monst *worm;
445.      boolean use_detection_glyph;
446.  {
447.      int num;
448.      struct wseg *curr = wtails[worm->wormno];
449.  
450.  /*  if (!mtmp->wormno) return;  bullet proofing */
451.  
452.      while (curr != wheads[worm->wormno]) {
453.  	num = use_detection_glyph ?
454.  		detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)) :
455.  		monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL));
456.  	show_glyph(curr->wx,curr->wy,num);
457.  	curr = curr->nseg;
458.      }
459.  }
460.  
461.  
462.  /*
463.   *  save_worm()
464.   *
465.   *  Save the worm information for later use.  The count is the number
466.   *  of segments, including the dummy.  Called from save.c.
467.   */
468.  void
469.  save_worm(fd, mode)
470.      int fd, mode;
471.  {
472.      int i;
473.      int count;
474.      struct wseg *curr, *temp;
475.  
476.      if (perform_bwrite(mode)) {
477.  	for (i = 1; i < MAX_NUM_WORMS; i++) {
478.  	    for (count = 0, curr = wtails[i]; curr; curr = curr->nseg) count++;
479.  	    /* Save number of segments */
480.  	    bwrite(fd, (genericptr_t) &count, sizeof(int));
481.  	    /* Save segment locations of the monster. */
482.  	    if (count) {
483.  		for (curr = wtails[i]; curr; curr = curr->nseg) {
484.  		    bwrite(fd, (genericptr_t) &(curr->wx), sizeof(xchar));
485.  		    bwrite(fd, (genericptr_t) &(curr->wy), sizeof(xchar));
486.  		}
487.  	    }
488.  	}
489.  	bwrite(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
490.      }
491.  
492.      if (release_data(mode)) {
493.  	/* Free the segments only.  savemonchn() will take care of the
494.  	 * monsters. */
495.  	for (i = 1; i < MAX_NUM_WORMS; i++) {
496.  	    if (!(curr = wtails[i])) continue;
497.  
498.  	    while (curr) {
499.  		temp = curr->nseg;
500.  		dealloc_seg(curr);		/* free the segment */
501.  		curr = temp;
502.  	    }
503.  	    wheads[i] = wtails[i] = (struct wseg *) 0;
504.  	}
505.      }
506.  
507.  }
508.  
509.  /*
510.   *  rest_worm()
511.   *
512.   *  Restore the worm information from the save file.  Called from restore.c
513.   */
514.  void
515.  rest_worm(fd)
516.      int fd;
517.  {
518.      int i, j, count;
519.      struct wseg *curr, *temp;
520.  
521.      for (i = 1; i < MAX_NUM_WORMS; i++) {
522.  	mread(fd, (genericptr_t) &count, sizeof(int));
523.  	if (!count) continue;	/* none */
524.  
525.  	/* Get the segments. */
526.  	for (curr = (struct wseg *) 0, j = 0; j < count; j++) {
527.  	    temp = newseg();
528.  	    temp->nseg = (struct wseg *) 0;
529.  	    mread(fd, (genericptr_t) &(temp->wx), sizeof(xchar));
530.  	    mread(fd, (genericptr_t) &(temp->wy), sizeof(xchar));
531.  	    if (curr)
532.  		curr->nseg = temp;
533.  	    else
534.  		wtails[i] = temp;
535.  	    curr = temp;
536.  	}
537.  	wheads[i] = curr;
538.      }
539.      mread(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
540.  }
541.  
542.  /*
543.   *  place_wsegs()
544.   *
545.   *  Place the segments of the given worm.  Called from restore.c
546.   */
547.  void
548.  place_wsegs(worm)
549.      struct monst *worm;
550.  {
551.      struct wseg *curr = wtails[worm->wormno];
552.  
553.  /*  if (!mtmp->wormno) return;  bullet proofing */
554.  
555.      while (curr != wheads[worm->wormno]) {
556.  	place_worm_seg(worm,curr->wx,curr->wy);
557.  	curr = curr->nseg;
558.      }
559.  }
560.  
561.  /*
562.   *  remove_worm()
563.   *
564.   *  This function is equivalent to the remove_monster #define in
565.   *  rm.h, only it will take the worm *and* tail out of the levels array.
566.   *  It does not get rid of (dealloc) the worm tail structures, and it does
567.   *  not remove the mon from the fmon chain.
568.   */
569.  void
570.  remove_worm(worm)
571.      register struct monst *worm;
572.  {
573.      register struct wseg *curr = wtails[worm->wormno];
574.  
575.  /*  if (!mtmp->wormno) return;  bullet proofing */
576.  
577.      while (curr) {
578.  	remove_monster(curr->wx, curr->wy);
579.  	newsym(curr->wx, curr->wy);
580.  	curr = curr->nseg;
581.      }
582.  }
583.  
584.  /*
585.   *  place_worm_tail_randomly()
586.   *
587.   *  Place a worm tail somewhere on a level behind the head.
588.   *  This routine essentially reverses the order of the wsegs from head
589.   *  to tail while placing them.
590.   *  x, and y are most likely the worm->mx, and worm->my, but don't *need* to
591.   *  be, if somehow the head is disjoint from the tail.
592.   */
593.  void
594.  place_worm_tail_randomly(worm, x, y)
595.      struct monst *worm;
596.      xchar x, y;
597.  {
598.      int wnum = worm->wormno;
599.      struct wseg *curr = wtails[wnum];
600.      struct wseg *new_tail;
601.      register xchar ox = x, oy = y;
602.  
603.  /*  if (!wnum) return;  bullet proofing */
604.  
605.      if (wnum && (!wtails[wnum] || !wheads[wnum]) ) {
606.  	impossible("place_worm_tail_randomly: wormno is set without a tail!");
607.  	return;
608.      }
609.  
610.      wheads[wnum] = new_tail = curr;
611.      curr = curr->nseg;
612.      new_tail->nseg = (struct wseg *) 0;
613.      new_tail->wx = x;
614.      new_tail->wy = y;
615.  
616.      while(curr)  {
617.  	xchar nx, ny;
618.  	char tryct = 0;
619.  
620.  	/* pick a random direction from x, y and search for goodpos() */
621.  
622.  	do {
623.  	    random_dir(ox, oy, &nx, &ny);
624.  	} while (!goodpos(nx, ny, worm, 0) && (tryct++ < 50));
625.  
626.  	if (tryct < 50)  {
627.  	    place_worm_seg(worm, nx, ny);
628.  	    curr->wx = ox = nx;
629.  	    curr->wy = oy = ny;
630.  	    wtails[wnum] = curr;
631.  	    curr = curr->nseg;
632.  	    wtails[wnum]->nseg = new_tail;
633.  	    new_tail = wtails[wnum];
634.  	    newsym(nx, ny);
635.  	} else {			/* Oops.  Truncate because there was */
636.  	    toss_wsegs(curr, FALSE);    /* no place for the rest of it */
637.  	    curr = (struct wseg *) 0;
638.  	}
639.      }
640.  }
641.  
642.  /*
643.   * Given a coordinate x, y.
644.   * return in *nx, *ny, the coordinates of one of the <= 8 squares adjoining.
645.   *
646.   * This function, and the loop it serves, could be eliminated by coding
647.   * enexto() with a search radius.
648.   */
649.  STATIC_OVL
650.  void
651.  random_dir(x, y, nx, ny)
652.      register xchar   x,   y;
653.      register xchar *nx, *ny;
654.  {
655.      *nx = x;
656.      *ny = y;
657.  
658.      *nx += (x > 1 ?			/* extreme left ? */
659.  		(x < COLNO ?		 /* extreme right ? */
660.  			(rn2(3) - 1)	  /* neither so +1, 0, or -1 */
661.  		:	-rn2(2))	 /* 0, or -1 */
662.  	   :	rn2(2));		/* 0, or 1 */
663.  
664.      *ny += (*nx == x ?			/* same kind of thing with y */
665.  		(y > 1 ?
666.  		    (y < ROWNO ?
667.  			(rn2(2) ?
668.  			    1
669.  			:   -1)
670.  		    :	-1)
671.  		:   1)
672.  	    :	(y > 1 ?
673.  		    (y < ROWNO ?
674.  			(rn2(3) - 1)
675.  		    :	-rn2(2))
676.  		:   rn2(2)));
677.  }
678.  
679.  /*  count_wsegs()
680.   *
681.   *  returns
682.   *  the number of visible segments that a worm has.
683.   */
684.  
685.  int
686.  count_wsegs(mtmp)
687.      struct monst *mtmp;
688.  {
689.      register int i=0;
690.      register struct wseg *curr = (wtails[mtmp->wormno])->nseg;
691.  
692.  /*  if (!mtmp->wormno) return 0;  bullet proofing */
693.  
694.      while (curr) {
695.  	i++;
696.  	curr = curr->nseg;
697.      }
698.  
699.      return i;
700.  }
701.  
702.  /*  create_worm_tail()
703.   *
704.   *  will create a worm tail chain of (num_segs + 1) and return a pointer to it.
705.   */
706.  STATIC_OVL
707.  struct wseg *
708.  create_worm_tail(num_segs)
709.      int num_segs;
710.  {
711.      register int i=0;
712.      register struct wseg *new_tail, *curr;
713.  
714.      if (!num_segs) return (struct wseg *)0;
715.  
716.      new_tail = curr = newseg();
717.      curr->nseg = (struct wseg *)0;
718.      curr->wx = 0;
719.      curr->wy = 0;
720.  
721.      while (i < num_segs) {
722.  	curr->nseg = newseg();
723.  	curr = curr->nseg;
724.  	curr->nseg = (struct wseg *)0;
725.  	curr->wx = 0;
726.  	curr->wy = 0;
727.  	i++;
728.      }
729.  
730.      return (new_tail);
731.  }
732.  
733.  /*  worm_known()
734.   *
735.   *  Is any segment of this worm in viewing range?  Note: caller must check
736.   *  invisibility and telepathy (which should only show the head anyway).
737.   *  Mostly used in the canseemon() macro.
738.   */
739.  boolean
740.  worm_known(worm)
741.  struct monst *worm;
742.  {
743.      struct wseg *curr = wtails[worm->wormno];
744.  
745.      while (curr) {
746.  	if(cansee(curr->wx,curr->wy)) return TRUE;
747.  	curr = curr->nseg;
748.      }
749.      return FALSE;
750.  }
751.  
752.  /*worm.c*/

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.