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