/* Force all chameleons to become normal */ void rescham() { struct monst *mtmp; for(mtmp = fmon; mtmp != NULL; mtmp = mtmp->nmon) { if(mtmp->cham != 0) { mtmp->cham = 0; newcham(mtmp, PM_CHAM); } } }
/* bhitm: monster mtmp was hit by the effect of wand otmp */ static void bhitm(struct monst *mtmp, struct obj *otmp) { wakeup(mtmp); switch (otmp->otyp) { case WAN_STRIKING: if (u.uswallow || rnd(20) < 10 + mtmp->data->ac) { int tmp = d(2, 12); hit("wand", mtmp, exclam(tmp)); mtmp->mhp -= tmp; if (mtmp->mhp < 1) killed(mtmp); } else miss("wand", mtmp); break; case WAN_SLOW_MONSTER: mtmp->mspeed = MSLOW; break; case WAN_SPEED_MONSTER: mtmp->mspeed = MFAST; break; case WAN_UNDEAD_TURNING: if (strchr(UNDEAD, mtmp->data->mlet)) { mtmp->mhp -= rnd(8); if (mtmp->mhp < 1) killed(mtmp); else mtmp->mflee = 1; } break; case WAN_POLYMORPH: if (newcham(mtmp, &mons[rn2(CMNUM)])) objects[otmp->otyp].oc_name_known = 1; break; case WAN_CANCELLATION: mtmp->mcan = 1; break; case WAN_TELEPORTATION: rloc(mtmp); break; case WAN_MAKE_INVISIBLE: mtmp->minvis = 1; break; #ifdef WAN_PROBING case WAN_PROBING: mstatusline(mtmp); break; #endif /* WAN_PROBING */ default: impossible("What an interesting wand (%u)", otmp->otyp); } }
/* * called with [x,y] = coordinates; * [0,0] means anyplace * [u.ux,u.uy] means: call mnexto (if !in_mklev) * * In case we make an Orc or killer bee, we make an entire horde (swarm); * note that in this case we return only one of them (the one at [x,y]). */ struct monst * makemon(struct permonst *ptr, int x, int y) { struct monst *mtmp; int tmp, ct; boolean anything = (!ptr); extern boolean in_mklev; if(x != 0 || y != 0) if(m_at(x,y)) return((struct monst *) 0); if(ptr){ if(strchr(fut_geno, ptr->mlet)) return((struct monst *) 0); } else { ct = CMNUM - strlen(fut_geno); if(strchr(fut_geno, 'm')) ct++; /* make only 1 minotaur */ if(strchr(fut_geno, '@')) ct++; if(ct <= 0) return(0); /* no more monsters! */ tmp = rn2(ct*dlevel/24 + 7); if(tmp < dlevel - 4) tmp = rn2(ct*dlevel/24 + 12); if(tmp >= ct) tmp = rn1(ct - ct/2, ct/2); for(ct = 0; ct < CMNUM; ct++){ ptr = &mons[ct]; if(strchr(fut_geno, ptr->mlet)) continue; if(!tmp--) goto gotmon; } panic("makemon?"); } gotmon: mtmp = newmonst(ptr->pxlth); *mtmp = zeromonst; /* clear all entries in structure */ for(ct = 0; ct < ptr->pxlth; ct++) ((char *) &(mtmp->mextra[0]))[ct] = 0; mtmp->nmon = fmon; fmon = mtmp; mtmp->m_id = flags.ident++; mtmp->data = ptr; mtmp->mxlth = ptr->pxlth; if(ptr->mlet == 'D') mtmp->mhpmax = mtmp->mhp = 80; else if(!ptr->mlevel) mtmp->mhpmax = mtmp->mhp = rnd(4); else mtmp->mhpmax = mtmp->mhp = d(ptr->mlevel, 8); mtmp->mx = x; mtmp->my = y; mtmp->mcansee = 1; if(ptr->mlet == 'M'){ mtmp->mimic = 1; mtmp->mappearance = ']'; } if(!in_mklev) { if(x == u.ux && y == u.uy && ptr->mlet != ' ') mnexto(mtmp); if(x == 0 && y == 0) rloc(mtmp); } if(ptr->mlet == 's' || ptr->mlet == 'S') { mtmp->mhide = mtmp->mundetected = 1; if(in_mklev) if(mtmp->mx && mtmp->my) (void) mkobj_at(0, mtmp->mx, mtmp->my); } if(ptr->mlet == ':') { mtmp->cham = 1; (void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); } if(ptr->mlet == 'I' || ptr->mlet == ';') mtmp->minvis = 1; if(ptr->mlet == 'L' || ptr->mlet == 'N' || (in_mklev && strchr("&w;", ptr->mlet) && rn2(5)) ) mtmp->msleep = 1; #ifndef NOWORM if(ptr->mlet == 'w' && getwn(mtmp)) initworm(mtmp); #endif /* NOWORM */ if(anything) if(ptr->mlet == 'O' || ptr->mlet == 'k') { coord mm; int cnt = rnd(10); mm.x = x; mm.y = y; while(cnt--) { mm = enexto(mm.x, mm.y); (void) makemon(ptr, mm.x, mm.y); } } return(mtmp); }
/* Returns 1 if monster died moving, 0 otherwise */ int dochug(struct monst *mtmp) { struct permonst *mdat; int tmp = 0; if((mtmp->cham != 0) && (rn2(6) == 0)) { newcham(mtmp, &mons[(dlevel + 14) + rn2((CMNUM - 14) - dlevel)]); } mdat = mtmp->data; if(mdat->mlevel < 0) { panic("bad monster %c (%d)", mdat->mlet, mdat->mlevel); } if((((moves % 20) == 0) || (index("ViT", mdat->mlet) != 0)) && (mtmp->mhp < mtmp->orig_hp)) { /* Regenerate monsters. */ ++mtmp->mhp; } if(mtmp->mfroz != 0) { /* Frozen monsters don't do anything. */ return 0; } if(mtmp->msleep != 0) { /* Wake up a monster, or get out of here. */ if((cansee(mtmp->mx, mtmp->my) != 0) && (Stealth == 0) && ((index("NL", mdat->mlet) == 0) || (rn2(50) == 0)) && ((Aggravate_monster != 0) || ((rn2(7) == 0) && (mtmp->mimic == 0)))) { mtmp->msleep = 0; } else { return 0; } } /* Not frozen or sleeping: wipe out texts written in the dust */ wipe_engr_at(mtmp->mx, mtmp->my, 1); /* Confused monsters get unconfused with small probability */ if((mtmp->mconf != 0) && (rn2(50) == 0)) { mtmp->mconf = 0; } /* Some monsters teleport */ if((mtmp->mflee != 0) && (index("tNL", mdat->mlet) != 0) && (rn2(40) == 0)) { rloc(mtmp); return 0; } if(mdat->mmove < rnd(6)) { return 0; } if((mtmp->mflee != 0) || (mtmp->mconf != 0) || ((index("BIuy", mdat->mlet) != 0) && (rn2(4) == 0)) || ((mdat->mlet == 'L') && (u.ugold == 0) && ((mtmp->mgold != 0) || (rn2(2) != 0))) || (dist(mtmp->mx, mtmp->my) > 2) || ((mtmp->mcansee == 0) && (rn2(4) == 0)) || (mtmp->mpeaceful != 0)) { tmp = m_move(mtmp, 0); if((tmp != 0) && (mdat->mmove < 12)) { if(tmp == 2) { return 1; } else { return 0; } } } if(tmp == 2) { /* Monster died moving */ return 1; } if((index("Ea", mdat->mlet) == 0) && (dist(mtmp->mx, mtmp->my) < 3) && (mtmp->mpeaceful == 0) && (u.uhp > 0) && (sengr_at("Elbereth", u.ux, u.uy) == 0) && (sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy) == 0)) { if(mhitu(mtmp) != 0) { /* Monster died (e.g. 'y' or 'F') */ return 1; } } /* Extra movement for fast monsters */ if((mdat->mmove - 12) > rnd(12)) { tmp = m_move(mtmp, 1); } if(tmp == 2) { return 1; } else { return 0; } }