示例#1
0
文件: hack.do.c 项目: lattera/openbsd
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);
}
示例#2
0
/* 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);
}