Difference between revisions of "Source:NetHack 3.4.3/src/worm.c"

From NetHackWiki
Jump to navigation Jump to search
(Automated source code upload)
 
m (add headers)
Line 1: Line 1:
 +
Below is the full text to src/worm.c from NetHack 3.4.3. To link to a particular line, write [[worm.c#line123|<nowiki>[[worm.c#line123]]</nowiki>]], for example.
 +
 +
== Top of file ==
  
Below is the full text to src/worm.c from NetHack 3.4.3. To link to a particular line, write [[worm.c#line123|<nowiki>[[worm.c#line123]]</nowiki>]], for example.
 
 
  <span id="line1">1.    /* SCCS Id: @(#)worm.c 3.4 1995/01/28 */</span>
 
  <span id="line1">1.    /* SCCS Id: @(#)worm.c 3.4 1995/01/28 */</span>
 
  <span id="line2">2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */</span>
 
  <span id="line2">2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */</span>
Line 75: Line 77:
 
  <span id="line70">70.  long     wgrowtime[MAX_NUM_WORMS] = DUMMY;</span>
 
  <span id="line70">70.  long     wgrowtime[MAX_NUM_WORMS] = DUMMY;</span>
 
  <span id="line71">71.  </span>
 
  <span id="line71">71.  </span>
 +
 +
== get_wormno ==
 +
 
  <span id="line72">72.  /*</span>
 
  <span id="line72">72.  /*</span>
 
  <span id="line73">73.    *  get_wormno()</span>
 
  <span id="line73">73.    *  get_wormno()</span>
Line 102: Line 107:
 
  <span id="line97">97.  }</span>
 
  <span id="line97">97.  }</span>
 
  <span id="line98">98.  </span>
 
  <span id="line98">98.  </span>
 +
 +
== initworm ==
 +
 
  <span id="line99">99.  /*</span>
 
  <span id="line99">99.  /*</span>
 
  <span id="line100">100.  *  initworm()</span>
 
  <span id="line100">100.  *  initworm()</span>
Line 137: Line 145:
 
  <span id="line132">132.  </span>
 
  <span id="line132">132.  </span>
 
  <span id="line133">133.  </span>
 
  <span id="line133">133.  </span>
 +
 +
== toss_wsegs ==
 +
 
  <span id="line134">134.  /*</span>
 
  <span id="line134">134.  /*</span>
 
  <span id="line135">135.  *  toss_wsegs()</span>
 
  <span id="line135">135.  *  toss_wsegs()</span>
Line 171: Line 182:
 
  <span id="line166">166.  </span>
 
  <span id="line166">166.  </span>
 
  <span id="line167">167.  </span>
 
  <span id="line167">167.  </span>
 +
 +
== shrink_worm ==
 +
 
  <span id="line168">168.  /*</span>
 
  <span id="line168">168.  /*</span>
 
  <span id="line169">169.  *  shrink_worm()</span>
 
  <span id="line169">169.  *  shrink_worm()</span>
Line 191: Line 205:
 
  <span id="line186">186.  }</span>
 
  <span id="line186">186.  }</span>
 
  <span id="line187">187.  </span>
 
  <span id="line187">187.  </span>
 +
 +
== worm_move ==
 +
 
  <span id="line188">188.  /*</span>
 
  <span id="line188">188.  /*</span>
 
  <span id="line189">189.  *  worm_move()</span>
 
  <span id="line189">189.  *  worm_move()</span>
Line 239: Line 256:
 
  <span id="line234">234.  }</span>
 
  <span id="line234">234.  }</span>
 
  <span id="line235">235.  </span>
 
  <span id="line235">235.  </span>
 +
 +
== worm_nomove ==
 +
 
  <span id="line236">236.  /*</span>
 
  <span id="line236">236.  /*</span>
 
  <span id="line237">237.  *  worm_nomove()</span>
 
  <span id="line237">237.  *  worm_nomove()</span>
Line 258: Line 278:
 
  <span id="line253">253.  }</span>
 
  <span id="line253">253.  }</span>
 
  <span id="line254">254.  </span>
 
  <span id="line254">254.  </span>
 +
 +
== wormgone ==
 +
 
  <span id="line255">255.  /*</span>
 
  <span id="line255">255.  /*</span>
 
  <span id="line256">256.  *  wormgone()</span>
 
  <span id="line256">256.  *  wormgone()</span>
Line 283: Line 306:
 
  <span id="line278">278.  }</span>
 
  <span id="line278">278.  }</span>
 
  <span id="line279">279.  </span>
 
  <span id="line279">279.  </span>
 +
 +
== wormhitu ==
 +
 
  <span id="line280">280.  /*</span>
 
  <span id="line280">280.  /*</span>
 
  <span id="line281">281.  *  wormhitu()</span>
 
  <span id="line281">281.  *  wormhitu()</span>
Line 309: Line 335:
 
  <span id="line304">304.  }</span>
 
  <span id="line304">304.  }</span>
 
  <span id="line305">305.  </span>
 
  <span id="line305">305.  </span>
 +
 +
== cutworm ==
 +
 
  <span id="line306">306.  /*  cutworm()</span>
 
  <span id="line306">306.  /*  cutworm()</span>
 
  <span id="line307">307.  *</span>
 
  <span id="line307">307.  *</span>
Line 415: Line 444:
 
  <span id="line410">410.  </span>
 
  <span id="line410">410.  </span>
 
  <span id="line411">411.  </span>
 
  <span id="line411">411.  </span>
 +
 +
== see_wsegs ==
 +
 
  <span id="line412">412.  /*</span>
 
  <span id="line412">412.  /*</span>
 
  <span id="line413">413.  *  see_wsegs()</span>
 
  <span id="line413">413.  *  see_wsegs()</span>
Line 436: Line 468:
 
  <span id="line431">431.  }</span>
 
  <span id="line431">431.  }</span>
 
  <span id="line432">432.  </span>
 
  <span id="line432">432.  </span>
 +
 +
== detect_wsegs ==
 +
 
  <span id="line433">433.  /*</span>
 
  <span id="line433">433.  /*</span>
 
  <span id="line434">434.  *  detect_wsegs()</span>
 
  <span id="line434">434.  *  detect_wsegs()</span>
Line 461: Line 496:
 
  <span id="line456">456.  </span>
 
  <span id="line456">456.  </span>
 
  <span id="line457">457.  </span>
 
  <span id="line457">457.  </span>
 +
 +
== save_worm ==
 +
 
  <span id="line458">458.  /*</span>
 
  <span id="line458">458.  /*</span>
 
  <span id="line459">459.  *  save_worm()</span>
 
  <span id="line459">459.  *  save_worm()</span>
Line 508: Line 546:
 
  <span id="line503">503.  }</span>
 
  <span id="line503">503.  }</span>
 
  <span id="line504">504.  </span>
 
  <span id="line504">504.  </span>
 +
 +
== rest_worm ==
 +
 
  <span id="line505">505.  /*</span>
 
  <span id="line505">505.  /*</span>
 
  <span id="line506">506.  *  rest_worm()</span>
 
  <span id="line506">506.  *  rest_worm()</span>
Line 541: Line 582:
 
  <span id="line536">536.  }</span>
 
  <span id="line536">536.  }</span>
 
  <span id="line537">537.  </span>
 
  <span id="line537">537.  </span>
 +
 +
== place_wsegs ==
 +
 
  <span id="line538">538.  /*</span>
 
  <span id="line538">538.  /*</span>
 
  <span id="line539">539.  *  place_wsegs()</span>
 
  <span id="line539">539.  *  place_wsegs()</span>
Line 560: Line 604:
 
  <span id="line555">555.  }</span>
 
  <span id="line555">555.  }</span>
 
  <span id="line556">556.  </span>
 
  <span id="line556">556.  </span>
 +
 +
== remove_worm ==
 +
 
  <span id="line557">557.  /*</span>
 
  <span id="line557">557.  /*</span>
 
  <span id="line558">558.  *  remove_worm()</span>
 
  <span id="line558">558.  *  remove_worm()</span>
Line 583: Line 630:
 
  <span id="line578">578.  }</span>
 
  <span id="line578">578.  }</span>
 
  <span id="line579">579.  </span>
 
  <span id="line579">579.  </span>
 +
 +
== place_worm_tail_randomly ==
 +
 
  <span id="line580">580.  /*</span>
 
  <span id="line580">580.  /*</span>
 
  <span id="line581">581.  *  place_worm_tail_randomly()</span>
 
  <span id="line581">581.  *  place_worm_tail_randomly()</span>
Line 641: Line 691:
 
  <span id="line636">636.  }</span>
 
  <span id="line636">636.  }</span>
 
  <span id="line637">637.  </span>
 
  <span id="line637">637.  </span>
 +
 +
== random_dir ==
 +
 
  <span id="line638">638.  /*</span>
 
  <span id="line638">638.  /*</span>
 
  <span id="line639">639.  * Given a coordinate x, y.</span>
 
  <span id="line639">639.  * Given a coordinate x, y.</span>
Line 678: Line 731:
 
  <span id="line673">673.  }</span>
 
  <span id="line673">673.  }</span>
 
  <span id="line674">674.  </span>
 
  <span id="line674">674.  </span>
 +
 +
== count_wsegs ==
 +
 
  <span id="line675">675.  /*  count_wsegs()</span>
 
  <span id="line675">675.  /*  count_wsegs()</span>
 
  <span id="line676">676.  *</span>
 
  <span id="line676">676.  *</span>
Line 701: Line 757:
 
  <span id="line696">696.  }</span>
 
  <span id="line696">696.  }</span>
 
  <span id="line697">697.  </span>
 
  <span id="line697">697.  </span>
 +
 +
== create_worm_tail ==
 +
 
  <span id="line698">698.  /*  create_worm_tail()</span>
 
  <span id="line698">698.  /*  create_worm_tail()</span>
 
  <span id="line699">699.  *</span>
 
  <span id="line699">699.  *</span>
Line 732: Line 791:
 
  <span id="line727">727.  }</span>
 
  <span id="line727">727.  }</span>
 
  <span id="line728">728.  </span>
 
  <span id="line728">728.  </span>
 +
 +
== worm_known ==
 +
 
  <span id="line729">729.  /*  worm_known()</span>
 
  <span id="line729">729.  /*  worm_known()</span>
 
  <span id="line730">730.  *</span>
 
  <span id="line730">730.  *</span>

Revision as of 16:06, 26 August 2006

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.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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.  

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