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