1 /* NetHack 3.6 worm.c $NHDT-Date: 1446887540 2015/11/07 09:12:20 $ $NHDT-Branch: master $:$NHDT-Revision: 1.19 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
8 #define newseg() (struct wseg *) alloc(sizeof (struct wseg))
9 #define dealloc_seg(wseg) free((genericptr_t) (wseg))
11 /* worm segment structure */
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
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;
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.
88 register int new_wormno = 1;
90 while (new_wormno < MAX_NUM_WORMS) {
91 if (!wheads[new_wormno])
92 return new_wormno; /* found an empty wtails[] slot at new_wormno
97 return 0; /* level infested with worms */
103 * Use if (mon->wormno = get_wormno()) before calling this function!
105 * Initialize the worm entry. This will set up the worm grow time, and
106 * create and initialize the dummy segment for wheads[] and wtails[].
108 * If the worm has no tail (ie get_wormno() fails) then this function need
112 initworm(worm, wseg_count)
116 register struct wseg *seg, *new_tail = create_worm_tail(wseg_count);
117 register int wnum = worm->wormno;
119 /* if (!wnum) return; bullet proofing */
122 wtails[wnum] = new_tail;
123 for (seg = new_tail; seg->nseg; seg = seg->nseg)
127 wtails[wnum] = wheads[wnum] = seg = newseg();
128 seg->nseg = (struct wseg *) 0;
132 wgrowtime[wnum] = 0L;
138 * Get rid of all worm segments on and following the given pointer curr.
139 * The display may or may not need to be updated as we free the segments.
143 toss_wsegs(curr, display_update)
144 register struct wseg *curr;
145 register boolean display_update;
147 register struct wseg *seg;
152 /* remove from level.monsters[][] */
154 /* need to check curr->wx for genocided while migrating_mon */
156 remove_monster(curr->wx, curr->wy);
158 /* update screen before deallocation */
160 newsym(curr->wx, curr->wy);
163 /* free memory used by the segment */
172 * Remove the tail segment of the worm (the starting segment of the list).
177 int wnum; /* worm number */
181 if (wtails[wnum] == wheads[wnum])
182 return; /* no tail */
185 wtails[wnum] = seg->nseg;
186 seg->nseg = (struct wseg *) 0;
187 toss_wsegs(seg, TRUE);
193 * Check for mon->wormno before calling this function!
195 * Move the worm. Maybe grow.
201 register struct wseg *seg, *new_seg; /* new segment */
202 register int wnum = worm->wormno; /* worm number */
204 /* if (!wnum) return; bullet proofing */
207 * Place a segment at the old worm head. The head has already moved.
210 place_worm_seg(worm, seg->wx, seg->wy);
211 newsym(seg->wx, seg->wy); /* display the new segment */
214 * Create a new dummy segment head and place it at the end of the list.
217 new_seg->wx = worm->mx;
218 new_seg->wy = worm->my;
219 new_seg->nseg = (struct wseg *) 0;
220 seg->nseg = new_seg; /* attach it to the end of the list */
221 wheads[wnum] = new_seg; /* move the end pointer */
223 if (wgrowtime[wnum] <= moves) {
224 if (!wgrowtime[wnum])
225 wgrowtime[wnum] = moves + rnd(5);
227 wgrowtime[wnum] += rn1(15, 3);
229 if (worm->mhp > MHPMAX)
231 if (worm->mhp > worm->mhpmax)
232 worm->mhpmax = worm->mhp;
234 /* The worm doesn't grow, so the last segment goes away. */
241 * Check for mon->wormno before calling this function!
243 * The worm don't move so it should shrink.
247 register struct monst *worm;
249 shrink_worm((int) worm->wormno); /* shrink */
252 worm->mhp -= 3; /* mhpmax not changed ! */
260 * Check for mon->wormno before calling this function!
266 register struct monst *worm;
268 register int wnum = worm->wormno;
270 /* if (!wnum) return; bullet proofing */
274 /* This will also remove the real monster (ie 'w') from the its
275 * position in level.monsters[][].
277 toss_wsegs(wtails[wnum], TRUE);
279 wheads[wnum] = wtails[wnum] = (struct wseg *) 0;
285 * Check for mon->wormno before calling this function!
287 * If the hero is near any part of the worm, the worm will try to attack.
291 register struct monst *worm;
293 register int wnum = worm->wormno;
294 register struct wseg *seg;
296 /* if (!wnum) return; bullet proofing */
298 /* This does not work right now because mattacku() thinks that the head
300 * out of range of the player. We might try to kludge, and bring the
302 * within range for a tiny moment, but this needs a bit more looking at
303 * before we decide to do this.
305 for (seg = wtails[wnum]; seg; seg = seg->nseg)
306 if (distu(seg->wx, seg->wy) < 3)
307 (void) mattacku(worm);
312 * Check for mon->wormno before calling this function!
314 * When hitting a worm (worm) at position x, y, with a weapon (weap),
315 * there is a chance that the worm will be cut in half, and a chance
316 * that both halves will survive.
319 cutworm(worm, x, y, weap)
324 register struct wseg *curr, *new_tail;
325 register struct monst *new_worm;
326 int wnum = worm->wormno;
327 int cut_chance, new_wnum;
330 return; /* bullet proofing */
332 if (x == worm->mx && y == worm->my)
333 return; /* hit on head */
335 /* cutting goes best with a bladed weapon */
336 cut_chance = rnd(20); /* Normally 1-16 does not cut */
337 /* Normally 17-20 does */
339 if (weap && is_blade(weap)) /* With a blade 1- 6 does not cut */
340 cut_chance += 10; /* 7-20 does */
343 return; /* not good enough */
345 /* Find the segment that was attacked. */
348 while ((curr->wx != x) || (curr->wy != y)) {
351 impossible("cutworm: no segment at (%d,%d)", (int) x, (int) y);
356 /* If this is the tail segment, then the worm just loses it. */
357 if (curr == wtails[wnum]) {
363 * Split the worm. The tail for the new worm is the old worm's tail.
364 * The tail for the old worm is the segment that follows "curr",
365 * and "curr" becomes the dummy segment under the new head.
367 new_tail = wtails[wnum];
368 wtails[wnum] = curr->nseg;
369 curr->nseg = (struct wseg *) 0; /* split the worm */
372 * At this point, the old worm is correct. Any new worm will have
373 * it's head at "curr" and its tail at "new_tail". The old worm
374 * must be at least level 3 in order to produce a new worm.
378 new_wnum = (worm->m_lev >= 3 && !rn2(3)) ? get_wormno() : 0;
380 remove_monster(x, y); /* clone_mon puts new head here */
381 /* clone_mon() will fail if enough long worms have been
382 created to have them be marked as extinct or if the hit
383 that cut the current one has dropped it down to 1 HP */
384 new_worm = clone_mon(worm, x, y);
387 /* Sometimes the tail end dies. */
389 if (context.mon_moving) {
390 if (canspotmon(worm))
391 pline("Part of %s tail has been cut off.",
392 s_suffix(mon_nam(worm)));
394 You("cut part of the tail off of %s.", mon_nam(worm));
395 toss_wsegs(new_tail, TRUE);
401 new_worm->wormno = new_wnum; /* affix new worm number */
402 new_worm->mcloned = 0; /* treat second worm as a normal monster */
404 /* Devalue the monster level of both halves of the worm.
405 Note: m_lev is always at least 3 in order to get this far. */
406 worm->m_lev = max((unsigned) worm->m_lev - 2, 3);
407 new_worm->m_lev = worm->m_lev;
409 /* Calculate the lower-level mhp; use <N>d8 for long worms.
410 Can't use newmonhp() here because it would reset m_lev. */
411 new_worm->mhpmax = new_worm->mhp = d((int) new_worm->m_lev, 8);
412 worm->mhpmax = d((int) worm->m_lev, 8); /* new maxHP for old worm */
413 if (worm->mhpmax < worm->mhp)
414 worm->mhp = worm->mhpmax;
416 wtails[new_wnum] = new_tail; /* We've got all the info right now */
417 wheads[new_wnum] = curr; /* so we can do this faster than */
418 wgrowtime[new_wnum] = 0L; /* trying to call initworm(). */
420 /* Place the new monster at all the segment locations. */
421 place_wsegs(new_worm);
423 if (context.mon_moving)
424 pline("%s is cut in half.", Monnam(worm));
426 You("cut %s in half.", mon_nam(worm));
432 * Refresh all of the segments of the given worm. This is only called
433 * from see_monster() in display.c or when a monster goes minvis. It
434 * is located here for modularity.
440 struct wseg *curr = wtails[worm->wormno];
442 /* if (!mtmp->wormno) return; bullet proofing */
444 while (curr != wheads[worm->wormno]) {
445 newsym(curr->wx, curr->wy);
453 * Display all of the segments of the given worm for detection.
456 detect_wsegs(worm, use_detection_glyph)
458 boolean use_detection_glyph;
461 struct wseg *curr = wtails[worm->wormno];
463 /* if (!mtmp->wormno) return; bullet proofing */
465 while (curr != wheads[worm->wormno]) {
466 num = use_detection_glyph
467 ? detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL))
469 ? petnum_to_glyph(what_mon(PM_LONG_WORM_TAIL))
470 : monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)));
471 show_glyph(curr->wx, curr->wy, num);
479 * Save the worm information for later use. The count is the number
480 * of segments, including the dummy. Called from save.c.
488 struct wseg *curr, *temp;
490 if (perform_bwrite(mode)) {
491 for (i = 1; i < MAX_NUM_WORMS; i++) {
492 for (count = 0, curr = wtails[i]; curr; curr = curr->nseg)
494 /* Save number of segments */
495 bwrite(fd, (genericptr_t) &count, sizeof(int));
496 /* Save segment locations of the monster. */
498 for (curr = wtails[i]; curr; curr = curr->nseg) {
499 bwrite(fd, (genericptr_t) & (curr->wx), sizeof(xchar));
500 bwrite(fd, (genericptr_t) & (curr->wy), sizeof(xchar));
504 bwrite(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
507 if (release_data(mode)) {
508 /* Free the segments only. savemonchn() will take care of the
510 for (i = 1; i < MAX_NUM_WORMS; i++) {
511 if (!(curr = wtails[i]))
516 dealloc_seg(curr); /* free the segment */
519 wheads[i] = wtails[i] = (struct wseg *) 0;
527 * Restore the worm information from the save file. Called from restore.c
534 struct wseg *curr, *temp;
536 for (i = 1; i < MAX_NUM_WORMS; i++) {
537 mread(fd, (genericptr_t) &count, sizeof(int));
541 /* Get the segments. */
542 for (curr = (struct wseg *) 0, j = 0; j < count; j++) {
544 temp->nseg = (struct wseg *) 0;
545 mread(fd, (genericptr_t) & (temp->wx), sizeof(xchar));
546 mread(fd, (genericptr_t) & (temp->wy), sizeof(xchar));
555 mread(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
561 * Place the segments of the given worm. Called from restore.c
567 struct wseg *curr = wtails[worm->wormno];
569 /* if (!mtmp->wormno) return; bullet proofing */
571 while (curr != wheads[worm->wormno]) {
572 place_worm_seg(worm, curr->wx, curr->wy);
580 * This function is equivalent to the remove_monster #define in
581 * rm.h, only it will take the worm *and* tail out of the levels array.
582 * It does not get rid of (dealloc) the worm tail structures, and it does
583 * not remove the mon from the fmon chain.
587 register struct monst *worm;
589 register struct wseg *curr = wtails[worm->wormno];
591 /* if (!mtmp->wormno) return; bullet proofing */
594 remove_monster(curr->wx, curr->wy);
595 newsym(curr->wx, curr->wy);
601 * place_worm_tail_randomly()
603 * Place a worm tail somewhere on a level behind the head.
604 * This routine essentially reverses the order of the wsegs from head
605 * to tail while placing them.
606 * x, and y are most likely the worm->mx, and worm->my, but don't *need* to
607 * be, if somehow the head is disjoint from the tail.
610 place_worm_tail_randomly(worm, x, y)
614 int wnum = worm->wormno;
615 struct wseg *curr = wtails[wnum];
616 struct wseg *new_tail;
617 register xchar ox = x, oy = y;
619 /* if (!wnum) return; bullet proofing */
621 if (wnum && (!wtails[wnum] || !wheads[wnum])) {
622 impossible("place_worm_tail_randomly: wormno is set without a tail!");
626 wheads[wnum] = new_tail = curr;
628 new_tail->nseg = (struct wseg *) 0;
636 /* pick a random direction from x, y and search for goodpos() */
639 random_dir(ox, oy, &nx, &ny);
640 } while (!goodpos(nx, ny, worm, 0) && (tryct++ < 50));
643 place_worm_seg(worm, nx, ny);
648 wtails[wnum]->nseg = new_tail;
649 new_tail = wtails[wnum];
651 } else { /* Oops. Truncate because there was */
652 toss_wsegs(curr, FALSE); /* no place for the rest of it */
653 curr = (struct wseg *) 0;
659 * Given a coordinate x, y.
660 * return in *nx, *ny, the coordinates of one of the <= 8 squares adjoining.
662 * This function, and the loop it serves, could be eliminated by coding
663 * enexto() with a search radius.
667 random_dir(x, y, nx, ny)
669 register xchar *nx, *ny;
674 *nx += (x > 1 /* extreme left ? */
675 ? (x < COLNO /* extreme right ? */
676 ? (rn2(3) - 1) /* neither so +1, 0, or -1 */
677 : -rn2(2)) /* 0, or -1 */
678 : rn2(2)); /* 0, or 1 */
680 *ny += (*nx == x /* same kind of thing with y */
681 ? (y > 1 ? (y < ROWNO ? (rn2(2) ? 1 : -1) : -1) : 1)
682 : (y > 1 ? (y < ROWNO ? (rn2(3) - 1) : -rn2(2)) : rn2(2)));
686 * returns the number of visible segments that a worm has.
693 register struct wseg *curr = (wtails[mtmp->wormno])->nseg;
695 /* if (!mtmp->wormno) return 0; bullet proofing */
705 /* create_worm_tail()
706 * will create a worm tail chain of (num_segs + 1) and return pointer to it.
710 create_worm_tail(num_segs)
714 register struct wseg *new_tail, *curr;
717 return (struct wseg *) 0;
719 new_tail = curr = newseg();
720 curr->nseg = (struct wseg *) 0;
724 while (i < num_segs) {
725 curr->nseg = newseg();
727 curr->nseg = (struct wseg *) 0;
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.
745 struct wseg *curr = wtails[worm->wormno];
748 if (cansee(curr->wx, curr->wy))
755 /* would moving from <x1,y1> to <x2,y2> involve passing between two
756 consecutive segments of the same worm? */
758 worm_cross(x1, y1, x2, y2)
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).
774 if (distmin(x1, y1, x2, y2) != 1) {
775 impossible("worm_cross checking for non-adjacent location?");
778 /* attempting to pass between worm segs is only relevant for diagonal */
779 if (x1 == x2 || y1 == y2)
782 /* is the same monster at <x1,y2> and at <x2,y1>? */
784 if (!worm || m_at(x2, y1) != worm)
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) {
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... */