Source:NetHack 3.4.0/mkobj.c

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