/* cutoff() * * Remove the tail of a worm and adjust the hp of the worm. */ static void cutoff(struct monst *worm, struct wseg *tail) { if (flags.mon_moving) pline("Part of the tail of %s is cut off.", mon_nam(worm)); else pline("You cut part of the tail off of %s.", mon_nam(worm)); toss_wsegs(level, tail, TRUE); if (worm->mhp > 1) worm->mhp /= 2; }
/* wnum: worm number */ static void shrink_worm(int wnum) { struct wseg *seg; if (level->wtails[wnum] == level->wheads[wnum]) return; /* no tail */ seg = level->wtails[wnum]; level->wtails[wnum] = seg->nseg; seg->nseg = NULL; toss_wsegs(level, seg, TRUE); }
/* * place_worm_tail_randomly() * * Place a worm tail somewhere on a level behind the head. * This routine essentially reverses the order of the wsegs from head * to tail while placing them. * x, and y are most likely the worm->mx, and worm->my, but don't *need* to * be, if somehow the head is disjoint from the tail. */ void place_worm_tail_randomly(struct monst *worm, xchar x, xchar y, enum rng rng) { int wnum = worm->wormno; struct level *lev = worm->dlevel; struct wseg *curr = lev->wtails[wnum]; struct wseg *new_tail; xchar ox = x, oy = y; /* if (!wnum) return; bullet proofing */ if (wnum && (!lev->wtails[wnum] || !lev->wheads[wnum])) { impossible("place_worm_tail_randomly: wormno is set without a tail!"); return; } lev->wheads[wnum] = new_tail = curr; curr = curr->nseg; new_tail->nseg = NULL; new_tail->wx = x; new_tail->wy = y; while (curr) { xchar nx, ny; char tryct = 0; /* pick a random direction from x, y and search for goodpos() */ do { random_dir(ox, oy, &nx, &ny, rng); } while (!goodpos(lev, nx, ny, worm, 0) && (tryct++ < 50)); if (tryct < 50) { place_worm_seg(worm, nx, ny); curr->wx = ox = nx; curr->wy = oy = ny; lev->wtails[wnum] = curr; curr = curr->nseg; lev->wtails[wnum]->nseg = new_tail; new_tail = lev->wtails[wnum]; if (lev == level) newsym(nx, ny); } else { /* Oops. Truncate because there was */ toss_wsegs(lev, curr, FALSE); /* no place for the rest of it */ curr = NULL; } } }
/* * wormgone() * * Check for mon->wormno before calling this function! * * Kill a worm tail. */ void wormgone(struct monst *worm) { struct level *lev = worm->dlevel; int wnum = worm->wormno; /* if (!wnum) return; bullet proofing */ worm->wormno = 0; /* This will also remove the real monster (ie 'w') from the its position in level->monsters[][]. */ toss_wsegs(lev, lev->wtails[wnum], TRUE); lev->wheads[wnum] = lev->wtails[wnum] = NULL; }