abstract
| - 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
", 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
", 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
", 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
", 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
", 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
", 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
", 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
", 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)
", 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
", 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
", 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*/
|