Source:NetHack 3.3.0/steal.c

Below is the full text to steal.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.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.3	1999/02/13	*/ 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" :  24.   		(otmp == uarmh) ? "helmet" : "armor"); 25.  }  26.    27.   long		/* actually returns something that fits in an int */ 28.  somegold 29.  {  30.   #ifdef LINT	/* long conv. ok */ 31.  	return(0L); 32.  #else 33.  	return (long)( (u.ugold < 100) ? u.ugold :  34.   		(u.ugold > 10000) ? rnd(10000) : rnd((int) u.ugold) ); 35.  #endif 36.  }  37.    38.   void 39.  stealgold(mtmp) 40.  register struct monst *mtmp; 41.  {  42.   	register struct obj *gold = g_at(u.ux, u.uy); 43.  	register long tmp; 44.   45.   	if (gold && ( !u.ugold || gold->quan > u.ugold || !rn2(5))) { 46.  	    mtmp->mgold += gold->quan; 47.  	    delobj(gold); 48.  	    newsym(u.ux, u.uy); 49.  	    pline("%s quickly snatches some gold from between your %s!",  50.   		    Monnam(mtmp), makeplural(body_part(FOOT))); 51.  	    if(!u.ugold || !rn2(5)) { 52.  		if (!tele_restrict(mtmp)) rloc(mtmp); 53.  		mtmp->mflee = 1; 54.  	    }  55.   	} else if(u.ugold) { 56.  	    u.ugold -= (tmp = somegold); 57.  	    Your("purse feels lighter."); 58.  	    mtmp->mgold += tmp; 59.  	    if (!tele_restrict(mtmp)) rloc(mtmp); 60.  	    mtmp->mflee = 1; 61.  	    flags.botl = 1; 62.  	}  63.   }  64.    65.   /* steal armor after you finish taking it off */ 66.  unsigned int stealoid;		/* object to be stolen */ 67.  unsigned int stealmid;		/* monster doing the stealing */ 68.   69.   STATIC_PTR int 70.  stealarm 71.  {  72.   	register struct monst *mtmp; 73.  	register struct obj *otmp; 74.   75.   	for(otmp = invent; otmp; otmp = otmp->nobj) { 76.  	    if(otmp->o_id == stealoid) { 77.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 78.  		    if(mtmp->m_id == stealmid) { 79.  			if(!dmgtype(mtmp->data, AD_SITM)) /* polymorphed */ 80.  			    goto botm; 81.  			if(otmp->unpaid) 82.  			    subfrombill(otmp, shop_keeper(*u.ushops)); 83.  			freeinv(otmp); 84.  			pline("%s steals %s!", Monnam(mtmp), doname(otmp)); 85.  			mpickobj(mtmp,otmp); 86.  			mtmp->mflee = 1; 87.  			if (!tele_restrict(mtmp)) rloc(mtmp); 88.  		        break; 89.  		    }  90.   		}  91.   		break; 92.  	    }  93.   	}  94.   botm:   stealoid = 0; 95.  	return 0; 96.  }  97.    98.   /* An object you're wearing has been taken off my a monster (theft or  99.      seduction). Also used if a worn item gets transformed (stone to flesh). */ 100.  void 101. remove_worn_item(obj) 102. struct obj *obj; 103. {  104.  	if (donning(obj)) 105. 	    cancel_don; 106. 	if (!obj->owornmask) 107. 	    return; 108.  109.  	switch (obj->oclass) { 110. 	 case TOOL_CLASS: 111. 	    if (obj == ublindf) Blindf_off(obj); 112. 	    break; 113. 	 case AMULET_CLASS: 114. 	    Amulet_off; 115. 	    break; 116. 	 case RING_CLASS: 117. 	 case FOOD_CLASS: /* meat ring */ 118. 	    Ring_gone(obj); 119. 	    break; 120. 	 case ARMOR_CLASS: 121. 	    if (obj == uarm) (void) Armor_off; 122. 	    else if (obj == uarmc) (void) Cloak_off; 123. 	    else if (obj == uarmf) (void) Boots_off; 124. 	    else if (obj == uarmg) (void) Gloves_off; 125. 	    else if (obj == uarmh) (void) Helmet_off; 126. 	    else if (obj == uarms) (void) Shield_off; 127. 	    else setworn((struct obj *)0, obj->owornmask & W_ARMOR); 128. 	    break; 129. 	 default: 130. 	    /* shouldn't reach here, but just in case... */ 131.  	    setnotworn(obj); 132. 	    break; 133. 	}  134.  }  135.   136.  /* Returns 1 when something was stolen (or at least, when N should flee now) 137.  * Returns -1 if the monster died in the attempt 138.  * Avoid stealing the object stealoid 139.  */  140.  int 141. steal(mtmp) 142. struct monst *mtmp; 143. {  144.  	register struct obj *otmp; 145. 	register int tmp; 146. 	register int named = 0; 147.  148.  	/* the following is true if successful on first of two attacks. */ 149.  	if(!monnear(mtmp, u.ux, u.uy)) return(0); 150.  151.  	if (!invent || (inv_cnt == 1 && uskin)) { 152. nothing_to_steal: 153. 	    /* Not even a thousand men in armor can strip a naked man. */ 154.  	    if(Blind) 155. 	      pline("Somebody tries to rob you, but finds nothing to steal."); 156. 	    else 157. 	      pline("%s tries to rob you, but there is nothing to steal!",  158.  		Monnam(mtmp)); 159. 	    return(1);	/* let her flee */ 160. 	}  161.   162.  	if (Adornment & LEFT_RING) { 163. 	    otmp = uleft; 164. 	    goto gotobj; 165. 	} else if (Adornment & RIGHT_RING) { 166. 	    otmp = uright; 167. 	    goto gotobj; 168. 	}  169.   170.  	tmp = 0; 171. 	for(otmp = invent; otmp; otmp = otmp->nobj) 172. 	    if ((!uarm || otmp != uarmc) && otmp != uskin  173.  #ifdef INVISIBLE_OBJECTS  174.  				&& (!otmp->oinvis || perceives(mtmp->data))  175.  #endif  176.  				) 177. 		tmp += ((otmp->owornmask & 178. 			(W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1); 179. 	if (!tmp) goto nothing_to_steal; 180. 	tmp = rn2(tmp); 181. 	for(otmp = invent; otmp; otmp = otmp->nobj) 182. 	    if ((!uarm || otmp != uarmc) && otmp != uskin  183.  #ifdef INVISIBLE_OBJECTS  184.  				&& (!otmp->oinvis || perceives(mtmp->data))  185.  #endif  186.  	    		) 187. 		if((tmp -= ((otmp->owornmask & 188. 			(W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1)) < 0) 189. 			break; 190. 	if(!otmp) { 191. 		impossible("Steal fails!"); 192. 		return(0); 193. 	}  194.  	/* can't steal gloves while wielding - so steal the wielded item. */ 195.  	if (otmp == uarmg && uwep) 196. 	    otmp = uwep; 197. 	/* can't steal armor while wearing cloak - so steal the cloak. */ 198.  	else if(otmp == uarm && uarmc) otmp = uarmc; 199. #ifdef TOURIST 200. 	else if(otmp == uarmu && uarmc) otmp = uarmc; 201. 	else if(otmp == uarmu && uarm) otmp = uarm; 202. #endif 203. gotobj: 204. 	if(otmp->o_id == stealoid) return(0); 205.  206.  	if(otmp->otyp == LEASH && otmp->leashmon) o_unleash(otmp); 207.  208.  	if((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))){ 209. 		switch(otmp->oclass) { 210. 		case TOOL_CLASS: 211. 		case AMULET_CLASS: 212. 		case RING_CLASS: 213. 		case FOOD_CLASS: /* meat ring */ 214. 			remove_worn_item(otmp); 215. 			break; 216. 		case ARMOR_CLASS: 217. 			/* Stop putting on armor which has been stolen. */ 218.  			if (donning(otmp) || is_animal(mtmp->data)) { 219. 			    remove_worn_item(otmp); 220. 			    break; 221. 			} else { 222. 			int curssv = otmp->cursed; 223.  224.  			otmp->cursed = 0; 225. 			stop_occupation; 226. 			if(flags.female) 227. 			    pline("%s charms you.  You gladly %s your %s.",  228.  				  Blind ? "She" : Monnam(mtmp),  229.  				  curssv ? "let her take" :  230.  	(objects[otmp->otyp].oc_delay > 1) ? "start removing" : "hand over",  231.  				  equipname(otmp)); 232. 			else 233. 			    pline("%s seduces you and %s off your %s.",  234.  				  Blind ? "It" : Adjmonnam(mtmp, "beautiful"),  235.  				  curssv ? "helps you to take" :  236.  	(objects[otmp->otyp].oc_delay > 1) ? "you start taking" : "you take",  237.  				  equipname(otmp)); 238. 			named++; 239. 			/* the following is to set multi for later on */ 240. 			nomul(-objects[otmp->otyp].oc_delay); 241. 			remove_worn_item(otmp); 242. 			otmp->cursed = curssv; 243. 			if(multi < 0){ 244. 				/*  245.  				multi = 0; 246. 				nomovemsg = 0; 247. 				afternmv = 0; 248. 				*/  249.  				stealoid = otmp->o_id; 250. 				stealmid = mtmp->m_id; 251. 				afternmv = stealarm; 252. 				return(0); 253. 			}  254.  		    }  255.  			break; 256. 		default: 257. 			impossible("Tried to steal a strange worn thing."); 258. 		}  259.  	}  260.  	else if (otmp == uwep) uwepgone; 261. 	else if (otmp == uquiver) uqwepgone; 262. 	else if (otmp == uswapwep) uswapwepgone; 263.  264.  	if(otmp == uball) unpunish; 265.  266.  	freeinv(otmp); 267. 	pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp)); 268. 	mpickobj(mtmp,otmp); 269. 	if (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]) &&  270.  		!(mtmp->misc_worn_check & W_ARMG)) { 271. 	    minstapetrify(mtmp, TRUE); 272. 	    return -1; 273. 	}  274.  	return((multi < 0) ? 0 : 1); 275. }  276.   277.  #endif /* OVLB */ 278. #ifdef OVL1 279.  280.  void 281. mpickobj(mtmp,otmp) 282. register struct monst *mtmp; 283. register struct obj *otmp; 284. {  285.      if (otmp->oclass == GOLD_CLASS) { 286. 	mtmp->mgold += otmp->quan; 287. 	obfree(otmp, (struct obj *)0); 288.     } else { 289. 	boolean snuff_otmp = FALSE; 290. 	/* don't want hidden light source inside the monster; assumes that 291. 	   engulfers won't have external inventories; whirly monsters cause 292. 	   the light to be extinguished rather than letting it shine thru */ 293. 	if (otmp->lamplit &&  /* hack to avoid function calls for most objs */  294.  		obj_sheds_light(otmp) &&  295.  		attacktype(mtmp->data, AT_ENGL)) { 296. 	    /* this is probably a burning object that you dropped or threw */ 297. 	    if (u.uswallow && mtmp == u.ustuck && !Blind) 298. 		pline("%s go%s out.", The(xname(otmp)),  299.  		      otmp->quan == 1L ? "es" : ""); 300. 	    snuff_otmp = TRUE; 301. 	}  302.  	/* Must do carrying effects on object prior to add_to_minv */ 303. 	carry_obj_effects(otmp); 304. 	/* add_to_minv might free otmp [if merged with something else], 305. 	   so we have to call it after doing the object checks */ 306. 	add_to_minv(mtmp, otmp); 307. 	/* and we had to defer this until object is in mtmp's inventory */ 308. 	if (snuff_otmp) snuff_light_source(mtmp->mx, mtmp->my); 309.     }  310.  }  311.   312.  #endif /* OVL1 */ 313. #ifdef OVLB 314.  315.  void 316. stealamulet(mtmp) 317. register struct monst *mtmp; 318. {  319.  	register struct obj *otmp; 320. 	register int	real, fake; 321.  322.  	/* select the artifact to steal */ 323. 	if(u.uhave.amulet) { 324. 		real = AMULET_OF_YENDOR ; 325. 		fake = FAKE_AMULET_OF_YENDOR ; 326. 	} else if(u.uhave.questart) { 327. 	    real = fake = 0;		/* gcc -Wall lint */ 328. 	    for(otmp = invent; otmp; otmp = otmp->nobj) 329. 	        if(is_quest_artifact(otmp)) goto snatch_it; 330. 	} else if(u.uhave.bell) { 331. 		real = BELL_OF_OPENING; 332. 		fake = BELL; 333. 	} else if(u.uhave.book) { 334. 		real = SPE_BOOK_OF_THE_DEAD; 335. 		fake = 0; 336. 	} else if(u.uhave.menorah) { 337. 		real = CANDELABRUM_OF_INVOCATION; 338. 		fake = 0; 339. 	} else return;	/* you have nothing of special interest */ 340.  341.  /*	If we get here, real and fake have been set up. */ 342.  	for(otmp = invent; otmp; otmp = otmp->nobj) { 343. 	    if(otmp->otyp == real || (otmp->otyp == fake && !mtmp->iswiz)) { 344. 		/* might be an imitation one */ 345. snatch_it: 346. 		if (otmp->owornmask) 347. 		    remove_worn_item(otmp); 348. 		freeinv(otmp); 349. 		mpickobj(mtmp,otmp); 350. 		pline("%s stole %s!", Monnam(mtmp), doname(otmp)); 351. 		if (can_teleport(mtmp->data) && !tele_restrict(mtmp)) 352. 			rloc(mtmp); 353. 		return; 354. 	    }  355.  	}  356.  }  357.   358.  #endif /* OVLB */ 359. #ifdef OVL0 360.  361.  /* release the objects the creature is carrying */ 362. void 363. relobj(mtmp,show,is_pet) 364. register struct monst *mtmp; 365. register int show; 366. boolean is_pet;		/* If true, pet should keep wielded/worn items */ 367. {  368.  	register struct obj *otmp; 369. 	register int omx = mtmp->mx, omy = mtmp->my; 370. 	struct obj *keepobj = 0; 371. 	struct obj *wep = MON_WEP(mtmp); 372. 	boolean item1 = FALSE, item2 = FALSE; 373.  374.  	if (!is_pet || mindless(mtmp->data) || is_animal(mtmp->data)) 375. 		item1 = item2 = TRUE; 376. 	if (!tunnels(mtmp->data) || !needspick(mtmp->data)) 377. 		item1 = TRUE; 378. 	while ((otmp = mtmp->minvent) != 0) { 379. 		obj_extract_self(otmp); 380. 		/* special case: pick-axe and unicorn horn are non-worn */ 381. 		/* items that we also want pets to keep 1 of */ 382. 		/* (It is a coincidence that these can also be wielded. */  383.  		if (otmp->owornmask || otmp == wep || 384. 		    ((!item1 && otmp->otyp == PICK_AXE) ||  385.  		     (!item2 && otmp->otyp == UNICORN_HORN && !otmp->cursed))) {  386.  			if (is_pet) { /* dont drop worn/wielded item */  387.  				if (otmp->otyp == PICK_AXE)  388.  					item1 = TRUE;  389.  				if (otmp->otyp == UNICORN_HORN && !otmp->cursed)  390.  					item2 = TRUE;  391.  				otmp->nobj = keepobj;  392.  				keepobj = otmp;  393.  				continue;  394.  			}  395.  			mtmp->misc_worn_check &= ~(otmp->owornmask);  396.  			otmp->owornmask = 0L;  397.  		}  398.  		if (is_pet && cansee(omx, omy) && flags.verbose)  399.  			pline("%s drops %s.", Monnam(mtmp), 400. 					distant_name(otmp, doname));  401.  		if (flooreffects(otmp, omx, omy, "fall")) continue;  402.  		place_object(otmp, omx, omy);  403.  		stackobj(otmp);  404.  	}  405.  	/* put kept objects back */  406.  	while ((otmp = keepobj) != (struct obj *)0) {  407.  	    keepobj = otmp->nobj;  408.  	    add_to_minv(mtmp, otmp);  409.  	}  410.   411.  	if (mtmp->mgold) {  412.  		register long g = mtmp->mgold;  413.  		(void) mkgold(g, omx, omy);  414.  		if (is_pet && cansee(omx, omy) && flags.verbose)  415.  			pline("%s drops %ld gold piece%s.", Monnam(mtmp), 416. 				g, plur(g));  417.  		mtmp->mgold = 0L;  418.  	}  419.  	if (show & cansee(omx, omy))  420.  		newsym(omx, omy);  421.  }  422.   423.  #endif /* OVL0 */  424.   425.  /*steal.c*/