Source:NetHack 3.4.0/steal.c

Below is the full text to steal.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/steal.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)steal.c	3.4	2002/01/04	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   STATIC_PTR int NDECL(stealarm); 8.    9.    #ifdef OVLB 10.  STATIC_DCL const char *FDECL(equipname, (struct obj *)); 11.   12.   STATIC_OVL const char * 13.  equipname(otmp) 14.  register struct obj *otmp; 15.  {  16.   	return (  17.   #ifdef TOURIST  18.   		(otmp == uarmu) ? "shirt" :  19.   #endif  20.   		(otmp == uarmf) ? "boots" :  21.   		(otmp == uarms) ? "shield" :  22.   		(otmp == uarmg) ? "gloves" :  23.   		(otmp == uarmc) ? cloak_simple_name(otmp) :  24.   		(otmp == uarmh) ? "helmet" : "armor"); 25.  }  26.    27.   #ifndef GOLDOBJ 28.  long		/* actually returns something that fits in an int */ 29.  somegold 30.  {  31.   #ifdef LINT	/* long conv. ok */ 32.  	return(0L); 33.  #else 34.  	return (long)( (u.ugold < 100) ? u.ugold :  35.   		(u.ugold > 10000) ? rnd(10000) : rnd((int) u.ugold) ); 36.  #endif 37.  }  38.    39.   void 40.  stealgold(mtmp) 41.  register struct monst *mtmp; 42.  {  43.   	register struct obj *gold = g_at(u.ux, u.uy); 44.  	register long tmp; 45.   46.   	if (gold && ( !u.ugold || gold->quan > u.ugold || !rn2(5))) { 47.  	    mtmp->mgold += gold->quan; 48.  	    delobj(gold); 49.  	    newsym(u.ux, u.uy); 50.  	    pline("%s quickly snatches some gold from between your %s!",  51.   		    Monnam(mtmp), makeplural(body_part(FOOT))); 52.  	    if(!u.ugold || !rn2(5)) { 53.  		if (!tele_restrict(mtmp)) rloc(mtmp); 54.  		monflee(mtmp, 0, FALSE, FALSE); 55.  	    }  56.   	} else if(u.ugold) { 57.  	    u.ugold -= (tmp = somegold); 58.  	    Your("purse feels lighter."); 59.  	    mtmp->mgold += tmp; 60.  	if (!tele_restrict(mtmp)) rloc(mtmp); 61.  	    monflee(mtmp, 0, FALSE, FALSE); 62.  	    flags.botl = 1; 63.  	}  64.   }  65.    66.   #else /* !GOLDOBJ */ 67.   68.   long		/* actually returns something that fits in an int */ 69.  somegold(umoney) 70.  long umoney; 71.  {  72.   #ifdef LINT	/* long conv. ok */ 73.  	return(0L); 74.  #else 75.  	return (long)( (umoney < 100) ? umoney :  76.   		(umoney > 10000) ? rnd(10000) : rnd((int) umoney) ); 77.  #endif 78.  }  79.    80.   /*  81.   Find the first (and hopefully only) gold object in a chain. 82.  Used when leprechaun (or you as leprechaun) looks for 83.  someone else's gold. Returns a pointer so the gold may 84.  be seized without further searching. 85.  May search containers too. 86.  Deals in gold only, as leprechauns don't care for lesser coins. 87.  */  88.   struct obj * 89.  findgold(chain) 90.  register struct obj *chain; 91.  {  92.           while (chain && chain->otyp != GOLD_PIECE) chain = chain->nobj; 93.          return chain; 94.  }  95.    96.   /*  97.   Steal gold coins only. Leprechauns don't care for lesser coins. 98.  */  99.   void 100. stealgold(mtmp) 101. register struct monst *mtmp; 102. {  103.  	register struct obj *fgold = g_at(u.ux, u.uy); 104. 	register struct obj *ygold; 105. 	register long tmp; 106.  107.          /* skip lesser coins on the floor */ 108.         while (fgold && fgold->otyp != GOLD_PIECE) fgold = fgold->nexthere; 109.  110.          /* Do you have real gold? */ 111.          ygold = findgold(invent); 112.  113.  	if (fgold && ( !ygold || fgold->quan > ygold->quan || !rn2(5))) { 114.             obj_extract_self(fgold); 115. 	    add_to_minv(mtmp, fgold); 116. 	    newsym(u.ux, u.uy); 117. 	    pline("%s quickly snatches some gold from between your %s!",  118.  		    Monnam(mtmp), makeplural(body_part(FOOT))); 119. 	    if(!ygold || !rn2(5)) { 120. 		if (!tele_restrict(mtmp)) rloc(mtmp); 121. 		monflee(mtmp, 0, FALSE, FALSE); 122. 	    }  123.  	} else if(ygold) { 124.             const int gold_price = objects[GOLD_PIECE].oc_cost; 125. 	    tmp = (somegold(money_cnt(invent)) + gold_price - 1) / gold_price; 126. 	    tmp = min(tmp, ygold->quan); 127.             if (tmp < ygold->quan) ygold = splitobj(ygold, tmp); 128.             freeinv(ygold); 129.             add_to_minv(mtmp, ygold); 130. 	    Your("purse feels lighter."); 131. 	    if (!tele_restrict(mtmp)) rloc(mtmp); 132. 	    monflee(mtmp, 0, FALSE, FALSE); 133. 	    flags.botl = 1; 134. 	}  135.  }  136.  #endif /* GOLDOBJ */ 137.  138.  /* steal armor after you finish taking it off */ 139. unsigned int stealoid;		/* object to be stolen */ 140. unsigned int stealmid;		/* monster doing the stealing */ 141.  142.  STATIC_PTR int 143. stealarm 144. {  145.  	register struct monst *mtmp; 146. 	register struct obj *otmp; 147.  148.  	for(otmp = invent; otmp; otmp = otmp->nobj) { 149. 	    if(otmp->o_id == stealoid) { 150. 		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 151. 		    if(mtmp->m_id == stealmid) { 152. 			if(DEADMONSTER(mtmp)) impossible("stealarm: dead monster stealing"); 153. 			if(!dmgtype(mtmp->data, AD_SITM)) /* polymorphed */ 154. 			    goto botm; 155. 			if(otmp->unpaid) 156. 			    subfrombill(otmp, shop_keeper(*u.ushops)); 157. 			freeinv(otmp); 158. 			pline("%s steals %s!", Monnam(mtmp), doname(otmp)); 159. 			(void) mpickobj(mtmp,otmp);	/* may free otmp */ 160. 			monflee(mtmp, 0, FALSE, FALSE); 161. 			if (!tele_restrict(mtmp)) rloc(mtmp); 162. 		        break; 163. 		    }  164.  		}  165.  		break; 166. 	    }  167.  	}  168.  botm:   stealoid = 0; 169. 	return 0; 170. }  171.   172.  /* An object you're wearing has been taken off by a monster (theft or  173.     seduction). Also used if a worn item gets transformed (stone to flesh). */ 174.  void 175. remove_worn_item(obj) 176. struct obj *obj; 177. {  178.  	if (donning(obj)) 179. 	    cancel_don; 180. 	if (!obj->owornmask) 181. 	    return; 182.  183.  	if (obj->owornmask & W_ARMOR) { 184. 	    if (obj == uskin) { 185. 		impossible("Removing embedded scales?"); 186. 		skinback(TRUE);		/* uarm = uskin; uskin = 0; */ 187. 	    }  188.  	    if (obj == uarm) (void) Armor_off; 189. 	    else if (obj == uarmc) (void) Cloak_off; 190. 	    else if (obj == uarmf) (void) Boots_off; 191. 	    else if (obj == uarmg) (void) Gloves_off; 192. 	    else if (obj == uarmh) (void) Helmet_off; 193. 	    else if (obj == uarms) (void) Shield_off; 194. 	    else setworn((struct obj *)0, obj->owornmask & W_ARMOR); 195. 	} else if (obj->owornmask & W_AMUL) { 196. 	    Amulet_off; 197. 	} else if (obj->owornmask & W_RING) { 198. 	    Ring_gone(obj); 199. 	} else if (obj->owornmask & W_TOOL) { 200. 	    Blindf_off(obj); 201. 	} else if (obj->owornmask & (W_BALL|W_CHAIN)) { 202. 	    unpunish; 203. 	} else if (obj->owornmask & (W_WEP|W_SWAPWEP|W_QUIVER)) { 204. 	    if (obj == uwep) 205. 		uwepgone; 206. 	    else if (obj == uswapwep) 207. 		uswapwepgone; 208. 	    else if (obj == uquiver) 209. 		uqwepgone; 210. 	}  211.   212.  	/* catchall */ 213. 	if (obj->owornmask) setnotworn(obj); 214. }  215.   216.  /* Returns 1 when something was stolen (or at least, when N should flee now) 217.  * Returns -1 if the monster died in the attempt 218.  * Avoid stealing the object stealoid 219.  */  220.  int 221. steal(mtmp, objnambuf) 222. struct monst *mtmp; 223. char *objnambuf; 224. {  225.  	struct obj *otmp; 226. 	int tmp, could_petrify, named = 0, armordelay; 227. 	boolean monkey_business; /* true iff an animal is doing the thievery */ 228.  229.  	if (objnambuf) *objnambuf = '\0'; 230. 	/* the following is true if successful on first of two attacks. */ 231.  	if(!monnear(mtmp, u.ux, u.uy)) return(0); 232.  233.  	/* food being eaten might already be used up but will not have 234. 	   been removed from inventory yet; we don't want to steal that, 235. 	   so this will cause it to be removed now */ 236. 	if (occupation) (void) maybe_finished_meal(FALSE); 237.  238.  	if (!invent || (inv_cnt == 1 && uskin)) { 239. nothing_to_steal: 240. 	    /* Not even a thousand men in armor can strip a naked man. */ 241.  	    if(Blind) 242. 	      pline("Somebody tries to rob you, but finds nothing to steal."); 243. 	    else 244. 	      pline("%s tries to rob you, but there is nothing to steal!",  245.  		Monnam(mtmp)); 246. 	    return(1);	/* let her flee */ 247. 	}  248.   249.  	monkey_business = is_animal(mtmp->data); 250. 	if (monkey_business) { 251. 	    ;	/* skip ring special cases */ 252. 	} else if (Adornment & LEFT_RING) { 253. 	    otmp = uleft; 254. 	    goto gotobj; 255. 	} else if (Adornment & RIGHT_RING) { 256. 	    otmp = uright; 257. 	    goto gotobj; 258. 	}  259.   260.  	tmp = 0; 261. 	for(otmp = invent; otmp; otmp = otmp->nobj) 262. 	    if ((!uarm || otmp != uarmc) && otmp != uskin  263.  #ifdef INVISIBLE_OBJECTS  264.  				&& (!otmp->oinvis || perceives(mtmp->data))  265.  #endif  266.  				) 267. 		tmp += ((otmp->owornmask & 268. 			(W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1); 269. 	if (!tmp) goto nothing_to_steal; 270. 	tmp = rn2(tmp); 271. 	for(otmp = invent; otmp; otmp = otmp->nobj) 272. 	    if ((!uarm || otmp != uarmc) && otmp != uskin  273.  #ifdef INVISIBLE_OBJECTS  274.  				&& (!otmp->oinvis || perceives(mtmp->data))  275.  #endif  276.  			) 277. 		if((tmp -= ((otmp->owornmask & 278. 			(W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1)) < 0) 279. 			break; 280. 	if(!otmp) { 281. 		impossible("Steal fails!"); 282. 		return(0); 283. 	}  284.  	/* can't steal gloves while wielding - so steal the wielded item. */ 285.  	if (otmp == uarmg && uwep) 286. 	    otmp = uwep; 287. 	/* can't steal armor while wearing cloak - so steal the cloak. */ 288.  	else if(otmp == uarm && uarmc) otmp = uarmc; 289. #ifdef TOURIST 290. 	else if(otmp == uarmu && uarmc) otmp = uarmc; 291. 	else if(otmp == uarmu && uarm) otmp = uarm; 292. #endif 293. gotobj: 294. 	if(otmp->o_id == stealoid) return(0); 295.  296.  	/* animals can't overcome curse stickiness nor unlock chains */ 297. 	if (monkey_business) { 298. 	    boolean ostuck; 299. 	    /* is the player prevented from voluntarily giving up this item? 300. 	       (ignores loadstones; the !can_carry check will catch those) */ 301. 	    if (otmp == uball) 302. 		ostuck = TRUE;	/* effectively worn; curse is implicit */ 303. 	    else if (otmp == uquiver || (otmp == uswapwep && !u.twoweap)) 304. 		ostuck = FALSE;	/* not really worn; curse doesn't matter */ 305. 	    else 306. 		ostuck = (otmp->cursed && otmp->owornmask); 307.  308.  	    if (ostuck || !can_carry(mtmp, otmp)) { 309. 		static const char *how[] = { "steal","snatch","grab","take" }; 310.  cant_take: 311. 		pline("%s tries to %s your %s but gives up.",  312.  		      Monnam(mtmp), how[rn2(SIZE(how))],  313.  		      (otmp->owornmask & W_ARMOR) ? equipname(otmp) :  314.  		       cxname(otmp)); 315. 		/* the fewer items you have, the less likely the thief 316. 		   is going to stick around to try again (0) instead of  317. running away (1) */ 318. 		return !rn2(inv_cnt / 5 + 2); 319. 	    }  320.  	}  321.   322.  	if (otmp->otyp == LEASH && otmp->leashmon) { 323. 	    if (monkey_business && otmp->cursed) goto cant_take; 324. 	    o_unleash(otmp); 325. 	}  326.   327.  	/* you're going to notice the theft... */ 328.  	stop_occupation; 329.  330.  	if((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))){ 331. 		switch(otmp->oclass) { 332. 		case TOOL_CLASS: 333. 		case AMULET_CLASS: 334. 		case RING_CLASS: 335. 		case FOOD_CLASS: /* meat ring */ 336. 		    remove_worn_item(otmp); 337. 		    break; 338. 		case ARMOR_CLASS: 339. 		    armordelay = objects[otmp->otyp].oc_delay; 340. 		    /* Stop putting on armor which has been stolen. */ 341.  		    if (donning(otmp)) { 342. 			remove_worn_item(otmp); 343. 			break; 344. 		    } else if (monkey_business) { 345. 			/* animals usually don't have enough patience 346. 			   to take off items which require extra time */ 347. 			if (armordelay >= 1 && rn2(10)) goto cant_take; 348. 			remove_worn_item(otmp); 349. 			break; 350. 		    } else { 351. 			int curssv = otmp->cursed; 352. 			int slowly; 353.  354.  			otmp->cursed = 0; 355. 			/* can't charm you without first waking you */ 356. 			if (multi < 0 && is_fainted) unmul((char *)0); 357. 			slowly = (armordelay >= 1 || multi < 0); 358. 			if(flags.female) 359. 			    pline("%s charms you.  You gladly %s your %s.",  360.  				  Blind ? "She" : Monnam(mtmp),  361.  				  curssv ? "let her take" :  362.  				  slowly ? "start removing" : "hand over",  363.  				  equipname(otmp)); 364. 			else 365. 			    pline("%s seduces you and %s off your %s.",  366.  				  Blind ? "It" : Adjmonnam(mtmp, "beautiful"),  367.  				  curssv ? "helps you to take" :  368.  				  slowly ? "you start taking" : "you take",  369.  				  equipname(otmp)); 370. 			named++; 371. 			/* the following is to set multi for later on */ 372. 			nomul(-armordelay); 373. 			remove_worn_item(otmp); 374. 			otmp->cursed = curssv; 375. 			if(multi < 0){ 376. 				/*  377.  				multi = 0; 378. 				nomovemsg = 0; 379. 				afternmv = 0; 380. 				*/  381.  				stealoid = otmp->o_id; 382. 				stealmid = mtmp->m_id; 383. 				afternmv = stealarm; 384. 				return(0); 385. 			}  386.  		    }  387.  		    break; 388. 		default: 389. 		    impossible("Tried to steal a strange worn thing. [%d]",  390.  			       otmp->oclass); 391. 		}  392.  	}  393.  	else if (otmp->owornmask) 394. 	    remove_worn_item(otmp); 395.  396.  	/* do this before removing it from inventory */ 397. 	if (objnambuf) Strcpy(objnambuf, yname(otmp)); 398.  399.  	freeinv(otmp); 400. 	pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp)); 401. 	could_petrify = (otmp->otyp == CORPSE &&  402.  			 touch_petrifies(&mons[otmp->corpsenm])); 403. 	(void) mpickobj(mtmp,otmp);	/* may free otmp */ 404. 	if (could_petrify && !(mtmp->misc_worn_check & W_ARMG)) { 405. 	    minstapetrify(mtmp, TRUE); 406. 	    return -1; 407. 	}  408.  	return((multi < 0) ? 0 : 1); 409. }  410.   411.  #endif /* OVLB */ 412. #ifdef OVL1 413.  414.  /* Returns 1 if otmp is free'd, 0 otherwise. */ 415.  int 416. mpickobj(mtmp,otmp) 417. register struct monst *mtmp; 418. register struct obj *otmp; 419. {  420.      int freed_otmp; 421.  422.  #ifndef GOLDOBJ 423.     if (otmp->oclass == GOLD_CLASS) { 424. 	mtmp->mgold += otmp->quan; 425. 	obfree(otmp, (struct obj *)0); 426. 	freed_otmp = 1; 427.     } else { 428. #endif 429.     boolean snuff_otmp = FALSE; 430.     /* don't want hidden light source inside the monster; assumes that 431.        engulfers won't have external inventories; whirly monsters cause 432.        the light to be extinguished rather than letting it shine thru */ 433.     if (otmp->lamplit &&  /* hack to avoid function calls for most objs */  434.        	obj_sheds_light(otmp) &&  435.  	attacktype(mtmp->data, AT_ENGL)) { 436. 	/* this is probably a burning object that you dropped or threw */ 437. 	if (u.uswallow && mtmp == u.ustuck && !Blind) 438. 	    pline("%s out.", Tobjnam(otmp, "go")); 439. 	snuff_otmp = TRUE; 440.     }  441.      /* Must do carrying effects on object prior to add_to_minv */ 442.     carry_obj_effects(otmp); 443.     /* add_to_minv might free otmp [if merged with something else], 444.        so we have to call it after doing the object checks */ 445.     freed_otmp = add_to_minv(mtmp, otmp); 446.     /* and we had to defer this until object is in mtmp's inventory */ 447.     if (snuff_otmp) snuff_light_source(mtmp->mx, mtmp->my); 448. #ifndef GOLDOBJ 449.     }  450.  #endif 451.     return freed_otmp; 452. }  453.   454.  #endif /* OVL1 */ 455. #ifdef OVLB 456.  457.  void 458. stealamulet(mtmp) 459. struct monst *mtmp; 460. {  461.      struct obj *otmp = (struct obj *)0; 462.     int real=0, fake=0; 463.  464.      /* select the artifact to steal */ 465.     if(u.uhave.amulet) { 466. 	real = AMULET_OF_YENDOR; 467. 	fake = FAKE_AMULET_OF_YENDOR; 468.     } else if(u.uhave.questart) { 469. 	for(otmp = invent; otmp; otmp = otmp->nobj) 470. 	    if(is_quest_artifact(otmp)) break; 471. 	if (!otmp) return;	/* should we panic instead? */ 472.      } else if(u.uhave.bell) { 473. 	real = BELL_OF_OPENING; 474. 	fake = BELL; 475.     } else if(u.uhave.book) { 476. 	real = SPE_BOOK_OF_THE_DEAD; 477.     } else if(u.uhave.menorah) { 478. 	real = CANDELABRUM_OF_INVOCATION; 479.     } else return;	/* you have nothing of special interest */ 480.  481.      if (!otmp) { 482. 	/* If we get here, real and fake have been set up. */ 483.  	for(otmp = invent; otmp; otmp = otmp->nobj) 484. 	    if(otmp->otyp == real || (otmp->otyp == fake && !mtmp->iswiz)) 485. 		break; 486.     }  487.   488.      if (otmp) { /* we have something to snatch */ 489. 	if (otmp->owornmask) 490. 	    remove_worn_item(otmp); 491. 	freeinv(otmp); 492. 	/* mpickobj wont merge otmp because none of the above things 493. 	   to steal are mergable */ 494. 	(void) mpickobj(mtmp,otmp);	/* may merge and free otmp */ 495. 	pline("%s stole %s!", Monnam(mtmp), doname(otmp)); 496. 	if (can_teleport(mtmp->data) && !tele_restrict(mtmp)) 497. 	    rloc(mtmp); 498.     }  499.  }  500.   501.  #endif /* OVLB */ 502. #ifdef OVL0 503.  504.  /* release the objects the creature is carrying */ 505. void 506. relobj(mtmp,show,is_pet) 507. register struct monst *mtmp; 508. register int show; 509. boolean is_pet;		/* If true, pet should keep wielded/worn items */ 510. {  511.  	register struct obj *otmp; 512. 	register int omx = mtmp->mx, omy = mtmp->my; 513. 	struct obj *keepobj = 0; 514. 	struct obj *wep = MON_WEP(mtmp); 515. 	boolean item1 = FALSE, item2 = FALSE; 516.  517.  	if (!is_pet || mindless(mtmp->data) || is_animal(mtmp->data)) 518. 		item1 = item2 = TRUE; 519. 	if (!tunnels(mtmp->data) || !needspick(mtmp->data)) 520. 		item1 = TRUE; 521. 	while ((otmp = mtmp->minvent) != 0) { 522. 		obj_extract_self(otmp); 523. 		/* special case: pick-axe and unicorn horn are non-worn */ 524. 		/* items that we also want pets to keep 1 of */ 525. 		/* (It is a coincidence that these can also be wielded. */  526.  		if (otmp->owornmask || otmp == wep || 527. 		    ((!item1 && otmp->otyp == PICK_AXE) ||  528.  		     (!item2 && otmp->otyp == UNICORN_HORN && !otmp->cursed))) {  529.  			if (is_pet) { /* dont drop worn/wielded item */  530.  				if (otmp->otyp == PICK_AXE)  531.  					item1 = TRUE;  532.  				if (otmp->otyp == UNICORN_HORN && !otmp->cursed)  533.  					item2 = TRUE;  534.  				otmp->nobj = keepobj;  535.  				keepobj = otmp;  536.  				continue;  537.  			}  538.  			mtmp->misc_worn_check &= ~(otmp->owornmask);  539.  #ifdef STEED  540.  			/* don't charge for an owned saddle on dead pet */  541.  			if (mtmp->mtame && mtmp->mhp == 0 && 542. 			    (otmp->owornmask & W_SADDLE) && !otmp->unpaid && 543. 			    costly_spot(mtmp->mx, mtmp->my))  544.  				otmp->no_charge = 1;  545.  #endif  546.  			otmp->owornmask = 0L;  547.  		}  548.  		if (is_pet && cansee(omx, omy) && flags.verbose)  549.  			pline("%s drops %s.", Monnam(mtmp), 550. 					distant_name(otmp, doname));  551.  		if (flooreffects(otmp, omx, omy, "fall")) continue;  552.  		place_object(otmp, omx, omy);  553.  		stackobj(otmp);  554.  	}  555.  	/* put kept objects back */  556.  	while ((otmp = keepobj) != (struct obj *)0) {  557.  	    keepobj = otmp->nobj;  558.  	    (void) add_to_minv(mtmp, otmp);  559.  	}  560.  #ifndef GOLDOBJ  561.  	if (mtmp->mgold) {  562.  		register long g = mtmp->mgold;  563.  		(void) mkgold(g, omx, omy);  564.  		if (is_pet && cansee(omx, omy) && flags.verbose)  565.  			pline("%s drops %ld gold piece%s.", Monnam(mtmp), 566. 				g, plur(g));  567.  		mtmp->mgold = 0L;  568.  	}  569.  #endif  570.  	  571.  	if (show & cansee(omx, omy))  572.  		newsym(omx, omy);  573.  }  574.   575.  #endif /* OVL0 */  576.   577.  /*steal.c*/