About: Source:NetHack 3.4.0/mkobj.c   Sponge Permalink

An Entity of Type : owl:Thing, within Data Space : 134.155.108.49:8890 associated with source dataset(s)

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

AttributesValues
rdfs:label
  • Source:NetHack 3.4.0/mkobj.c
rdfs:comment
  • 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
dcterms:subject
dbkwik:nethack/pro...iPageUsesTemplate
abstract
  • 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 ", 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 ", 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 ", 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 ", 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 ", 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 ", 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 ", 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 ", 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) ", 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 ", 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 ", 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*/
Alternative Linked Data Views: ODE     Raw Data in: CXML | CSV | RDF ( N-Triples N3/Turtle JSON XML ) | OData ( Atom JSON ) | Microdata ( JSON HTML) | JSON-LD    About   
This material is Open Knowledge   W3C Semantic Web Technology [RDF Data] Valid XHTML + RDFa
OpenLink Virtuoso version 07.20.3217, on Linux (x86_64-pc-linux-gnu), Standard Edition
Data on this page belongs to its respective rights holders.
Virtuoso Faceted Browser Copyright © 2009-2012 OpenLink Software