/* * worm_nomove() * * Check for mon->wormno before calling this function! * * The worm don't move so it should shrink. */ void worm_nomove(struct monst *worm) { shrink_worm((int) worm->wormno); /* shrink */ if (worm->mhp > 3) worm->mhp -= 3; /* mhpmax not changed ! */ else worm->mhp = 1; }
/* * worm_move() * * Check for mon->wormno before calling this function! * * Move the worm. Maybe grow. */ void worm_move(struct monst *worm) { struct wseg *seg, *new_seg; /* new segment */ int wnum = worm->wormno; /* worm number */ /* if (!wnum) return; bullet proofing */ /* * Place a segment at the old worm head. The head has already moved. */ seg = level->wheads[wnum]; place_worm_seg(worm, seg->wx, seg->wy); newsym(seg->wx, seg->wy); /* display the new segment */ /* * Create a new dummy segment head and place it at the end of the list. */ new_seg = malloc(sizeof (struct wseg)); new_seg->wx = worm->mx; new_seg->wy = worm->my; new_seg->nseg = NULL; seg->nseg = new_seg; /* attach it to the end of the list */ level->wheads[wnum] = new_seg; /* move the end pointer */ if (level->wgrowtime[wnum] <= moves) { if (!level->wgrowtime[wnum]) level->wgrowtime[wnum] = moves + rnd(5); else level->wgrowtime[wnum] += rn1(15, 3); worm->mhp += 3; if (worm->mhp > MHPMAX) worm->mhp = MHPMAX; if (worm->mhp > worm->mhpmax) worm->mhpmax = worm->mhp; } else /* The worm doesn't grow, so the last segment goes away. */ shrink_worm(wnum); }
/* cutworm() * * Check for mon->wormno before calling this function! * * When hitting a worm (worm) at position x, y, with a weapon (weap), * there is a chance that the worm will be cut in half, and a chance * that both halves will survive. */ void cutworm(struct monst *worm, xchar x, xchar y, struct obj *weap) { struct wseg *curr, *new_tail; struct monst *new_worm; int wnum = worm->wormno; int cut_chance, new_wnum; if (!wnum) return; /* bullet proofing */ if (x == worm->mx && y == worm->my) return; /* hit on head */ /* cutting goes best with a bladed weapon */ cut_chance = rnd(20); /* Normally 1-16 does not cut */ /* Normally 17-20 does */ if (weap && objects[weap->otyp].oc_dir & SLASH) cut_chance += 10; /* With a slashing weapon 1- 6 does not cut */ /* 7-20 does */ if (cut_chance < 17) return; /* not good enough */ /* Find the segment that was attacked. */ curr = level->wtails[wnum]; while ((curr->wx != x) || (curr->wy != y)) { curr = curr->nseg; if (!curr) { impossible("cutworm: no segment at (%d,%d)", (int)x, (int)y); return; } } /* If this is the tail segment, then the worm just loses it. */ if (curr == level->wtails[wnum]) { shrink_worm(wnum); return; } /* * Split the worm. The tail for the new worm is the old worm's tail. * The tail for the old worm is the segment that follows "curr", * and "curr" becomes the dummy segment under the new head. */ new_tail = level->wtails[wnum]; level->wtails[wnum] = curr->nseg; curr->nseg = NULL; /* split the worm */ /* * At this point, the old worm is correct. Any new worm will have * it's head at "curr" and its tail at "new_tail". */ /* Sometimes the tail end dies. */ if (rn2(3) || !(new_wnum = get_wormno(level)) || !worm->m_lev) { cutoff(worm, new_tail); return; } remove_monster(level, x, y); /* clone_mon puts new head here */ if (!(new_worm = clone_mon(worm, x, y))) { cutoff(worm, new_tail); return; } new_worm->wormno = new_wnum; /* affix new worm number */ /* Devalue the monster level of both halves of the worm. */ worm->m_lev = ((unsigned)worm->m_lev <= 3) ? (unsigned)worm->m_lev : max((unsigned)worm->m_lev - 2, 3); new_worm->m_lev = worm->m_lev; /* Calculate the mhp on the new_worm for the (lower) monster level. */ new_worm->mhpmax = new_worm->mhp = dice((int)new_worm->m_lev, 8); /* Calculate the mhp on the old worm for the (lower) monster level. */ if (worm->m_lev > 3) { worm->mhpmax = dice((int)worm->m_lev, 8); if (worm->mhpmax < worm->mhp) worm->mhp = worm->mhpmax; } level->wtails[new_wnum] = new_tail; /* We've got all the info right now */ level->wheads[new_wnum] = curr; /* so we can do this faster than */ level->wgrowtime[new_wnum] = 0L; /* trying to call initworm(). */ /* Place the new monster at all the segment locations. */ place_wsegs(new_worm); if (flags.mon_moving) pline(msgc_monneutral, "%s is cut in half.", Monnam(worm)); else pline(msgc_combatgood, "You cut %s in half.", mon_nam(worm)); }