Source:SLASH'EM 0.0.7E7F2/worm.c

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.

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*/