void hit(const char *str, struct monst *mtmp, const char *force) /* force: usually either "." or "!" */ { if(!cansee(mtmp->mx,mtmp->my)) pline("The %s hits it.", str); else pline("The %s hits %s%s", str, monnam(mtmp), force); }
void miss(const char *str, struct monst *mtmp) { if (!cansee(mtmp->mx, mtmp->my)) pline("The %s misses it.", str); else pline("The %s misses %s.", str, monnam(mtmp)); }
/* ARGSUSED */ static void use_camera(struct obj *obj) { struct monst *mtmp; if (!getdir(1)){ /* ask: in what direction? */ flags.move = multi = 0; return; } if (u.uswallow) { pline("You take a picture of %s's stomach.", monnam(u.ustuck)); return; } if (u.dz) { pline("You take a picture of the %s.", (u.dz > 0) ? "floor" : "ceiling"); return; } if ((mtmp = bchit(u.dx, u.dy, COLNO, '!'))) { if(mtmp->msleep){ mtmp->msleep = 0; pline("The flash awakens %s.", monnam(mtmp)); /* a3 */ } else if(mtmp->data->mlet != 'y') if(mtmp->mcansee || mtmp->mblinded){ int tmp = dist(mtmp->mx,mtmp->my); int tmp2; if(cansee(mtmp->mx,mtmp->my)) pline("%s is blinded by the flash!", Monnam(mtmp)); setmangry(mtmp); if(tmp < 9 && !mtmp->isshk && rn2(4)) { mtmp->mflee = 1; if(rn2(4)) mtmp->mfleetim = rnd(100); } if(tmp < 3) mtmp->mcansee = mtmp->mblinded = 0; else { tmp2 = mtmp->mblinded; tmp2 += rnd(1 + 50/tmp); if(tmp2 > 127) tmp2 = 127; mtmp->mblinded = tmp2; mtmp->mcansee = 0; } } } }
int dozap(void) { struct obj *obj; xchar zx,zy; obj = getobj("/", "zap"); if(!obj) return(0); if(obj->spe < 0 || (obj->spe == 0 && rn2(121))) { pline("Nothing Happens."); return(1); } if(obj->spe == 0) pline("You wrest one more spell from the worn-out wand."); if(!(objects[obj->otyp].bits & NODIR) && !getdir(1)) return(1); /* make him pay for knowing !NODIR */ obj->spe--; if(objects[obj->otyp].bits & IMMEDIATE) { if(u.uswallow) bhitm(u.ustuck, obj); else if(u.dz) { if(u.dz > 0) { struct obj *otmp = o_at(u.ux, u.uy); if(otmp) bhito(otmp, obj); } } else bhit(u.dx,u.dy,rn1(8,6),0,bhitm,bhito,obj); } else { switch(obj->otyp){ case WAN_LIGHT: litroom(TRUE); break; case WAN_SECRET_DOOR_DETECTION: if(!findit()) return(1); break; case WAN_CREATE_MONSTER: { int cnt = 1; if(!rn2(23)) cnt += rn2(7) + 1; while(cnt--) makemon(NULL, u.ux, u.uy); } break; case WAN_WISHING: { char buf[BUFSZ]; struct obj *otmp; if(u.uluck + rn2(5) < 0) { pline("Unfortunately, nothing happens."); break; } pline("You may wish for an object. What do you want? "); getlin(buf); if(buf[0] == '\033') buf[0] = 0; otmp = readobjnam(buf); otmp = addinv(otmp); prinv(otmp); break; } case WAN_DIGGING: /* Original effect (approximately): * from CORR: dig until we pierce a wall * from ROOM: piece wall and dig until we reach * an ACCESSIBLE place. * Currently: dig for digdepth positions; * also down on request of Lennart Augustsson. */ { struct rm *room; int digdepth; if(u.uswallow) { struct monst *mtmp = u.ustuck; pline("You pierce %s's stomach wall!", monnam(mtmp)); mtmp->mhp = 1; /* almost dead */ unstuck(mtmp); mnexto(mtmp); break; } if(u.dz) { if(u.dz < 0) { pline("You loosen a rock from the ceiling."); pline("It falls on your head!"); losehp(1, "falling rock"); mksobj_at(ROCK, u.ux, u.uy); fobj->quan = 1; stackobj(fobj); if(Invisible) newsym(u.ux, u.uy); } else { dighole(); } break; } zx = u.ux+u.dx; zy = u.uy+u.dy; digdepth = 8 + rn2(18); Tmp_at(-1, '*'); /* open call */ while(--digdepth >= 0) { if(!isok(zx,zy)) break; room = &levl[zx][zy]; Tmp_at(zx,zy); if(!xdnstair){ if(zx < 3 || zx > COLNO-3 || zy < 3 || zy > ROWNO-3) break; if(room->typ == HWALL || room->typ == VWALL){ room->typ = ROOM; break; } } else if(room->typ == HWALL || room->typ == VWALL || room->typ == SDOOR || room->typ == LDOOR){ room->typ = DOOR; digdepth -= 2; } else if(room->typ == SCORR || !room->typ) { room->typ = CORR; digdepth--; } mnewsym(zx,zy); zx += u.dx; zy += u.dy; } mnewsym(zx,zy); /* not always necessary */ Tmp_at(-1,-1); /* closing call */ break; } default: buzz((int) obj->otyp - WAN_MAGIC_MISSILE, u.ux, u.uy, u.dx, u.dy); break; } } return(1); }
/* Be careful not to call panic from here! */ void done(const char *st1) { #ifdef WIZARD if(wizard && *st1 == 'd'){ u.uswldtim = 0; if(u.uhpmax < 0) u.uhpmax = 100; /* arbitrary */ u.uhp = u.uhpmax; pline("For some reason you are still alive."); flags.move = 0; if(multi > 0) multi = 0; else multi = -1; flags.botl = 1; return; } #endif /* WIZARD */ signal(SIGINT, done_intr); signal(SIGQUIT, done_intr); signal(SIGHUP, done_hangup); if(*st1 == 'q' && u.uhp < 1){ st1 = "died"; killer = "quit while already on Charon's boat"; } if(*st1 == 's') killer = "starvation"; else if(*st1 == 'd' && st1[1] == 'r') killer = "drowning"; else if(*st1 == 'p') killer = "panic"; else if(*st1 == 't') killer = "trickery"; else if(!index("bcd", *st1)) killer = st1; paybill(); clearlocks(); if(flags.toplin == 1) more(); if(index("bcds", *st1)){ #ifdef WIZARD if(!wizard) #endif /* WIZARD */ savebones(); if(!flags.notombstone) outrip(); } if(*st1 == 'c') killer = st1; /* after outrip() */ settty(NULL); /* does a clear_screen() */ if(!done_stopprint) printf("Goodbye %s %s...\n\n", pl_character, plname); { long int tmp; tmp = u.ugold - u.ugold0; if(tmp < 0) tmp = 0; if(*st1 == 'd' || *st1 == 'b') tmp -= tmp/10; u.urexp += tmp; u.urexp += 50 * maxdlevel; if(maxdlevel > 20) u.urexp += 1000*((maxdlevel > 30) ? 10 : maxdlevel - 20); } if(*st1 == 'e') { struct monst *mtmp; struct obj *otmp; int i; unsigned worthlessct = 0; boolean has_amulet = FALSE; killer = st1; keepdogs(); mtmp = mydogs; if(mtmp) { if(!done_stopprint) printf("You"); while(mtmp) { if(!done_stopprint) printf(" and %s", monnam(mtmp)); if(mtmp->mtame) u.urexp += mtmp->mhp; mtmp = mtmp->nmon; } if(!done_stopprint) printf("\nescaped from the dungeon with %ld points,\n", u.urexp); } else if(!done_stopprint) printf("You escaped from the dungeon with %ld points,\n", u.urexp); for(otmp = invent; otmp; otmp = otmp->nobj) { if(otmp->olet == GEM_SYM){ i = otmp->quan*objects[otmp->otyp].g_val; if(i == 0) { worthlessct += otmp->quan; continue; } u.urexp += i; if(!done_stopprint) printf("\t%s (worth %d Zorkmids),\n", doname(otmp), i); } else if(otmp->olet == AMULET_SYM) { i = (otmp->spe < 0) ? 2 : 5000; u.urexp += i; if(!done_stopprint) printf("\t%s (worth %d Zorkmids),\n", doname(otmp), i); if(otmp->spe >= 0) { has_amulet = TRUE; killer = "escaped (with amulet)"; } } } if(worthlessct) if(!done_stopprint) printf("\t%u worthless piece%s of coloured glass,\n", worthlessct, plur(worthlessct)); if(has_amulet) u.urexp *= 2; } else if(!done_stopprint) printf("You %s on dungeon level %d with %ld points,\n", st1, dlevel, u.urexp); if(!done_stopprint) printf("and %ld piece%s of gold, after %ld move%s.\n", u.ugold, plur(u.ugold), moves, plur(moves)); if(!done_stopprint) printf("You were level %u with a maximum of %d hit points when you %s.\n", u.ulevel, u.uhpmax, st1); if(*st1 == 'e' && !done_stopprint){ getret(); /* all those pieces of coloured glass ... */ cls(); } #ifdef WIZARD if(!wizard) #endif /* WIZARD */ topten(); if(done_stopprint) printf("\n\n"); exit(0); }
/* return 0 (no move), 1 (move) or 2 (dead) */ int dog_move(struct monst *mtmp, int after) { int nx, ny, omx, omy, appr, nearer, j; int udist, chi, i, whappr; struct monst *mtmp2; struct permonst *mdat = mtmp->data; struct edog *edog = EDOG(mtmp); struct obj *obj; struct trap *trap; xchar cnt, chcnt, nix, niy; schar dogroom, uroom; xchar gx, gy, gtyp, otyp; /* current goal */ coord poss[9]; int info[9]; #define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy)) #define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy)) if(moves <= edog->eattime) return(0); /* dog is still eating */ omx = mtmp->mx; omy = mtmp->my; whappr = (moves - EDOG(mtmp)->whistletime < 5); if(moves > edog->hungrytime + 500 && !mtmp->mconf){ mtmp->mconf = 1; mtmp->mhpmax /= 3; if(mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax; if(cansee(omx,omy)) pline("%s is confused from hunger.", Monnam(mtmp)); else pline("You feel worried about %s.", monnam(mtmp)); } else if(moves > edog->hungrytime + 750 || mtmp->mhp < 1){ if(cansee(omx,omy)) pline("%s dies from hunger.", Monnam(mtmp)); else pline("You have a sad feeling for a moment, then it passes."); mondied(mtmp); return(2); } dogroom = inroom(omx,omy); uroom = inroom(u.ux,u.uy); udist = dist(omx,omy); /* maybe we tamed him while being swallowed --jgm */ if(!udist) return(0); /* if we are carrying sth then we drop it (perhaps near @) */ /* Note: if apport == 1 then our behaviour is independent of udist */ if(mtmp->minvent){ if(!rn2(udist) || !rn2((int) edog->apport)) if(rn2(10) < edog->apport){ relobj(mtmp, (int) mtmp->minvis); if(edog->apport > 1) edog->apport--; edog->dropdist = udist; /* hpscdi!jon */ edog->droptime = moves; } } else { if ((obj = o_at(omx,omy))) if(!strchr("0_", obj->olet)){ if((otyp = dogfood(obj)) <= CADAVER){ nix = omx; niy = omy; goto eatobj; } if (obj->owt < 10*mtmp->data->mlevel) if (rn2(20) < edog->apport+3) if (rn2(udist) || !rn2((int) edog->apport)){ freeobj(obj); unpobj(obj); /* if(levl[omx][omy].scrsym == obj->olet) newsym(omx,omy); */ mpickobj(mtmp,obj); } } } /* first we look for food */ gtyp = UNDEF; /* no goal as yet */ gx = gy = 0; for(obj = fobj; obj; obj = obj->nobj) { otyp = dogfood(obj); if(otyp > gtyp || otyp == UNDEF) continue; if(inroom(obj->ox,obj->oy) != dogroom) continue; if(otyp < MANFOOD && (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) { if(otyp < gtyp || (otyp == gtyp && DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){ gx = obj->ox; gy = obj->oy; gtyp = otyp; } } else if(gtyp == UNDEF && dogroom >= 0 && uroom == dogroom && !mtmp->minvent && edog->apport > rn2(8)){ gx = obj->ox; gy = obj->oy; gtyp = APPORT; } } if(gtyp == UNDEF || (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)){ if(dogroom < 0 || dogroom == uroom){ gx = u.ux; gy = u.uy; #ifndef QUEST } else { int tmp = rooms[(int)dogroom].fdoor; cnt = rooms[(int)dogroom].doorct; gx = gy = FAR; /* random, far away */ while(cnt--){ if(dist(gx,gy) > dist(doors[tmp].x, doors[tmp].y)){ gx = doors[tmp].x; gy = doors[tmp].y; } tmp++; } /* here gx == FAR e.g. when dog is in a vault */ if(gx == FAR || (gx == omx && gy == omy)){ gx = u.ux; gy = u.uy; } #endif /* QUEST */ } appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0; if(after && udist <= 4 && gx == u.ux && gy == u.uy) return(0); if(udist > 1){ if (!IS_ROOM(levl[(int)u.ux][(int)u.uy].typ) || !rn2(4) || whappr || (mtmp->minvent && rn2((int) edog->apport))) appr = 1; } /* if you have dog food he'll follow you more closely */ if (appr == 0) { obj = invent; while(obj){ if(obj->otyp == TRIPE_RATION){ appr = 1; break; } obj = obj->nobj; } } } else appr = 1; /* gtyp != UNDEF */ if(mtmp->mconf) appr = 0; if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)){ coord *cp; cp = gettrack(omx,omy); if(cp){ gx = cp->x; gy = cp->y; } } nix = omx; niy = omy; cnt = mfndpos(mtmp,poss,info,ALLOW_M | ALLOW_TRAPS); chcnt = 0; chi = -1; for(i=0; i<cnt; i++){ nx = poss[i].x; ny = poss[i].y; if(info[i] & ALLOW_M){ mtmp2 = m_at(nx,ny); if(mtmp2->data->mlevel >= mdat->mlevel+2 || mtmp2->data->mlet == 'c') continue; if(after) return(0); /* hit only once each move */ if(hitmm(mtmp, mtmp2) == 1 && rn2(4) && mtmp2->mlstmv != moves && hitmm(mtmp2,mtmp) == 2) return(2); return(0); } /* dog avoids traps */ /* but perhaps we have to pass a trap in order to follow @ */ if((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))){ if(!trap->tseen && rn2(40)) continue; if(rn2(10)) continue; } /* dog eschewes cursed objects */ /* but likes dog food */ obj = fobj; while(obj){ if(obj->ox != nx || obj->oy != ny) goto nextobj; if(obj->cursed) goto nxti; if(obj->olet == FOOD_SYM && (otyp = dogfood(obj)) < MANFOOD && (otyp < ACCFOOD || edog->hungrytime <= moves)){ /* Note: our dog likes the food so much that he might eat it even when it conceals a cursed object */ nix = nx; niy = ny; chi = i; eatobj: edog->eattime = moves + obj->quan * objects[obj->otyp].oc_delay; if(edog->hungrytime < moves) edog->hungrytime = moves; edog->hungrytime += 5*obj->quan * objects[obj->otyp].nutrition; mtmp->mconf = 0; if(cansee(nix,niy)) pline("%s ate %s.", Monnam(mtmp), doname(obj)); /* perhaps this was a reward */ if(otyp != CADAVER) edog->apport += 200/(edog->dropdist+moves-edog->droptime); delobj(obj); goto newdogpos; } nextobj: obj = obj->nobj; } for(j=0; j<MTSZ && j<cnt-1; j++) if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y) if(rn2(4*(cnt-j))) goto nxti; /* Some stupid C compilers cannot compute the whole expression at once. */ nearer = GDIST(nx,ny); nearer -= GDIST(nix,niy); nearer *= appr; if((nearer == 0 && !rn2(++chcnt)) || nearer<0 || (nearer > 0 && !whappr && ((omx == nix && omy == niy && !rn2(3)) || !rn2(12)) )){ nix = nx; niy = ny; if(nearer < 0) chcnt = 0; chi = i; } nxti: ; } newdogpos: if(nix != omx || niy != omy){ if(info[chi] & ALLOW_U){ (void) hitu(mtmp, d(mdat->damn, mdat->damd)+1); return(0); } mtmp->mx = nix; mtmp->my = niy; for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1]; mtmp->mtrack[0].x = omx; mtmp->mtrack[0].y = omy; } if(mintrap(mtmp) == 2) /* he died */ return(2); pmon(mtmp); return(1); }
void potionhit(struct monst *mon, struct obj *obj) { char *botlnam = bottlenames[rn2(SIZE(bottlenames))]; boolean uclose, isyou = (mon == &youmonst); if(isyou) { uclose = TRUE; pline("The %s crashes on your head and breaks into shivers.", botlnam); losehp(rnd(2), "thrown potion"); } else { uclose = (dist(mon->mx,mon->my) < 3); /* perhaps 'E' and 'a' have no head? */ pline("The %s crashes on %s's head and breaks into shivers.", botlnam, monnam(mon)); if(rn2(5) && mon->mhp > 1) mon->mhp--; } pline("The %s evaporates.", xname(obj)); if(!isyou && !rn2(3)) switch(obj->otyp) { case POT_RESTORE_STRENGTH: case POT_GAIN_STRENGTH: case POT_HEALING: case POT_EXTRA_HEALING: if(mon->mhp < mon->mhpmax) { mon->mhp = mon->mhpmax; pline("%s looks sound and hale again!", Monnam(mon)); } break; case POT_SICKNESS: if(mon->mhpmax > 3) mon->mhpmax /= 2; if(mon->mhp > 2) mon->mhp /= 2; break; case POT_CONFUSION: case POT_BOOZE: mon->mconf = 1; break; case POT_INVISIBILITY: unpmon(mon); mon->minvis = 1; pmon(mon); break; case POT_PARALYSIS: mon->mfroz = 1; break; case POT_SPEED: mon->mspeed = MFAST; break; case POT_BLINDNESS: mon->mblinded |= 64 + rn2(64); break; /* case POT_GAIN_LEVEL: case POT_LEVITATION: case POT_FRUIT_JUICE: case POT_MONSTER_DETECTION: case POT_OBJECT_DETECTION: break; */ } if(uclose && rn2(5)) potionbreathe(obj); obfree(obj, Null(obj)); }
int dopay(void) { long ltmp; struct bill_x *bp; struct monst *shkp; int pass, tmp; multi = 0; inshop(); for (shkp = fmon; shkp; shkp = shkp->nmon) if (shkp->isshk && dist(shkp->mx, shkp->my) < 3) break; if (!shkp && u.uinshop && inroom(shopkeeper->mx, shopkeeper->my) == ESHK(shopkeeper)->shoproom) shkp = shopkeeper; if (!shkp) { pline("There is nobody here to receive your payment."); return (0); } ltmp = ESHK(shkp)->robbed; if (shkp != shopkeeper && NOTANGRY(shkp)) { if (!ltmp) pline("You do not owe %s anything.", monnam(shkp)); else if (!u.ugold) pline("You have no money."); else { long ugold = u.ugold; if (u.ugold > ltmp) { pline("You give %s the %ld gold pieces he asked for.", monnam(shkp), ltmp); pay(ltmp, shkp); } else { pline("You give %s all your gold.", monnam(shkp)); pay(u.ugold, shkp); } if (ugold < ltmp / 2) pline("Unfortunately, he doesn't look satisfied."); else { ESHK(shkp)->robbed = 0; ESHK(shkp)->following = 0; if (ESHK(shkp)->shoplevel != dlevel) { /* For convenience's sake, let him disappear */ shkp->minvent = 0; /* %% */ shkp->mgold = 0; mondead(shkp); } } } return (1); } if (!ESHK(shkp)->billct) { pline("You do not owe %s anything.", monnam(shkp)); if (!u.ugold) { pline("Moreover, you have no money."); return (1); } if (ESHK(shkp)->robbed) { #define min(a, b) ((a < b) ? a : b) pline("But since his shop has been robbed recently,"); pline("you %srepay %s's expenses.", (u.ugold < ESHK(shkp)->robbed) ? "partially " : "", monnam(shkp)); pay(min(u.ugold, ESHK(shkp)->robbed), shkp); ESHK(shkp)->robbed = 0; return (1); } if (ANGRY(shkp)) { pline("But in order to appease %s,", amonnam(shkp, "angry")); if (u.ugold >= 1000) { ltmp = 1000; pline(" you give him 1000 gold pieces."); } else { ltmp = u.ugold; pline(" you give him all your money."); } pay(ltmp, shkp); if (strncmp(ESHK(shkp)->customer, plname, PL_NSIZ) || rn2(3)) { pline("%s calms down.", Monnam(shkp)); NOTANGRY(shkp) = 1; } else pline("%s is as angry as ever.", Monnam(shkp)); } return (1); } if (shkp != shopkeeper) { impossible("dopay: not to shopkeeper?"); if (shopkeeper) setpaid(); return (0); } for (pass = 0; pass <= 1; pass++) { tmp = 0; while (tmp < ESHK(shopkeeper)->billct) { bp = &bill[tmp]; if (!pass && !bp->useup) { tmp++; continue; } if (!dopayobj(bp)) return (1); bill[tmp] = bill[--ESHK(shopkeeper)->billct]; } } pline("Thank you for shopping in %s's %s store!", shkname(shopkeeper), shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]); NOTANGRY(shopkeeper) = 1; return (1); }
int dothrow() { struct obj *obj; struct monst *mon; int tmp; obj = getobj("#)", "throw"); /* it is also possible to throw food */ /* (or jewels, or iron balls ... ) */ if(!obj || !getdir(1)) /* ask "in what direction?" */ return(0); if(obj->owornmask & (W_ARMOR | W_RING)){ pline("You can't throw something you are wearing."); return(0); } u_wipe_engr(2); if(obj == uwep){ if(obj->cursed){ pline("Your weapon is welded to your hand."); return(1); } if(obj->quan > 1) setuwep(splitobj(obj, 1)); else setuwep((struct obj *) 0); } else if(obj->quan > 1) (void) splitobj(obj, 1); freeinv(obj); if(u.uswallow) { mon = u.ustuck; bhitpos.x = mon->mx; bhitpos.y = mon->my; } else if(u.dz) { if(u.dz < 0) { pline("%s hits the ceiling, then falls back on top of your head.", Doname(obj)); /* note: obj->quan == 1 */ if(obj->olet == POTION_SYM) potionhit(&youmonst, obj); else { if(uarmh) pline("Fortunately, you are wearing a helmet!"); losehp(uarmh ? 1 : rnd((int)(obj->owt)), "falling object"); dropy(obj); } } else { pline("%s hits the floor.", Doname(obj)); if(obj->otyp == EXPENSIVE_CAMERA) { pline("It is shattered in a thousand pieces!"); obfree(obj, Null(obj)); } else if(obj->otyp == EGG) { pline("\"Splash!\""); obfree(obj, Null(obj)); } else if(obj->olet == POTION_SYM) { pline("The flask breaks, and you smell a peculiar odor ..."); potionbreathe(obj); obfree(obj, Null(obj)); } else { dropy(obj); } } return(1); } else if(obj->otyp == BOOMERANG) { mon = boomhit(u.dx, u.dy); if(mon == &youmonst) { /* the thing was caught */ (void) addinv(obj); return(1); } } else { if(obj->otyp == PICK_AXE && shkcatch(obj)) return(1); mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 : (!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1, obj->olet, NULL, NULL, obj); } if(mon) { /* awake monster if sleeping */ wakeup(mon); if(obj->olet == WEAPON_SYM) { tmp = -1+u.ulevel+mon->data->ac+abon(); if(obj->otyp < ROCK) { if(!uwep || uwep->otyp != obj->otyp+(BOW-ARROW)) tmp -= 4; else { tmp += uwep->spe; } } else if(obj->otyp == BOOMERANG) tmp += 4; tmp += obj->spe; if(u.uswallow || tmp >= rnd(20)) { if(hmon(mon,obj,1) == TRUE){ /* mon still alive */ #ifndef NOWORM cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp); #endif /* NOWORM */ } else mon = 0; /* weapons thrown disappear sometimes */ if(obj->otyp < BOOMERANG && rn2(3)) { /* check bill; free */ obfree(obj, (struct obj *) 0); return(1); } } else miss(objects[obj->otyp].oc_name, mon); } else if(obj->otyp == HEAVY_IRON_BALL) { tmp = -1+u.ulevel+mon->data->ac+abon(); if(!Punished || obj != uball) tmp += 2; if(u.utrap) tmp -= 2; if(u.uswallow || tmp >= rnd(20)) { if(hmon(mon,obj,1) == FALSE) mon = 0; /* he died */ } else miss("iron ball", mon); } else if(obj->olet == POTION_SYM && u.ulevel > rn2(15)) { potionhit(mon, obj); return(1); } else { if(cansee(bhitpos.x,bhitpos.y)) pline("You miss %s.",monnam(mon)); else pline("You miss it."); if(obj->olet == FOOD_SYM && mon->data->mlet == 'd') if(tamedog(mon,obj)) return(1); if(obj->olet == GEM_SYM && mon->data->mlet == 'u' && !mon->mtame){ if(obj->dknown && objects[obj->otyp].oc_name_known){ if(objects[obj->otyp].g_val > 0){ u.uluck += 5; goto valuable; } else { pline("%s is not interested in your junk.", Monnam(mon)); } } else { /* value unknown to @ */ u.uluck++; valuable: if(u.uluck > LUCKMAX) /* dan@ut-ngp */ u.uluck = LUCKMAX; pline("%s graciously accepts your gift.", Monnam(mon)); mpickobj(mon, obj); rloc(mon); return(1); } } } } /* the code following might become part of dropy() */ if(obj->otyp == CRYSKNIFE) obj->otyp = WORM_TOOTH; obj->ox = bhitpos.x; obj->oy = bhitpos.y; obj->nobj = fobj; fobj = obj; /* prevent him from throwing articles to the exit and escaping */ /* subfrombill(obj); */ stackobj(obj); if(Punished && obj == uball && (bhitpos.x != u.ux || bhitpos.y != u.uy)){ freeobj(uchain); unpobj(uchain); if(u.utrap){ if(u.utraptype == TT_PIT) pline("The ball pulls you out of the pit!"); else { long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE; pline("The ball pulls you out of the bear trap."); pline("Your %s leg is severely damaged.", (side == LEFT_SIDE) ? "left" : "right"); set_wounded_legs(side, 500+rn2(1000)); losehp(2, "thrown ball"); } u.utrap = 0; } unsee(); uchain->nobj = fobj; fobj = uchain; u.ux = uchain->ox = bhitpos.x - u.dx; u.uy = uchain->oy = bhitpos.y - u.dy; setsee(); (void) inshop(); } if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y); return(1); }
/* u.dx and u.dy must be set */ bool attack(struct monst *mtmp) { schar tmp; boolean malive = TRUE; struct permonst *mdat; mdat = mtmp->data; u_wipe_engr(3); /* andrew@orca: prevent unlimited pick-axe attacks */ if (mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep && !mtmp->mconf && mtmp->mcansee && !rn2(7) && (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */ mtmp->mx != u.ux + u.dx || mtmp->my != u.uy + u.dy)) return (FALSE); if (mtmp->mimic) { if (!u.ustuck && !mtmp->mflee) u.ustuck = mtmp; switch (levl[u.ux + u.dx][u.uy + u.dy].scrsym) { case '+': pline("The door actually was a Mimic."); break; case '$': pline("The chest was a Mimic!"); break; default: pline("Wait! That's a Mimic!"); } wakeup(mtmp); /* clears mtmp->mimic */ return (TRUE); } wakeup(mtmp); if (mtmp->mhide && mtmp->mundetected) { struct obj *obj; mtmp->mundetected = 0; if ((obj = o_at(mtmp->mx, mtmp->my)) && !Blind) pline("Wait! There's a %s hiding under %s!", mdat->mname, doname(obj)); return (TRUE); } tmp = u.uluck + u.ulevel + mdat->ac + abon(); if (uwep) { if (uwep->olet == WEAPON_SYM || uwep->otyp == PICK_AXE) tmp += uwep->spe; if (uwep->otyp == TWO_HANDED_SWORD) tmp -= 1; else if (uwep->otyp == DAGGER) tmp += 2; else if (uwep->otyp == CRYSKNIFE) tmp += 3; else if (uwep->otyp == SPEAR && strchr("XDne", mdat->mlet)) tmp += 2; } if (mtmp->msleep) { mtmp->msleep = 0; tmp += 2; } if (mtmp->mfroz) { tmp += 4; if (!rn2(10)) mtmp->mfroz = 0; } if (mtmp->mflee) tmp += 2; if (u.utrap) tmp -= 3; /* with a lot of luggage, your agility diminishes */ tmp -= (inv_weight() + 40) / 20; if (tmp <= rnd(20) && !u.uswallow) { if (Blind) pline("You miss it."); else pline("You miss %s.", monnam(mtmp)); } else { /* we hit the monster; be careful: it might die! */ if ((malive = hmon(mtmp, uwep, 0)) == TRUE) { /* monster still alive */ if (!rn2(25) && mtmp->mhp < mtmp->mhpmax / 2) { mtmp->mflee = 1; if (!rn2(3)) mtmp->mfleetim = rnd(100); if (u.ustuck == mtmp && !u.uswallow) u.ustuck = 0; } #ifndef NOWORM if (mtmp->wormno) cutworm(mtmp, u.ux + u.dx, u.uy + u.dy, uwep ? uwep->otyp : 0); #endif /* NOWORM */ } if (mdat->mlet == 'a') { if (rn2(2)) { pline("You are splashed by the blob's acid!"); losehp_m(rnd(6), mtmp); if (!rn2(30)) corrode_armor(); } if (!rn2(6)) corrode_weapon(); } } if (malive && mdat->mlet == 'E' && canseemon(mtmp) && !mtmp->mcan && rn2(3)) { if (mtmp->mcansee) { pline("You are frozen by the floating eye's gaze!"); nomul((u.ulevel > 6 || rn2(4)) ? rn1(20, -21) : -200); } else { pline("The blinded floating eye cannot defend itself."); if (!rn2(500)) if ((int)u.uluck > LUCKMIN) u.uluck--; } } return (TRUE); }
/* return TRUE if mon still alive */ bool hmon(struct monst *mon, struct obj *obj, int thrown) { int tmp; bool hittxt = FALSE; if (!obj) { tmp = rnd(2); /* attack with bare hands */ if (mon->data->mlet == 'c' && !uarmg) { pline("You hit the cockatrice with your bare hands."); pline("You turn to stone ..."); done_in_by(mon); } } else if (obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE) { if (obj == uwep && (obj->otyp > SPEAR || obj->otyp < BOOMERANG)) tmp = rnd(2); else { if (strchr(mlarge, mon->data->mlet)) { tmp = rnd(objects[obj->otyp].wldam); if (obj->otyp == TWO_HANDED_SWORD) tmp += d(2, 6); else if (obj->otyp == FLAIL) tmp += rnd(4); } else tmp = rnd(objects[obj->otyp].wsdam); tmp += obj->spe; if (!thrown && obj == uwep && obj->otyp == BOOMERANG && !rn2(3)) { pline("As you hit %s, the boomerang breaks into splinters.", monnam(mon)); freeinv(obj); setworn(NULL, obj->owornmask); obfree(obj, NULL); tmp++; } } if (mon->data->mlet == 'O' && obj->otyp == TWO_HANDED_SWORD && !strcmp(ONAME(obj), "Orcrist")) tmp += rnd(10); } else switch (obj->otyp) { case HEAVY_IRON_BALL: tmp = rnd(25); break; case EXPENSIVE_CAMERA: pline("You succeed in destroying your camera. Congratulations!"); freeinv(obj); if (obj->owornmask) setworn(NULL, obj->owornmask); obfree(obj, NULL); return (TRUE); case DEAD_COCKATRICE: pline("You hit %s with the cockatrice corpse.", monnam(mon)); if (mon->data->mlet == 'c') { tmp = 1; hittxt = TRUE; break; } pline("%s is turned to stone!", Monnam(mon)); killed(mon); return (FALSE); case CLOVE_OF_GARLIC: /* no effect against demons */ if (strchr(UNDEAD, mon->data->mlet)) mon->mflee = 1; tmp = 1; break; default: /* non-weapons can damage because of their weight */ /* (but not too much) */ tmp = obj->owt / 10; if (tmp < 1) tmp = 1; else tmp = rnd(tmp); if (tmp > 6) tmp = 6; } /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */ tmp += u.udaminc + dbon(); if (u.uswallow) { if ((tmp -= u.uswldtim) <= 0) { pline("Your arms are no longer able to hit."); return (TRUE); } } if (tmp < 1) tmp = 1; mon->mhp -= tmp; if (mon->mhp < 1) { killed(mon); return (FALSE); } if (mon->mtame && (!mon->mflee || mon->mfleetim)) { mon->mflee = 1; /* Rick Richardson */ mon->mfleetim += 10 * rnd(tmp); } if (!hittxt) { if (thrown) { /* this assumes that we cannot throw plural things */ hit(xname(obj) /* or: objects[obj->otyp].oc_name */, mon, exclam(tmp)); } else if (Blind) pline("You hit it."); else pline("You hit %s%s", monnam(mon), exclam(tmp)); } if (u.umconf && !thrown) { if (!Blind) { pline("Your hands stop glowing blue."); if (!mon->mfroz && !mon->msleep) pline("%s appears confused.", Monnam(mon)); } mon->mconf = 1; u.umconf = 0; } return (TRUE); /* mon still alive */ }
/* hitmm returns 0 (miss), 1 (hit), or 2 (kill) */ int hitmm(struct monst *magr, struct monst *mdef) { struct permonst *pa = magr->data, *pd = mdef->data; int ht; schar tmp; boolean vis; if (strchr("Eauy", pa->mlet)) return (0); if (magr->mfroz) /* riv05!a3 */ return (0); tmp = pd->ac + pa->mlevel; if (mdef->mconf || mdef->mfroz || mdef->msleep) { tmp += 4; if (mdef->msleep) mdef->msleep = 0; } ht = (tmp > rnd(20)); if (ht) mdef->msleep = 0; vis = (cansee(magr->mx, magr->my) && cansee(mdef->mx, mdef->my)); if (vis) { char buf[BUFSZ]; if (mdef->mimic) seemimic(mdef); if (magr->mimic) seemimic(magr); sprintf(buf, "%s %s", Monnam(magr), ht ? "hits" : "misses"); pline("%s %s.", buf, monnam(mdef)); } else { boolean far = (dist(magr->mx, magr->my) > 15); if (far != far_noise || moves - noisetime > 10) { far_noise = far; noisetime = moves; pline("You hear some noises%s.", far ? " in the distance" : ""); } } if (ht) { if (magr->data->mlet == 'c' && !magr->cham) { magr->mhpmax += 3; if (vis) pline("%s is turned to stone!", Monnam(mdef)); else if (mdef->mtame) pline("You have a peculiarly sad feeling for a moment, then it passes."); monstone(mdef); ht = 2; } else if ((mdef->mhp -= d(pa->damn, pa->damd)) < 1) { magr->mhpmax += 1 + rn2(pd->mlevel + 1); if (magr->mtame && magr->mhpmax > 8 * pa->mlevel) { if (pa == &li_dog) magr->data = pa = &dog; else if (pa == &dog) magr->data = pa = &la_dog; } if (vis) pline("%s is killed!", Monnam(mdef)); else if (mdef->mtame) pline("You have a sad feeling for a moment, then it passes."); mondied(mdef); ht = 2; } } return (ht); }
// What does the return value indicate?? Boolean dopay() { Long ltmp; bill_t *bp; monst_t *shkp; Short pass, tmp; multi = 0; inshop(); for (shkp = fmon ; shkp ; shkp = shkp->nmon) if ((shkp->bitflags & M_IS_SHOPKEEPER) && dist(shkp->mx,shkp->my) < 3) break; if (!shkp && you.uinshop && inroom(shopkeeper->mx,shopkeeper->my) == ESHK(shopkeeper)->shoproom) shkp = shopkeeper; if (!shkp) { message("There is nobody here to receive your payment."); return false; } ltmp = ESHK(shkp)->robbed; if (shkp != shopkeeper && NOTANGRY(shkp)) { if (!ltmp) { StrPrintF(ScratchBuffer, "You do not owe %s anything.", monnam(shkp)); message(ScratchBuffer); } else if (!you.ugold) { message("You have no money."); } else { Long ugold = you.ugold; if (you.ugold > ltmp) { StrPrintF(ScratchBuffer, "You give %s the %ld gold pieces he asked for.", monnam(shkp), ltmp); message(ScratchBuffer); pay(ltmp, shkp); } else { StrPrintF(ScratchBuffer, "You give %s all your gold.", monnam(shkp)); message(ScratchBuffer); pay(you.ugold, shkp); } if (ugold < ltmp/2) { message("Unfortunately, he doesn't look satisfied."); } else { ESHK(shkp)->robbed = 0; ESHK(shkp)->following = false; if (ESHK(shkp)->shoplevel != dlevel) { /* For convenience's sake, let him disappear */ shkp->minvent = NULL; /* %% */ // xxx leak? shkp->mgold = 0; mondead(shkp); } } } return true; } if (!ESHK(shkp)->billct) { StrPrintF(ScratchBuffer, "You do not owe %s anything.", monnam(shkp)); message(ScratchBuffer); if (!you.ugold) { message("Moreover, you have no money."); return true; } if (ESHK(shkp)->robbed) { message("But since his shop has been robbed recently,"); StrPrintF(ScratchBuffer, "you%srepay %s's expenses.", (you.ugold < ESHK(shkp)->robbed) ? " partially " : " ", monnam(shkp)); message(ScratchBuffer); pay(min(you.ugold, ESHK(shkp)->robbed), shkp); ESHK(shkp)->robbed = 0; return true; } if (ANGRY(shkp)) { StrPrintF(ScratchBuffer, "But in order to appease %s,", amonnam(shkp, "angry")); message(ScratchBuffer); if (you.ugold >= 1000) { ltmp = 1000; message(" you give him 1000 gold pieces."); } else { ltmp = you.ugold; message(" you give him all your money."); } pay(ltmp, shkp); if (StrNCompare(ESHK(shkp)->customer, plname, PL_NSIZ) || rund(3)){ StrPrintF(ScratchBuffer, "%s calms down.", Monnam(shkp)); message(ScratchBuffer); shkp->bitflags |= M_IS_PEACEFUL; // NOTANGRY(shopkeeper) = 1; } else { StrPrintF(ScratchBuffer, "%s is as angry as ever.", Monnam(shkp)); message(ScratchBuffer); } } return true; } if (shkp != shopkeeper) { message("BUG: dopay: not to shopkeeper?"); if (shopkeeper) setpaid(); return false; } for (pass = 0 ; pass <= 1 ; pass++) { tmp = 0; while (tmp < ESHK(shopkeeper)->billct) { bp = &bill[tmp]; if (!pass && !bp->useup) { tmp++; continue; } if (!dopayobj(bp)) return true; bill[tmp] = bill[--ESHK(shopkeeper)->billct]; } } StrPrintF(ScratchBuffer, "Thank you for shopping in %s's %s store!", shkname(shopkeeper), shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]); shopkeeper->bitflags |= M_IS_PEACEFUL; // NOTANGRY(shopkeeper) = 1; return true; }
// NOTE: To hit "you" with a potion p, call "potionhit(NULL, p)". no "youmonst" void potionhit(monst_t *mon, obj_t *obj) { Char *botlnam = bottlenames[rund(MAX_BOTTLES)]; Boolean uclose; // , isyou = (mon==NULL); if (!mon) { uclose = true; StrPrintF(ScratchBuffer, "The %s crashes on your head and breaks into shivers.", botlnam); message(ScratchBuffer); losehp(rnd(2), "thrown potion"); } else { uclose = (dist(mon->mx,mon->my) < 3); /* perhaps 'E' and 'a' have no head? */ StrPrintF(ScratchBuffer, "The %s crashes on %s's head and breaks into shivers.", botlnam, monnam(mon)); message(ScratchBuffer); if (rund(5) && mon->mhp > 1) mon->mhp--; } StrPrintF(ScratchBuffer, "The %s evaporates.", xname(obj)); message(ScratchBuffer); if (mon && !rund(3)) { switch(obj->otype) { case POT_RESTORE_STRENGTH: case POT_GAIN_STRENGTH: case POT_HEALING: case POT_EXTRA_HEALING: if (mon->mhp < mon->mhpmax) { mon->mhp = mon->mhpmax; StrPrintF(ScratchBuffer, "%s looks sound and hale again!", Monnam(mon)); message(ScratchBuffer); } break; case POT_SICKNESS: if (mon->mhpmax > 3) mon->mhpmax /= 2; if (mon->mhp > 2) mon->mhp /= 2; break; case POT_CONFUSION: case POT_BOOZE: mon->bitflags |= M_IS_CONFUSED; // mon->mconf = 1; break; case POT_INVISIBILITY: unpmon(mon); mon->bitflags |= M_IS_INVISIBLE; // mon->minvis = 1; pmon(mon); break; case POT_PARALYSIS: mon->bitflags |= M_IS_FROZEN; // mon->mfroz = 1; break; case POT_SPEED: mon->mspeed = MFAST; break; case POT_BLINDNESS: mon->mcansee_and_blinded |= 64 + rund(64); // "|="? "=" to turn off SEE? break; /* case POT_GAIN_LEVEL: case POT_LEVITATION: case POT_FRUIT_JUICE: case POT_MONSTER_DETECTION: case POT_OBJECT_DETECTION: break; */ default: break; } } if (uclose && rund(5)) potionbreathe(obj); free_obj(obj, NULL); }
/* * mhitu: monster hits you * returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise */ bool mhitu(struct monst *mtmp) { struct permonst *mdat = mtmp->data; int tmp, ctmp; nomul(0); /* If swallowed, can only be affected by hissers and by u.ustuck */ if (u.uswallow) { if (mtmp != u.ustuck) { if (mdat->mlet == 'c' && !rn2(13)) { pline("Outside, you hear %s's hissing!", monnam(mtmp)); pline("%s gets turned to stone!", Monnam(u.ustuck)); pline("And the same fate befalls you."); done_in_by(mtmp); /* "notreached": not return(1); */ } return (0); } switch (mdat->mlet) { /* now mtmp == u.ustuck */ case ',': youswld(mtmp, (u.uac > 0) ? u.uac + 4 : 4, 5, "The trapper"); break; case '\'': youswld(mtmp, rnd(6), 7, "The lurker above"); break; case 'P': youswld(mtmp, d(2, 4), 12, "The purple worm"); break; default: /* This is not impossible! */ pline("The mysterious monster totally digests you."); u.uhp = 0; } if (u.uhp < 1) done_in_by(mtmp); return (0); } if (mdat->mlet == 'c' && Stoned) return (0); /* make eels visible the moment they hit/miss us */ if (mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx, mtmp->my)) { mtmp->minvis = 0; pmon(mtmp); } if (!strchr("1&DuxynNF", mdat->mlet)) tmp = hitu(mtmp, d(mdat->damn, mdat->damd)); else tmp = 0; if (strchr(UNDEAD, mdat->mlet) && midnight()) tmp += hitu(mtmp, d(mdat->damn, mdat->damd)); ctmp = tmp && !mtmp->mcan && (!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50)); switch (mdat->mlet) { case '1': if (wiz_hit(mtmp)) /* he disappeared */ return (1); break; case '&': if (!mtmp->cham && !mtmp->mcan && !rn2(13)) { makemon(PM_DEMON, u.ux, u.uy); } else { hitu(mtmp, d(2, 6)); hitu(mtmp, d(2, 6)); hitu(mtmp, rnd(3)); hitu(mtmp, rnd(3)); hitu(mtmp, rn1(4, 2)); } break; case ',': if (tmp) justswld(mtmp, "The trapper"); break; case '\'': if (tmp) justswld(mtmp, "The lurker above"); break; case ';': if (ctmp) { if (!u.ustuck && !rn2(10)) { pline("%s swings itself around you!", Monnam(mtmp)); u.ustuck = mtmp; } else if (u.ustuck == mtmp && levl[mtmp->mx][mtmp->my].typ == POOL) { pline("%s drowns you ...", Monnam(mtmp)); done("drowned"); } } break; case 'A': if (ctmp && rn2(2)) { if (Poison_resistance) pline("The sting doesn't seem to affect you."); else { pline("You feel weaker!"); losestr(1); } } break; case 'C': hitu(mtmp, rnd(6)); break; case 'c': if (!rn2(5)) { pline("You hear %s's hissing!", monnam(mtmp)); if (ctmp || !rn2(20) || (flags.moonphase == NEW_MOON && !carrying(DEAD_LIZARD))) Stoned = 5; } break; case 'D': if (rn2(6) || mtmp->mcan) { hitu(mtmp, d(3, 10)); hitu(mtmp, rnd(8)); hitu(mtmp, rnd(8)); break; } kludge("%s breathes fire!", "The dragon"); buzz(-1, mtmp->mx, mtmp->my, u.ux - mtmp->mx, u.uy - mtmp->my); break; case 'd': hitu(mtmp, d(2, (flags.moonphase == FULL_MOON) ? 3 : 4)); break; case 'e': hitu(mtmp, d(3, 6)); break; case 'F': if (mtmp->mcan) break; kludge("%s explodes!", "The freezing sphere"); if (Cold_resistance) pline("You don't seem affected by it."); else { xchar dn; if (17 - (u.ulevel / 2) > rnd(20)) { pline("You get blasted!"); dn = 6; } else { pline("You duck the blast..."); dn = 3; } losehp_m(d(dn, 6), mtmp); } mondead(mtmp); return (1); case 'g': if (ctmp && multi >= 0 && !rn2(3)) { kludge("You are frozen by %ss juices", "the cube'"); nomul(-rnd(10)); } break; case 'h': if (ctmp && multi >= 0 && !rn2(5)) { nomul(-rnd(10)); kludge("You are put to sleep by %ss bite!", "the homunculus'"); } break; case 'j': tmp = hitu(mtmp, rnd(3)); tmp &= hitu(mtmp, rnd(3)); if (tmp) { hitu(mtmp, rnd(4)); hitu(mtmp, rnd(4)); } break; case 'k': if ((hitu(mtmp, rnd(4)) || !rn2(3)) && ctmp) poisoned("bee's sting", mdat->mname); break; case 'L': if (tmp) stealgold(mtmp); break; case 'N': if (mtmp->mcan && !Blind) { pline("%s tries to seduce you, but you seem not interested.", Amonnam(mtmp, "plain")); if (rn2(3)) rloc(mtmp); } else if (steal(mtmp)) { rloc(mtmp); mtmp->mflee = 1; } break; case 'n': if (!uwep && !uarm && !uarmh && !uarms && !uarmg) { pline("%s hits! (I hope you don't mind)", Monnam(mtmp)); u.uhp += rnd(7); if (!rn2(7)) u.uhpmax++; if (u.uhp > u.uhpmax) u.uhp = u.uhpmax; flags.botl = 1; if (!rn2(50)) rloc(mtmp); } else { hitu(mtmp, d(2, 6)); hitu(mtmp, d(2, 6)); } break; case 'o': tmp = hitu(mtmp, rnd(6)); if (hitu(mtmp, rnd(6)) && tmp && /* hits with both paws */ !u.ustuck && rn2(2)) { u.ustuck = mtmp; kludge("%s has grabbed you!", "The owlbear"); u.uhp -= d(2, 8); } else if (u.ustuck == mtmp) { u.uhp -= d(2, 8); pline("You are being crushed."); } break; case 'P': if (ctmp && !rn2(4)) justswld(mtmp, "The purple worm"); else hitu(mtmp, d(2, 4)); break; case 'Q': hitu(mtmp, rnd(2)); hitu(mtmp, rnd(2)); break; case 'R': if (tmp && uarmh && !uarmh->rustfree && (int)uarmh->spe >= -1) { pline("Your helmet rusts!"); uarmh->spe--; } else if (ctmp && uarm && !uarm->rustfree && /* Mike Newton */ uarm->otyp < STUDDED_LEATHER_ARMOR && (int)uarm->spe >= -1) { pline("Your armor rusts!"); uarm->spe--; } break; case 'S': if (ctmp && !rn2(8)) poisoned("snake's bite", mdat->mname); break; case 's': if (tmp && !rn2(8)) poisoned("scorpion's sting", mdat->mname); hitu(mtmp, rnd(8)); hitu(mtmp, rnd(8)); break; case 'T': hitu(mtmp, rnd(6)); hitu(mtmp, rnd(6)); break; case 't': if (!rn2(5)) rloc(mtmp); break; case 'u': mtmp->mflee = 1; break; case 'U': hitu(mtmp, d(3, 4)); hitu(mtmp, d(3, 4)); break; case 'v': if (ctmp && !u.ustuck) u.ustuck = mtmp; break; case 'V': if (tmp) u.uhp -= 4; if (ctmp) losexp(); break; case 'W': if (ctmp) losexp(); break; #ifndef NOWORM case 'w': if (tmp) wormhit(mtmp); #endif /* NOWORM */ break; case 'X': hitu(mtmp, rnd(5)); hitu(mtmp, rnd(5)); hitu(mtmp, rnd(5)); break; case 'x': { long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE; pline("%s pricks in your %s leg!", Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left"); set_wounded_legs(side, rnd(50)); losehp_m(2, mtmp); break; } case 'y': if (mtmp->mcan) break; mondead(mtmp); if (!Blind) { pline("You are blinded by a blast of light!"); Blind = d(4, 12); seeoff(0); } return (1); case 'Y': hitu(mtmp, rnd(6)); break; } if (u.uhp < 1) done_in_by(mtmp); return (0); }
void killed(struct monst *mtmp) { #define NEW_SCORING int tmp; int tmp2; int nk; int x; int y; struct permonst *mdat = mtmp->data; if(mtmp->cham != 0) { mdat = PM_CHAM; } if(Blind != 0) { pline("You destroy it!"); } else { if(mtmp->mtame != 0) { pline("You destroy %s!", amonnam(mtmp, "poor")); } else { pline("You destroy %s!", monnam(mtmp)); } } if(u.umconf != 0) { if(Blind == 0) { pline("Your hands stop clowing blue."); u.umconf = 0; } } /* Count killed monsters */ #define MAXMONNO 100 /* In case we cannot find it in mons */ nk = 1; /* Index in mons array (if not 'd', '@', ...) */ tmp = mdat - mons; if((tmp >= 0) && (tmp < (CMNUM + 2))) { extern char fut_geno[]; ++u.nr_killed[tmp]; nk = u.nr_killed[tmp]; if((nk > MAXMONNO) && (index(fut_geno, mdat->mlet) == 0)) { charcat(fut_geno, mdat->mlet); } } /* Punish bad behaviour */ if(mdat->mlet == '@') { Telepat = 0; u.uluck -= 2; } if((mtmp->mpeaceful != 0) || (mtmp->mtame != 0)) { --u.uluck; } if(mdat->mlet == 'u') { u.uluck -= 5; } /* Give experience points */ tmp = 1 + (mdat->mlevel * mdat->mlevel); if(mdat->ac < 3) { tmp += (2 * (7 - mdat->ac)); } if(index("AcsSDXaeRTVWU&In:P", mdat->mlet) != 0) { tmp += (2 * mdat->mlevel); } if(index("DeV&P", mdat->mlet) != 0) { tmp += (7 * mdat->mlevel); } if(mdat->mlevel > 6) { tmp += 50; } #ifdef NEW_SCORING /* * ------- Recent addition: make number of points decrease * when this is not the first of this kind */ int ul = u.ulevel; int ml = mdat->mlevel; /* Points are given based on present and future level */ if(ul < 14) { for(tmp2 = 0; (tmp2 == 0) || ((ul + tmp2) <= ml); ++tmp2) { if(tmp <= 0) { if(((u.uexp + 1) + ((tmp + (0)) / nk)) >= (10 * pow(2, (unsigned)(ul - 1)))) { ++ul; if(ul == 14) { break; } } } else { if(((u.uexp + 1) + ((tmp + (4 << (tmp2 - 1))) / nk)) >= (10 * pow(2, (unsigned)(ul - 1)))) { ++ul; if(ul == 14) { break; } } } } } tmp2 = (ml - ul) - 1; if(tmp2 < 0) { tmp = (tmp + (0)) / nk; } else { tmp = (tmp + (4 << tmp2)) / nk; } if(tmp == 0) { tmp = 1; } /* * Note: ul is not necessarily the future value of u.ulevel * ------- End of recent valuation change ------- */ #endif u.uexp += tmp; u.urexp += (4 * tmp); flags.botl = 1; while((u.ulevel < 14) && (u.uexp >= (10 * pow(2, u.ulevel - 1)))) { ++u.ulevel; pline("Welcome to level %d.", u.ulevel); tmp = rnd(30); if(tmp < 3) { tmp = rnd(10); } u.uhpmax += tmp; u.uhp += tmp; flags.botl = 1; } /* Dispose of monster and make cadaver */ x = mtmp->mx; y = mtmp->my; mondead(mtmp); tmp = mdat->mlet; if(tmp == 'm') { /* He killed a minotaur, give him a wand of digging */ /* Note: The dead minotaur will be on top of it! */ mksobj_at(WAND_SYM, WAN_DIGGING, x, y); /* * if(cansee(x, y) != 0) { * atl(x, y, fobj->olet); * } */ stackobj(fobj); } #ifndef NOWORM else if(tmp == 'w') { mksobj_at(WEAPON_SYM, WORM_TOOTH, x, y); stackobj(fobj); } #endif else { if((letter(tmp) == 0) || (rn2(3) == 0)) { tmp = 0; } if(levl[x][y].typ >= DOOR) { /* Might be a mimic in wall */ if((x != u.ux) || (y != u.uy)) { /* Might be here after swallowed */ if((index("NTVm&", mdat->mlet) != NULL) || (rn2(5) != 0)) { mkobj_at(tmp, x, y); if(cansee(x, y) != 0) { atl(x, y, fobj->olet); } stackobj(fobj); } } } } }
/* called with dx = dy = 0 with vertical bolts */ void buzz(int type, xchar sx, xchar sy, int dx, int dy) { int abstype = abs(type); const char *fltxt = (type == -1) ? "blaze of fire" : fl[abstype]; struct rm *lev; xchar range; struct monst *mon; if(u.uswallow) { int tmp; if(type < 0) return; tmp = zhit(u.ustuck, type); pline("The %s rips into %s%s", fltxt, monnam(u.ustuck), exclam(tmp)); return; } if(type < 0) pru(); range = rn1(7,7); Tmp_at(-1, dirlet(dx,dy)); /* open call */ while(range-- > 0) { sx += dx; sy += dy; if((lev = &levl[sx][sy])->typ) Tmp_at(sx,sy); else { int bounce = 0; if(cansee(sx-dx,sy-dy)) pline("The %s bounces!", fltxt); if(ZAP_POS(levl[sx][sy-dy].typ)) bounce = 1; if(ZAP_POS(levl[sx-dx][sy].typ)) { if(!bounce || rn2(2)) bounce = 2; } switch(bounce){ case 0: dx = -dx; dy = -dy; continue; case 1: dy = -dy; sx -= dx; break; case 2: dx = -dx; sy -= dy; break; } Tmp_at(-2,dirlet(dx,dy)); continue; } if(lev->typ == POOL && abstype == 1 /* fire */) { range -= 3; lev->typ = ROOM; if(cansee(sx,sy)) { mnewsym(sx,sy); pline("The water evaporates."); } else pline("You hear a hissing sound."); } if((mon = m_at(sx,sy)) && (type != -1 || mon->data->mlet != 'D')) { wakeup(mon); if(rnd(20) < 18 + mon->data->ac) { int tmp = zhit(mon,abstype); if(mon->mhp < 1) { if(type < 0) { if(cansee(mon->mx,mon->my)) pline("%s is killed by the %s!", Monnam(mon), fltxt); mondied(mon); } else killed(mon); } else hit(fltxt, mon, exclam(tmp)); range -= 2; } else miss(fltxt,mon); } else if(sx == u.ux && sy == u.uy) { nomul(0); if(rnd(20) < 18+u.uac) { int dam = 0; range -= 2; pline("The %s hits you!",fltxt); switch(abstype) { case 0: dam = d(2,6); break; case 1: if(Fire_resistance) pline("You don't feel hot!"); else dam = d(6,6); if(!rn2(3)) burn_scrolls(); break; case 2: nomul(-rnd(25)); /* sleep ray */ break; case 3: if(Cold_resistance) pline("You don't feel cold!"); else dam = d(6,6); break; case 4: u.uhp = -1; } losehp(dam,fltxt); } else pline("The %s whizzes by you!",fltxt); stop_occupation(); } if(!ZAP_POS(lev->typ)) { int bounce = 0, rmn; if(cansee(sx,sy)) pline("The %s bounces!",fltxt); range--; if(!dx || !dy || !rn2(20)){ dx = -dx; dy = -dy; } else { if(ZAP_POS(rmn = levl[sx][sy-dy].typ) && (IS_ROOM(rmn) || ZAP_POS(levl[sx+dx][sy-dy].typ))) bounce = 1; if(ZAP_POS(rmn = levl[sx-dx][sy].typ) && (IS_ROOM(rmn) || ZAP_POS(levl[sx-dx][sy+dy].typ))) if(!bounce || rn2(2)) bounce = 2; switch(bounce){ case 0: dy = -dy; dx = -dx; break; case 1: dy = -dy; break; case 2: dx = -dx; break; } Tmp_at(-2, dirlet(dx,dy)); } } } Tmp_at(-1,-1); }
Short mon_in_trap(monst_t *mtmp) // was mintrap { trap_t *trap = trap_at(mtmp->mx, mtmp->my); Boolean wasintrap = (mtmp->bitflags & M_IS_TRAPPED); if (!trap) { mtmp->bitflags &= ~M_IS_TRAPPED; /* perhaps teleported? */ } else if (wasintrap) { if (!rund(40)) mtmp->bitflags &= ~M_IS_TRAPPED; } else { Short tt = get_trap_type(trap->trap_info); Short in_sight = cansee(mtmp->mx, mtmp->my); if (mtmp->mtraps_seen & (1 << tt)) { /* he has been in such a trap - perhaps he escapes */ if (rund(4)) return 0; } mtmp->mtraps_seen |= (1 << tt); switch (tt) { case BEAR_TRAP: if (StrChr(mlarge, mtmp->data->mlet)) { if (in_sight) { StrPrintF(ScratchBuffer,"%s is caught in a bear trap!",Monnam(mtmp)); message(ScratchBuffer); } else if (mtmp->data->mlet == 'o') message("You hear the roaring of an angry bear!"); mtmp->bitflags |= M_IS_TRAPPED; } break; case PIT: /* there should be a mtmp/data -> floating */ if (!StrChr("EywBfk'& ", mtmp->data->mlet)) { /* ab */ mtmp->bitflags |= M_IS_TRAPPED; if (in_sight) { StrPrintF(ScratchBuffer, "%s falls in a pit!", Monnam(mtmp)); message(ScratchBuffer); } } break; case SLP_GAS_TRAP: if (!(mtmp->bitflags & (M_IS_ASLEEP | M_IS_FROZEN))) { mtmp->bitflags |= M_IS_ASLEEP; if (in_sight) { StrPrintF(ScratchBuffer, "%s suddenly falls asleep!", Monnam(mtmp)); message(ScratchBuffer); } } break; case TELEP_TRAP: rloc(mtmp); if (in_sight && !cansee(mtmp->mx,mtmp->my)) { StrPrintF(ScratchBuffer, "%s suddenly disappears!", Monnam(mtmp)); message(ScratchBuffer); } break; case ARROW_TRAP: if (in_sight) { StrPrintF(ScratchBuffer, "%s is hit by an arrow!", Monnam(mtmp)); message(ScratchBuffer); } mtmp->mhp -= 3; break; case DART_TRAP: if (in_sight) { StrPrintF(ScratchBuffer, "%s is hit by a dart!", Monnam(mtmp)); message(ScratchBuffer); } mtmp->mhp -= 2; /* not mondied here !! */ break; case TRAPDOOR: if (!xdnstair) { mtmp->mhp -= 10; if (in_sight) { StrPrintF(ScratchBuffer, "A trap door in the ceiling opens and a rock hits %s!", monnam(mtmp)); message(ScratchBuffer); } break; } if (mtmp->data->mlet != 'w') { fall_down(mtmp); if (in_sight) { StrPrintF(ScratchBuffer, "Suddenly, %s disappears out of sight.", monnam(mtmp)); message(ScratchBuffer); } return 2; /* no longer on this level */ } break; case PIERC: break; default: message("BUG: Some monster encountered a strange trap."); } } return ((mtmp->bitflags & M_IS_TRAPPED) != 0); }