Source:NetHack 3.3.0/mkobj.c

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

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

1.   /*	SCCS Id: @(#)mkobj.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.    #include "artifact.h"  7.    #include "prop.h"  8. 9.   STATIC_DCL void FDECL(mkbox_cnts,(struct obj *)); 10.  STATIC_DCL void FDECL(obj_timer_checks,(struct obj *, XCHAR_P, XCHAR_P, int)); 11.  #ifdef OVL1 12.  STATIC_DCL void FDECL(container_weight, (struct obj *)); 13.  STATIC_DCL struct obj *FDECL(save_mtraits, (struct obj *, struct monst *)); 14.  #ifdef WIZARD 15.  STATIC_DCL const char *FDECL(where_name, (int)); 16.  STATIC_DCL void FDECL(check_contained, (struct obj *,const char *)); 17.  #endif 18.  #endif /* OVL1 */ 19.   20.   /*#define DEBUG_EFFECTS*/	/* show some messages for debugging */ 21.   22.   struct icp { 23.      int  iprob;		/* probability of an item type */ 24.      char iclass;	/* item class */ 25.  };  26.    27.   #ifdef OVL1 28.   29.   const struct icp mkobjprobs[] = { 30.  {10, WEAPON_CLASS}, 31.  {10, ARMOR_CLASS}, 32.  {20, FOOD_CLASS}, 33.  { 8, TOOL_CLASS}, 34.  { 8, GEM_CLASS}, 35.  {16, POTION_CLASS}, 36.  {16, SCROLL_CLASS}, 37.  { 4, SPBOOK_CLASS}, 38.  { 4, WAND_CLASS}, 39.  { 3, RING_CLASS}, 40.  { 1, AMULET_CLASS} 41.  };  42.    43.   const struct icp boxiprobs[] = { 44.  {18, GEM_CLASS}, 45.  {15, FOOD_CLASS}, 46.  {18, POTION_CLASS}, 47.  {18, SCROLL_CLASS}, 48.  {12, SPBOOK_CLASS}, 49.  { 7, GOLD_CLASS}, 50.  { 6, WAND_CLASS}, 51.  { 5, RING_CLASS}, 52.  { 1, AMULET_CLASS} 53.  };  54.    55.   #ifdef REINCARNATION 56.  const struct icp rogueprobs[] = { 57.  {12, WEAPON_CLASS}, 58.  {12, ARMOR_CLASS}, 59.  {22, FOOD_CLASS}, 60.  {22, POTION_CLASS}, 61.  {22, SCROLL_CLASS}, 62.  { 5, WAND_CLASS}, 63.  { 5, RING_CLASS} 64.  };  65.   #endif 66.   67.   const struct icp hellprobs[] = { 68.  {20, WEAPON_CLASS}, 69.  {20, ARMOR_CLASS}, 70.  {16, FOOD_CLASS}, 71.  {12, TOOL_CLASS}, 72.  {10, GEM_CLASS}, 73.  { 1, POTION_CLASS}, 74.  { 1, SCROLL_CLASS}, 75.  { 8, WAND_CLASS}, 76.  { 8, RING_CLASS}, 77.  { 4, AMULET_CLASS} 78.  };  79.    80.   struct obj * 81.  mkobj_at(let,x,y, artif) 82.  char let; 83.  int x,y; 84.  boolean artif; 85.  {  86.   	register struct obj *otmp; 87.   88.   	otmp = mkobj(let,artif); 89.  	place_object(otmp, x, y); 90.  	return(otmp); 91.  }  92.    93.   struct obj * 94.  mksobj_at(otyp,x,y,init) 95.  int otyp,x,y; 96.  boolean init; 97.  {  98.   	register struct obj *otmp; 99.   100.  	otmp = mksobj(otyp,init,TRUE); 101. 	place_object(otmp, x, y); 102. 	return(otmp); 103. }  104.   105.  struct obj * 106. mkobj(oclass, artif) 107. char oclass; 108. boolean artif; 109. {  110.  	register int tprob, i, prob = rnd(1000); 111.  112.  	if(oclass == RANDOM_CLASS) { 113. 		const struct icp *iprobs = 114. #ifdef REINCARNATION 115. 				    (Is_rogue_level(&u.uz)) ? 116. 				    (const struct icp *)rogueprobs : 117. #endif 118. 				    Inhell ? (const struct icp *)hellprobs : 119. 				    (const struct icp *)mkobjprobs; 120.  121.  		for(tprob = rnd(100);  122.  		    (tprob -= iprobs->iprob) > 0;  123.  		    iprobs++); 124. 		oclass = iprobs->iclass; 125. 	}  126.   127.  	i = bases[(int)oclass]; 128. 	while((prob -= objects[i].oc_prob) > 0) i++; 129.  130.  	if(objects[i].oc_class != oclass || !OBJ_NAME(objects[i])) 131. 		panic("probtype error, oclass=%d i=%d", (int) oclass, i); 132.  133.  	return(mksobj(i, TRUE, artif)); 134. }  135.   136.  STATIC_OVL void 137. mkbox_cnts(box) 138. struct obj *box; 139. {  140.  	register int n;  141. register struct obj *otmp, *gold = 0; 142.  143.  	box->cobj = (struct obj *) 0; 144.  145.  	switch(box->otyp) { 146. 		case ICE_BOX:		n = 20; break; 147. 		case CHEST:		n = 5; break; 148. 		case LARGE_BOX:		n = 3; break; 149. 		case SACK: 150. 		case OILSKIN_SACK: 151. 				/* initial inventory: sack starts out empty */ 152. 				if (moves <= 1 && !in_mklev) { n = 0; break; } 153. 				/*else FALLTHRU*/ 154. 		case BAG_OF_HOLDING:	n = 1; break; 155. 		default:		n = 0; break; 156. 	}  157.   158.  	for (n = rn2(n+1); n > 0; n--) { 159. 	    if (box->otyp == ICE_BOX) { 160. 		if (!(otmp = mksobj(CORPSE, TRUE, TRUE))) continue; 161. 		/* Note: setting age to 0 is correct. Age has a different 162. 		 * from usual meaning for objects stored in ice boxes. -KAA 163. 		 */  164.  		otmp->age = 0L; 165. 		if (otmp->timed) { 166. 		    (void) stop_timer(ROT_CORPSE, (genericptr_t)otmp); 167. 		    (void) stop_timer(REVIVE_MON, (genericptr_t)otmp); 168. 		}  169.  	    } else { 170. 		register int tprob; 171. 		const struct icp *iprobs = boxiprobs; 172.  173.  		for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++) 174. 		    ;  175.  		if (!(otmp = mkobj(iprobs->iclass, TRUE))) continue; 176.  177.  		/* handle a couple of special cases */ 178. 		if (otmp->oclass == GOLD_CLASS) { 179. 		    /* 2.5 x level's usual amount; weight adjusted below */ 180. 		    otmp->quan = (long)(rnd(level_difficulty+2) * rnd(75)); 181. 		    if (gold) {			/* gold already in this box */ 182. 			gold->quan += otmp->quan;	/* merge */ 183. 			dealloc_obj(otmp);	/* note: not yet in any chain */ 184. 			continue; 185. 		    } else { 186. 			gold = otmp;		/* remember this object */ 187. 		    }  188.  		} else while (otmp->otyp == ROCK) { 189. 		    otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LOADSTONE); 190. 		    if (otmp->quan > 2L) otmp->quan = 1L; 191. 		    otmp->owt = weight(otmp); 192. 		}  193.  		if (box->otyp == BAG_OF_HOLDING) { 194. 		    if (Is_mbag(otmp)) { 195. 			otmp->otyp = SACK; 196. 			otmp->spe = 0; 197. 			otmp->owt = weight(otmp); 198. 		    } else while (otmp->otyp == WAN_CANCELLATION) 199. 			    otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING); 200. 		}  201.  	    }  202.  	    add_to_container(box, otmp); 203. 	}  204.  	if (gold) gold->owt = weight(gold);	/* quantity was diddled */ 205. 	return; 206. }  207.   208.  int 209. rndmonnum	/* select a random, common monster type */ 210. {  211.  	register struct permonst *ptr; 212. 	register int	i; 213.  214.  	/* Plan A: get a level-appropriate common monster */ 215. 	ptr = rndmonst; 216. 	if (ptr) return(monsndx(ptr)); 217.  218.  	/* Plan B: get any common monster */ 219. 	do { 220. 	    i = rn1(SPECIAL_PM - LOW_PM, LOW_PM); 221. 	    ptr = &mons[i]; 222. 	} while((ptr->geno & G_NOGEN) || (!Inhell && (ptr->geno & G_HELL))); 223.  224.  	return(i); 225. }  226.   227.  /*  228.   * Split obj so that it gets size num. The remainder is put in the object 229.  * structure delivered by this call. The object is positioned just 230.  * following the original in the nobj chain (and nexthere chain when on  231.   * the floor). 232.  */  233.  struct obj * 234. splitobj(obj, num) 235. struct obj *obj; 236. long num; 237. {  238.  	struct obj *otmp; 239.  240.  	if (obj->cobj || num <= 0L || obj->quan < num) 241. 	    panic("splitobj");	/* can't split containers */ 242. 	otmp = newobj(obj->oxlth + obj->onamelth); 243. 	*otmp = *obj;		/* copies whole structure */ 244. 	otmp->o_id = flags.ident++; 245. 	if (!otmp->o_id) otmp->o_id = flags.ident++;	/* ident overflowed */ 246. 	otmp->timed = 0;	/* not timed, yet */ 247. 	otmp->lamplit = 0;	/* ditto */ 248. 	obj->quan = num; 249. 	obj->owt = weight(obj); 250. 	otmp->quan -= num; 251. 	otmp->owt = weight(otmp);	/* -= obj->owt ? */ 252.  	obj->nobj = otmp; 253. 	/* Only set nexthere when on the floor, nexthere is also used */ 254. 	/* as a back pointer to the container object when contained. */ 255.  	if (obj->where == OBJ_FLOOR) 256. 	    obj->nexthere = otmp; 257. 	if (obj->oxlth) 258. 	    (void)memcpy((genericptr_t)otmp->oextra, (genericptr_t)obj->oextra,  259.  			obj->oxlth); 260. 	if (obj->onamelth) 261. 	    (void)strncpy(ONAME(otmp), ONAME(obj), (int)obj->onamelth); 262. 	if (obj->unpaid) splitbill(obj,otmp); 263. 	if (obj->timed) obj_split_timers(obj, otmp); 264. 	if (obj_sheds_light(obj)) obj_split_light_source(obj, otmp); 265. 	return otmp; 266. }  267.   268.  /*  269.   * Create a dummy duplicate to put on shop bill. The duplicate exists 270.  * only in the billobjs chain. This function is used when a shop object 271.  * is being altered, and a copy of the original is needed for billing 272.  * purposes. For example, when eating, where an interruption will yield 273.  * an object which is different from what it started out as; the "I x"  274. * command needs to display the original object. 275.  */  276.  void 277. bill_dummy_object(otmp) 278. register struct obj *otmp; 279. {  280.  	register struct obj *dummy; 281.  282.  	if (otmp->unpaid) 283. 	    subfrombill(otmp, shop_keeper(*u.ushops)); 284. 	dummy = newobj(otmp->oxlth + otmp->onamelth); 285. 	*dummy = *otmp; 286. 	dummy->where = OBJ_FREE; 287. 	dummy->o_id = flags.ident++; 288. 	if (!dummy->o_id) dummy->o_id = flags.ident++;	/* ident overflowed */ 289. 	dummy->timed = 0; 290. 	if (otmp->oxlth) 291. 	    (void)memcpy((genericptr_t)dummy->oextra,  292.  			(genericptr_t)otmp->oextra, otmp->oxlth); 293. 	if (otmp->onamelth) 294. 	    (void)strncpy(ONAME(dummy), ONAME(otmp), (int)otmp->onamelth); 295. 	if (Is_candle(dummy)) dummy->lamplit = 0; 296. 	addtobill(dummy, FALSE, TRUE, TRUE); 297. }  298.   299.  #endif /* OVL1 */ 300. #ifdef OVLB 301.  302.  static const char dknowns[] = { 303. 		WAND_CLASS, RING_CLASS, POTION_CLASS, SCROLL_CLASS, 304. 		GEM_CLASS, SPBOOK_CLASS, WEAPON_CLASS, TOOL_CLASS, 0 305. };  306.   307.  struct obj * 308. mksobj(otyp, init, artif) 309. int otyp; 310. boolean init; 311. boolean artif; 312. {  313.  	int mndx, tryct; 314. 	struct obj *otmp; 315. 	char let = objects[otyp].oc_class; 316.  317.  	otmp = newobj(0); 318. 	*otmp = zeroobj; 319. 	otmp->age = monstermoves; 320. 	otmp->o_id = flags.ident++; 321. 	if (!otmp->o_id) otmp->o_id = flags.ident++;	/* ident overflowed */ 322. 	otmp->quan = 1L; 323. 	otmp->oclass = let; 324. 	otmp->otyp = otyp; 325. 	otmp->where = OBJ_FREE; 326. 	otmp->dknown = index(dknowns, let) ? 0 : 1; 327.  	if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD) ||  328.  			otmp->otyp == SHIELD_OF_REFLECTION) 329. 		otmp->dknown = 0; 330. 	if (!objects[otmp->otyp].oc_uses_known) 331. 		otmp->known = 1; 332. #ifdef INVISIBLE_OBJECTS 333. 	otmp->oinvis = !rn2(1250); 334. #endif 335. 	if (init) switch (let) { 336. 	case WEAPON_CLASS: 337. 		otmp->quan = is_multigen(otmp) ? (long) rn1(6,6) : 1L; 338. 		if(!rn2(11)) { 339. 			otmp->spe = rne(3); 340. 			otmp->blessed = rn2(2); 341. 		} else if(!rn2(10)) { 342. 			curse(otmp); 343. 			otmp->spe = -rne(3); 344. 		} else	blessorcurse(otmp, 10); 345. 		if (is_poisonable(otmp) && !rn2(100)) 346. 			otmp->opoisoned = 1; 347.  348.  		if (artif && !rn2(20)) 349. 		    otmp = mk_artifact(otmp, (aligntyp)A_NONE); 350. 		break; 351. 	case FOOD_CLASS: 352. 	    otmp->oeaten = 0; 353. 	    switch(otmp->otyp) { 354. 	    case CORPSE: 355. 		/* possibly overridden by mkcorpstat */ 356. 		tryct = 50; 357. 		do otmp->corpsenm = undead_to_corpse(rndmonnum); 358. 		while ((mvitals[otmp->corpsenm].mvflags & G_NOCORPSE) && (--tryct > 0)); 359. 		if (tryct == 0) { 360. 		/* perhaps rndmonnum only wants to make G_NOCORPSE monsters on  361. this level; let's create an adventurer's corpse instead, then */ 362. 			otmp->corpsenm = PM_HUMAN; 363. 		}  364.  		start_corpse_timeout(otmp); 365. 		break; 366. 	    case EGG: 367. 		otmp->corpsenm = NON_PM;	/* generic egg */ 368. 		if (!rn2(3)) for (tryct = 200; tryct > 0; --tryct) { 369. 		    mndx = can_be_hatched(rndmonnum); 370. 		    if (mndx != NON_PM && !dead_species(mndx, TRUE)) { 371. 			otmp->corpsenm = mndx;		/* typed egg */ 372. 			attach_egg_hatch_timeout(otmp); 373. 			break; 374. 		    }  375.  		}  376.  		break; 377. 	    case TIN: 378. 		otmp->corpsenm = NON_PM;	/* empty (so far) */ 379. 		if (!rn2(6)) 380. 		    otmp->spe = 1;		/* spinach */ 381. 		else for (tryct = 200; tryct > 0; --tryct) { 382. 		    mndx = undead_to_corpse(rndmonnum); 383. 		    if (mons[mndx].cnutrit &&  384.  			    !(mvitals[mndx].mvflags & G_NOCORPSE)) { 385. 			otmp->corpsenm = mndx; 386. 			break; 387. 		    }  388.  		}  389.  		blessorcurse(otmp, 10); 390. 		break; 391. 	    case SLIME_MOLD: 392. 		otmp->spe = current_fruit; 393. 		break; 394. 	    }  395.  	    if (otmp->otyp == CORPSE || otmp->otyp == MEAT_RING) break; 396. 	    /* fall into next case */ 397.  398.  	case GEM_CLASS: 399. 		if (otmp->otyp == LOADSTONE) curse(otmp); 400. 		else if (otmp->otyp == ROCK) otmp->quan = (long) rn1(6,6); 401. 		else if (otmp->otyp == KELP_FROND) otmp->quan = (long) rnd(4); 402. 		else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2L; 403. 		else otmp->quan = 1L; 404. 		break; 405. 	case TOOL_CLASS: 406. 	    switch(otmp->otyp) { 407. 		case TALLOW_CANDLE: 408. 		case WAX_CANDLE:	otmp->spe = 1; 409. 					otmp->age = 20L * /* 400 or 200 */ 410. 					      (long)objects[otmp->otyp].oc_cost; 411. 					otmp->lamplit = 0; 412. 					otmp->quan = 1L + 413. 					      (long)(rn2(2) ? rn2(7) : 0); 414. 					blessorcurse(otmp, 5); 415. 					break; 416. 		case BRASS_LANTERN: 417. 		case OIL_LAMP:		otmp->spe = 1; 418. 					otmp->age = (long) rn1(500,1000); 419. 					otmp->lamplit = 0; 420. 					blessorcurse(otmp, 5); 421. 					break; 422. 		case MAGIC_LAMP:	otmp->spe = 1; 423. 					otmp->lamplit = 0; 424. 					blessorcurse(otmp, 2); 425. 					break; 426. 		case CHEST: 427. 		case LARGE_BOX:		otmp->olocked = !!(rn2(5)); 428. 					otmp->otrapped = !(rn2(10)); 429. 		case ICE_BOX: 430. 		case SACK: 431. 		case OILSKIN_SACK: 432. 		case BAG_OF_HOLDING:	mkbox_cnts(otmp); 433. 					break; 434. #ifdef TOURIST 435. 		case EXPENSIVE_CAMERA: 436. #endif 437. 		case TINNING_KIT: 438. 		case MAGIC_MARKER:	otmp->spe = rn1(70,30); 439. 					break; 440. 		case CAN_OF_GREASE:	otmp->spe = rnd(25); 441. 					blessorcurse(otmp, 10); 442. 					break; 443. 		case CRYSTAL_BALL:	otmp->spe = rnd(5); 444. 					blessorcurse(otmp, 2); 445. 					break; 446. 		case HORN_OF_PLENTY: 447. 		case BAG_OF_TRICKS:	otmp->spe = rnd(20); 448. 					break; 449. 		case FIGURINE:	{	int tryct2 = 0; 450. 					do 451. 					    otmp->corpsenm = rndmonnum; 452. 					while(is_human(&mons[otmp->corpsenm])  453.  						&& tryct2++ < 30); 454. 					blessorcurse(otmp, 4); 455. 					break; 456. 				}  457.  		case BELL_OF_OPENING:   otmp->spe = 3; 458. 					break; 459. 		case MAGIC_FLUTE: 460. 		case MAGIC_HARP: 461. 		case FROST_HORN: 462. 		case FIRE_HORN: 463. 		case DRUM_OF_EARTHQUAKE: 464. 					otmp->spe = rn1(5,4); 465. 					break; 466. 	    }  467.  	    break; 468. 	case AMULET_CLASS: 469. 		if(rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION || 470. 		   otmp->otyp == AMULET_OF_CHANGE || 471. 		   otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) { 472. 			curse(otmp); 473. 		} else	blessorcurse(otmp, 10); 474. 	case VENOM_CLASS: 475. 	case CHAIN_CLASS: 476. 	case BALL_CLASS: 477. 		break; 478. 	case POTION_CLASS: 479. 		if (otmp->otyp == POT_OIL) 480. 		    otmp->age = MAX_OIL_IN_FLASK;	/* amount of oil */ 481. 		/* fall through */ 482. 	case SCROLL_CLASS: 483. #ifdef MAIL 484. 		if (otmp->otyp != SCR_MAIL) 485. #endif 486. 			blessorcurse(otmp, 4); 487. 		break; 488. 	case SPBOOK_CLASS: 489. 		blessorcurse(otmp, 17); 490. 		break; 491. 	case ARMOR_CLASS: 492. 		if(rn2(10) && (otmp->otyp == FUMBLE_BOOTS || 493. 		   otmp->otyp == LEVITATION_BOOTS || 494. 		   otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT || 495. 		   otmp->otyp == GAUNTLETS_OF_FUMBLING || 496. 		   !rn2(11))) { 497. 			curse(otmp); 498. 			otmp->spe = -rne(3); 499. 		} else if(!rn2(10)) { 500. 			otmp->blessed = rn2(2); 501. 			otmp->spe = rne(3); 502. 		} else	blessorcurse(otmp, 10); 503. 		if (artif && !rn2(40)) 504. 		    otmp = mk_artifact(otmp, (aligntyp)A_NONE); 505. 		/* simulate lacquered armor for samurai */ 506. 		if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL &&  507.  		    (moves <= 1 || In_quest(&u.uz))) { 508. #ifdef UNIXPC 509. 			/* optimizer bitfield bug */ 510. 			otmp->oerodeproof = 1; 511. 			otmp->rknown = 1; 512. #else 513. 			otmp->oerodeproof = otmp->rknown = 1; 514. #endif 515. 		}  516.  		break; 517. 	case WAND_CLASS: 518. 		if(otmp->otyp == WAN_WISHING) otmp->spe = rnd(3); else 519. 		otmp->spe = rn1(5,  520.  			(objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4); 521. 		blessorcurse(otmp, 17); 522. 		otmp->recharged = 0; /* used to control recharging */ 523. 		break; 524. 	case RING_CLASS: 525. 		if(objects[otmp->otyp].oc_charged) { 526. 		    blessorcurse(otmp, 3); 527. 		    if(rn2(10)) { 528. 			if(rn2(10) && bcsign(otmp)) 529. 			    otmp->spe = bcsign(otmp) * rne(3); 530. 			else otmp->spe = rn2(2) ? rne(3) : -rne(3); 531. 		    }  532.  		    /* make useless +0 rings much less common */ 533. 		    if (otmp->spe == 0) otmp->spe = rn2(4) - rn2(3); 534. 		    /* negative rings are usually cursed */ 535. 		    if (otmp->spe < 0 && rn2(5)) curse(otmp); 536. 		} else if(rn2(10) && (otmp->otyp == RIN_TELEPORTATION || 537. 			  otmp->otyp == RIN_POLYMORPH || 538. 			  otmp->otyp == RIN_AGGRAVATE_MONSTER || 539. 			  otmp->otyp == RIN_HUNGER || !rn2(9))) { 540. 			curse(otmp); 541. 		}  542.  		break; 543. 	case ROCK_CLASS: 544. 		switch (otmp->otyp) { 545. 		    case STATUE: 546. 			/* possibly overridden by mkcorpstat */ 547. 			otmp->corpsenm = rndmonnum; 548. 			if (!verysmall(&mons[otmp->corpsenm]) &&  549.  				rn2(level_difficulty/2 + 10) > 10) 550. 			    add_to_container(otmp, mkobj(SPBOOK_CLASS,FALSE)); 551. 		}  552.  		break; 553. 	case GOLD_CLASS: 554. 		break;	/* do nothing */ 555. 	default: 556. 		impossible("impossible mkobj %d, sym '%c'.", otmp->otyp,  557.  						objects[otmp->otyp].oc_class); 558. 		return (struct obj *)0; 559. 	}  560.  	/* unique objects may have an associated artifact entry */ 561. 	if (objects[otyp].oc_unique && !otmp->oartifact) 562. 	    otmp = mk_artifact(otmp, (aligntyp)A_NONE); 563. 	otmp->owt = weight(otmp); 564. 	return(otmp); 565. }  566.   567.  /*  568.   * Start a corpse decay or revive timer. This assumes that the corpse 569.  * was just dropped and its age is 0. 570.  */  571.  void 572. start_corpse_timeout(body) 573. 	struct obj *body; 574. {  575.  	long when; 576. 	int rot_adjust; 577. 	short action; 578.  579.  #define TAINT_AGE (50L)		/* age when corpses go bad */ 580. #define TROLL_REVIVE_CHANCE 37	/* 1/37 chance for 50 turns ~ 75% chance */ 581. #define ROT_AGE (250L)	/* age when corpses rot away */ 582.  583.  	/* lizards and lichen don't rot or revive */ 584. 	if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN) return; 585.  586.  	action = ROT_CORPSE;		/* default action: rot away */ 587. 	when = ROT_AGE;			/* rot away when this old */ 588. 	rot_adjust = in_mklev ? 25 : 10;	/* give some variation */ 589. 	when += (long)(rnz(rot_adjust) - rot_adjust); 590.  591.  	if (is_rider(&mons[body->corpsenm])) { 592. 		/*  593.  		 * Riders always revive. They have a 1/3 chance per turn 594. 		 * of reviving after 12 turns. Always revive by 500. 595. 		 */  596.  		action = REVIVE_MON; 597. 		for (when = 12L; when < 500L; when++) 598. 		    if (!rn2(3)) break; 599.  600.  	} else if (mons[body->corpsenm].mlet == S_TROLL) { 601. 		long age; 602. 		for (age = 2; age <= TAINT_AGE; age++) 603. 		    if (!rn2(TROLL_REVIVE_CHANCE)) {	/* troll revives */ 604. 			action = REVIVE_MON; 605. 			when = age; 606. 			break; 607. 		    }  608.  	}  609.   610.  	(void) start_timer(when, TIMER_OBJECT, action, (genericptr_t)body); 611. }  612.   613.  void 614. bless(otmp) 615. register struct obj *otmp; 616. {  617.  	otmp->cursed = 0; 618. 	otmp->blessed = 1; 619. 	if (otmp->otyp == LUCKSTONE  620.  		|| (otmp->oartifact && spec_ability(otmp, SPFX_LUCK))) 621. 	    set_moreluck; 622. 	else if (otmp->otyp == BAG_OF_HOLDING) 623. 	    otmp->owt = weight(otmp); 624. 	else if (otmp->otyp == FIGURINE && otmp->timed) 625. 		(void) stop_timer(FIG_TRANSFORM, (genericptr_t) otmp); 626. 	return; 627. }  628.   629.  void 630. unbless(otmp) 631. register struct obj *otmp; 632. {  633.  	otmp->blessed = 0; 634. 	if (otmp->otyp == LUCKSTONE  635.  		|| (otmp->oartifact && spec_ability(otmp, SPFX_LUCK))) 636. 	    set_moreluck; 637. 	else if (otmp->otyp == BAG_OF_HOLDING) 638. 	    otmp->owt = weight(otmp); 639. }  640.   641.  void 642. curse(otmp) 643. register struct obj *otmp; 644. {  645.  	otmp->blessed = 0; 646. 	otmp->cursed = 1; 647. 	if (otmp->otyp == LUCKSTONE  648.  		|| (otmp->oartifact && spec_ability(otmp, SPFX_LUCK))) 649. 	    set_moreluck; 650. 	else if (otmp->otyp == BAG_OF_HOLDING) 651. 	    otmp->owt = weight(otmp); 652. 	else if (otmp->otyp == FIGURINE) { 653. 		if (otmp->corpsenm != NON_PM  654.  	    	    && !dead_species(otmp->corpsenm,TRUE)  655.  		    && (carried(otmp) || mcarried(otmp))) 656. 			attach_fig_transform_timeout(otmp); 657. 	}  658.   	return; 659. }  660.   661.  void 662. uncurse(otmp) 663. register struct obj *otmp; 664. {  665.  	otmp->cursed = 0; 666. 	if (otmp->otyp == LUCKSTONE  667.  		|| (otmp->oartifact && spec_ability(otmp, SPFX_LUCK))) 668. 	    set_moreluck; 669. 	else if (otmp->otyp == BAG_OF_HOLDING) 670. 		otmp->owt = weight(otmp); 671. 	else if (otmp->otyp == FIGURINE && otmp->timed) 672. 		(void) stop_timer(FIG_TRANSFORM, (genericptr_t) otmp); 673. 	return; 674. }  675.   676.  #endif /* OVLB */ 677. #ifdef OVL1 678.  679.  void 680. blessorcurse(otmp, chance) 681. register struct obj *otmp; 682. register int chance; 683. {  684.  	if(otmp->blessed || otmp->cursed) return; 685.  686.  	if(!rn2(chance)) 687. 	    if(!rn2(2)) { 688. 		curse(otmp); 689. 	    } else { 690. 		bless(otmp); 691. 	    }  692.  	return; 693. }  694.   695.  #endif /* OVL1 */ 696. #ifdef OVLB 697.  698.  int 699. bcsign(otmp) 700. register struct obj *otmp; 701. {  702.  	return(!!otmp->blessed - !!otmp->cursed); 703. }  704.   705.  #endif /* OVLB */ 706. #ifdef OVL0 707.  708.  /*  709.   *  Calculate the weight of the given object. This will recursively follow 710.  *  and calculate the weight of any containers. 711.  *  712.   *  Note:  It is possible to end up with an incorrect weight if some part 713.  *	   of the code messes with a contained object and doesn't update the 714.  *	   container's weight. 715.  */  716.  int 717. weight(obj) 718. register struct obj *obj; 719. {  720.  	int wt = objects[obj->otyp].oc_weight; 721.  722.  	if (obj->otyp == LARGE_BOX && obj->spe == 1) /* Schroedinger's Cat */ 723. 		wt += mons[PM_HOUSECAT].cwt; 724. 	if (Is_container(obj) || obj->otyp == STATUE) { 725. 		struct obj *contents; 726. 		register int cwt = 0; 727.  728.  		if (obj->otyp == STATUE && obj->corpsenm >= LOW_PM) 729. 		    wt = (int)obj->quan * 730. 			 ((int)mons[obj->corpsenm].cwt * 3 / 2); 731.  732.  		for(contents=obj->cobj; contents; contents=contents->nobj) 733. 			cwt += weight(contents); 734. 		/*  735.  		 *  The weight of bags of holding is calculated as the weight 736. 		 *  of the bag plus the weight of the bag's contents modified 737. 		 *  as follows: 738. 		 *  739.  		 *	Bag status	Weight of contents 740. 		 *	--	--  741.  		 *	cursed			2x 742. 		 *	blessed			x/4 + 1 743. 		 *	otherwise		x/2 + 1 744. 		 *  745.  		 *  The macro DELTA_CWT in pickup.c also implements these 746. 		 *  weight equations. 747. 		 *  748.  		 *  Note:  The above checks are performed in the given order. 749. 		 *	   this means that if an object is both blessed and 750. 		 *	   cursed (not supposed to happen), it will be treated 751. 		 *	   as cursed. 752. 		 */  753.  		if (obj->otyp == BAG_OF_HOLDING) 754. 		    cwt = obj->cursed ? (cwt * 2) : 755. 					(1 + (cwt / (obj->blessed ? 4 : 2))); 756.  757.  		return wt + cwt; 758. 	}  759.  	if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) 760. 		return (int)obj->quan * mons[obj->corpsenm].cwt; 761. 	else if (obj->oclass == GOLD_CLASS) 762. 		return (int)((obj->quan + 50L) / 100L); 763. 	else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0) 764. 		return((int)(obj->owt));	/* kludge for "very" heavy iron ball */ 765. 	return(wt ? wt*(int)obj->quan : ((int)obj->quan + 1)>>1); 766. }  767.   768.  static int treefruits[] = {APPLE,ORANGE,PEAR,BANANA,EUCALYPTUS_LEAF}; 769.  770.  struct obj * 771. rnd_treefruit_at(x,y) 772. {  773.  	return mksobj_at(treefruits[rn2(SIZE(treefruits)-1)],x,y,TRUE); 774. }  775.  #endif /* OVL0 */ 776. #ifdef OVLB 777.  778.  struct obj * 779. mkgold(amount, x, y)  780. long amount; 781. int x, y;  782. { 783.      register struct obj *gold = g_at(x,y); 784.  785.      if (amount <= 0L) amount = (long)(1 + rnd(level_difficulty+2) * rnd(30)); 786.     if (gold) { 787. 	gold->quan += amount; 788.     } else { 789. 	gold = mksobj_at(GOLD_PIECE,x,y,TRUE); 790. 	gold->quan = amount; 791.     }  792.      gold->owt = weight(gold); 793.     return (gold); 794. }  795.   796.  #endif /* OVLB */ 797. #ifdef OVL1 798.  799.  /* return TRUE if the corpse has special timing */ 800. #define special_corpse(num)  (((num) == PM_LIZARD)		\  801.  				|| ((num) == PM_LICHEN)		\  802.  				|| (is_rider(&mons[num]))	\  803.  				|| (mons[num].mlet == S_TROLL)) 804.  805.  /*  806.   * OEXTRA note: Passing mtmp causes mtraits to be saved 807.  * even if ptr passed as well, but ptr is always used for 808.  * the corpse type (corpsenm). That allows the corpse type 809.  * to be different from the original monster, 810.  *	i.e.  vampire -> human corpse 811.  * yet still allow restoration of the original monster upon 812.  * resurrection. 813.  */  814.  struct obj * 815. mkcorpstat(objtype, mtmp, ptr, x, y, init) 816. int objtype;	/* CORPSE or STATUE */ 817. struct monst *mtmp; 818. struct permonst *ptr; 819. int x, y;  820. boolean init; 821. {  822.  	register struct obj *otmp; 823.  824.  	if (objtype != CORPSE && objtype != STATUE) 825. 	    impossible("making corpstat type %d", objtype); 826. 	otmp = mksobj_at(objtype, x, y, init); 827. 	if (otmp) { 828. 	    if (mtmp) { 829. 		struct obj *otmp2; 830.  831.  		if (!ptr) ptr = mtmp->data; 832. 		/* save_mtraits frees original data pointed to by otmp */ 833. 		otmp2 = save_mtraits(otmp, mtmp); 834. 		if (otmp2) otmp = otmp2; 835. 	    }  836.  	    /* use the corpse or statue produced by mksobj as-is 837. 	       unless `ptr' is non-null */ 838. 	    if (ptr) { 839. 		int old_corpsenm = otmp->corpsenm; 840.  841.  		otmp->corpsenm = monsndx(ptr); 842. 		otmp->owt = weight(otmp); 843. 		if (otmp->otyp == CORPSE &&  844.  			(special_corpse(old_corpsenm) || 845. 				special_corpse(otmp->corpsenm))) { 846. 		    obj_stop_timers(otmp); 847. 		    start_corpse_timeout(otmp); 848. 		}  849.  	    }  850.  	}  851.  	return(otmp); 852. }  853.   854.  static struct obj * 855. save_mtraits(obj, mtmp) 856. struct obj *obj; 857. struct monst *mtmp; 858. {  859.  	struct obj *otmp; 860. 	int lth, namelth; 861.  862.  	lth = sizeof(struct monst) + mtmp->mxlth + mtmp->mnamelth; 863. 	namelth = obj->onamelth ? strlen(ONAME(obj)) + 1 : 0; 864. 	otmp = realloc_obj(obj, lth, (genericptr_t) mtmp, namelth, ONAME(obj)); 865. 	if (otmp && otmp->oxlth) { 866. 		struct monst *mtmp2 = (struct monst *)otmp->oextra; 867. 		if (mtmp->data) mtmp2->mnum = monsndx(mtmp->data); 868. 		/* invalidate pointers and m_id */ 869. 		mtmp2->m_id     = 0; 870. 		mtmp2->nmon     = (struct monst *)0; 871. 		mtmp2->data     = (struct permonst *)0; 872. 		mtmp2->minvent  = (struct obj *)0; 873. 		otmp->oattached = OATTACHED_MONST;	/* mark it */ 874. 	}  875.  	return otmp; 876. }  877.   878.  /* returns a pointer to a new monst structure based on  879. * the one contained within the obj. 880.  */  881.  struct monst * 882. get_mtraits(obj, copyof) 883. struct obj *obj; 884. boolean copyof; 885. {  886.  	struct monst *mtmp = (struct monst *)0; 887. 	struct monst *mnew = (struct monst *)0; 888.  889.  	if (obj->oxlth && obj->oattached == OATTACHED_MONST) 890. 		mtmp = (struct monst *)obj->oextra; 891. 	if (mtmp) { 892. 	    if (copyof) { 893. 		int lth = mtmp->mxlth + mtmp->mnamelth; 894. 		mnew = newmonst(lth); 895. 		lth += sizeof(struct monst); 896. 		(void) memcpy((genericptr_t)mnew,  897.  				(genericptr_t)mtmp, lth); 898. 	    } else { 899. 	      /* Never insert this returned pointer into mon chains! */ 900.  	    	mnew = mtmp; 901. 	    }  902.  	}  903.  	return mnew; 904. }  905.   906.  #endif /* OVL1 */ 907. #ifdef OVLB 908.  909.  /* make an object named after someone listed in the scoreboard file */ 910. struct obj * 911. mk_tt_object(objtype, x, y)  912. int objtype; /* CORPSE or STATUE */ 913. register int x, y;  914. { 915.  	register struct obj *otmp, *otmp2; 916. 	boolean initialize_it; 917.  918.  	/* player statues never contain books */ 919. 	initialize_it = (objtype != STATUE); 920. 	if ((otmp = mksobj_at(objtype, x, y, initialize_it)) != 0) { 921. 	    /* tt_oname will return null if the scoreboard is empty */ 922. 	    if ((otmp2 = tt_oname(otmp)) != 0) otmp = otmp2; 923. 	}  924.  	return(otmp); 925. }  926.   927.  /* make a new corpse or statue, uninitialized if a statue (i.e. no books) */ 928. struct obj * 929. mk_named_object(objtype, ptr, x, y, nm) 930. int objtype;	/* CORPSE or STATUE */ 931. struct permonst *ptr; 932. int x, y;  933. const char *nm; 934. {  935.  	struct obj *otmp; 936.  937.  	otmp = mkcorpstat(objtype, (struct monst *)0, ptr,  938.  				x, y, (boolean)(objtype != STATUE)); 939. 	if (nm) 940. 		otmp = oname(otmp, nm); 941. 	return(otmp); 942. }  943.   944.  boolean 945. is_flammable(otmp) 946. register struct obj *otmp; 947. {  948.  	int otyp = otmp->otyp; 949.  950.  	if (objects[otyp].oc_oprop == FIRE_RES) return FALSE; 951.  952.  	return((boolean)(objects[otyp].oc_material <= WOOD && 953. 			objects[otyp].oc_material != LIQUID)); 954. }  955.   956.  #endif /* OVLB */ 957. #ifdef OVL1 958.  959.  /*  960.   * These routines maintain the single-linked lists headed in level.objects[][] 961.  * and threaded through the nexthere fields in the object-instance structure. 962.  */  963.   964.  /* put the object at the given location */ 965. void 966. place_object(otmp, x, y)  967. register struct obj *otmp; 968. int x, y;  969. { 970.      register struct obj *otmp2 = level.objects[x][y]; 971.  972.      if (otmp->where != OBJ_FREE) 973. 	panic("place_object: obj not free"); 974.  975.      if (otmp->otyp == BOULDER) block_point(x,y);	/* vision */ 976.  977.      /* obj goes under boulders */ 978.     if (otmp2 && (otmp2->otyp == BOULDER)) { 979. 	otmp->nexthere = otmp2->nexthere; 980. 	otmp2->nexthere = otmp; 981.     } else { 982. 	otmp->nexthere = otmp2; 983. 	level.objects[x][y] = otmp; 984.     }  985.   986.      /* set the new object's location */ 987.     otmp->ox = x;  988. otmp->oy = y; 989. 990.     otmp->where = OBJ_FLOOR; 991.  992.      /* add to floor chain */ 993.     otmp->nobj = fobj; 994.     fobj = otmp; 995.     if (otmp->timed) obj_timer_checks(otmp, x, y, 0); 996. }  997.   998.  #define ON_ICE(a) ((a)->recharged) 999. #define ROT_ICE_ADJUSTMENT 2	/* rotting on ice takes 2 times as long */ 1000. 1001. /* If ice was affecting any objects correct that now 1002. * Also used for starting ice effects too. [zap.c] 1003. */ 1004. void 1005. obj_ice_effects(x, y, do_buried) 1006. int x, y; 1007. boolean do_buried; 1008. { 1009. 	struct obj *otmp; 1010. 1011. 	for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) { 1012. 		if (otmp->timed) obj_timer_checks(otmp, x, y, 0); 1013. 	} 1014. 	if (do_buried) { 1015. 	   for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) { 1016. 		if (otmp->ox == x && otmp->oy == y) { 1017. 			if (otmp->timed) obj_timer_checks(otmp, x, y, 0); 1018. 		} 1019. 	    }  1020. 	}  1021. }  1022.  1023. /*  1024.  * Returns an obj->age for a corpse object on ice, that would be the 1025. * actual obj->age if the corpse had just been lifted from the ice. 1026. * This is useful when just using obj->age in a check or calculation because 1027. * rot timers pertaining to the object don't have to be stopped and 1028. * restarted etc. 1029. */  1030. long 1031. peek_at_iced_corpse_age(otmp) 1032. struct obj *otmp; 1033. { 1034.     long age, retval = otmp->age; 1035.     1036.     if (otmp->otyp == CORPSE && ON_ICE(otmp)) { 1037. 	/* Adjust the age; must be same as obj_timer_checks for off ice*/ 1038. 	age = monstermoves - otmp->age; 1039. 	retval = otmp->age + (age / ROT_ICE_ADJUSTMENT); 1040. #ifdef DEBUG_EFFECTS 1041. 	pline_The("%s age has ice modifications:otmp->age = %ld, returning %ld.", 1042. 		s_suffix(doname(otmp)),otmp->age, retval); 1043. 	pline("Effective age of corpse: %ld.", 1044. 		monstermoves - retval); 1045. #endif 1046.    }  1047.     return retval; 1048. } 1049.  1050. STATIC_OVL void 1051. obj_timer_checks(otmp, x, y, force) 1052. struct obj *otmp; 1053. xchar x, y; 1054. int force;	/* 0 = no force so do checks, <0 = force off, >0 force on */ 1055. { 1056.     long tleft = 0L; 1057.    short action = ROT_CORPSE; 1058.    boolean restart_timer = FALSE; 1059.    boolean on_floor = (otmp->where == OBJ_FLOOR); 1060.    boolean buried = (otmp->where == OBJ_BURIED); 1061. 1062.     /* Check for corpses just placed on or in ice */ 1063.    if (otmp->otyp == CORPSE && (on_floor || buried) && is_ice(x,y)) { 1064. 	tleft = stop_timer(action, (genericptr_t)otmp); 1065. 	if (tleft == 0L) { 1066. 		action = REVIVE_MON; 1067. 		tleft = stop_timer(action, (genericptr_t)otmp); 1068. 	} 1069. 	if (tleft != 0L) { 1070. 	   long age; 1071. 	    1072. 	    tleft = tleft - monstermoves; 1073. 	   /* mark the corpse as being on ice */ 1074. 	   ON_ICE(otmp) = 1; 1075. #ifdef DEBUG_EFFECTS 1076. 	   pline("%s is now on ice at %d,%d.", The(xname(otmp)),x,y); 1077. #endif 1078. 	   /* Adjust the time remaining */ 1079. 	   tleft *= ROT_ICE_ADJUSTMENT; 1080. 	   restart_timer = TRUE; 1081. 	   /* Adjust the age; must be same as in obj_ice_age */ 1082. 	   age = monstermoves - otmp->age; 1083. 	   otmp->age = monstermoves - (age * ROT_ICE_ADJUSTMENT); 1084. 	} 1085.     }  1086.     /* Check for corpses coming off ice */ 1087.    else if ((force < 0) ||  1088. 	     (otmp->otyp == CORPSE && ON_ICE(otmp) && 1089. 	    ((on_floor && !is_ice(x,y)) || !on_floor))) { 1090. 	tleft = stop_timer(action, (genericptr_t)otmp); 1091. 	if (tleft == 0L) { 1092. 		action = REVIVE_MON; 1093. 		tleft = stop_timer(action, (genericptr_t)otmp); 1094. 	} 1095. 	if (tleft != 0L) { 1096. 		long age; 1097. 1098. 		tleft = tleft - monstermoves; 1099. 		ON_ICE(otmp) = 0; 1100. #ifdef DEBUG_EFFECTS 1101. 	   	pline("%s is no longer on ice at %d,%d.", The(xname(otmp)),x,y); 1102. #endif 1103. 		/* Adjust the remaining time */ 1104. 		tleft /= ROT_ICE_ADJUSTMENT; 1105. 		restart_timer = TRUE; 1106. 		/* Adjust the age */ 1107. 		age = monstermoves - otmp->age; 1108. 		otmp->age = otmp->age + (age / ROT_ICE_ADJUSTMENT); 1109. 	} 1110.     }  1111.     /* now re-start the timer with the appropriate modifications */ 1112.    if (restart_timer) 1113. 	(void) start_timer(tleft, TIMER_OBJECT, action, (genericptr_t)otmp); 1114. } 1115.  1116. #undef ON_ICE 1117. #undef ROT_ICE_ADJUSTMENT 1118. 1119. void 1120. remove_object(otmp) 1121. register struct obj *otmp; 1122. { 1123.     xchar x = otmp->ox; 1124.    xchar y = otmp->oy; 1125. 1126.     if (otmp->where != OBJ_FLOOR) 1127. 	panic("remove_object: obj not on floor"); 1128.    if (otmp->otyp == BOULDER) unblock_point(x,y); /* vision */ 1129.    extract_nexthere(otmp, &level.objects[x][y]); 1130.    extract_nobj(otmp, &fobj); 1131.    if (otmp->timed) obj_timer_checks(otmp,x,y,0); 1132. } 1133.  1134. /* throw away all of a monster's inventory */ 1135. void 1136. discard_minvent(mtmp) 1137. struct monst *mtmp; 1138. { 1139.     struct obj *otmp; 1140. 1141.     while ((otmp = mtmp->minvent) != 0) { 1142. 	obj_extract_self(otmp); 1143. 	obfree(otmp, (struct obj *)0);	/* dealloc_obj isn't sufficient */ 1144.    }  1145. }  1146.  1147. /*  1148.  * Free obj from whatever list it is on in preperation of deleting it or  1149. * moving it elsewhere. This will perform all high-level consequences 1150. * involved with removing the item. E.g. if the object is in the hero's 1151. * inventory and confers heat resistance, the hero will lose it. 1152. *  1153.  * Object positions: 1154. *	OBJ_FREE	not on any list 1155. *	OBJ_FLOOR	fobj, level.locations[][] chains (use remove_object) 1156. *	OBJ_CONTAINED	cobj chain of container object 1157. *	OBJ_INVENT	hero's invent chain (use freeinv) 1158. *	OBJ_MINVENT	monster's invent chain 1159. *	OBJ_MIGRATING	migrating chain 1160. *	OBJ_BURIED	level.buriedobjs chain 1161. *	OBJ_ONBILL	on billobjs chain 1162. */  1163. void 1164. obj_extract_self(obj) 1165.    struct obj *obj; 1166. { 1167.     switch (obj->where) { 1168. 	case OBJ_FREE: 1169. 	   break; 1170. 	case OBJ_FLOOR: 1171. 	   remove_object(obj); 1172. 	   break; 1173. 	case OBJ_CONTAINED: 1174. 	   extract_nobj(obj, &obj->ocontainer->cobj); 1175. 	   container_weight(obj->ocontainer); 1176. 	   break; 1177. 	case OBJ_INVENT: 1178. 	   freeinv(obj); 1179. 	   break; 1180. 	case OBJ_MINVENT: 1181. 	   extract_nobj(obj, &obj->ocarry->minvent); 1182. 	   break; 1183. 	case OBJ_MIGRATING: 1184. 	   extract_nobj(obj, &migrating_objs); 1185. 	   break; 1186. 	case OBJ_BURIED: 1187. 	   extract_nobj(obj, &level.buriedobjlist); 1188. 	   break; 1189. 	case OBJ_ONBILL: 1190. 	   extract_nobj(obj, &billobjs); 1191. 	   break; 1192. 	default: 1193. 	   panic("obj_extract_self"); 1194. 	   break; 1195.    }  1196. }  1197.  1198.  1199. /* Extract the given object from the chain, following nobj chain. */ 1200. void 1201. extract_nobj(obj, head_ptr) 1202.    struct obj *obj, **head_ptr; 1203. { 1204.     struct obj *curr, *prev; 1205. 1206.     curr = *head_ptr; 1207.    for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nobj) { 1208. 	if (curr == obj) { 1209. 	   if (prev) 1210. 		prev->nobj = curr->nobj; 1211. 	   else 1212. 		*head_ptr = curr->nobj; 1213. 	   break; 1214. 	} 1215.     }  1216.     if (!curr) panic("extract_nobj: object lost"); 1217.    obj->where = OBJ_FREE; 1218. } 1219.  1220.  1221. /*  1222.  * Extract the given object from the chain, following nexthere chain. 1223. *  1224.  * This does not set obj->where, this function is expected to be called 1225. * in tandem with extract_nobj, which does set it. 1226. */  1227. void 1228. extract_nexthere(obj, head_ptr) 1229.    struct obj *obj, **head_ptr; 1230. { 1231.     struct obj *curr, *prev; 1232. 1233.     curr = *head_ptr; 1234.    for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nexthere) { 1235. 	if (curr == obj) { 1236. 	   if (prev) 1237. 		prev->nexthere = curr->nexthere; 1238. 	   else 1239. 		*head_ptr = curr->nexthere; 1240. 	   break; 1241. 	} 1242.     }  1243.     if (!curr) panic("extract_nexthere: object lost"); 1244. } 1245.  1246.  1247. void 1248. add_to_minv(mon, obj) 1249.    struct monst *mon; 1250.    struct obj *obj; 1251. { 1252.     struct obj *otmp; 1253. 1254.     if (obj->where != OBJ_FREE) 1255. 	panic("add_to_minv: obj not free"); 1256. 1257.     /* merge if possible */ 1258.    for (otmp = mon->minvent; otmp; otmp = otmp->nobj) 1259. 	if (merged(&otmp, &obj)) 1260. 	   return; 1261.    /* else insert; don't bother forcing it to end of chain */ 1262.    obj->where = OBJ_MINVENT; 1263.    obj->ocarry = mon; 1264.    obj->nobj = mon->minvent; 1265.    mon->minvent = obj; 1266. } 1267.  1268. void 1269. add_to_container(container, obj) 1270.    struct obj *container, *obj; 1271. { 1272.     if (obj->where != OBJ_FREE) 1273. 	panic("add_to_container: obj not free"); 1274. 1275.     obj->where = OBJ_CONTAINED; 1276.    obj->ocontainer = container; 1277.    obj->nobj = container->cobj; 1278.    container->cobj = obj; 1279. } 1280.  1281. void 1282. add_to_migration(obj) 1283.    struct obj *obj; 1284. { 1285.     if (obj->where != OBJ_FREE) 1286. 	panic("add_to_migration: obj not free"); 1287. 1288.     obj->where = OBJ_MIGRATING; 1289.    obj->nobj = migrating_objs; 1290.    migrating_objs = obj; 1291. } 1292.  1293. void 1294. add_to_buried(obj) 1295.    struct obj *obj; 1296. { 1297.     if (obj->where != OBJ_FREE) 1298. 	panic("add_to_buried: obj not free"); 1299. 1300.     obj->where = OBJ_BURIED; 1301.    obj->nobj = level.buriedobjlist; 1302.    level.buriedobjlist = obj; 1303. } 1304.  1305. /* Recalculate the weight of this container and all of _its_ containers. */ 1306. STATIC_OVL void 1307. container_weight(container) 1308.    struct obj *container; 1309. { 1310.     container->owt = weight(container); 1311.    if (container->where == OBJ_CONTAINED) 1312. 	container_weight(container->ocontainer); 1313. /* 1314.     else if (container->where == OBJ_INVENT) 1315. 	recalculate load delay here ??? 1316. */ 1317. }  1318.  1319. /*  1320.  * Deallocate the object. _All_ objects should be run through here for 1321. * them to be deallocated. 1322. */  1323. void 1324. dealloc_obj(obj) 1325.    struct obj *obj; 1326. { 1327.     if (obj->where != OBJ_FREE) 1328. 	panic("dealloc_obj: obj not free"); 1329. 1330.     /* free up any timers attached to the object */ 1331.    if (obj->timed) 1332. 	obj_stop_timers(obj); 1333. 1334.     /*  1335.      * Free up any light sources attached to the object. 1336.     *  1337.      * We may want to just call del_light_source without any 1338.     * checks (requires a code change there). Otherwise this 1339.     * list must track all objects that can have a light source 1340.     * attached to it (and also requires lamplit to be set). 1341.     */  1342.     if (obj_sheds_light(obj)) 1343. 	del_light_source(LS_OBJECT, (genericptr_t) obj); 1344. 1345.     free((genericptr_t) obj); 1346. } 1347.  1348. #ifdef WIZARD 1349. /* Check all object lists for consistency. */ 1350. void 1351. obj_sanity_check 1352. { 1353.     int x, y;  1354. struct obj *obj; 1355.    struct monst *mon; 1356.    const char *mesg; 1357.    char obj_address[20], mon_address[20];  /* room for formatted pointers */ 1358. 1359.     mesg = "fobj sanity"; 1360.    for (obj = fobj; obj; obj = obj->nobj) { 1361. 	if (obj->where != OBJ_FLOOR) { 1362. 	   pline("%s obj %s %s@(%d,%d): %s\n", mesg,  1363. 		fmt_ptr((genericptr_t)obj, obj_address),  1364. 		where_name(obj->where),  1365. 		obj->ox, obj->oy, doname(obj)); 1366. 	} 1367. 	check_contained(obj, mesg); 1368.    }  1369.  1370.     mesg = "location sanity"; 1371.    for (x = 0; x < COLNO; x++) 1372. 	for (y = 0; y < ROWNO; y++) 1373. 	   for (obj = level.objects[x][y]; obj; obj = obj->nexthere) 1374. 		if (obj->where != OBJ_FLOOR) { 1375. 		   pline("%s obj %s %s@(%d,%d): %s\n", mesg,  1376. 			fmt_ptr((genericptr_t)obj, obj_address),  1377. 			where_name(obj->where),  1378. 			obj->ox, obj->oy, doname(obj)); 1379. 		} 1380.  1381.     mesg = "invent sanity"; 1382.    for (obj = invent; obj; obj = obj->nobj) { 1383. 	if (obj->where != OBJ_INVENT) { 1384. 	   pline("%s obj %s %s: %s\n", mesg,  1385. 		fmt_ptr((genericptr_t)obj, obj_address),  1386. 		where_name(obj->where), doname(obj)); 1387. 	} 1388. 	check_contained(obj, mesg); 1389.    }  1390.  1391.     mesg = "migrating sanity"; 1392.    for (obj = migrating_objs; obj; obj = obj->nobj) { 1393. 	if (obj->where != OBJ_MIGRATING) { 1394. 	   pline("%s obj %s %s: %s\n", mesg,  1395. 		fmt_ptr((genericptr_t)obj, obj_address),  1396. 		where_name(obj->where), doname(obj)); 1397. 	} 1398. 	check_contained(obj, mesg); 1399.    }  1400.  1401.     mesg = "buried sanity"; 1402.    for (obj = level.buriedobjlist; obj; obj = obj->nobj) { 1403. 	if (obj->where != OBJ_BURIED) { 1404. 	   pline("%s obj %s %s: %s\n", mesg,  1405. 		fmt_ptr((genericptr_t)obj, obj_address),  1406. 		where_name(obj->where), doname(obj)); 1407. 	} 1408. 	check_contained(obj, mesg); 1409.    }  1410.  1411.     mesg = "bill sanity"; 1412.    for (obj = billobjs; obj; obj = obj->nobj) { 1413. 	if (obj->where != OBJ_ONBILL) { 1414. 	   pline("%s obj %s %s: %s\n", mesg,  1415. 		fmt_ptr((genericptr_t)obj, obj_address),  1416. 		where_name(obj->where), doname(obj)); 1417. 	} 1418. 	/* shouldn't be a full container on the bill */ 1419. 	if (obj->cobj) { 1420. 	   pline("%s obj %s contains something! %s\n", mesg,  1421. 		fmt_ptr((genericptr_t)obj, obj_address),  1422. 		doname(obj)); 1423. 	} 1424.     }  1425.  1426.     mesg = "minvent sanity"; 1427.    for (mon = fmon; mon; mon = mon->nmon) 1428. 	for (obj = mon->minvent; obj; obj = obj->nobj) { 1429. 	   if (obj->where != OBJ_MINVENT) { 1430. 		pline("%s obj %s %s: %s\n", mesg, 1431. 			fmt_ptr((genericptr_t)obj, obj_address),  1432. 			where_name(obj->where), doname(obj)); 1433. 	   }  1434. 	    if (obj->ocarry != mon) { 1435. 		pline("%s obj %s (%s) not held by mon %s (%s)\n", mesg, 1436. 			fmt_ptr((genericptr_t)obj, obj_address),  1437. 			doname(obj),  1438. 			fmt_ptr((genericptr_t)mon, mon_address),  1439. 			mon_nam(mon)); 1440. 	   }  1441. 	    check_contained(obj, mesg); 1442. 	} 1443. }  1444.  1445. /* This must stay consistent with the defines in obj.h. */ 1446. static const char *obj_state_names[NOBJ_STATES] = { 1447. 	"free",		"floor",	"contained",	"invent", 1448. 	"minvent",	"migrating",	"buried",	"onbill" 1449. }; 1450.  1451. STATIC_OVL const char * 1452. where_name(where) 1453.    int where; 1454. { 1455.     return (where<0 || where>=NOBJ_STATES) ? "unknown" : obj_state_names[where]; 1456. } 1457.  1458. /* obj sanity check: check objs contained by container */ 1459. STATIC_OVL void 1460. check_contained(container, mesg) 1461.    struct obj *container; 1462.    const char *mesg; 1463. { 1464.     struct obj *obj; 1465.    char obj1_address[20], obj2_address[20]; 1466. 1467.     for (obj = container->cobj; obj; obj = obj->nobj) { 1468. 	if (obj->where != OBJ_CONTAINED) 1469. 	   pline("contained %s obj %s: %s\n", mesg,  1470. 		fmt_ptr((genericptr_t)obj, obj1_address),  1471. 		where_name(obj->where)); 1472. 	else if (obj->ocontainer != container) 1473. 	   pline("%s obj %s not in container %s\n", mesg,  1474. 		fmt_ptr((genericptr_t)obj, obj1_address),  1475. 		fmt_ptr((genericptr_t)container, obj2_address)); 1476.    }  1477. }  1478. #endif /* WIZARD */ 1479. 1480. #endif /* OVL1 */ 1481. 1482. /*mkobj.c*/