NetHack->aNetHack
[aNetHack.git] / src / worm.c
blobac69ea72b235e6a7a2e10761183ce1c723ae4c11
1 /* NetHack 3.6 worm.c $NHDT-Date: 1456528599 2016/02/26 23:16:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
6 #include "lev.h"
8 #define newseg() (struct wseg *) alloc(sizeof (struct wseg))
9 #define dealloc_seg(wseg) free((genericptr_t) (wseg))
11 /* worm segment structure */
12 struct wseg {
13 struct wseg *nseg;
14 xchar wx, wy; /* the segment's position */
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));
22 /* Description of long worm implementation.
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.
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.
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.
38 * wtails: The first (starting struct) of a linked list. This points
39 * to the tail (last) segment of the worm.
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
46 * are 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.
53 * One final worm array is:
55 * wgrowtime: This tells us when to add another segment to the worm.
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.
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.
69 struct wseg *wheads[MAX_NUM_WORMS] = DUMMY, *wtails[MAX_NUM_WORMS] = DUMMY;
70 long wgrowtime[MAX_NUM_WORMS] = DUMMY;
73 * get_wormno()
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.
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).
83 * Implementation is left to the interested hacker.
85 int
86 get_wormno()
88 register int new_wormno = 1;
90 while (new_wormno < MAX_NUM_WORMS) {
91 if (!wheads[new_wormno])
92 return new_wormno; /* found empty wtails[] slot at new_wormno */
93 new_wormno++;
95 return 0; /* level infested with worms */
99 * initworm()
101 * Use if (mon->wormno = get_wormno()) before calling this function!
103 * Initialize the worm entry. This will set up the worm grow time, and
104 * create and initialize the dummy segment for wheads[] and wtails[].
106 * If the worm has no tail (ie get_wormno() fails) then this function need
107 * not be called.
109 void
110 initworm(worm, wseg_count)
111 struct monst *worm;
112 int wseg_count;
114 register struct wseg *seg, *new_tail = create_worm_tail(wseg_count);
115 register int wnum = worm->wormno;
117 /* if (!wnum) return; bullet proofing */
119 if (new_tail) {
120 wtails[wnum] = new_tail;
121 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;
130 wgrowtime[wnum] = 0L;
134 * toss_wsegs()
136 * Get rid of all worm segments on and following the given pointer curr.
137 * The display may or may not need to be updated as we free the segments.
139 STATIC_OVL
140 void
141 toss_wsegs(curr, display_update)
142 register struct wseg *curr;
143 register boolean display_update;
145 register struct wseg *seg;
147 while (curr) {
148 seg = curr->nseg;
150 /* remove from level.monsters[][] */
152 /* need to check curr->wx for genocided while migrating_mon */
153 if (curr->wx) {
154 remove_monster(curr->wx, curr->wy);
156 /* update screen before deallocation */
157 if (display_update)
158 newsym(curr->wx, curr->wy);
161 /* free memory used by the segment */
162 dealloc_seg(curr);
163 curr = seg;
168 * shrink_worm()
170 * Remove the tail segment of the worm (the starting segment of the list).
172 STATIC_OVL
173 void
174 shrink_worm(wnum)
175 int wnum; /* worm number */
177 struct wseg *seg;
179 if (wtails[wnum] == wheads[wnum])
180 return; /* no tail */
182 seg = wtails[wnum];
183 wtails[wnum] = seg->nseg;
184 seg->nseg = (struct wseg *) 0;
185 toss_wsegs(seg, TRUE);
189 * worm_move()
191 * Check for mon->wormno before calling this function!
193 * Move the worm. Maybe grow.
195 void
196 worm_move(worm)
197 struct monst *worm;
199 register struct wseg *seg, *new_seg; /* new segment */
200 register int wnum = worm->wormno; /* worm number */
202 /* if (!wnum) return; bullet proofing */
205 * Place a segment at the old worm head. The head has already moved.
207 seg = wheads[wnum];
208 place_worm_seg(worm, seg->wx, seg->wy);
209 newsym(seg->wx, seg->wy); /* display the new segment */
212 * Create a new dummy segment head and place it at the end of the list.
214 new_seg = newseg();
215 new_seg->wx = worm->mx;
216 new_seg->wy = worm->my;
217 new_seg->nseg = (struct wseg *) 0;
218 seg->nseg = new_seg; /* attach it to the end of the list */
219 wheads[wnum] = new_seg; /* move the end pointer */
221 if (wgrowtime[wnum] <= moves) {
222 if (!wgrowtime[wnum])
223 wgrowtime[wnum] = moves + rnd(5);
224 else
225 wgrowtime[wnum] += rn1(15, 3);
226 worm->mhp += 3;
227 if (worm->mhp > MHPMAX)
228 worm->mhp = MHPMAX;
229 if (worm->mhp > worm->mhpmax)
230 worm->mhpmax = worm->mhp;
231 } else
232 /* The worm doesn't grow, so the last segment goes away. */
233 shrink_worm(wnum);
237 * worm_nomove()
239 * Check for mon->wormno before calling this function!
241 * The worm don't move so it should shrink.
243 void
244 worm_nomove(worm)
245 register struct monst *worm;
247 shrink_worm((int) worm->wormno); /* shrink */
249 if (worm->mhp > 3)
250 worm->mhp -= 3; /* mhpmax not changed ! */
251 else
252 worm->mhp = 1;
256 * wormgone()
258 * Check for mon->wormno before calling this function!
260 * Kill a worm tail.
262 void
263 wormgone(worm)
264 register struct monst *worm;
266 register int wnum = worm->wormno;
268 /* if (!wnum) return; bullet proofing */
270 worm->wormno = 0;
272 /* This will also remove the real monster (ie 'w') from the its
273 * position in level.monsters[][].
275 toss_wsegs(wtails[wnum], TRUE);
277 wheads[wnum] = wtails[wnum] = (struct wseg *) 0;
281 * wormhitu()
283 * Check for mon->wormno before calling this function!
285 * If the hero is near any part of the worm, the worm will try to attack.
287 void
288 wormhitu(worm)
289 register struct monst *worm;
291 register int wnum = worm->wormno;
292 register struct wseg *seg;
294 /* if (!wnum) return; bullet proofing */
296 /* This does not work right now because mattacku() thinks that the head
297 * is out of range of the player. We might try to kludge, and bring
298 * the head within range for a tiny moment, but this needs a bit more
299 * looking at before we decide to do this.
301 for (seg = wtails[wnum]; seg; seg = seg->nseg)
302 if (distu(seg->wx, seg->wy) < 3)
303 (void) mattacku(worm);
306 /* cutworm()
308 * Check for mon->wormno before calling this function!
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.
314 void
315 cutworm(worm, x, y, weap)
316 struct monst *worm;
317 xchar x, y;
318 struct obj *weap;
320 register struct wseg *curr, *new_tail;
321 register struct monst *new_worm;
322 int wnum = worm->wormno;
323 int cut_chance, new_wnum;
325 if (!wnum)
326 return; /* bullet proofing */
328 if (x == worm->mx && y == worm->my)
329 return; /* hit on head */
331 /* cutting goes best with a bladed weapon */
332 cut_chance = rnd(20); /* Normally 1-16 does not cut */
333 /* Normally 17-20 does */
335 if (weap && is_blade(weap)) /* With a blade 1- 6 does not cut */
336 cut_chance += 10; /* 7-20 does */
338 if (cut_chance < 17)
339 return; /* not good enough */
341 /* Find the segment that was attacked. */
342 curr = wtails[wnum];
344 while ((curr->wx != x) || (curr->wy != y)) {
345 curr = curr->nseg;
346 if (!curr) {
347 impossible("cutworm: no segment at (%d,%d)", (int) x, (int) y);
348 return;
352 /* If this is the tail segment, then the worm just loses it. */
353 if (curr == wtails[wnum]) {
354 shrink_worm(wnum);
355 return;
359 * Split the worm. The tail for the new worm is the old worm's tail.
360 * The tail for the old worm is the segment that follows "curr",
361 * and "curr" becomes the dummy segment under the new head.
363 new_tail = wtails[wnum];
364 wtails[wnum] = curr->nseg;
365 curr->nseg = (struct wseg *) 0; /* split the worm */
368 * At this point, the old worm is correct. Any new worm will have
369 * it's head at "curr" and its tail at "new_tail". The old worm
370 * must be at least level 3 in order to produce a new worm.
372 new_worm = 0;
373 new_wnum = (worm->m_lev >= 3 && !rn2(3)) ? get_wormno() : 0;
374 if (new_wnum) {
375 remove_monster(x, y); /* clone_mon puts new head here */
376 /* clone_mon() will fail if enough long worms have been
377 created to have them be marked as extinct or if the hit
378 that cut the current one has dropped it down to 1 HP */
379 new_worm = clone_mon(worm, x, y);
382 /* Sometimes the tail end dies. */
383 if (!new_worm) {
384 if (context.mon_moving) {
385 if (canspotmon(worm))
386 pline("Part of %s tail has been cut off.",
387 s_suffix(mon_nam(worm)));
388 } else
389 You("cut part of the tail off of %s.", mon_nam(worm));
390 toss_wsegs(new_tail, TRUE);
391 if (worm->mhp > 1)
392 worm->mhp /= 2;
393 return;
396 new_worm->wormno = new_wnum; /* affix new worm number */
397 new_worm->mcloned = 0; /* treat second worm as a normal monster */
399 /* Devalue the monster level of both halves of the worm.
400 Note: m_lev is always at least 3 in order to get this far. */
401 worm->m_lev = max((unsigned) worm->m_lev - 2, 3);
402 new_worm->m_lev = worm->m_lev;
404 /* Calculate the lower-level mhp; use <N>d8 for long worms.
405 Can't use newmonhp() here because it would reset m_lev. */
406 new_worm->mhpmax = new_worm->mhp = d((int) new_worm->m_lev, 8);
407 worm->mhpmax = d((int) worm->m_lev, 8); /* new maxHP for old worm */
408 if (worm->mhpmax < worm->mhp)
409 worm->mhp = worm->mhpmax;
411 wtails[new_wnum] = new_tail; /* We've got all the info right now */
412 wheads[new_wnum] = curr; /* so we can do this faster than */
413 wgrowtime[new_wnum] = 0L; /* trying to call initworm(). */
415 /* Place the new monster at all the segment locations. */
416 place_wsegs(new_worm);
418 if (context.mon_moving)
419 pline("%s is cut in half.", Monnam(worm));
420 else
421 You("cut %s in half.", mon_nam(worm));
425 * see_wsegs()
427 * Refresh all of the segments of the given worm. This is only called
428 * from see_monster() in display.c or when a monster goes minvis. It
429 * is located here for modularity.
431 void
432 see_wsegs(worm)
433 struct monst *worm;
435 struct wseg *curr = wtails[worm->wormno];
437 /* if (!mtmp->wormno) return; bullet proofing */
439 while (curr != wheads[worm->wormno]) {
440 newsym(curr->wx, curr->wy);
441 curr = curr->nseg;
446 * detect_wsegs()
448 * Display all of the segments of the given worm for detection.
450 void
451 detect_wsegs(worm, use_detection_glyph)
452 struct monst *worm;
453 boolean use_detection_glyph;
455 int num;
456 struct wseg *curr = wtails[worm->wormno];
458 /* if (!mtmp->wormno) return; bullet proofing */
460 while (curr != wheads[worm->wormno]) {
461 num = use_detection_glyph
462 ? detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL))
463 : (worm->mtame
464 ? petnum_to_glyph(what_mon(PM_LONG_WORM_TAIL))
465 : monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)));
466 show_glyph(curr->wx, curr->wy, num);
467 curr = curr->nseg;
472 * save_worm()
474 * Save the worm information for later use. The count is the number
475 * of segments, including the dummy. Called from save.c.
477 void
478 save_worm(fd, mode)
479 int fd, mode;
481 int i;
482 int count;
483 struct wseg *curr, *temp;
485 if (perform_bwrite(mode)) {
486 for (i = 1; i < MAX_NUM_WORMS; i++) {
487 for (count = 0, curr = wtails[i]; curr; curr = curr->nseg)
488 count++;
489 /* Save number of segments */
490 bwrite(fd, (genericptr_t) &count, sizeof(int));
491 /* Save segment locations of the monster. */
492 if (count) {
493 for (curr = wtails[i]; curr; curr = curr->nseg) {
494 bwrite(fd, (genericptr_t) & (curr->wx), sizeof(xchar));
495 bwrite(fd, (genericptr_t) & (curr->wy), sizeof(xchar));
499 bwrite(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
502 if (release_data(mode)) {
503 /* Free the segments only. savemonchn() will take care of the
504 * monsters. */
505 for (i = 1; i < MAX_NUM_WORMS; i++) {
506 if (!(curr = wtails[i]))
507 continue;
509 while (curr) {
510 temp = curr->nseg;
511 dealloc_seg(curr); /* free the segment */
512 curr = temp;
514 wheads[i] = wtails[i] = (struct wseg *) 0;
520 * rest_worm()
522 * Restore the worm information from the save file. Called from restore.c
524 void
525 rest_worm(fd)
526 int fd;
528 int i, j, count;
529 struct wseg *curr, *temp;
531 for (i = 1; i < MAX_NUM_WORMS; i++) {
532 mread(fd, (genericptr_t) &count, sizeof(int));
533 if (!count)
534 continue; /* none */
536 /* Get the segments. */
537 for (curr = (struct wseg *) 0, j = 0; j < count; j++) {
538 temp = newseg();
539 temp->nseg = (struct wseg *) 0;
540 mread(fd, (genericptr_t) & (temp->wx), sizeof(xchar));
541 mread(fd, (genericptr_t) & (temp->wy), sizeof(xchar));
542 if (curr)
543 curr->nseg = temp;
544 else
545 wtails[i] = temp;
546 curr = temp;
548 wheads[i] = curr;
550 mread(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
554 * place_wsegs()
556 * Place the segments of the given worm. Called from restore.c
558 void
559 place_wsegs(worm)
560 struct monst *worm;
562 struct wseg *curr = wtails[worm->wormno];
564 /* if (!mtmp->wormno) return; bullet proofing */
566 while (curr != wheads[worm->wormno]) {
567 place_worm_seg(worm, curr->wx, curr->wy);
568 curr = curr->nseg;
573 * remove_worm()
575 * This function is equivalent to the remove_monster #define in
576 * rm.h, only it will take the worm *and* tail out of the levels array.
577 * It does not get rid of (dealloc) the worm tail structures, and it does
578 * not remove the mon from the fmon chain.
580 void
581 remove_worm(worm)
582 register struct monst *worm;
584 register struct wseg *curr = wtails[worm->wormno];
586 /* if (!mtmp->wormno) return; bullet proofing */
588 while (curr) {
589 remove_monster(curr->wx, curr->wy);
590 newsym(curr->wx, curr->wy);
591 curr = curr->nseg;
596 * place_worm_tail_randomly()
598 * Place a worm tail somewhere on a level behind the head.
599 * This routine essentially reverses the order of the wsegs from head
600 * to tail while placing them.
601 * x, and y are most likely the worm->mx, and worm->my, but don't *need* to
602 * be, if somehow the head is disjoint from the tail.
604 void
605 place_worm_tail_randomly(worm, x, y)
606 struct monst *worm;
607 xchar x, y;
609 int wnum = worm->wormno;
610 struct wseg *curr = wtails[wnum];
611 struct wseg *new_tail;
612 register xchar ox = x, oy = y;
614 /* if (!wnum) return; bullet proofing */
616 if (wnum && (!wtails[wnum] || !wheads[wnum])) {
617 impossible("place_worm_tail_randomly: wormno is set without a tail!");
618 return;
621 wheads[wnum] = new_tail = curr;
622 curr = curr->nseg;
623 new_tail->nseg = (struct wseg *) 0;
624 new_tail->wx = x;
625 new_tail->wy = y;
627 while (curr) {
628 xchar nx, ny;
629 char tryct = 0;
631 /* pick a random direction from x, y and search for goodpos() */
633 do {
634 random_dir(ox, oy, &nx, &ny);
635 } while (!goodpos(nx, ny, worm, 0) && (tryct++ < 50));
637 if (tryct < 50) {
638 place_worm_seg(worm, nx, ny);
639 curr->wx = ox = nx;
640 curr->wy = oy = ny;
641 wtails[wnum] = curr;
642 curr = curr->nseg;
643 wtails[wnum]->nseg = new_tail;
644 new_tail = wtails[wnum];
645 newsym(nx, ny);
646 } else { /* Oops. Truncate because there was */
647 toss_wsegs(curr, FALSE); /* no place for the rest of it */
648 curr = (struct wseg *) 0;
654 * Given a coordinate x, y.
655 * return in *nx, *ny, the coordinates of one of the <= 8 squares adjoining.
657 * This function, and the loop it serves, could be eliminated by coding
658 * enexto() with a search radius.
660 STATIC_OVL
661 void
662 random_dir(x, y, nx, ny)
663 register xchar x, y;
664 register xchar *nx, *ny;
666 *nx = x;
667 *ny = y;
669 *nx += (x > 1 /* extreme left ? */
670 ? (x < COLNO /* extreme right ? */
671 ? (rn2(3) - 1) /* neither so +1, 0, or -1 */
672 : -rn2(2)) /* 0, or -1 */
673 : rn2(2)); /* 0, or 1 */
675 *ny += (*nx == x /* same kind of thing with y */
676 ? (y > 1 ? (y < ROWNO ? (rn2(2) ? 1 : -1) : -1) : 1)
677 : (y > 1 ? (y < ROWNO ? (rn2(3) - 1) : -rn2(2)) : rn2(2)));
680 /* for size_monst(cmd.c) to support #stats */
682 size_wseg(worm)
683 struct monst *worm;
685 return (int) (count_wsegs(worm) * sizeof (struct wseg));
688 /* count_wsegs()
689 * returns the number of segments that a worm has.
692 count_wsegs(mtmp)
693 struct monst *mtmp;
695 register int i = 0;
696 register struct wseg *curr;
698 if (mtmp->wormno) {
699 for (curr = wtails[mtmp->wormno]->nseg; curr; curr = curr->nseg)
700 i++;
702 return i;
705 /* create_worm_tail()
706 * will create a worm tail chain of (num_segs + 1) and return pointer to it.
708 STATIC_OVL
709 struct wseg *
710 create_worm_tail(num_segs)
711 int num_segs;
713 register int i = 0;
714 register struct wseg *new_tail, *curr;
716 if (!num_segs)
717 return (struct wseg *) 0;
719 new_tail = curr = newseg();
720 curr->nseg = (struct wseg *) 0;
721 curr->wx = 0;
722 curr->wy = 0;
724 while (i < num_segs) {
725 curr->nseg = newseg();
726 curr = curr->nseg;
727 curr->nseg = (struct wseg *) 0;
728 curr->wx = 0;
729 curr->wy = 0;
730 i++;
733 return new_tail;
736 /* worm_known()
737 * Is any segment of this worm in viewing range? Note: caller must check
738 * invisibility and telepathy (which should only show the head anyway).
739 * Mostly used in the canseemon() macro.
741 boolean
742 worm_known(worm)
743 struct monst *worm;
745 struct wseg *curr = wtails[worm->wormno];
747 while (curr) {
748 if (cansee(curr->wx, curr->wy))
749 return TRUE;
750 curr = curr->nseg;
752 return FALSE;
755 /* would moving from <x1,y1> to <x2,y2> involve passing between two
756 consecutive segments of the same worm? */
757 boolean
758 worm_cross(x1, y1, x2, y2)
759 int x1, y1, x2, y2;
761 struct monst *worm;
762 struct wseg *curr, *wnxt;
765 * With digits representing relative sequence number of the segments,
766 * returns true when testing between @ and ? (passes through worm's
767 * body), false between @ and ! (stays on same side of worm).
768 * .w1?..
769 * ..@2..
770 * .65!3.
771 * ...4..
774 if (distmin(x1, y1, x2, y2) != 1) {
775 impossible("worm_cross checking for non-adjacent location?");
776 return FALSE;
778 /* attempting to pass between worm segs is only relevant for diagonal */
779 if (x1 == x2 || y1 == y2)
780 return FALSE;
782 /* is the same monster at <x1,y2> and at <x2,y1>? */
783 worm = m_at(x1, y2);
784 if (!worm || m_at(x2, y1) != worm)
785 return FALSE;
787 /* same monster is at both adjacent spots, so must be a worm; we need
788 to figure out if the two spots are occupied by consecutive segments */
789 for (curr = wtails[worm->wormno]; curr; curr = wnxt) {
790 wnxt = curr->nseg;
791 if (!wnxt)
792 break; /* no next segment; can't continue */
794 /* we don't know which of <x1,y2> or <x2,y1> we'll hit first, but
795 whichever it is, they're consecutive iff next seg is the other */
796 if (curr->wx == x1 && curr->wy == y2)
797 return (boolean) (wnxt->wx == x2 && wnxt->wy == y1);
798 if (curr->wx == x2 && curr->wy == y1)
799 return (boolean) (wnxt->wx == x1 && wnxt->wy == y2);
801 /* should never reach here... */
802 return FALSE;
805 /* construct an index number for a worm tail segment */
807 wseg_at(worm, x, y)
808 struct monst *worm;
809 int x, y;
811 int res = 0;
813 if (worm && worm->wormno && m_at(x, y) == worm) {
814 struct wseg *curr;
815 int i, n;
816 xchar wx = (xchar) x, wy = (xchar) y;
818 for (i = 0, curr = wtails[worm->wormno]; curr; curr = curr->nseg) {
819 if (curr->wx == wx && curr->wy == wy)
820 break;
821 ++i;
823 for (n = i; curr; curr = curr->nseg)
824 ++n;
825 res = n - i;
827 return res;
830 /*worm.c*/