1 /* NetHack 3.6 worm.c $NHDT-Date: 1561340880 2019/06/24 01:48:00 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.30 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2009. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020 */
9 /* JNetHack may be freely redistributed. See license for details. */
14 #define newseg() (struct wseg *) alloc(sizeof (struct wseg))
15 #define dealloc_seg(wseg) free((genericptr_t) (wseg))
17 /* worm segment structure */
20 xchar wx, wy; /* the segment's position */
23 STATIC_DCL void FDECL(toss_wsegs, (struct wseg *, BOOLEAN_P));
24 STATIC_DCL void FDECL(shrink_worm, (int));
25 STATIC_DCL void FDECL(random_dir, (XCHAR_P, XCHAR_P, xchar *, xchar *));
26 STATIC_DCL struct wseg *FDECL(create_worm_tail, (int));
28 /* Description of long worm implementation.
30 * Each monst struct of the head of a tailed worm has a wormno set to
31 * 1 <= wormno < MAX_NUM_WORMS
32 * If wormno == 0 this does not mean that the monster is not a worm,
33 * it just means that the monster does not have a long worm tail.
35 * The actual segments of a worm are not full blown monst structs.
36 * They are small wseg structs, and their position in the levels.monsters[][]
37 * array is held by the monst struct of the head of the worm. This makes
38 * things like probing and hit point bookkeeping much easier.
40 * The segments of the long worms on a level are kept as an array of
41 * singly threaded linked lists. The wormno variable is used as an index
42 * for these segment arrays.
44 * wtails: The first (starting struct) of a linked list. This points
45 * to the tail (last) segment of the worm.
47 * wheads: The last (end) of a linked list of segments. This points to
48 * the segment that is at the same position as the real monster
49 * (the head). Note that the segment that wheads[wormno] points
50 * to, is not displayed. It is simply there to keep track of
51 * where the head came from, so that worm movement and display
52 * are simplified later.
53 * Keeping the head segment of the worm at the end of the list
54 * of tail segments is an endless source of confusion, but it is
56 * From now on, we will use "start" and "end" to refer to the
57 * linked list and "head" and "tail" to refer to the worm.
59 * One final worm array is:
61 * wgrowtime: This tells us when to add another segment to the worm.
63 * When a worm is moved, we add a new segment at the head, and delete the
64 * segment at the tail (unless we want it to grow). This new head segment is
65 * located in the same square as the actual head of the worm. If we want
66 * to grow the worm, we don't delete the tail segment, and we give the worm
67 * extra hit points, which possibly go into its maximum.
69 * Non-moving worms (worm_nomove) are assumed to be surrounded by their own
70 * tail, and, thus, shrink instead of grow (as their tails keep going while
71 * their heads are stopped short). In this case, we delete the last tail
72 * segment, and remove hit points from the worm.
75 struct wseg *wheads[MAX_NUM_WORMS] = DUMMY, *wtails[MAX_NUM_WORMS] = DUMMY;
76 long wgrowtime[MAX_NUM_WORMS] = DUMMY;
81 * Find an unused worm tail slot and return the index. A zero means that
82 * there are no slots available. This means that the worm head can exist,
83 * it just cannot ever grow a tail.
85 * It, also, means that there is an optimisation to made. The [0] positions
86 * of the arrays are never used. Meaning, we really *could* have one more
87 * tailed worm on the level, or use a smaller array (using wormno - 1).
89 * Implementation is left to the interested hacker.
94 register int new_wormno = 1;
96 while (new_wormno < MAX_NUM_WORMS) {
97 if (!wheads[new_wormno])
98 return new_wormno; /* found empty wtails[] slot at new_wormno */
101 return 0; /* level infested with worms */
107 * Use if (mon->wormno = get_wormno()) before calling this function!
109 * Initialize the worm entry. This will set up the worm grow time, and
110 * create and initialize the dummy segment for wheads[] and wtails[].
112 * If the worm has no tail (ie get_wormno() fails) then this function need
116 initworm(worm, wseg_count)
120 register struct wseg *seg, *new_tail = create_worm_tail(wseg_count);
121 register int wnum = worm->wormno;
123 /* if (!wnum) return; bullet proofing */
126 wtails[wnum] = new_tail;
127 for (seg = new_tail; seg->nseg; seg = seg->nseg)
131 wtails[wnum] = wheads[wnum] = seg = newseg();
132 seg->nseg = (struct wseg *) 0;
136 wgrowtime[wnum] = 0L;
142 * Get rid of all worm segments on and following the given pointer curr.
143 * The display may or may not need to be updated as we free the segments.
147 toss_wsegs(curr, display_update)
148 register struct wseg *curr;
149 register boolean display_update;
151 register struct wseg *seg;
156 /* remove from level.monsters[][] */
158 /* need to check curr->wx for genocided while migrating_mon */
160 remove_monster(curr->wx, curr->wy);
162 /* update screen before deallocation */
164 newsym(curr->wx, curr->wy);
167 /* free memory used by the segment */
176 * Remove the tail segment of the worm (the starting segment of the list).
181 int wnum; /* worm number */
185 if (wtails[wnum] == wheads[wnum])
186 return; /* no tail */
189 wtails[wnum] = seg->nseg;
190 seg->nseg = (struct wseg *) 0;
191 toss_wsegs(seg, TRUE);
197 * Check for mon->wormno before calling this function!
199 * Move the worm. Maybe grow.
205 register struct wseg *seg, *new_seg; /* new segment */
206 register int wnum = worm->wormno; /* worm number */
208 /* if (!wnum) return; bullet proofing */
211 * Place a segment at the old worm head. The head has already moved.
214 place_worm_seg(worm, seg->wx, seg->wy);
215 newsym(seg->wx, seg->wy); /* display the new segment */
218 * Create a new dummy segment head and place it at the end of the list.
221 new_seg->wx = worm->mx;
222 new_seg->wy = worm->my;
223 new_seg->nseg = (struct wseg *) 0;
224 seg->nseg = new_seg; /* attach it to the end of the list */
225 wheads[wnum] = new_seg; /* move the end pointer */
227 if (wgrowtime[wnum] <= moves) {
228 if (!wgrowtime[wnum])
229 wgrowtime[wnum] = moves + rnd(5);
231 wgrowtime[wnum] += rn1(15, 3);
233 if (worm->mhp > MHPMAX)
235 if (worm->mhp > worm->mhpmax)
236 worm->mhpmax = worm->mhp;
238 /* The worm doesn't grow, so the last segment goes away. */
245 * Check for mon->wormno before calling this function!
247 * The worm don't move so it should shrink.
251 register struct monst *worm;
253 shrink_worm((int) worm->wormno); /* shrink */
256 worm->mhp -= 3; /* mhpmax not changed ! */
264 * Check for mon->wormno before calling this function!
270 register struct monst *worm;
272 register int wnum = worm->wormno;
274 /* if (!wnum) return; bullet proofing */
278 /* This will also remove the real monster (ie 'w') from the its
279 * position in level.monsters[][].
281 toss_wsegs(wtails[wnum], TRUE);
283 wheads[wnum] = wtails[wnum] = (struct wseg *) 0;
289 * Check for mon->wormno before calling this function!
291 * If the hero is near any part of the worm, the worm will try to attack.
295 register struct monst *worm;
297 register int wnum = worm->wormno;
298 register struct wseg *seg;
300 /* if (!wnum) return; bullet proofing */
302 /* This does not work right now because mattacku() thinks that the head
303 * is out of range of the player. We might try to kludge, and bring
304 * the head within range for a tiny moment, but this needs a bit more
305 * looking at before we decide to do this.
307 for (seg = wtails[wnum]; seg; seg = seg->nseg)
308 if (distu(seg->wx, seg->wy) < 3)
310 return; /* your passive ability killed the worm */
315 * Check for mon->wormno before calling this function!
317 * When hitting a worm (worm) at position x, y, with a weapon (weap),
318 * there is a chance that the worm will be cut in half, and a chance
319 * that both halves will survive.
322 cutworm(worm, x, y, cuttier)
325 boolean cuttier; /* hit is by wielded blade or axe or by thrown axe */
327 register struct wseg *curr, *new_tail;
328 register struct monst *new_worm;
329 int wnum = worm->wormno;
330 int cut_chance, new_wnum;
333 return; /* bullet proofing */
335 if (x == worm->mx && y == worm->my)
336 return; /* hit on head */
338 /* cutting goes best with a cuttier weapon */
339 cut_chance = rnd(20); /* Normally 1-16 does not cut, 17-20 does, */
341 cut_chance += 10; /* with a blade 1- 6 does not cut, 7-20 does. */
344 return; /* not good enough */
346 /* Find the segment that was attacked. */
349 while ((curr->wx != x) || (curr->wy != y)) {
352 impossible("cutworm: no segment at (%d,%d)", (int) x, (int) y);
357 /* If this is the tail segment, then the worm just loses it. */
358 if (curr == wtails[wnum]) {
364 * Split the worm. The tail for the new worm is the old worm's tail.
365 * The tail for the old worm is the segment that follows "curr",
366 * and "curr" becomes the dummy segment under the new head.
368 new_tail = wtails[wnum];
369 wtails[wnum] = curr->nseg;
370 curr->nseg = (struct wseg *) 0; /* split the worm */
373 * At this point, the old worm is correct. Any new worm will have
374 * it's head at "curr" and its tail at "new_tail". The old worm
375 * 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 place_worm_seg(worm, x, y); /* place the "head" segment back */
390 if (context.mon_moving) {
391 if (canspotmon(worm))
393 pline("Part of %s tail has been cut off.",
394 s_suffix(mon_nam(worm)));
396 pline("%s
\82Ì
\90K
\94ö
\82Ì
\88ê
\95\94\95ª
\82ª
\90Ø
\82è
\97\8e\82Æ
\82³
\82ê
\82½
\81D",
401 You("cut part of the tail off of %s.", mon_nam(worm));
403 You("%s
\82Ì
\90K
\94ö
\82Ì
\88ê
\95\94\95ª
\82ð
\90Ø
\82Á
\82½
\81D", mon_nam(worm));
404 toss_wsegs(new_tail, TRUE);
410 new_worm->wormno = new_wnum; /* affix new worm number */
411 new_worm->mcloned = 0; /* treat second worm as a normal monster */
413 /* Devalue the monster level of both halves of the worm.
414 Note: m_lev is always at least 3 in order to get this far. */
415 worm->m_lev = max((unsigned) worm->m_lev - 2, 3);
416 new_worm->m_lev = worm->m_lev;
418 /* Calculate the lower-level mhp; use <N>d8 for long worms.
419 Can't use newmonhp() here because it would reset m_lev. */
420 new_worm->mhpmax = new_worm->mhp = d((int) new_worm->m_lev, 8);
421 worm->mhpmax = d((int) worm->m_lev, 8); /* new maxHP for old worm */
422 if (worm->mhpmax < worm->mhp)
423 worm->mhp = worm->mhpmax;
425 wtails[new_wnum] = new_tail; /* We've got all the info right now */
426 wheads[new_wnum] = curr; /* so we can do this faster than */
427 wgrowtime[new_wnum] = 0L; /* trying to call initworm(). */
429 /* Place the new monster at all the segment locations. */
430 place_wsegs(new_worm, worm);
432 if (context.mon_moving)
434 pline("%s is cut in half.", Monnam(worm));
436 pline("%s
\82Í
\90^
\82Á
\82Õ
\82½
\82Â
\82É
\82³
\82ê
\82½
\81D", Monnam(worm));
439 You("cut %s in half.", mon_nam(worm));
441 You("%s
\82ð
\90^
\82Á
\82Õ
\82½
\82Â
\82É
\82µ
\82½
\81D", mon_nam(worm));
447 * Refresh all of the segments of the given worm. This is only called
448 * from see_monster() in display.c or when a monster goes minvis. It
449 * is located here for modularity.
455 struct wseg *curr = wtails[worm->wormno];
457 /* if (!mtmp->wormno) return; bullet proofing */
459 while (curr != wheads[worm->wormno]) {
460 newsym(curr->wx, curr->wy);
468 * Display all of the segments of the given worm for detection.
471 detect_wsegs(worm, use_detection_glyph)
473 boolean use_detection_glyph;
476 struct wseg *curr = wtails[worm->wormno];
478 /* if (!mtmp->wormno) return; bullet proofing */
479 int what_tail = what_mon(PM_LONG_WORM_TAIL, newsym_rn2);
481 while (curr != wheads[worm->wormno]) {
482 num = use_detection_glyph
483 ? detected_monnum_to_glyph(what_tail)
485 ? petnum_to_glyph(what_tail)
486 : monnum_to_glyph(what_tail));
487 show_glyph(curr->wx, curr->wy, num);
495 * Save the worm information for later use. The count is the number
496 * of segments, including the dummy. Called from save.c.
504 struct wseg *curr, *temp;
506 if (perform_bwrite(mode)) {
507 for (i = 1; i < MAX_NUM_WORMS; i++) {
508 for (count = 0, curr = wtails[i]; curr; curr = curr->nseg)
510 /* Save number of segments */
511 bwrite(fd, (genericptr_t) &count, sizeof(int));
512 /* Save segment locations of the monster. */
514 for (curr = wtails[i]; curr; curr = curr->nseg) {
515 bwrite(fd, (genericptr_t) & (curr->wx), sizeof(xchar));
516 bwrite(fd, (genericptr_t) & (curr->wy), sizeof(xchar));
520 bwrite(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
523 if (release_data(mode)) {
524 /* Free the segments only. savemonchn() will take care of the
526 for (i = 1; i < MAX_NUM_WORMS; i++) {
527 if (!(curr = wtails[i]))
532 dealloc_seg(curr); /* free the segment */
535 wheads[i] = wtails[i] = (struct wseg *) 0;
543 * Restore the worm information from the save file. Called from restore.c
550 struct wseg *curr, *temp;
552 for (i = 1; i < MAX_NUM_WORMS; i++) {
553 mread(fd, (genericptr_t) &count, sizeof(int));
557 /* Get the segments. */
558 for (curr = (struct wseg *) 0, j = 0; j < count; j++) {
560 temp->nseg = (struct wseg *) 0;
561 mread(fd, (genericptr_t) & (temp->wx), sizeof(xchar));
562 mread(fd, (genericptr_t) & (temp->wy), sizeof(xchar));
571 mread(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
577 * Place the segments of the given worm. Called from restore.c
578 * If oldworm is not NULL, assumes the oldworm segments are on map
579 * in the same location as worm segments
582 place_wsegs(worm, oldworm)
583 struct monst *worm, *oldworm;
585 struct wseg *curr = wtails[worm->wormno];
587 /* if (!mtmp->wormno) return; bullet proofing */
589 while (curr != wheads[worm->wormno]) {
594 if (m_at(x,y) == oldworm)
595 remove_monster(x, y);
597 impossible("placing worm seg <%i,%i> over another mon", x, y);
599 place_worm_seg(worm, x, y);
605 sanity_check_worm(worm)
613 panic("not a worm?!");
615 curr = wtails[worm->wormno];
617 while (curr != wheads[worm->wormno]) {
619 if (!isok(curr->wx, curr->wy))
620 panic("worm seg not isok");
621 if (level.monsters[curr->wx][curr->wy] != worm)
622 panic("worm not at seg location");
631 * This function is equivalent to the remove_monster #define in
632 * rm.h, only it will take the worm *and* tail out of the levels array.
633 * It does not get rid of (dealloc) the worm tail structures, and it does
634 * not remove the mon from the fmon chain.
638 register struct monst *worm;
640 register struct wseg *curr = wtails[worm->wormno];
642 /* if (!mtmp->wormno) return; bullet proofing */
646 remove_monster(curr->wx, curr->wy);
647 newsym(curr->wx, curr->wy);
655 * place_worm_tail_randomly()
657 * Place a worm tail somewhere on a level behind the head.
658 * This routine essentially reverses the order of the wsegs from head
659 * to tail while placing them.
660 * x, and y are most likely the worm->mx, and worm->my, but don't *need* to
661 * be, if somehow the head is disjoint from the tail.
664 place_worm_tail_randomly(worm, x, y)
668 int wnum = worm->wormno;
669 struct wseg *curr = wtails[wnum];
670 struct wseg *new_tail;
671 register xchar ox = x, oy = y;
673 /* if (!wnum) return; bullet proofing */
675 if (wnum && (!wtails[wnum] || !wheads[wnum])) {
676 impossible("place_worm_tail_randomly: wormno is set without a tail!");
680 wheads[wnum] = new_tail = curr;
682 new_tail->nseg = (struct wseg *) 0;
690 /* pick a random direction from x, y and search for goodpos() */
692 random_dir(ox, oy, &nx, &ny);
693 } while (!goodpos(nx, ny, worm, 0) && (tryct++ < 50));
696 place_worm_seg(worm, nx, ny);
701 wtails[wnum]->nseg = new_tail;
702 new_tail = wtails[wnum];
704 } else { /* Oops. Truncate because there was */
705 toss_wsegs(curr, FALSE); /* no place for the rest of it */
706 curr = (struct wseg *) 0;
712 * Given a coordinate x, y.
713 * return in *nx, *ny, the coordinates of one of the <= 8 squares adjoining.
715 * This function, and the loop it serves, could be eliminated by coding
716 * enexto() with a search radius.
720 random_dir(x, y, nx, ny)
724 *nx = x + (x > 1 /* extreme left ? */
725 ? (x < COLNO - 1 /* extreme right ? */
726 ? (rn2(3) - 1) /* neither so +1, 0, or -1 */
727 : -rn2(2)) /* right edge, use -1 or 0 */
728 : rn2(2)); /* left edge, use 0 or 1 */
729 if (*nx != x) /* if x has changed, do same thing with y */
730 *ny = y + (y > 0 /* y==0 is ok (x==0 is not) */
735 else /* when x has remained the same, force y to change */
738 ? (rn2(2) ? 1 : -1) /* not at edge, so +1 or -1 */
739 : -1) /* bottom, use -1 */
740 : 1); /* top, use +1 */
743 /* for size_monst(cmd.c) to support #stats */
748 return (int) (count_wsegs(worm) * sizeof (struct wseg));
752 * returns the number of segments that a worm has.
759 register struct wseg *curr;
762 for (curr = wtails[mtmp->wormno]->nseg; curr; curr = curr->nseg)
768 /* create_worm_tail()
769 * will create a worm tail chain of (num_segs + 1) and return pointer to it.
773 create_worm_tail(num_segs)
777 register struct wseg *new_tail, *curr;
780 return (struct wseg *) 0;
782 new_tail = curr = newseg();
783 curr->nseg = (struct wseg *) 0;
787 while (i < num_segs) {
788 curr->nseg = newseg();
790 curr->nseg = (struct wseg *) 0;
800 * Is any segment of this worm in viewing range? Note: caller must check
801 * invisibility and telepathy (which should only show the head anyway).
802 * Mostly used in the canseemon() macro.
808 struct wseg *curr = wtails[worm->wormno];
811 if (cansee(curr->wx, curr->wy))
818 /* would moving from <x1,y1> to <x2,y2> involve passing between two
819 consecutive segments of the same worm? */
821 worm_cross(x1, y1, x2, y2)
825 struct wseg *curr, *wnxt;
828 * With digits representing relative sequence number of the segments,
829 * returns true when testing between @ and ? (passes through worm's
830 * body), false between @ and ! (stays on same side of worm).
837 if (distmin(x1, y1, x2, y2) != 1) {
838 impossible("worm_cross checking for non-adjacent location?");
841 /* attempting to pass between worm segs is only relevant for diagonal */
842 if (x1 == x2 || y1 == y2)
845 /* is the same monster at <x1,y2> and at <x2,y1>? */
847 if (!worm || m_at(x2, y1) != worm)
850 /* same monster is at both adjacent spots, so must be a worm; we need
851 to figure out if the two spots are occupied by consecutive segments */
852 for (curr = wtails[worm->wormno]; curr; curr = wnxt) {
855 break; /* no next segment; can't continue */
857 /* we don't know which of <x1,y2> or <x2,y1> we'll hit first, but
858 whichever it is, they're consecutive iff next seg is the other */
859 if (curr->wx == x1 && curr->wy == y2)
860 return (boolean) (wnxt->wx == x2 && wnxt->wy == y1);
861 if (curr->wx == x2 && curr->wy == y1)
862 return (boolean) (wnxt->wx == x1 && wnxt->wy == y2);
864 /* should never reach here... */
868 /* construct an index number for a worm tail segment */
876 if (worm && worm->wormno && m_at(x, y) == worm) {
879 xchar wx = (xchar) x, wy = (xchar) y;
881 for (i = 0, curr = wtails[worm->wormno]; curr; curr = curr->nseg) {
882 if (curr->wx == wx && curr->wy == wy)
886 for (n = i; curr; curr = curr->nseg)