1 /* NetHack 3.7 mkobj.c $NHDT-Date: 1619919403 2021/05/02 01:36:43 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.198 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Derek S. Ray, 2015. */
4 /* NetHack may be freely redistributed. See license for details. */
5
6 #include "hack.h"
7
8 static void mkbox_cnts(struct obj *);
9 static unsigned nextoid(struct obj *, struct obj *);
10 static boolean may_generate_eroded(struct obj *);
11 static void maybe_adjust_light(struct obj *, int);
12 static void obj_timer_checks(struct obj *, xchar, xchar, int);
13 static void container_weight(struct obj *);
14 static struct obj *save_mtraits(struct obj *, struct monst *);
15 static void objlist_sanity(struct obj *, int, const char *);
16 static void mon_obj_sanity(struct monst *, const char *);
17 static const char *where_name(struct obj *);
18 static void insane_object(struct obj *, const char *, const char *,
19 struct monst *);
20 static void check_contained(struct obj *, const char *);
21 static void check_glob(struct obj *, const char *);
22 static void sanity_check_worn(struct obj *);
23 static void init_thiefstone(struct obj *);
24 static const struct icp* material_list(struct obj *);
25 static boolean invalid_obj_material(struct obj *, uchar);
26
27 struct icp {
28 int iprob; /* probability of an item type */
29 char iclass; /* item class */
30 };
31
32 static const struct icp mkobjprobs[] = { { 10, WEAPON_CLASS },
33 { 10, ARMOR_CLASS },
34 { 20, FOOD_CLASS },
35 { 8, TOOL_CLASS },
36 { 8, GEM_CLASS },
37 { 16, POTION_CLASS },
38 { 16, SCROLL_CLASS },
39 { 4, SPBOOK_CLASS },
40 { 4, WAND_CLASS },
41 { 3, RING_CLASS },
42 { 1, AMULET_CLASS } };
43
44 static const struct icp boxiprobs[] = { { 18, GEM_CLASS },
45 { 15, FOOD_CLASS },
46 { 18, POTION_CLASS },
47 { 18, SCROLL_CLASS },
48 { 12, SPBOOK_CLASS },
49 { 7, COIN_CLASS },
50 { 6, WAND_CLASS },
51 { 5, RING_CLASS },
52 { 1, AMULET_CLASS } };
53
54 static const struct icp hellprobs[] = { { 20, WEAPON_CLASS },
55 { 20, ARMOR_CLASS },
56 { 16, FOOD_CLASS },
57 { 12, TOOL_CLASS },
58 { 10, GEM_CLASS },
59 { 1, POTION_CLASS },
60 { 1, SCROLL_CLASS },
61 { 8, WAND_CLASS },
62 { 8, RING_CLASS },
63 { 4, AMULET_CLASS } };
64
65 static const struct oextra zerooextra = DUMMY;
66
67 static void
init_oextra(struct oextra * oex)68 init_oextra(struct oextra* oex)
69 {
70 *oex = zerooextra;
71 }
72
73 struct oextra *
newoextra(void)74 newoextra(void)
75 {
76 struct oextra *oextra;
77
78 oextra = (struct oextra *) alloc(sizeof (struct oextra));
79 init_oextra(oextra);
80 return oextra;
81 }
82
83 void
dealloc_oextra(struct obj * o)84 dealloc_oextra(struct obj* o)
85 {
86 struct oextra *x = o->oextra;
87
88 if (x) {
89 if (x->oname)
90 free((genericptr_t) x->oname);
91 if (x->omonst)
92 free_omonst(o); /* 'o' rather than 'x' */
93 if (x->omailcmd)
94 free((genericptr_t) x->omailcmd);
95
96 free((genericptr_t) x);
97 o->oextra = (struct oextra *) 0;
98 }
99 }
100
101 void
newomonst(struct obj * otmp)102 newomonst(struct obj* otmp)
103 {
104 if (!otmp->oextra)
105 otmp->oextra = newoextra();
106
107 if (!OMONST(otmp)) {
108 struct monst *m = newmonst();
109
110 *m = cg.zeromonst;
111 OMONST(otmp) = m;
112 }
113 }
114
115 void
free_omonst(struct obj * otmp)116 free_omonst(struct obj* otmp)
117 {
118 if (otmp->oextra) {
119 struct monst *m = OMONST(otmp);
120
121 if (m) {
122 if (m->mextra)
123 dealloc_mextra(m);
124 free((genericptr_t) m);
125 OMONST(otmp) = (struct monst *) 0;
126 }
127 }
128 }
129
130 void
newomid(struct obj * otmp)131 newomid(struct obj* otmp)
132 {
133 if (!otmp->oextra)
134 otmp->oextra = newoextra();
135 OMID(otmp) = 0;
136 }
137
138 void
free_omid(struct obj * otmp)139 free_omid(struct obj* otmp)
140 {
141 OMID(otmp) = 0;
142 }
143
144 void
new_omailcmd(struct obj * otmp,const char * response_cmd)145 new_omailcmd(struct obj* otmp, const char * response_cmd)
146 {
147 if (!otmp->oextra)
148 otmp->oextra = newoextra();
149 if (OMAILCMD(otmp))
150 free_omailcmd(otmp);
151 OMAILCMD(otmp) = dupstr(response_cmd);
152 }
153
154 void
free_omailcmd(struct obj * otmp)155 free_omailcmd(struct obj* otmp)
156 {
157 if (otmp->oextra && OMAILCMD(otmp)) {
158 free((genericptr_t) OMAILCMD(otmp));
159 OMAILCMD(otmp) = (char *) 0;
160 }
161 }
162
163 struct obj *
mkobj_at(char let,int x,int y,boolean artif)164 mkobj_at(char let, int x, int y, boolean artif)
165 {
166 struct obj *otmp;
167
168 otmp = mkobj(let, artif);
169 place_object(otmp, x, y);
170 return otmp;
171 }
172
173 struct obj *
mksobj_at(int otyp,int x,int y,boolean init,boolean artif)174 mksobj_at(int otyp, int x, int y, boolean init, boolean artif)
175 {
176 struct obj *otmp;
177
178 otmp = mksobj(otyp, init, artif);
179 place_object(otmp, x, y);
180 return otmp;
181 }
182
183 struct obj *
mksobj_migr_to_species(int otyp,unsigned int mflags2,boolean init,boolean artif)184 mksobj_migr_to_species(
185 int otyp,
186 unsigned int mflags2,
187 boolean init,
188 boolean artif)
189 {
190 struct obj *otmp;
191
192 otmp = mksobj(otyp, init, artif);
193 add_to_migration(otmp);
194 otmp->owornmask = (long) MIGR_TO_SPECIES;
195 otmp->migr_species = mflags2;
196 return otmp;
197 }
198
199 /* mkobj(): select a type of item from a class, use mksobj() to create it;
200 result is always non-Null */
201 struct obj *
mkobj(int oclass,boolean artif)202 mkobj(int oclass, boolean artif)
203 {
204 int tprob, i, prob;
205 int first_obj, last_obj, total_prob;
206
207 if (oclass == RANDOM_CLASS) {
208 const struct icp *iprobs = Inhell ? (const struct icp *) hellprobs
209 : (const struct icp *) mkobjprobs;
210
211 for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
212 continue;
213 oclass = iprobs->iclass;
214 }
215
216 /* get total probability of objects in this class */
217 if (oclass == SPBOOK_no_NOVEL) {
218 /* Constant for when mkobj() should only produce an actual spellbook, not
219 * some other sort of book like a novel. */
220 first_obj = g.bases[SPBOOK_CLASS];
221 last_obj = SPE_BLANK_PAPER;
222 oclass = SPBOOK_CLASS; /* for sanity check below */
223 }
224 else if (oclass + 1 < MAXOCLASSES) {
225 first_obj = g.bases[(int) oclass];
226 last_obj = g.bases[(int) oclass + 1] - 1;
227 }
228 else {
229 first_obj = g.bases[(int) oclass];
230 /* bases[oclass + 1] doesn't exist in this case */
231 last_obj = NUM_OBJECTS - 1;
232 }
233 total_prob = 0;
234 for (i = first_obj; i <= last_obj; ++i) {
235 total_prob += objects[i].oc_prob;
236 }
237
238 prob = rnd(total_prob);
239 i = first_obj;
240 while ((prob -= objects[i].oc_prob) > 0)
241 ++i;
242
243 if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
244 panic("probtype error, oclass=%d i=%d", (int) oclass, i);
245
246 return mksobj(i, TRUE, artif);
247 }
248
249 static void
mkbox_cnts(struct obj * box)250 mkbox_cnts(struct obj* box)
251 {
252 register int n;
253 register struct obj *otmp;
254
255 box->cobj = (struct obj *) 0;
256
257 switch (box->otyp) {
258 case ICE_BOX:
259 n = 20;
260 break;
261 case CHEST:
262 n = box->olocked ? 7 : 5;
263 break;
264 case LARGE_BOX:
265 n = box->olocked ? 5 : 3;
266 break;
267 case SACK:
268 case OILSKIN_SACK:
269 /* initial inventory: sack starts out empty */
270 if (g.moves <= 1 && !g.in_mklev) {
271 n = 0;
272 break;
273 }
274 /*FALLTHRU*/
275 case BAG_OF_HOLDING:
276 n = 1;
277 break;
278 default:
279 n = 0;
280 break;
281 }
282
283 for (n = rn2(n + 1); n > 0; n--) {
284 if (box->otyp == ICE_BOX) {
285 otmp = mksobj(CORPSE, TRUE, TRUE);
286 /* Note: setting age to 0 is correct. Age has a different
287 * from usual meaning for objects stored in ice boxes. -KAA
288 */
289 otmp->age = 0L;
290 if (otmp->timed) {
291 (void) stop_timer(ROT_CORPSE, obj_to_any(otmp));
292 (void) stop_timer(MOLDY_CORPSE, obj_to_any(otmp));
293 (void) stop_timer(REVIVE_MON, obj_to_any(otmp));
294 }
295 } else {
296 register int tprob;
297 const struct icp *iprobs = boxiprobs;
298
299 for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
300 ;
301 if (!(otmp = mkobj(iprobs->iclass, TRUE)))
302 continue;
303
304 /* handle a couple of special cases */
305 if (otmp->oclass == COIN_CLASS) {
306 /* 2.5 x level's usual amount; weight adjusted below */
307 otmp->quan = (long) (rnd(level_difficulty() + 2) * rnd(75));
308 otmp->owt = weight(otmp);
309 } else
310 while (otmp->otyp == ROCK) {
311 otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LUCKSTONE);
312 if (otmp->quan > 2L)
313 otmp->quan = 1L;
314 otmp->owt = weight(otmp);
315 }
316 if (box->otyp == BAG_OF_HOLDING) {
317 if (Is_mbag(otmp)) {
318 otmp->otyp = SACK;
319 otmp->spe = 0;
320 otmp->owt = weight(otmp);
321 } else
322 while (otmp->otyp == WAN_CANCELLATION)
323 otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
324 }
325 }
326 (void) add_to_container(box, otmp);
327 }
328 }
329
330 /* select a random, common monster type */
331 int
rndmonnum(void)332 rndmonnum(void)
333 {
334 register struct permonst *ptr;
335 register int i;
336 unsigned short excludeflags;
337
338 /* Plan A: get a level-appropriate common monster */
339 ptr = rndmonst();
340 if (ptr)
341 return monsndx(ptr);
342
343 /* Plan B: get any common monster */
344 excludeflags = G_UNIQ | G_NOGEN | (Inhell ? G_NOHELL : G_HELL);
345 do {
346 i = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
347 ptr = &mons[i];
348 } while ((ptr->geno & excludeflags) != 0);
349
350 return i;
351 }
352
353 void
copy_oextra(struct obj * obj2,struct obj * obj1)354 copy_oextra(struct obj* obj2, struct obj* obj1)
355 {
356 if (!obj2 || !obj1 || !obj1->oextra)
357 return;
358
359 if (!obj2->oextra)
360 obj2->oextra = newoextra();
361 if (has_oname(obj1))
362 oname(obj2, ONAME(obj1));
363 if (has_omonst(obj1)) {
364 if (!OMONST(obj2))
365 newomonst(obj2);
366 (void) memcpy((genericptr_t) OMONST(obj2),
367 (genericptr_t) OMONST(obj1), sizeof (struct monst));
368 OMONST(obj2)->mextra = (struct mextra *) 0;
369 OMONST(obj2)->nmon = (struct monst *) 0;
370 #if 0
371 OMONST(obj2)->m_id = g.context.ident++;
372 if (OMONST(obj2)->m_id) /* ident overflowed */
373 OMONST(obj2)->m_id = g.context.ident++;
374 #endif
375 if (OMONST(obj1)->mextra)
376 copy_mextra(OMONST(obj2), OMONST(obj1));
377 }
378 if (has_omailcmd(obj1)) {
379 new_omailcmd(obj2, OMAILCMD(obj1));
380 }
381 if (has_omid(obj1)) {
382 if (!OMID(obj2))
383 newomid(obj2);
384 OMID(obj2) = OMID(obj1);
385 }
386 }
387
388 /*
389 * Split obj so that it gets size gets reduced by num. The quantity num is
390 * put in the object structure delivered by this call. The returned object
391 * has its wornmask cleared and is positioned just following the original
392 * in the nobj chain (and nexthere chain when on the floor).
393 */
394 struct obj *
splitobj(struct obj * obj,long num)395 splitobj(struct obj* obj, long num)
396 {
397 struct obj *otmp;
398
399 if (obj->cobj || num <= 0L || obj->quan <= num)
400 panic("splitobj"); /* can't split containers */
401 otmp = newobj();
402 *otmp = *obj; /* copies whole structure */
403 otmp->oextra = (struct oextra *) 0;
404 otmp->o_id = nextoid(obj, otmp);
405 otmp->timed = 0; /* not timed, yet */
406 otmp->lamplit = 0; /* ditto */
407 otmp->owornmask = 0L; /* new object isn't worn */
408 obj->quan -= num;
409 obj->owt = weight(obj);
410 otmp->quan = num;
411 otmp->owt = weight(otmp); /* -= obj->owt ? */
412 otmp->lua_ref_cnt = 0;
413
414 g.context.objsplit.parent_oid = obj->o_id;
415 g.context.objsplit.child_oid = otmp->o_id;
416 obj->nobj = otmp;
417 /* Only set nexthere when on the floor, nexthere is also used */
418 /* as a back pointer to the container object when contained. */
419 if (obj->where == OBJ_FLOOR)
420 obj->nexthere = otmp;
421 copy_oextra(otmp, obj);
422 if (has_omid(otmp))
423 free_omid(otmp); /* only one association with m_id*/
424 if (obj->unpaid)
425 splitbill(obj, otmp);
426 if (obj->timed)
427 obj_split_timers(obj, otmp);
428 if (obj_sheds_light(obj))
429 obj_split_light_source(obj, otmp);
430 return otmp;
431 }
432
433 /* when splitting a stack that has o_id-based shop prices, pick an
434 o_id value for the new stack that will maintain the same price */
435 static unsigned
nextoid(struct obj * oldobj,struct obj * newobj)436 nextoid(struct obj* oldobj, struct obj* newobj)
437 {
438 int olddif, newdif, trylimit = 256; /* limit of 4 suffices at present */
439 unsigned oid = g.context.ident - 1; /* loop increment will reverse -1 */
440
441 olddif = oid_price_adjustment(oldobj, oldobj->o_id);
442 do {
443 ++oid;
444 if (!oid) /* avoid using 0 (in case value wrapped) */
445 ++oid;
446 newdif = oid_price_adjustment(newobj, oid);
447 } while (newdif != olddif && --trylimit >= 0);
448 g.context.ident = oid + 1; /* ready for next new object */
449 return oid;
450 }
451
452 /* try to find the stack obj was split from, then merge them back together;
453 returns the combined object if unsplit is successful, null otherwise */
454 struct obj *
unsplitobj(struct obj * obj)455 unsplitobj(struct obj* obj)
456 {
457 unsigned target_oid = 0;
458 struct obj *oparent = 0, *ochild = 0, *list = 0;
459
460 /*
461 * We don't operate on floor objects (we're following o->nobj rather
462 * than o->nexthere), on free objects (don't know which list to use when
463 * looking for obj's parent or child), on bill objects (too complicated,
464 * not needed), or on buried or migrating objects (not needed).
465 * [This could be improved, but at present additional generality isn't
466 * necessary.]
467 */
468 switch (obj->where) {
469 case OBJ_FREE:
470 case OBJ_FLOOR:
471 case OBJ_ONBILL:
472 case OBJ_MIGRATING:
473 case OBJ_BURIED:
474 default:
475 return (struct obj *) 0;
476 case OBJ_INVENT:
477 list = g.invent;
478 break;
479 case OBJ_MINVENT:
480 list = obj->ocarry->minvent;
481 break;
482 case OBJ_CONTAINED:
483 list = obj->ocontainer->cobj;
484 break;
485 }
486
487 /* first try the expected case; obj is split from another stack */
488 if (obj->o_id == g.context.objsplit.child_oid) {
489 /* parent probably precedes child and will require list traversal */
490 ochild = obj;
491 target_oid = g.context.objsplit.parent_oid;
492 if (obj->nobj && obj->nobj->o_id == target_oid)
493 oparent = obj->nobj;
494 } else if (obj->o_id == g.context.objsplit.parent_oid) {
495 /* alternate scenario: another stack was split from obj;
496 child probably follows parent and will be found here */
497 oparent = obj;
498 target_oid = g.context.objsplit.child_oid;
499 if (obj->nobj && obj->nobj->o_id == target_oid)
500 ochild = obj->nobj;
501 }
502 /* if we have only half the split, scan obj's list to find other half */
503 if (ochild && !oparent) {
504 /* expected case */
505 for (obj = list; obj; obj = obj->nobj)
506 if (obj->o_id == target_oid) {
507 oparent = obj;
508 break;
509 }
510 } else if (oparent && !ochild) {
511 /* alternate scenario */
512 for (obj = list; obj; obj = obj->nobj)
513 if (obj->o_id == target_oid) {
514 ochild = obj;
515 break;
516 }
517 }
518 /* if we have both parent and child, try to merge them;
519 if successful, return the combined stack, otherwise return null */
520 return (oparent && ochild && merged(&oparent, &ochild)) ? oparent : 0;
521 }
522
523 /* reset splitobj()/unsplitobj() context */
524 void
clear_splitobjs(void)525 clear_splitobjs(void)
526 {
527 g.context.objsplit.parent_oid = g.context.objsplit.child_oid = 0;
528 }
529
530 /*
531 * Insert otmp right after obj in whatever chain(s) it is on. Then extract
532 * obj from the chain(s). This function does a literal swap. It is up to
533 * the caller to provide a valid context for the swap. When done, obj will
534 * still exist, but not on any chain.
535 *
536 * Note: Don't use use obj_extract_self() -- we are doing an in-place swap,
537 * not actually moving something.
538 */
539 void
replace_object(struct obj * obj,struct obj * otmp)540 replace_object(struct obj* obj, struct obj* otmp)
541 {
542 otmp->where = obj->where;
543 switch (obj->where) {
544 case OBJ_FREE:
545 /* do nothing */
546 break;
547 case OBJ_INVENT:
548 otmp->nobj = obj->nobj;
549 obj->nobj = otmp;
550 extract_nobj(obj, &g.invent);
551 break;
552 case OBJ_CONTAINED:
553 otmp->nobj = obj->nobj;
554 otmp->ocontainer = obj->ocontainer;
555 obj->nobj = otmp;
556 extract_nobj(obj, &obj->ocontainer->cobj);
557 break;
558 case OBJ_MINVENT:
559 otmp->nobj = obj->nobj;
560 otmp->ocarry = obj->ocarry;
561 obj->nobj = otmp;
562 extract_nobj(obj, &obj->ocarry->minvent);
563 break;
564 case OBJ_FLOOR:
565 fuzl_xyi("replace_obj floor", obj->ox, obj->oy, obj->otyp);
566 otmp->nobj = obj->nobj;
567 otmp->nexthere = obj->nexthere;
568 otmp->ox = obj->ox;
569 otmp->oy = obj->oy;
570 obj->nobj = otmp;
571 obj->nexthere = otmp;
572 extract_nobj(obj, &fobj);
573 extract_nexthere(obj, &g.level.objects[obj->ox][obj->oy]);
574 break;
575 default:
576 panic("replace_object: obj position");
577 break;
578 }
579 }
580
581 /* is 'obj' inside a container whose contents aren't known?
582 if so, return the outermost container meeting that criterium */
583 struct obj *
unknwn_contnr_contents(struct obj * obj)584 unknwn_contnr_contents(struct obj* obj)
585 {
586 struct obj *result = 0, *parent;
587
588 while (obj->where == OBJ_CONTAINED) {
589 parent = obj->ocontainer;
590 if (!parent->cknown)
591 result = parent;
592 obj = parent;
593 }
594 return result;
595 }
596
597 /*
598 * Create a dummy duplicate to put on shop bill. The duplicate exists
599 * only in the billobjs chain. This function is used when a shop object
600 * is being altered, and a copy of the original is needed for billing
601 * purposes. For example, when eating, where an interruption will yield
602 * an object which is different from what it started out as; the "I x"
603 * command needs to display the original object.
604 *
605 * The caller is responsible for checking otmp->unpaid and
606 * costly_spot(u.ux, u.uy). This function will make otmp no charge.
607 *
608 * Note that check_unpaid_usage() should be used instead for partial
609 * usage of an object.
610 */
611 void
bill_dummy_object(struct obj * otmp)612 bill_dummy_object(struct obj* otmp)
613 {
614 register struct obj *dummy;
615 long cost = 0L;
616
617 if (otmp->unpaid) {
618 cost = unpaid_cost(otmp, FALSE);
619 subfrombill(otmp, shop_keeper(*u.ushops));
620 }
621 dummy = newobj();
622 *dummy = *otmp;
623 dummy->oextra = (struct oextra *) 0;
624 dummy->where = OBJ_FREE;
625 dummy->o_id = nextoid(otmp, dummy);
626 dummy->timed = 0;
627 copy_oextra(dummy, otmp);
628 if (has_omid(dummy))
629 free_omid(dummy); /* only one association with m_id*/
630 if (Is_candle(dummy))
631 dummy->lamplit = 0;
632 dummy->owornmask = 0L; /* dummy object is not worn */
633 addtobill(dummy, FALSE, TRUE, TRUE);
634 if (cost)
635 alter_cost(dummy, -cost);
636 /* no_charge is only valid for some locations */
637 otmp->no_charge = (otmp->where == OBJ_FLOOR
638 || otmp->where == OBJ_CONTAINED) ? 1 : 0;
639 otmp->unpaid = 0;
640 return;
641 }
642
643 /* alteration types; must match COST_xxx macros in hack.h */
644 static const char *const alteration_verbs[] = {
645 "cancel", "drain", "uncharge", "unbless", "uncurse", "disenchant",
646 "degrade", "dilute", "erase", "burn", "neutralize", "destroy", "splatter",
647 "bite", "open", "break the lock on", "rust", "rot", "tarnish", "ferment"
648 };
649
650 /* possibly bill for an object which the player has just modified */
651 void
costly_alteration(struct obj * obj,int alter_type)652 costly_alteration(struct obj* obj, int alter_type)
653 {
654 xchar ox, oy;
655 char objroom;
656 boolean learn_bknown;
657 const char *those, *them;
658 struct monst *shkp = 0;
659
660 if (alter_type < 0 || alter_type >= SIZE(alteration_verbs)) {
661 impossible("invalid alteration type (%d)", alter_type);
662 alter_type = 0;
663 }
664
665 ox = oy = 0; /* lint suppression */
666 objroom = '\0'; /* ditto */
667 if (carried(obj) || obj->where == OBJ_FREE) {
668 /* OBJ_FREE catches obj_no_longer_held()'s transformation
669 of crysknife back into worm tooth; the object has been
670 removed from inventory but not necessarily placed at
671 its new location yet--the unpaid flag will still be set
672 if this item is owned by a shop */
673 if (!obj->unpaid)
674 return;
675 } else {
676 /* this get_obj_location shouldn't fail, but if it does,
677 use hero's location */
678 if (!get_obj_location(obj, &ox, &oy, CONTAINED_TOO))
679 ox = u.ux, oy = u.uy;
680 if (!costly_spot(ox, oy))
681 return;
682 objroom = *in_rooms(ox, oy, SHOPBASE);
683 /* if no shop cares about it, we're done */
684 if (!billable(&shkp, obj, objroom, FALSE))
685 return;
686 }
687
688 if (obj->quan == 1L)
689 those = "that", them = "it";
690 else
691 those = "those", them = "them";
692
693 /* when shopkeeper describes the object as being uncursed or unblessed
694 hero will know that it is now uncursed; will also make the feedback
695 from `I x' after bill_dummy_object() be more specific for this item */
696 learn_bknown = (alter_type == COST_UNCURS || alter_type == COST_UNBLSS);
697
698 switch (obj->where) {
699 case OBJ_FREE: /* obj_no_longer_held() */
700 case OBJ_INVENT:
701 if (learn_bknown)
702 set_bknown(obj, 1);
703 verbalize("You %s %s %s, you pay for %s!",
704 alteration_verbs[alter_type], those, simpleonames(obj),
705 them);
706 bill_dummy_object(obj);
707 break;
708 case OBJ_FLOOR:
709 if (learn_bknown)
710 obj->bknown = 1; /* ok to bypass set_bknown() here */
711 if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) {
712 verbalize("You %s %s, you pay for %s!",
713 alteration_verbs[alter_type], those, them);
714 bill_dummy_object(obj);
715 } else {
716 (void) stolen_value(obj, ox, oy, FALSE, FALSE);
717 }
718 break;
719 }
720 }
721
722 static const char dknowns[] = { WAND_CLASS, RING_CLASS, POTION_CLASS,
723 SCROLL_CLASS, GEM_CLASS, SPBOOK_CLASS,
724 WEAPON_CLASS, TOOL_CLASS, 0 };
725
726 static boolean
may_generate_eroded(struct obj * otmp)727 may_generate_eroded(struct obj* otmp) {
728 /* don't generate eroded or fixed items in initial hero inventory */
729 if (g.moves <= 1 && !g.in_mklev) {
730 return FALSE;
731 }
732 /* item cannot be eroded or damaged, because of material, existing
733 * erodeproofing, etc */
734 if (otmp->oerodeproof || !erosion_matters(otmp) || !is_damageable(otmp)) {
735 return FALSE;
736 }
737 /* item is part of a monster's body and produced when it dies */
738 if (otmp->otyp == WORM_TOOTH || otmp->otyp == UNICORN_HORN) {
739 return FALSE;
740 }
741 /* item is an artifact */
742 if (otmp->oartifact) {
743 return FALSE;
744 }
745
746 return TRUE;
747 }
748
749 /* mksobj(): create a specific type of object; result it always non-Null */
750 struct obj *
mksobj(int otyp,boolean init,boolean artif)751 mksobj(int otyp, boolean init, boolean artif)
752 {
753 int mndx, tryct;
754 struct obj *otmp;
755 char let = objects[otyp].oc_class;
756
757 otmp = newobj();
758 *otmp = cg.zeroobj;
759 otmp->age = g.monstermoves;
760 otmp->o_id = g.context.ident++;
761 if (!otmp->o_id)
762 otmp->o_id = g.context.ident++; /* ident overflowed */
763 otmp->quan = 1L;
764 otmp->oclass = let;
765 otmp->otyp = otyp;
766 otmp->where = OBJ_FREE;
767 otmp->dknown = index(dknowns, let) ? 0 : 1;
768 if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD)
769 || otmp->otyp == SHIELD_OF_REFLECTION
770 || objects[otmp->otyp].oc_merge)
771 otmp->dknown = 0;
772 if (!objects[otmp->otyp].oc_uses_known)
773 otmp->known = 1;
774 otmp->lknown = 0;
775 otmp->cknown = 0;
776 otmp->corpsenm = NON_PM;
777 otmp->lua_ref_cnt = 0;
778 set_material(otmp, objects[otmp->otyp].oc_material);
779
780 if (init) {
781 init_obj_material(otmp);
782 switch (let) {
783 case WEAPON_CLASS:
784 otmp->quan = is_multigen(otmp) ? (long) rn1(6, 6) : 1L;
785 if (!rn2(11)) {
786 otmp->spe = rne(3);
787 otmp->blessed = rn2(2);
788 } else if (!rn2(10)) {
789 curse(otmp);
790 otmp->spe = -rne(3);
791 } else
792 blessorcurse(otmp, 10);
793 if (is_poisonable(otmp) && !rn2(100))
794 otmp->opoisoned = 1;
795
796 if (artif && !rn2(20))
797 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
798
799 /* check oartifact here because mk_artifact isn't guaranteed to
800 * create an artifact */
801 if (!otmp->oartifact && !otmp->cursed
802 && (otmp->spe + otmp->oerodeproof > (long) rnd(5)))
803 otmp = weapon_oname(otmp);
804
805 break;
806 case FOOD_CLASS:
807 otmp->oeaten = 0;
808 switch (otmp->otyp) {
809 case CORPSE:
810 /* possibly overridden by mkcorpstat() */
811 tryct = 50;
812 do
813 otmp->corpsenm = undead_to_corpse(rndmonnum());
814 while ((g.mvitals[otmp->corpsenm].mvflags & G_NOCORPSE)
815 && (--tryct > 0));
816 if (tryct == 0) {
817 /* perhaps rndmonnum() only wants to make G_NOCORPSE
818 monsters on this g.level; create an adventurer's
819 corpse instead, then */
820 otmp->corpsenm = PM_HUMAN;
821 }
822 /* timer set below */
823 break;
824 case EGG:
825 otmp->corpsenm = NON_PM; /* generic egg */
826 if (!rn2(3))
827 for (tryct = 200; tryct > 0; --tryct) {
828 mndx = can_be_hatched(rndmonnum());
829 if (mndx != NON_PM && !dead_species(mndx, TRUE)) {
830 otmp->corpsenm = mndx; /* typed egg */
831 break;
832 }
833 }
834 /* timer set below */
835 break;
836 case TIN:
837 otmp->corpsenm = NON_PM; /* empty (so far) */
838 otmp->tinseed = rand();
839 if (!rn2(6))
840 set_tin_variety(otmp, SPINACH_TIN);
841 else
842 for (tryct = 200; tryct > 0; --tryct) {
843 mndx = undead_to_corpse(rndmonnum());
844 if (mons[mndx].cnutrit
845 && !(g.mvitals[mndx].mvflags & G_NOCORPSE)) {
846 otmp->corpsenm = mndx;
847 set_tin_variety(otmp, RANDOM_TIN);
848 break;
849 }
850 }
851 blessorcurse(otmp, 10);
852 if (!rn2(30))
853 otmp->otrapped = TRUE;
854 break;
855 case SLIME_MOLD:
856 otmp->spe = g.context.current_fruit;
857 if (g.in_mklev) {
858 int holiday = current_holidays();
859 const char* foods[10];
860 int idx = 0;
861 if (holiday & HOLIDAY_VALENTINES_DAY) {
862 foods[idx++] = "box of chocolates";
863 foods[idx++] = "chocolate-covered strawberry";
864 }
865 if (holiday & HOLIDAY_MARDI_GRAS) {
866 foods[idx++] = "slice of king cake";
867 foods[idx++] = "beignet";
868 foods[idx++] = "bowl of gumbo";
869 foods[idx++] = "bowl of jambalaya";
870 }
871 if (holiday & HOLIDAY_PI_DAY) {
872 foods[idx++] = "irrational pie";
873 foods[idx++] = "perfectly circular pie";
874 }
875 if (holiday & HOLIDAY_EASTER) {
876 foods[idx++] = "easter egg";
877 foods[idx++] = "chocolate bunny";
878 foods[idx++] = "bag of jelly beans";
879 }
880 if (holiday & HOLIDAY_CANADA_DAY) {
881 foods[idx++] = "maple sugar candy";
882 }
883 if (holiday & HOLIDAY_HALLOWEEN) {
884 foods[idx++] = "bag of candy corn";
885 foods[idx++] = "lollipop";
886 foods[idx++] = "popcorn ball";
887 }
888 if (holiday & HOLIDAY_THANKSGIVING) {
889 foods[idx++] = "roast turkey drumstick";
890 foods[idx++] = "mashed potato with gravy";
891 foods[idx++] = "cup of cranberry sauce";
892 foods[idx++] = "slice of pumpkin pie";
893 }
894 if (holiday & HOLIDAY_EID_AL_FITR) {
895 foods[idx++] = "ma'amoul";
896 foods[idx++] = "baklava";
897 foods[idx++] = "kleicha";
898 }
899 if (holiday & HOLIDAY_LOS_MUERTOS) {
900 foods[idx++] = "pan de muerto";
901 }
902 if (holiday & HOLIDAY_ROSH_HASHANAH) {
903 foods[idx++] = "honeyed apple";
904 }
905 if (holiday & HOLIDAY_PASSOVER) {
906 foods[idx++] = "matzo ball";
907 }
908 if (holiday & HOLIDAY_HANUKKAH) {
909 foods[idx++] = "latke";
910 foods[idx++] = "sufganiyah";
911 }
912 if (holiday & HOLIDAY_CHRISTMAS) {
913 foods[idx++] = "sugar plum";
914 foods[idx++] = "candy cane";
915 foods[idx++] = "figgy pudding";
916 foods[idx++] = "fruitcake";
917 }
918 if (idx >= 10) {
919 impossible("Too many holiday foods!");
920 idx = 9;
921 }
922 if (idx > 0) {
923 /* fruitadd requires a modifiable string */
924 char foodbuf[BUFSZ];
925 Strcpy(foodbuf, foods[rn2(idx)]);
926 otmp->spe = fruitadd(foodbuf, NULL);
927 }
928 }
929 flags.made_fruit = TRUE;
930 break;
931 case KELP_FROND:
932 otmp->quan = (long) rnd(2);
933 break;
934 case CANDY_BAR:
935 /* set otmp->spe */
936 assign_candy_wrapper(otmp);
937 break;
938 default:
939 break;
940 }
941 if (Is_pudding(otmp)) {
942 otmp->quan = 1L; /* for emphasis; glob quantity is always 1 */
943 otmp->globby = 1;
944 otmp->known = otmp->dknown = 1;
945 otmp->corpsenm = PM_GRAY_OOZE
946 + (otmp->otyp - GLOB_OF_GRAY_OOZE);
947 } else {
948 if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING
949 && otmp->otyp != KELP_FROND && !rn2(6)) {
950 otmp->quan = 2L;
951 }
952 }
953 break;
954 case GEM_CLASS:
955 if (otmp->otyp == ROCK)
956 otmp->quan = (long) rn1(6, 6);
957 else if (otmp->otyp != LUCKSTONE && otmp->otyp != THIEFSTONE
958 && !rn2(6))
959 otmp->quan = 2L;
960 else if (otmp->otyp == THIEFSTONE)
961 init_thiefstone(otmp);
962 else
963 otmp->quan = 1L;
964 break;
965 case TOOL_CLASS:
966 switch (otmp->otyp) {
967 case TALLOW_CANDLE:
968 case WAX_CANDLE:
969 otmp->spe = 1;
970 otmp->age = 20L * /* 400 or 200 */
971 (long) objects[otmp->otyp].oc_cost;
972 otmp->lamplit = 0;
973 otmp->quan = 1L + (long) (rn2(2) ? rn2(7) : 0);
974 blessorcurse(otmp, 5);
975 break;
976 case LANTERN:
977 case OIL_LAMP:
978 otmp->spe = 1;
979 otmp->age = (long) rn1(500, 1000);
980 otmp->lamplit = 0;
981 blessorcurse(otmp, 5);
982 break;
983 case MAGIC_LAMP:
984 otmp->spe = 1;
985 otmp->lamplit = 0;
986 blessorcurse(otmp, 2);
987 break;
988 case CHEST:
989 case LARGE_BOX:
990 otmp->olocked = !!(rn2(5));
991 otmp->otrapped = !(rn2(10));
992 /*FALLTHRU*/
993 case ICE_BOX:
994 case SACK:
995 case OILSKIN_SACK:
996 case BAG_OF_HOLDING:
997 mkbox_cnts(otmp);
998 break;
999 case EXPENSIVE_CAMERA:
1000 case TINNING_KIT:
1001 case MAGIC_MARKER:
1002 otmp->spe = rn1(70, 30);
1003 break;
1004 case CAN_OF_GREASE:
1005 otmp->spe = rn1(21, 5); /* 0..20 + 5 => 5..25 */
1006 blessorcurse(otmp, 10);
1007 break;
1008 case CRYSTAL_BALL:
1009 otmp->spe = rnd(25);
1010 blessorcurse(otmp, 2);
1011 break;
1012 case HORN_OF_PLENTY:
1013 case BAG_OF_TRICKS:
1014 otmp->spe = rn1(18, 3); /* 0..17 + 3 => 3..20 */
1015 break;
1016 case FIGURINE:
1017 tryct = 0;
1018 do
1019 otmp->corpsenm = rndmonnum();
1020 while (is_human(&mons[otmp->corpsenm]) && tryct++ < 30);
1021 blessorcurse(otmp, 4);
1022 break;
1023 case BELL_OF_OPENING:
1024 otmp->spe = 3;
1025 break;
1026 case MAGIC_FLUTE:
1027 case MAGIC_HARP:
1028 case FROST_HORN:
1029 case FIRE_HORN:
1030 case DRUM_OF_EARTHQUAKE:
1031 otmp->spe = rn1(5, 4);
1032 break;
1033 }
1034 break;
1035 case AMULET_CLASS:
1036 if (otmp->otyp == AMULET_OF_YENDOR)
1037 g.context.made_amulet = TRUE;
1038 if (rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION
1039 || otmp->otyp == AMULET_OF_CHANGE
1040 || otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) {
1041 curse(otmp);
1042 } else
1043 blessorcurse(otmp, 10);
1044 break;
1045 case VENOM_CLASS:
1046 case CHAIN_CLASS:
1047 case BALL_CLASS:
1048 break;
1049 case POTION_CLASS: /* note: potions get some additional init below */
1050 case SCROLL_CLASS:
1051 #ifdef MAIL_STRUCTURES
1052 if (otmp->otyp != SCR_MAIL)
1053 #endif
1054 blessorcurse(otmp, 4);
1055 break;
1056 case SPBOOK_CLASS:
1057 otmp->spestudied = 0;
1058 blessorcurse(otmp, 17);
1059 break;
1060 case ARMOR_CLASS:
1061 if (rn2(10)
1062 && (otmp->otyp == FUMBLE_BOOTS
1063 || otmp->otyp == LEVITATION_BOOTS
1064 || otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT
1065 || otmp->otyp == GAUNTLETS_OF_FUMBLING || !rn2(11))) {
1066 curse(otmp);
1067 otmp->spe = -rne(3);
1068 } else if (!rn2(10)) {
1069 otmp->blessed = rn2(2);
1070 otmp->spe = rne(3);
1071 } else
1072 blessorcurse(otmp, 10);
1073 if (artif && !rn2(40))
1074 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
1075 /* simulate lacquered armor for samurai */
1076 if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL
1077 && (g.moves <= 1 || In_quest(&u.uz))) {
1078 #ifdef UNIXPC
1079 /* optimizer bitfield bug */
1080 otmp->oerodeproof = 1;
1081 otmp->rknown = 1;
1082 #else
1083 otmp->oerodeproof = otmp->rknown = 1;
1084 #endif
1085 }
1086 break;
1087 case WAND_CLASS:
1088 if (otmp->otyp == WAN_WISHING)
1089 otmp->spe = 1;
1090 else
1091 otmp->spe =
1092 rn1(5, (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
1093 blessorcurse(otmp, 17);
1094 otmp->recharged = 0; /* used to control recharging */
1095 break;
1096 case RING_CLASS:
1097 if (objects[otmp->otyp].oc_charged) {
1098 schar multiplier = 1;
1099 blessorcurse(otmp, 3);
1100 /* This multiplier formula is from FIQHack:
1101 * Beatitude | +1 | 0 | -1
1102 * Blessed: 94% 2% 4%
1103 * Uncursed: 67% 2% 31%
1104 * Cursed: 13% 2% 85%
1105 */
1106 if (rn2(10)) {
1107 /* For 81% of rings that were already cursed, and for 40.5%
1108 * of rings that were uncursed, make enchantment negative.
1109 */
1110 if (rn2(10) && (otmp->cursed || (!bcsign(otmp) && !rn2(3))))
1111 multiplier = -1;
1112 }
1113 else if (!rn2(5)) {
1114 /* 2% of all charged rings are +0 */
1115 multiplier = 0;
1116 }
1117 else if (!rn2(2)) {
1118 /* 4% of all charged rings are made negative, even blessed
1119 * ones */
1120 multiplier = -1;
1121 }
1122 /* use rne(2) to get higher values; nobody really likes
1123 * low-enchanted rings that much. */
1124 otmp->spe = rne(2) * multiplier;
1125 } else if (rn2(10) && (otmp->otyp == RIN_TELEPORTATION
1126 || otmp->otyp == RIN_POLYMORPH
1127 || otmp->otyp == RIN_AGGRAVATE_MONSTER
1128 || otmp->otyp == RIN_HUNGER || !rn2(9))) {
1129 curse(otmp);
1130 }
1131 break;
1132 case ROCK_CLASS:
1133 switch (otmp->otyp) {
1134 case STATUE:
1135 /* possibly overridden by mkcorpstat() */
1136 otmp->corpsenm = rndmonnum();
1137 if (!verysmall(&mons[otmp->corpsenm])
1138 && rn2(level_difficulty() / 2 + 10) > 10)
1139 (void) add_to_container(otmp,
1140 mkobj(SPBOOK_no_NOVEL, FALSE));
1141 }
1142 break;
1143 case COIN_CLASS:
1144 break; /* do nothing */
1145 default:
1146 /* 3.6.3: this used to be impossible() followed by return 0
1147 but most callers aren't prepared to deal with Null result
1148 and cluttering them up to do so is pointless */
1149 panic("mksobj tried to make type %d, class %d.",
1150 (int) otmp->otyp, (int) objects[otmp->otyp].oc_class);
1151 /*NOTREACHED*/
1152 }
1153 if (may_generate_eroded(otmp)) {
1154 /* A small fraction of non-artifact items will generate eroded or
1155 * possibly erodeproof. An item that generates eroded will never be
1156 * erodeproof, and vice versa. */
1157 if (!rn2(40)) {
1158 otmp->oerodeproof = 1;
1159 }
1160 else {
1161 if (!rn2(40) && (is_flammable(otmp) || is_rustprone(otmp))) {
1162 do {
1163 otmp->oeroded++;
1164 } while (otmp->oeroded < 3 && !rn2(9));
1165 }
1166 if (!rn2(40) && (is_rottable(otmp) || is_corrodeable(otmp))) {
1167 do {
1168 otmp->oeroded2++;
1169 } while (otmp->oeroded2 < 3 && !rn2(9));
1170 }
1171 }
1172 /* and an extremely small fraction of the time, erodable items
1173 * will generate greased */
1174 if (!rn2(23263)) {
1175 otmp->greased = 1;
1176 }
1177 }
1178 }
1179
1180 /* some things must get done (corpsenm, timers) even if init = 0 */
1181 switch ((otmp->oclass == POTION_CLASS && otmp->otyp != POT_OIL)
1182 ? POT_WATER
1183 : otmp->otyp) {
1184 case CORPSE:
1185 if (otmp->corpsenm == NON_PM) {
1186 otmp->corpsenm = undead_to_corpse(rndmonnum());
1187 if (g.mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE | G_GONE))
1188 otmp->corpsenm = g.urole.malenum;
1189 }
1190 /*FALLTHRU*/
1191 case STATUE:
1192 case FIGURINE:
1193 if (otmp->corpsenm == NON_PM)
1194 otmp->corpsenm = rndmonnum();
1195 /*FALLTHRU*/
1196 case EGG:
1197 /* case TIN: */
1198 set_corpsenm(otmp, otmp->corpsenm);
1199 break;
1200 case POT_OIL:
1201 otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */
1202 /*FALLTHRU*/
1203 case POT_WATER: /* POTION_CLASS */
1204 otmp->fromsink = 0; /* overloads corpsenm, which was set to NON_PM */
1205 break;
1206 case LEASH:
1207 otmp->leashmon = 0; /* overloads corpsenm, which was set to NON_PM */
1208 break;
1209 case SPE_NOVEL:
1210 otmp->novelidx = -1; /* "none of the above"; will be changed */
1211 otmp = oname(otmp, noveltitle(&otmp->novelidx));
1212 break;
1213 }
1214
1215 /* unique objects may have an associated artifact entry */
1216 if (objects[otyp].oc_unique && !otmp->oartifact)
1217 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
1218 otmp->owt = weight(otmp);
1219 return otmp;
1220 }
1221
1222 /*
1223 * Several areas of the code made direct reassignments
1224 * to obj->corpsenm. Because some special handling is
1225 * required in certain cases, place that handling here
1226 * and call this routine in place of the direct assignment.
1227 *
1228 * If the object was a lizard or lichen corpse:
1229 * - ensure that you don't end up with some
1230 * other corpse type which has no rot-away timer.
1231 *
1232 * If the object was a troll corpse:
1233 * - ensure that you don't end up with some other
1234 * corpse type which resurrects from the dead.
1235 *
1236 * Re-calculates the weight of figurines and corpses to suit the
1237 * new species.
1238 *
1239 * Existing timeout value for egg hatch is preserved.
1240 *
1241 */
1242 void
set_corpsenm(struct obj * obj,int id)1243 set_corpsenm(struct obj *obj, int id)
1244 {
1245 int old_id = obj->corpsenm;
1246 long when = 0L;
1247
1248 if (obj->timed) {
1249 if (obj->otyp == EGG) {
1250 when = stop_timer(HATCH_EGG, obj_to_any(obj));
1251 } else {
1252 when = 0L;
1253 obj_stop_timers(obj); /* corpse or figurine */
1254 }
1255 }
1256 /* oeaten is used to determine how much nutrition is left in
1257 multiple-bite food and also used to derive how many hit points
1258 a creature resurrected from a partly eaten corpse gets; latter
1259 is of interest when a <foo> corpse revives as a <foo> zombie
1260 in case they are defined with different mons[].cnutrit values */
1261 if (obj->otyp == CORPSE && obj->oeaten != 0
1262 /* when oeaten is non-zero, index old_id can't be NON_PM
1263 and divisor mons[old_id].cnutrit can't be zero */
1264 && mons[old_id].cnutrit != mons[id].cnutrit) {
1265 /* oeaten and cnutrit are unsigned; theoretically that could
1266 be 16 bits and the calculation might overflow, so force long */
1267 obj->oeaten = (unsigned) ((long) obj->oeaten
1268 * (long) mons[id].cnutrit
1269 / (long) mons[old_id].cnutrit);
1270 }
1271
1272 obj->corpsenm = id;
1273 switch (obj->otyp) {
1274 case CORPSE:
1275 start_corpse_timeout(obj);
1276 obj->owt = weight(obj);
1277 break;
1278 case FIGURINE:
1279 if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE)
1280 && (carried(obj) || mcarried(obj)))
1281 attach_fig_transform_timeout(obj);
1282 obj->owt = weight(obj);
1283 break;
1284 case EGG:
1285 if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE))
1286 attach_egg_hatch_timeout(obj, when);
1287 break;
1288 default: /* tin, etc. */
1289 obj->owt = weight(obj);
1290 break;
1291 }
1292 }
1293
1294 /* Return the number of turns after which a Rider corpse revives */
1295 long
rider_revival_time(struct obj * body,boolean retry)1296 rider_revival_time(struct obj* body, boolean retry)
1297 {
1298 long when;
1299 long minturn = retry ? 3L : (body->corpsenm == PM_DEATH) ? 6L : 12L;
1300
1301 /* Riders have a 1/3 chance per turn of reviving after 12, 6, or 3 turns.
1302 Always revive by 67. */
1303 for (when = minturn; when < 67L; when++)
1304 if (!rn2(3))
1305 break;
1306 return when;
1307 }
1308
1309 /*
1310 * Start a corpse decay or revive timer.
1311 * This takes the age of the corpse into consideration as of 3.4.0.
1312 */
1313 void
start_corpse_timeout(struct obj * body)1314 start_corpse_timeout(struct obj* body)
1315 {
1316 long when; /* rot away when this old */
1317 long age; /* age of corpse */
1318 int rot_adjust;
1319 short action;
1320
1321 /*
1322 * Note:
1323 * if body->norevive is set, the corpse will rot away instead
1324 * of revive when its REVIVE_MON timer finishes.
1325 */
1326
1327 /* lizards and lichen don't rot or revive */
1328 if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN)
1329 return;
1330
1331 action = ROT_CORPSE; /* default action: rot away */
1332 rot_adjust = g.in_mklev ? 25 : 10; /* give some variation */
1333 age = g.monstermoves - body->age;
1334 if (age > ROT_AGE)
1335 when = rot_adjust;
1336 else
1337 when = ROT_AGE - age;
1338 when += (long) (rnz(rot_adjust) - rot_adjust);
1339
1340 if (is_rider(&mons[body->corpsenm])) {
1341 action = REVIVE_MON;
1342 when = rider_revival_time(body, FALSE);
1343 } else if (mons[body->corpsenm].mlet == S_TROLL) {
1344 for (age = 2; age <= TAINT_AGE; age++) {
1345 if (!rn2(TROLL_REVIVE_CHANCE)) { /* troll revives */
1346 action = REVIVE_MON;
1347 when = age;
1348 break;
1349 }
1350 }
1351 } else if (g.zombify && zombie_form(&mons[body->corpsenm]) != NON_PM
1352 && !body->zombie_corpse && !body->norevive) {
1353 action = ZOMBIFY_MON;
1354 when = rn1(15, 5); /* 5..19 */
1355 if (g.zombify == ZOMBIFY_TAME) {
1356 body->tamed_zombie = 1;
1357 }
1358 } else if (body->zombie_corpse && !body->norevive) {
1359 for (age = 2; age <= ROT_AGE; age++) {
1360 if (!rn2(ZOMBIE_REVIVE_CHANCE)) { /* zombie revives */
1361 action = REVIVE_MON;
1362 when = age;
1363 break;
1364 }
1365 }
1366 }
1367 /* independent if block so that a corpse which is eligible to revive but
1368 * fails to will still possibly grow mold, rather than having all troll
1369 * corpses just never grow mold. */
1370 if (action == ROT_CORPSE) {
1371 /* Corpses get moldy. */
1372 for (age = TAINT_AGE + 1; age <= ROT_AGE; age++) {
1373 if (!rn2(MOLDY_CHANCE)) { /* "revives" as a random s_fungus */
1374 action = MOLDY_CORPSE;
1375 when = age;
1376 break;
1377 }
1378 }
1379 }
1380
1381 (void) start_timer(when, TIMER_OBJECT, action, obj_to_any(body));
1382 }
1383
1384 static void
maybe_adjust_light(struct obj * obj,int old_range)1385 maybe_adjust_light(struct obj* obj, int old_range)
1386 {
1387 char buf[BUFSZ];
1388 xchar ox, oy;
1389 int new_range = arti_light_radius(obj), delta = new_range - old_range;
1390
1391 /* radius of light emitting artifact varies by curse/bless state
1392 so will change after blessing or cursing */
1393 if (delta) {
1394 obj_adjust_light_radius(obj, new_range);
1395 /* simplifying assumptions: hero is wielding this object;
1396 artifacts have to be in use to emit light and monsters'
1397 gear won't change bless or curse state */
1398 if (!Blind && get_obj_location(obj, &ox, &oy, 0)) {
1399 *buf = '\0';
1400 if (iflags.last_msg == PLNMSG_OBJ_GLOWS)
1401 /* we just saw "The <obj> glows <color>." from dipping */
1402 Strcpy(buf, (obj->quan == 1L) ? "It" : "They");
1403 else if (carried(obj) || cansee(ox, oy))
1404 Strcpy(buf, Yname2(obj));
1405 if (*buf) {
1406 /* initial activation says "dimly" if cursed,
1407 "brightly" if uncursed, and "brilliantly" if blessed;
1408 when changing intensity, using "less brightly" is
1409 straightforward for dimming, but we need "brighter"
1410 rather than "more brightly" for brightening; ugh */
1411 pline("%s %s %s%s.", buf, otense(obj, "shine"),
1412 (abs(delta) > 1) ? "much " : "",
1413 (delta > 0) ? "brighter" : "less brightly");
1414 }
1415 }
1416 }
1417 }
1418
1419 /*
1420 * bless(), curse(), unbless(), uncurse() -- any relevant message
1421 * about glowing amber/black/&c should be delivered prior to calling
1422 * these routines to make the actual curse/bless state change.
1423 */
1424
1425 void
bless(struct obj * otmp)1426 bless(struct obj* otmp)
1427 {
1428 int old_light = 0;
1429
1430 if (otmp->oclass == COIN_CLASS)
1431 return;
1432 if (otmp->lamplit)
1433 old_light = arti_light_radius(otmp);
1434 otmp->cursed = 0;
1435 otmp->blessed = 1;
1436 if (carried(otmp) && confers_luck(otmp))
1437 set_moreluck();
1438 else if (otmp->otyp == BAG_OF_HOLDING)
1439 otmp->owt = weight(otmp);
1440 else if (otmp->otyp == FIGURINE && otmp->timed)
1441 (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
1442 if (otmp->lamplit)
1443 maybe_adjust_light(otmp, old_light);
1444 return;
1445 }
1446
1447 void
unbless(struct obj * otmp)1448 unbless(struct obj* otmp)
1449 {
1450 int old_light = 0;
1451
1452 if (otmp->lamplit)
1453 old_light = arti_light_radius(otmp);
1454 otmp->blessed = 0;
1455 if (carried(otmp) && confers_luck(otmp))
1456 set_moreluck();
1457 else if (otmp->otyp == BAG_OF_HOLDING)
1458 otmp->owt = weight(otmp);
1459 if (otmp->lamplit)
1460 maybe_adjust_light(otmp, old_light);
1461 }
1462
1463 void
curse(struct obj * otmp)1464 curse(struct obj* otmp)
1465 {
1466 unsigned already_cursed;
1467 int old_light = 0;
1468
1469 if (otmp->oclass == COIN_CLASS)
1470 return;
1471 if (otmp->lamplit)
1472 old_light = arti_light_radius(otmp);
1473 already_cursed = otmp->cursed;
1474 otmp->blessed = 0;
1475 otmp->cursed = 1;
1476 /* welded two-handed weapon interferes with some armor removal */
1477 if (otmp == uwep && bimanual(uwep))
1478 reset_remarm();
1479 /* rules at top of wield.c state that twoweapon cannot be done
1480 with cursed alternate weapon */
1481 if (otmp == uswapwep && u.twoweap)
1482 drop_uswapwep();
1483 /* some cursed items need immediate updating */
1484 if (carried(otmp) && confers_luck(otmp)) {
1485 set_moreluck();
1486 } else if (otmp->otyp == BAG_OF_HOLDING) {
1487 otmp->owt = weight(otmp);
1488 } else if (otmp->otyp == FIGURINE) {
1489 if (otmp->corpsenm != NON_PM && !dead_species(otmp->corpsenm, TRUE)
1490 && (carried(otmp) || mcarried(otmp)))
1491 attach_fig_transform_timeout(otmp);
1492 } else if (otmp->oclass == SPBOOK_CLASS) {
1493 /* if book hero is reading becomes cursed, interrupt */
1494 if (!already_cursed)
1495 book_cursed(otmp);
1496 }
1497 if (otmp->where == OBJ_INVENT && !already_cursed) {
1498 /* Can't just check owornmask here, as some slots (e.g. W_ART) don't
1499 * actually indicate having otmp equipped. W_SWAPWEP is trickier as it
1500 * depends on whether the player is currently dual-wielding. */
1501 long really_wornmask = W_ARMOR | W_ACCESSORY | W_WEP;
1502 if (u.twoweap) {
1503 really_wornmask |= W_SWAPWEP;
1504 }
1505 if ((really_wornmask & W_WEP) && !will_weld(otmp)) {
1506 /* if player is wielding something that won't weld to their hand,
1507 * like a potion, suppress the weld message */
1508 really_wornmask &= ~W_WEP;
1509 }
1510 if (otmp->owornmask & really_wornmask) {
1511 cursed_gear_welds(otmp);
1512 }
1513 }
1514 if (otmp->lamplit)
1515 maybe_adjust_light(otmp, old_light);
1516 return;
1517 }
1518
1519 void
uncurse(struct obj * otmp)1520 uncurse(struct obj* otmp)
1521 {
1522 int old_light = 0;
1523 /* note: welded() sets bknown = 1, so avoid it doing that if the hero
1524 * somehow is wielding a welded weapon with bknown = 0 (maybe they got hit
1525 * with a curse while wielding a non-bknown weapon?) */
1526 boolean welded_wep = (otmp == uwep && otmp->bknown && welded(uwep));
1527
1528 if (otmp->lamplit)
1529 old_light = arti_light_radius(otmp);
1530 otmp->cursed = 0;
1531 if (carried(otmp) && confers_luck(otmp))
1532 set_moreluck();
1533 else if (otmp->otyp == BAG_OF_HOLDING)
1534 otmp->owt = weight(otmp);
1535 else if (otmp->otyp == FIGURINE && otmp->timed)
1536 (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
1537 if (otmp->lamplit)
1538 maybe_adjust_light(otmp, old_light);
1539 if (otmp->where == OBJ_INVENT && otmp->owornmask && otmp->bknown) {
1540 if (welded_wep) {
1541 const char* hand = body_part(HAND);
1542 if (bimanual(uwep))
1543 hand = makeplural(hand);
1544 pline("%s is no longer welded to your %s.",
1545 upstart(yname(otmp)), hand);
1546 }
1547 else if (otmp->owornmask & (W_ARMOR | W_ACCESSORY)) {
1548 if (Hallucination)
1549 pline("The adhesion of %s has diminished.", yname(otmp));
1550 else if (otmp->otyp != AMULET_OF_STRANGULATION)
1551 pline("%s seems to loosen a bit.", upstart(yname(otmp)));
1552 }
1553 }
1554 return;
1555 }
1556
1557 void
blessorcurse(struct obj * otmp,int chance)1558 blessorcurse(struct obj* otmp, int chance)
1559 {
1560 if (otmp->blessed || otmp->cursed)
1561 return;
1562
1563 if (!rn2(chance)) {
1564 if (!rn2(2)) {
1565 curse(otmp);
1566 } else {
1567 bless(otmp);
1568 }
1569 }
1570 return;
1571 }
1572
1573 int
bcsign(struct obj * otmp)1574 bcsign(struct obj* otmp)
1575 {
1576 return (!!otmp->blessed - !!otmp->cursed);
1577 }
1578
1579 /* set the object's bless/curse-state known flag */
1580 void
set_bknown(struct obj * obj,unsigned int onoff)1581 set_bknown(struct obj* obj, unsigned int onoff /* 1 or 0 */)
1582 {
1583 if (obj->bknown != onoff) {
1584 obj->bknown = onoff;
1585 if (obj->where == OBJ_INVENT && g.moves > 1L)
1586 update_inventory();
1587 }
1588 }
1589
1590 /* Relative weights of different materials.
1591 * This used to be an attempt at making them super realistic, with densities in
1592 * terms of their kg/m^3 and as close to real life as possible, but that just
1593 * doesn't work because it makes materials infeasible to use. Nobody wants
1594 * anything gold or platinum if it weighs three times as much as its iron
1595 * counterpart, and things such as wooden plate mails were incredibly
1596 * overpowered by weighing about one-tenth as much as the iron counterpart.
1597 * Instead, use arbitrary units. */
1598 static
1599 const int matdensities[] = {
1600 0, // will cause div/0 errors if anything is this material
1601 10, // LIQUID
1602 15, // WAX
1603 10, // VEGGY
1604 10, // FLESH
1605 5, // PAPER
1606 10, // CLOTH
1607 15, // LEATHER
1608 30, // WOOD
1609 25, // BONE
1610 20, // DRAGONHIDE
1611 80, // IRON
1612 70, // METAL
1613 85, // COPPER
1614 90, // SILVER
1615 120, // GOLD
1616 120, // PLATINUM
1617 50, // MITHRIL
1618 20, // PLASTIC
1619 60, // GLASS
1620 55, // GEMSTONE
1621 70 // MINERAL
1622 };
1623
1624 /*
1625 * Calculate the weight of the given object. This will recursively follow
1626 * and calculate the weight of any containers.
1627 *
1628 * Note: It is possible to end up with an incorrect weight if some part
1629 * of the code messes with a contained object and doesn't update the
1630 * container's weight.
1631 */
1632 int
weight(struct obj * obj)1633 weight(struct obj* obj)
1634 {
1635 int wt = (int) objects[obj->otyp].oc_weight;
1636
1637 /* Modify weight according to the relative densities of the two materials,
1638 * if they differ. */
1639 if (obj->material != objects[obj->otyp].oc_material) {
1640 wt = (wt * matdensities[obj->material])
1641 / matdensities[objects[obj->otyp].oc_material];
1642 }
1643
1644 /* glob absorpsion means that merging globs accumulates weight while
1645 quantity stays 1, so update 'wt' to reflect that, unless owt is 0,
1646 when we assume this is a brand new glob so use objects[].oc_weight */
1647 if (obj->globby && obj->owt > 0)
1648 wt = obj->owt;
1649 if (Is_container(obj) || obj->otyp == STATUE) {
1650 struct obj *contents;
1651 register int cwt = 0;
1652
1653 if (obj->otyp == STATUE && obj->corpsenm >= LOW_PM)
1654 wt = (int) obj->quan * ((int) mons[obj->corpsenm].cwt * 3 / 2);
1655
1656 for (contents = obj->cobj; contents; contents = contents->nobj)
1657 cwt += weight(contents);
1658 /*
1659 * The weight of bags of holding is calculated as the weight
1660 * of the bag plus the weight of the bag's contents modified
1661 * as follows:
1662 *
1663 * Bag status Weight of contents
1664 * ---------- ------------------
1665 * cursed 2x
1666 * blessed x/4 [rounded up: (x+3)/4]
1667 * otherwise x/2 [rounded up: (x+1)/2]
1668 *
1669 * The macro DELTA_CWT in pickup.c also implements these
1670 * weight equations.
1671 */
1672 if (obj->otyp == BAG_OF_HOLDING)
1673 cwt = obj->cursed ? (cwt * 2) : obj->blessed ? ((cwt + 3) / 4)
1674 : ((cwt + 1) / 2);
1675
1676 return wt + cwt;
1677 }
1678 if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) {
1679 long long_wt = obj->quan * (long) mons[obj->corpsenm].cwt;
1680
1681 wt = (long_wt > LARGEST_INT) ? LARGEST_INT : (int) long_wt;
1682 if (obj->oeaten)
1683 wt = eaten_stat(wt, obj);
1684 return wt;
1685 } else if (obj->oclass == FOOD_CLASS && obj->oeaten) {
1686 return eaten_stat((int) obj->quan * wt, obj);
1687 } else if (obj->oclass == COIN_CLASS) {
1688 return (int) ((obj->quan + 50L) / 100L);
1689 } else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0) {
1690 return (int) obj->owt; /* kludge for "very" heavy iron ball */
1691 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->spe) {
1692 return wt + obj->spe * (int) objects[TALLOW_CANDLE].oc_weight;
1693 } else if (obj->oclass == ARMOR_CLASS && (obj->owornmask & W_ARMOR)) {
1694 return ((wt * 3) + 3) / 4;
1695 }
1696 return (wt ? wt * (int) obj->quan : ((int) obj->quan + 1) >> 1);
1697 }
1698
1699 /* Relative defensiveness of various materials. The only thing that should ever
1700 * matter is the difference between two of these quantities, so the values are
1701 * adjusted up so that there are no negatives.
1702 * The units involved here are AC points (but again, only the difference
1703 * matters.) */
1704 const int matac[] = {
1705 0,
1706 0, // LIQUID
1707 1, // WAX
1708 1, // VEGGY
1709 3, // FLESH
1710 1, // PAPER
1711 2, // CLOTH
1712 3, // LEATHER
1713 4, // WOOD
1714 4, // BONE
1715 10, // DRAGON_HIDE
1716 5, // IRON - de facto baseline for metal armor
1717 5, // METAL
1718 4, // COPPER
1719 5, // SILVER
1720 3, // GOLD
1721 4, // PLATINUM
1722 6, // MITHRIL
1723 3, // PLASTIC
1724 5, // GLASS
1725 7, // GEMSTONE
1726 6 // MINERAL
1727 };
1728
1729 /* Compute the bonus or penalty to AC an armor piece should get for being a
1730 * non-default material. */
1731 int
material_bonus(struct obj * obj)1732 material_bonus(struct obj *obj)
1733 {
1734 int diff = matac[obj->material] - matac[objects[obj->otyp].oc_material];
1735
1736 /* don't allow the armor's base AC to go below 0...
1737 * or go below 1, if the armor is metallic */
1738 const int min_ac = is_metallic(obj) ? 1 : 0;
1739 if (objects[obj->otyp].a_ac + diff < min_ac) {
1740 diff = min_ac - objects[obj->otyp].a_ac;
1741 }
1742 return diff;
1743 }
1744
1745 static const int treefruits[] = { APPLE, ORANGE, PEAR, BANANA, EUCALYPTUS_LEAF };
1746
1747 /* called when a tree is kicked; never returns Null */
1748 struct obj *
rnd_treefruit_at(int x,int y)1749 rnd_treefruit_at(int x, int y)
1750 {
1751 return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE);
1752 }
1753
1754 /* create a stack of N gold pieces; never returns Null */
1755 struct obj *
mkgold(long amount,int x,int y)1756 mkgold(long amount, int x, int y)
1757 {
1758 struct obj *gold = g_at(x, y);
1759
1760 if (amount <= 0L) {
1761 long mul = rnd(30 / max(12-depth(&u.uz), 2));
1762
1763 amount = (long) (1 + rnd(level_difficulty() + 2) * mul);
1764 }
1765 if (gold) {
1766 gold->quan += amount;
1767 } else {
1768 gold = mksobj_at(GOLD_PIECE, x, y, TRUE, FALSE);
1769 gold->quan = amount;
1770 }
1771 gold->owt = weight(gold);
1772 return gold;
1773 }
1774
1775 /* return TRUE if the corpse has special timing;
1776 lizards and lichen don't rot, trolls and Riders and zombies auto-revive */
1777 #define special_corpse(num) \
1778 (((num) == PM_LIZARD || (num) == PM_LICHEN) || is_reviver(&mons[num]))
1779
1780 /* mkcorpstat: make a corpse or statue; never returns Null.
1781 *
1782 * OEXTRA note: Passing mtmp causes mtraits to be saved
1783 * even if ptr passed as well, but ptr is always used for
1784 * the corpse type (corpsenm). That allows the corpse type
1785 * to be different from the original monster,
1786 * i.e. vampire -> human corpse
1787 * yet still allow restoration of the original monster upon
1788 * resurrection.
1789 */
1790 struct obj *
mkcorpstat(int objtype,struct monst * mtmp,struct permonst * ptr,int x,int y,unsigned corpstatflags)1791 mkcorpstat(
1792 int objtype, /* CORPSE or STATUE */
1793 struct monst *mtmp, /* dead monster, might be Null */
1794 struct permonst *ptr, /* if non-Null, overrides mtmp->mndx */
1795 int x, int y, /* where to place corpse; <0,0> => random */
1796 unsigned corpstatflags)
1797 {
1798 struct obj *otmp;
1799 boolean init = ((corpstatflags & CORPSTAT_INIT) != 0);
1800
1801 if (objtype != CORPSE && objtype != STATUE)
1802 impossible("making corpstat type %d", objtype);
1803 if (x == 0 && y == 0) { /* special case - random placement */
1804 otmp = mksobj(objtype, init, FALSE);
1805 (void) rloco(otmp);
1806 } else {
1807 otmp = mksobj_at(objtype, x, y, init, FALSE);
1808 }
1809 otmp->norevive = g.mkcorpstat_norevive;
1810
1811 if ((corpstatflags & CORPSTAT_ZOMBIE) != 0) {
1812 otmp->zombie_corpse = 1;
1813 }
1814
1815 /* when 'mtmp' is non-null save the monster's details with the
1816 corpse or statue; it will also force the 'ptr' override below */
1817 if (mtmp) {
1818 /* save_mtraits updates otmp->oextra->omonst in place */
1819 (void) save_mtraits(otmp, mtmp);
1820
1821 if (!ptr)
1822 ptr = mtmp->data;
1823
1824 /* don't give a revive timer to a cancelled troll's corpse */
1825 if (mtmp->mcan && !is_rider(ptr))
1826 otmp->norevive = 1;
1827 }
1828
1829 /* when 'ptr' is non-null it comes from our caller or from 'mtmp';
1830 override mkobjs()'s initialization of a random monster type */
1831 if (ptr) {
1832 int old_corpsenm = otmp->corpsenm;
1833
1834 otmp->corpsenm = monsndx(ptr);
1835 otmp->owt = weight(otmp);
1836 if (otmp->otyp == CORPSE && (g.zombify || special_corpse(old_corpsenm)
1837 || special_corpse(otmp->corpsenm))) {
1838 obj_stop_timers(otmp);
1839 if (mtmp && is_reviver(mtmp->data) && !is_rider(mtmp->data)
1840 && mtmp->mcan) {
1841 otmp->norevive = 1;
1842 }
1843 start_corpse_timeout(otmp);
1844 }
1845 }
1846 return otmp;
1847 }
1848
1849 /*
1850 * Return the type of monster that this corpse will
1851 * revive as, even if it has a monster structure
1852 * attached to it. In that case, you can't just
1853 * use obj->corpsenm, because the stored monster
1854 * type can, and often is, different.
1855 * The return value is an index into mons[].
1856 */
1857 int
corpse_revive_type(struct obj * obj)1858 corpse_revive_type(struct obj* obj)
1859 {
1860 int revivetype = obj->corpsenm;
1861 struct monst *mtmp;
1862
1863 if (has_omonst(obj) && ((mtmp = get_mtraits(obj, FALSE)) != 0)) {
1864 /* mtmp is a temporary pointer to a monster's stored
1865 attributes, not a real monster */
1866 revivetype = mtmp->mnum;
1867 }
1868 return revivetype;
1869 }
1870
1871 /*
1872 * Attach a monster id to an object, to provide
1873 * a lasting association between the two.
1874 */
1875 struct obj *
obj_attach_mid(struct obj * obj,unsigned int mid)1876 obj_attach_mid(struct obj* obj, unsigned int mid)
1877 {
1878 if (!mid || !obj)
1879 return (struct obj *) 0;
1880 newomid(obj);
1881 OMID(obj) = mid;
1882 return obj;
1883 }
1884
1885 static struct obj *
save_mtraits(struct obj * obj,struct monst * mtmp)1886 save_mtraits(struct obj* obj, struct monst* mtmp)
1887 {
1888 if (mtmp->ispriest)
1889 forget_temple_entry(mtmp); /* EPRI() */
1890 if (!has_omonst(obj))
1891 newomonst(obj);
1892 if (has_omonst(obj)) {
1893 int baselevel = mtmp->data->mlevel;
1894 struct monst *mtmp2 = OMONST(obj);
1895
1896 *mtmp2 = *mtmp;
1897 mtmp2->mextra = (struct mextra *) 0;
1898 if (mtmp->data)
1899 mtmp2->mnum = monsndx(mtmp->data);
1900 /* invalidate pointers */
1901 /* m_id is needed to know if this is a revived quest leader */
1902 /* but m_id must be cleared when loading bones */
1903 mtmp2->nmon = (struct monst *) 0;
1904 mtmp2->data = (struct permonst *) 0;
1905 mtmp2->minvent = (struct obj *) 0;
1906 if (mtmp->mextra)
1907 copy_mextra(mtmp2, mtmp);
1908 /* if mtmp is a long worm with segments, its saved traits will
1909 be one without any segments */
1910 mtmp2->wormno = 0;
1911 /* mtmp might have been killed by repeated life draining; make sure
1912 mtmp2 can survive if revived ('baselevel' will be 0 for 1d4 mon) */
1913 if (mtmp2->mhpmax <= baselevel)
1914 mtmp2->mhpmax = baselevel + 1;
1915 /* mtmp is assumed to be dead but we don't kill it or its saved
1916 traits, just force those to have a sane value for current HP */
1917 if (mtmp2->mhp > mtmp2->mhpmax)
1918 mtmp2->mhp = mtmp2->mhpmax;
1919 if (mtmp2->mhp < 1)
1920 mtmp2->mhp = 0;
1921 }
1922 return obj;
1923 }
1924
1925 /* returns a pointer to a new monst structure based on
1926 * the one contained within the obj.
1927 */
1928 struct monst *
get_mtraits(struct obj * obj,boolean copyof)1929 get_mtraits(struct obj* obj, boolean copyof)
1930 {
1931 struct monst *mtmp = (struct monst *) 0;
1932 struct monst *mnew = (struct monst *) 0;
1933
1934 if (has_omonst(obj))
1935 mtmp = OMONST(obj);
1936 if (mtmp) {
1937 if (copyof) {
1938 mnew = newmonst();
1939 *mnew = *mtmp;
1940 mnew->mextra = (struct mextra *) 0;
1941 if (mtmp->mextra)
1942 copy_mextra(mnew, mtmp);
1943 } else {
1944 /* Never insert this returned pointer into mon chains! */
1945 mnew = mtmp;
1946 }
1947 mnew->data = &mons[mnew->mnum];
1948 }
1949 return mnew;
1950 }
1951
1952 /* make an object named after someone listed in the scoreboard file;
1953 never returns Null */
1954 struct obj *
mk_tt_object(int objtype,int x,int y)1955 mk_tt_object(
1956 int objtype, /* CORPSE or STATUE */
1957 int x, int y)
1958 {
1959 struct obj *otmp;
1960 boolean initialize_it;
1961
1962 /* player statues never contain books */
1963 initialize_it = (objtype != STATUE);
1964 otmp = mksobj_at(objtype, x, y, initialize_it, FALSE);
1965
1966 /* tt_oname() will return null if the scoreboard is empty, which in
1967 turn leaves the random corpsenm value; force it to match a player */
1968 if (!tt_oname(otmp)) {
1969 int pm = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1, PM_ARCHEOLOGIST);
1970
1971 /* update weight for either, force timer sanity for corpses */
1972 set_corpsenm(otmp, pm);
1973 }
1974
1975 return otmp;
1976 }
1977
1978 /* make a new corpse or statue, uninitialized if a statue (i.e. no books);
1979 never returns Null */
1980 struct obj *
mk_named_object(int objtype,struct permonst * ptr,int x,int y,const char * nm)1981 mk_named_object(
1982 int objtype, /* CORPSE or STATUE */
1983 struct permonst *ptr,
1984 int x, int y,
1985 const char *nm)
1986 {
1987 struct obj *otmp;
1988 unsigned corpstatflags = (objtype != STATUE) ? CORPSTAT_INIT
1989 : CORPSTAT_NONE;
1990
1991 otmp = mkcorpstat(objtype, (struct monst *) 0, ptr, x, y, corpstatflags);
1992 if (nm)
1993 otmp = oname(otmp, nm);
1994 return otmp;
1995 }
1996
1997 boolean
is_flammable(struct obj * otmp)1998 is_flammable(struct obj* otmp)
1999 {
2000 int otyp = otmp->otyp;
2001 int omat = otmp->material;
2002
2003 /* Candles can be burned, but they're not flammable in the sense that
2004 * they can't get fire damage and it makes no sense for them to be
2005 * fireproofed.
2006 */
2007 if (Is_candle(otmp))
2008 return FALSE;
2009
2010 if (objects[otyp].oc_oprop == FIRE_RES || otyp == WAN_FIRE)
2011 return FALSE;
2012
2013 return (boolean) ((omat <= BONE && omat != LIQUID) || omat == PLASTIC);
2014 }
2015
2016 boolean
is_rottable(struct obj * otmp)2017 is_rottable(struct obj* otmp)
2018 {
2019 return (boolean) (otmp->material <= WOOD && otmp->material != LIQUID);
2020 }
2021
2022 /*
2023 * These routines maintain the single-linked lists headed in g.level.objects[][]
2024 * and threaded through the nexthere fields in the object-instance structure.
2025 */
2026
2027 /* put the object at the given location */
2028 void
place_object(struct obj * otmp,int x,int y)2029 place_object(struct obj* otmp, int x, int y)
2030 {
2031 register struct obj *otmp2 = g.level.objects[x][y];
2032 fuzl_xyi("place_object", x,y, otmp->otyp);
2033
2034 if (!isok(x, y)) { /* validate location */
2035 void (*func)(const char *, ...);
2036
2037 func = (x < 0 || y < 0 || x > COLNO - 1 || y > ROWNO - 1) ? panic
2038 : impossible;
2039 (*func)("place_object: \"%s\" [%d] off map <%d,%d>",
2040 safe_typename(otmp->otyp), otmp->where, x, y);
2041 }
2042 if (otmp->where != OBJ_FREE)
2043 panic("place_object: obj \"%s\" [%d] not free",
2044 safe_typename(otmp->otyp), otmp->where);
2045
2046 obj_no_longer_held(otmp);
2047 if (otmp->otyp == BOULDER) {
2048 if (!otmp2 || otmp2->otyp != BOULDER)
2049 block_point(x, y); /* vision */
2050 }
2051
2052 /* non-boulder object goes under boulders so that map will show boulder
2053 here without display code needing to traverse pile chain to find one */
2054 if (otmp2 && otmp2->otyp == BOULDER && otmp->otyp != BOULDER) {
2055 /* 3.6.3: put otmp under last consecutive boulder rather than under
2056 just the first one; multiple boulders at same spot in new games
2057 will be consecutive due to this, ones in old games saved before
2058 this change might not be; can affect the map display if the top
2059 boulder is moved/removed by some means other than pushing */
2060 while (otmp2->nexthere && otmp2->nexthere->otyp == BOULDER)
2061 otmp2 = otmp2->nexthere;
2062 otmp->nexthere = otmp2->nexthere;
2063 otmp2->nexthere = otmp;
2064 } else {
2065 /* put on top of current pile */
2066 otmp->nexthere = otmp2;
2067 g.level.objects[x][y] = otmp;
2068 }
2069
2070 /* set the new object's location */
2071 otmp->ox = x;
2072 otmp->oy = y;
2073 otmp->where = OBJ_FLOOR;
2074
2075 /* add to floor chain */
2076 otmp->nobj = fobj;
2077 fobj = otmp;
2078 if (otmp->timed)
2079 obj_timer_checks(otmp, x, y, 0);
2080 }
2081
2082 #define ROT_ICE_ADJUSTMENT 2 /* rotting on ice takes 2 times as long */
2083
2084 /* If ice was affecting any objects correct that now
2085 * Also used for starting ice effects too. [zap.c]
2086 */
2087 void
obj_ice_effects(int x,int y,boolean do_buried)2088 obj_ice_effects(int x, int y, boolean do_buried)
2089 {
2090 struct obj *otmp;
2091
2092 for (otmp = g.level.objects[x][y]; otmp; otmp = otmp->nexthere) {
2093 if (otmp->timed)
2094 obj_timer_checks(otmp, x, y, 0);
2095 }
2096 if (do_buried) {
2097 for (otmp = g.level.buriedobjlist; otmp; otmp = otmp->nobj) {
2098 if (otmp->ox == x && otmp->oy == y) {
2099 if (otmp->timed)
2100 obj_timer_checks(otmp, x, y, 0);
2101 }
2102 }
2103 }
2104 }
2105
2106 /*
2107 * Returns an obj->age for a corpse object on ice, that would be the
2108 * actual obj->age if the corpse had just been lifted from the ice.
2109 * This is useful when just using obj->age in a check or calculation because
2110 * rot timers pertaining to the object don't have to be stopped and
2111 * restarted etc.
2112 */
2113 long
peek_at_iced_corpse_age(struct obj * otmp)2114 peek_at_iced_corpse_age(struct obj* otmp)
2115 {
2116 long age, retval = otmp->age;
2117
2118 if (otmp->otyp == CORPSE && otmp->on_ice) {
2119 /* Adjust the age; must be same as obj_timer_checks() for off ice*/
2120 age = g.monstermoves - otmp->age;
2121 retval += age * (ROT_ICE_ADJUSTMENT - 1) / ROT_ICE_ADJUSTMENT;
2122 debugpline3(
2123 "The %s age has ice modifications: otmp->age = %ld, returning %ld.",
2124 s_suffix(doname(otmp)), otmp->age, retval);
2125 debugpline1("Effective age of corpse: %ld.", g.monstermoves - retval);
2126 }
2127 return retval;
2128 }
2129
2130 static void
obj_timer_checks(struct obj * otmp,xchar x,xchar y,int force)2131 obj_timer_checks(
2132 struct obj* otmp,
2133 xchar x, xchar y,
2134 int force) /* 0 = no force so do checks, <0 = force off, >0 force on */
2135 {
2136 long tleft = 0L;
2137 short action = ROT_CORPSE;
2138 boolean restart_timer = FALSE;
2139 boolean on_floor = (otmp->where == OBJ_FLOOR);
2140 boolean buried = (otmp->where == OBJ_BURIED);
2141
2142 /* Check for corpses just placed on or in ice */
2143 if (otmp->otyp == CORPSE && (on_floor || buried) && is_ice(x, y)) {
2144 tleft = stop_timer(action, obj_to_any(otmp));
2145 if (tleft == 0L) {
2146 action = MOLDY_CORPSE;
2147 tleft = stop_timer(action, obj_to_any(otmp));
2148 }
2149 if (tleft == 0L) {
2150 action = REVIVE_MON;
2151 tleft = stop_timer(action, obj_to_any(otmp));
2152 }
2153 if (tleft != 0L) {
2154 long age;
2155
2156 /* mark the corpse as being on ice */
2157 otmp->on_ice = 1;
2158 debugpline3("%s is now on ice at <%d,%d>.", The(xname(otmp)), x,
2159 y);
2160 /* Adjust the time remaining */
2161 tleft *= ROT_ICE_ADJUSTMENT;
2162 restart_timer = TRUE;
2163 /* Adjust the age; time spent off ice needs to be multiplied
2164 by the ice adjustment and subtracted from the age so that
2165 later calculations behave as if it had been on ice during
2166 that time (longwinded way of saying this is the inverse
2167 of removing it from the ice and of peeking at its age). */
2168 age = g.monstermoves - otmp->age;
2169 otmp->age = g.monstermoves - (age * ROT_ICE_ADJUSTMENT);
2170 }
2171
2172 /* Check for corpses coming off ice */
2173 } else if (force < 0 || (otmp->otyp == CORPSE && otmp->on_ice
2174 && !((on_floor || buried) && is_ice(x, y)))) {
2175 tleft = stop_timer(action, obj_to_any(otmp));
2176 if (tleft == 0L) {
2177 action = MOLDY_CORPSE;
2178 tleft = stop_timer(action, obj_to_any(otmp));
2179 }
2180 if (tleft == 0L) {
2181 action = REVIVE_MON;
2182 tleft = stop_timer(action, obj_to_any(otmp));
2183 }
2184 if (tleft != 0L) {
2185 long age;
2186
2187 otmp->on_ice = 0;
2188 debugpline3("%s is no longer on ice at <%d,%d>.",
2189 The(xname(otmp)), x, y);
2190 /* Adjust the remaining time */
2191 tleft /= ROT_ICE_ADJUSTMENT;
2192 restart_timer = TRUE;
2193 /* Adjust the age */
2194 age = g.monstermoves - otmp->age;
2195 otmp->age += age * (ROT_ICE_ADJUSTMENT - 1) / ROT_ICE_ADJUSTMENT;
2196 }
2197 }
2198
2199 /* now re-start the timer with the appropriate modifications */
2200 if (restart_timer)
2201 (void) start_timer(tleft, TIMER_OBJECT, action, obj_to_any(otmp));
2202 }
2203
2204 #undef ROT_ICE_ADJUSTMENT
2205
2206 void
remove_object(struct obj * otmp)2207 remove_object(struct obj* otmp)
2208 {
2209 xchar x = otmp->ox;
2210 xchar y = otmp->oy;
2211
2212 if (otmp->where != OBJ_FLOOR)
2213 panic("remove_object: obj not on floor");
2214 extract_nexthere(otmp, &g.level.objects[x][y]);
2215 extract_nobj(otmp, &fobj);
2216 /* update vision iff this was the only boulder at its spot */
2217 if (otmp->otyp == BOULDER && !sobj_at(BOULDER, x, y))
2218 unblock_point(x, y); /* vision */
2219 if (otmp->timed)
2220 obj_timer_checks(otmp, x, y, 0);
2221 }
2222
2223 /* throw away all of a monster's inventory */
2224 void
discard_minvent(struct monst * mtmp,boolean uncreate_artifacts)2225 discard_minvent(struct monst* mtmp, boolean uncreate_artifacts)
2226 {
2227 struct obj *otmp;
2228
2229 while ((otmp = mtmp->minvent) != 0) {
2230 /* this has now become very similar to m_useupall()... */
2231 extract_from_minvent(mtmp, otmp, TRUE, TRUE);
2232 if (uncreate_artifacts && otmp->oartifact)
2233 artifact_exists(otmp, safe_oname(otmp), FALSE);
2234 obfree(otmp, (struct obj *) 0); /* dealloc_obj() isn't sufficient */
2235 }
2236 }
2237
2238 /*
2239 * Free obj from whatever list it is on in preparation for deleting it
2240 * or moving it elsewhere; obj->where will end up set to OBJ_FREE.
2241 * Doesn't handle unwearing of objects in hero's or monsters' inventories.
2242 *
2243 * Object positions:
2244 * OBJ_FREE not on any list
2245 * OBJ_FLOOR fobj, level.locations[][] chains (use remove_object)
2246 * OBJ_CONTAINED cobj chain of container object
2247 * OBJ_INVENT hero's invent chain (use freeinv)
2248 * OBJ_MINVENT monster's invent chain
2249 * OBJ_MIGRATING migrating chain
2250 * OBJ_BURIED level.buriedobjs chain
2251 * OBJ_ONBILL on g.billobjs chain
2252 * OBJ_LUAFREE obj is dealloc'd from core, but still used by lua
2253 * OBJ_INTRAP obj is in a trap as ammo (use extract_nobj instead)
2254 */
2255 void
obj_extract_self(struct obj * obj)2256 obj_extract_self(struct obj* obj)
2257 {
2258 switch (obj->where) {
2259 case OBJ_FREE:
2260 case OBJ_LUAFREE:
2261 break;
2262 case OBJ_FLOOR:
2263 remove_object(obj);
2264 break;
2265 case OBJ_CONTAINED:
2266 extract_nobj(obj, &obj->ocontainer->cobj);
2267 container_weight(obj->ocontainer);
2268 obj->ocontainer = (struct obj *) 0; /* clear stale back-link */
2269 break;
2270 case OBJ_INVENT:
2271 freeinv(obj);
2272 break;
2273 case OBJ_MINVENT:
2274 extract_nobj(obj, &obj->ocarry->minvent);
2275 obj->ocarry = (struct monst *) 0; /* clear stale back-link */
2276 break;
2277 case OBJ_MIGRATING:
2278 extract_nobj(obj, &g.migrating_objs);
2279 break;
2280 case OBJ_BURIED:
2281 extract_nobj(obj, &g.level.buriedobjlist);
2282 break;
2283 case OBJ_ONBILL:
2284 extract_nobj(obj, &g.billobjs);
2285 break;
2286 case OBJ_INTRAP:
2287 /* Objects don't store a pointer to their containing trap.
2288 * The only place that we should be trying to extract an object inside a
2289 * trap is from within trap code that has a pointer to the trap that
2290 * contains the object. We should never be trying to extract an object
2291 * inside a trap without that context. */
2292 panic("trying to extract object from trap with no trap info");
2293 break;
2294 default:
2295 panic("obj_extract_self");
2296 break;
2297 }
2298 }
2299
2300 /* Extract the given object from the chain, following nobj chain. */
2301 void
extract_nobj(struct obj * obj,struct obj ** head_ptr)2302 extract_nobj(struct obj* obj, struct obj** head_ptr)
2303 {
2304 struct obj *curr, *prev;
2305
2306 curr = *head_ptr;
2307 for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nobj) {
2308 if (curr == obj) {
2309 if (prev)
2310 prev->nobj = curr->nobj;
2311 else
2312 *head_ptr = curr->nobj;
2313 break;
2314 }
2315 }
2316 if (!curr)
2317 panic("extract_nobj: object lost");
2318 obj->where = OBJ_FREE;
2319 obj->nobj = (struct obj *) 0;
2320 }
2321
2322 /*
2323 * Extract the given object from the chain, following nexthere chain.
2324 *
2325 * This does not set obj->where, this function is expected to be called
2326 * in tandem with extract_nobj, which does set it.
2327 */
2328 void
extract_nexthere(struct obj * obj,struct obj ** head_ptr)2329 extract_nexthere(struct obj* obj, struct obj** head_ptr)
2330 {
2331 struct obj *curr, *prev;
2332
2333 curr = *head_ptr;
2334 for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nexthere) {
2335 if (curr == obj) {
2336 if (prev)
2337 prev->nexthere = curr->nexthere;
2338 else
2339 *head_ptr = curr->nexthere;
2340 break;
2341 }
2342 }
2343 if (!curr)
2344 panic("extract_nexthere: object lost");
2345 obj->nexthere = (struct obj *) 0;
2346 }
2347
2348 /*
2349 * Add obj to mon's inventory. If obj is able to merge with something already
2350 * in the inventory, then the passed obj is deleted and 1 is returned.
2351 * Otherwise 0 is returned.
2352 */
2353 int
add_to_minv(struct monst * mon,struct obj * obj)2354 add_to_minv(struct monst *mon, struct obj* obj)
2355 {
2356 struct obj *otmp;
2357
2358 if (obj->where != OBJ_FREE)
2359 panic("add_to_minv: obj not free");
2360
2361 /* merge if possible */
2362 for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
2363 if (merged(&otmp, &obj))
2364 return 1; /* obj merged and then free'd */
2365 /* else insert; don't bother forcing it to end of chain */
2366 obj->where = OBJ_MINVENT;
2367 obj->ocarry = mon;
2368 obj->nobj = mon->minvent;
2369 mon->minvent = obj;
2370 return 0; /* obj on mon's inventory chain */
2371 }
2372
2373 /*
2374 * Add obj to container, make sure obj is "free". Returns (merged) obj.
2375 * The input obj may be deleted in the process.
2376 */
2377 struct obj *
add_to_container(struct obj * container,struct obj * obj)2378 add_to_container(struct obj* container, struct obj* obj)
2379 {
2380 struct obj *otmp;
2381
2382 if (obj->where != OBJ_FREE)
2383 panic("add_to_container: obj not free");
2384 if (container->where != OBJ_INVENT && container->where != OBJ_MINVENT)
2385 obj_no_longer_held(obj);
2386
2387 /* merge if possible */
2388 for (otmp = container->cobj; otmp; otmp = otmp->nobj)
2389 if (merged(&otmp, &obj))
2390 return otmp;
2391
2392 obj->where = OBJ_CONTAINED;
2393 obj->ocontainer = container;
2394 obj->nobj = container->cobj;
2395 container->cobj = obj;
2396 return obj;
2397 }
2398
2399 void
add_to_migration(struct obj * obj)2400 add_to_migration(struct obj* obj)
2401 {
2402 if (obj->where != OBJ_FREE)
2403 panic("add_to_migration: obj not free");
2404
2405 /* lock picking context becomes stale if it's for this object */
2406 if (Is_container(obj))
2407 maybe_reset_pick(obj);
2408
2409 obj->where = OBJ_MIGRATING;
2410 obj->nobj = g.migrating_objs;
2411 obj->omigr_from_dnum = u.uz.dnum;
2412 obj->omigr_from_dlevel = u.uz.dlevel;
2413 g.migrating_objs = obj;
2414 }
2415
2416 void
add_to_buried(struct obj * obj)2417 add_to_buried(struct obj* obj)
2418 {
2419 if (obj->where != OBJ_FREE)
2420 panic("add_to_buried: obj not free");
2421
2422 obj->where = OBJ_BURIED;
2423 obj->nobj = g.level.buriedobjlist;
2424 g.level.buriedobjlist = obj;
2425 }
2426
2427 /* Recalculate the weight of this container and all of _its_ containers. */
2428 static void
container_weight(struct obj * container)2429 container_weight(struct obj* container)
2430 {
2431 container->owt = weight(container);
2432 if (container->where == OBJ_CONTAINED)
2433 container_weight(container->ocontainer);
2434 /*
2435 else if (container->where == OBJ_INVENT)
2436 recalculate load delay here ???
2437 */
2438 }
2439
2440 /*
2441 * Deallocate the object. _All_ objects should be run through here for
2442 * them to be deallocated.
2443 */
2444 void
dealloc_obj(struct obj * obj)2445 dealloc_obj(struct obj* obj)
2446 {
2447 if (obj->where != OBJ_FREE && obj->where != OBJ_LUAFREE)
2448 panic("dealloc_obj: obj not free");
2449 if (obj->nobj)
2450 panic("dealloc_obj with nobj");
2451 if (obj->cobj)
2452 panic("dealloc_obj with cobj");
2453
2454 /* free up any timers attached to the object */
2455 if (obj->timed)
2456 obj_stop_timers(obj);
2457
2458 /*
2459 * Free up any light sources attached to the object.
2460 *
2461 * We may want to just call del_light_source() without any
2462 * checks (requires a code change there). Otherwise this
2463 * list must track all objects that can have a light source
2464 * attached to it (and also requires lamplit to be set).
2465 */
2466 if (obj_sheds_light(obj)) {
2467 del_light_source(LS_OBJECT, obj_to_any(obj));
2468 obj->lamplit = 0;
2469 }
2470
2471 if (obj == g.thrownobj)
2472 g.thrownobj = 0;
2473 if (obj == g.kickedobj)
2474 g.kickedobj = 0;
2475
2476 if (obj->oextra)
2477 dealloc_oextra(obj);
2478 if (obj->lua_ref_cnt) {
2479 /* obj is referenced from a lua script, let lua gc free it */
2480 obj->where = OBJ_LUAFREE;
2481 return;
2482 }
2483 free((genericptr_t) obj);
2484 }
2485
2486 /* create an object from a horn of plenty; mirrors bagotricks(makemon.c) */
2487 int
hornoplenty(struct obj * horn,boolean tipping)2488 hornoplenty(
2489 struct obj* horn,
2490 boolean tipping) /* caller emptying entire contents; affects shop handling */
2491 {
2492 int objcount = 0;
2493
2494 if (!horn || horn->otyp != HORN_OF_PLENTY) {
2495 impossible("bad horn o' plenty");
2496 } else if (horn->spe < 1) {
2497 pline1(nothing_happens);
2498 } else {
2499 struct obj *obj;
2500 const char *what;
2501
2502 consume_obj_charge(horn, !tipping);
2503 if (!rn2(13)) {
2504 obj = mkobj(POTION_CLASS, FALSE);
2505 if (objects[obj->otyp].oc_magic)
2506 do {
2507 obj->otyp = rnd_class(POT_BOOZE, POT_WATER);
2508 } while (obj->otyp == POT_SICKNESS);
2509 what = (obj->quan > 1L) ? "Some potions" : "A potion";
2510 } else {
2511 obj = mkobj(FOOD_CLASS, FALSE);
2512 if (obj->otyp == FOOD_RATION && !rn2(7))
2513 obj->otyp = LUMP_OF_ROYAL_JELLY;
2514 what = "Some food";
2515 }
2516 ++objcount;
2517 pline("%s %s out.", what, vtense(what, "spill"));
2518 obj->blessed = horn->blessed;
2519 obj->cursed = horn->cursed;
2520 obj->owt = weight(obj);
2521 /* using a shop's horn of plenty entails a usage fee and also
2522 confers ownership of the created item to the shopkeeper */
2523 if (horn->unpaid)
2524 addtobill(obj, FALSE, FALSE, tipping);
2525 /* if it ended up on bill, we don't want "(unpaid, N zorkids)"
2526 being included in its formatted name during next message */
2527 iflags.suppress_price++;
2528 if (!tipping) {
2529 obj = hold_another_object(obj,
2530 u.uswallow
2531 ? "Oops! %s out of your reach!"
2532 : (Is_airlevel(&u.uz)
2533 || Is_waterlevel(&u.uz)
2534 || levl[u.ux][u.uy].typ < IRONBARS
2535 || levl[u.ux][u.uy].typ >= ICE)
2536 ? "Oops! %s away from you!"
2537 : "Oops! %s to the floor!",
2538 The(aobjnam(obj, "slip")), (char *) 0);
2539 nhUse(obj);
2540 } else {
2541 /* assumes this is taking place at hero's location */
2542 if (!can_reach_floor(TRUE)) {
2543 hitfloor(obj, TRUE); /* does altar check, message, drop */
2544 } else {
2545 if (IS_ALTAR(levl[u.ux][u.uy].typ))
2546 doaltarobj(obj); /* does its own drop message */
2547 else
2548 pline("%s %s to the %s.", Doname2(obj),
2549 otense(obj, "drop"), surface(u.ux, u.uy));
2550 dropy(obj);
2551 }
2552 }
2553 iflags.suppress_price--;
2554 if (horn->dknown)
2555 makeknown(HORN_OF_PLENTY);
2556 }
2557 return objcount;
2558 }
2559
2560 /* support for wizard-mode's `sanity_check' option */
2561
2562 static const char NEARDATA /* pline formats for insane_object() */
2563 ofmt0[] = "%s obj %s %s: %s",
2564 ofmt3[] = "%s [not null] %s %s: %s",
2565 /* " held by mon %p (%s)" will be appended, filled by M,mon_nam(M) */
2566 mfmt1[] = "%s obj %s %s (%s)",
2567 mfmt2[] = "%s obj %s %s (%s) *not*";
2568
2569 /* Check all object lists for consistency. */
2570 void
obj_sanity_check(void)2571 obj_sanity_check(void)
2572 {
2573 int x, y;
2574 struct obj *obj;
2575
2576 /*
2577 * TODO:
2578 * Should check whether the obj->bypass and/or obj->nomerge bits
2579 * are set. Those are both used for temporary purposes and should
2580 * be clear between moves.
2581 */
2582
2583 objlist_sanity(fobj, OBJ_FLOOR, "floor sanity");
2584
2585 /* check that the map's record of floor objects is consistent;
2586 those objects should have already been sanity checked via
2587 the floor list so container contents are skipped here */
2588 for (x = 0; x < COLNO; x++)
2589 for (y = 0; y < ROWNO; y++)
2590 for (obj = g.level.objects[x][y]; obj; obj = obj->nexthere) {
2591 /* <ox,oy> should match <x,y>; <0,*> should always be empty */
2592 if (obj->where != OBJ_FLOOR || x == 0
2593 || obj->ox != x || obj->oy != y) {
2594 char at_fmt[BUFSZ];
2595
2596 Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>",
2597 x, y, obj->ox, obj->oy);
2598 insane_object(obj, at_fmt, "location sanity",
2599 (struct monst *) 0);
2600 }
2601 }
2602
2603 objlist_sanity(g.invent, OBJ_INVENT, "invent sanity");
2604 objlist_sanity(g.migrating_objs, OBJ_MIGRATING, "migrating sanity");
2605 objlist_sanity(g.level.buriedobjlist, OBJ_BURIED, "buried sanity");
2606 objlist_sanity(g.billobjs, OBJ_ONBILL, "bill sanity");
2607
2608 mon_obj_sanity(fmon, "minvent sanity");
2609 mon_obj_sanity(g.migrating_mons, "migrating minvent sanity");
2610 /* monsters temporarily in transit;
2611 they should have arrived with hero by the time we get called */
2612 if (g.mydogs) {
2613 impossible("g.mydogs sanity [not empty]");
2614 mon_obj_sanity(g.mydogs, "mydogs minvent sanity");
2615 }
2616
2617 /* objects temporarily freed from invent/floor lists;
2618 they should have arrived somewhere by the time we get called */
2619 if (g.thrownobj)
2620 insane_object(g.thrownobj, ofmt3, "g.thrownobj sanity",
2621 (struct monst *) 0);
2622 if (g.kickedobj)
2623 insane_object(g.kickedobj, ofmt3, "g.kickedobj sanity",
2624 (struct monst *) 0);
2625 /* g.current_wand isn't removed from invent while in use, but should
2626 be Null between moves when we're called */
2627 if (g.current_wand)
2628 insane_object(g.current_wand, ofmt3, "g.current_wand sanity",
2629 (struct monst *) 0);
2630 }
2631
2632 /* sanity check for objects on specified list (fobj, &c) */
2633 static void
objlist_sanity(struct obj * objlist,int wheretype,const char * mesg)2634 objlist_sanity(struct obj* objlist, int wheretype, const char * mesg)
2635 {
2636 struct obj *obj;
2637
2638 for (obj = objlist; obj; obj = obj->nobj) {
2639 if (obj->where != wheretype)
2640 insane_object(obj, ofmt0, mesg, (struct monst *) 0);
2641 if (Has_contents(obj)) {
2642 if (wheretype == OBJ_ONBILL)
2643 /* containers on shop bill should always be empty */
2644 insane_object(obj, "%s obj contains something! %s %s: %s",
2645 mesg, (struct monst *) 0);
2646 check_contained(obj, mesg);
2647 }
2648 if (obj->owornmask) {
2649 char maskbuf[40];
2650 boolean bc_ok = FALSE;
2651
2652 switch (obj->where) {
2653 case OBJ_INVENT:
2654 case OBJ_MINVENT:
2655 sanity_check_worn(obj);
2656 break;
2657 case OBJ_MIGRATING:
2658 /* migrating objects overload the owornmask field
2659 with a destination code; skip attempt to check it */
2660 break;
2661 case OBJ_FLOOR:
2662 /* note: ball and chain can also be OBJ_FREE, but not across
2663 turns so this sanity check shouldn't encounter that */
2664 bc_ok = TRUE;
2665 /*FALLTHRU*/
2666 default:
2667 if ((obj != uchain && obj != uball) || !bc_ok) {
2668 /* discovered an object not in inventory which
2669 erroneously has worn mask set */
2670 Sprintf(maskbuf, "worn mask 0x%08lx", obj->owornmask);
2671 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2672 }
2673 break;
2674 }
2675 if (obj->globby)
2676 check_glob(obj, mesg);
2677 }
2678 }
2679 }
2680
2681 /* sanity check for objects carried by all monsters in specified list */
2682 static void
mon_obj_sanity(struct monst * monlist,const char * mesg)2683 mon_obj_sanity(struct monst* monlist, const char* mesg)
2684 {
2685 struct monst *mon;
2686 struct obj *obj, *mwep;
2687
2688 for (mon = monlist; mon; mon = mon->nmon) {
2689 if (DEADMONSTER(mon))
2690 continue;
2691 mwep = MON_WEP(mon);
2692 if (mwep) {
2693 if (!mcarried(mwep))
2694 insane_object(mwep, mfmt1, mesg, mon);
2695 if (mwep->ocarry != mon)
2696 insane_object(mwep, mfmt2, mesg, mon);
2697 }
2698 for (obj = mon->minvent; obj; obj = obj->nobj) {
2699 if (obj->where != OBJ_MINVENT)
2700 insane_object(obj, mfmt1, mesg, mon);
2701 if (obj->ocarry != mon)
2702 insane_object(obj, mfmt2, mesg, mon);
2703 if (obj->globby)
2704 check_glob(obj, mesg);
2705 check_contained(obj, mesg);
2706 }
2707 }
2708 }
2709
2710 /* This must stay consistent with the defines in obj.h. */
2711 static const char *obj_state_names[NOBJ_STATES] = { "free", "floor",
2712 "contained", "invent",
2713 "minvent", "migrating",
2714 "buried", "onbill",
2715 "luafree" };
2716
2717 static const char *
where_name(struct obj * obj)2718 where_name(struct obj* obj)
2719 {
2720 static char unknown[32]; /* big enough to handle rogue 64-bit int */
2721 int where;
2722
2723 if (!obj)
2724 return "nowhere";
2725 where = obj->where;
2726 if (where < 0 || where >= NOBJ_STATES || !obj_state_names[where]) {
2727 Sprintf(unknown, "unknown[%d]", where);
2728 return unknown;
2729 }
2730 return obj_state_names[where];
2731 }
2732
2733 static void
insane_object(struct obj * obj,const char * fmt,const char * mesg,struct monst * mon)2734 insane_object(
2735 struct obj* obj,
2736 const char* fmt,
2737 const char* mesg,
2738 struct monst* mon)
2739 {
2740 const char *objnm, *monnm;
2741 char altfmt[BUFSZ];
2742
2743 objnm = monnm = "null!";
2744 if (obj) {
2745 iflags.override_ID++;
2746 objnm = doname(obj);
2747 iflags.override_ID--;
2748 }
2749 if (mon || (strstri(mesg, "minvent") && !strstri(mesg, "contained"))) {
2750 Strcat(strcpy(altfmt, fmt), " held by mon %s (%s)");
2751 if (mon)
2752 monnm = x_monnam(mon, ARTICLE_A, (char *) 0, EXACT_NAME, TRUE);
2753 impossible(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
2754 objnm, fmt_ptr((genericptr_t) mon), monnm);
2755 } else {
2756 impossible(fmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
2757 objnm);
2758 }
2759 }
2760
2761 /*
2762 * Initialize a dummy obj with just enough info
2763 * to allow some of the tests in obj.h that
2764 * take an obj pointer to work.
2765 */
2766 struct obj *
init_dummyobj(struct obj * obj,short otyp,long oquan)2767 init_dummyobj(struct obj* obj, short otyp, long oquan)
2768 {
2769 if (obj) {
2770 *obj = cg.zeroobj;
2771 obj->otyp = otyp;
2772 obj->oclass = objects[otyp].oc_class;
2773 /* obj->dknown = 0; */
2774 /* suppress known except for amulets (needed for fakes & real AoY) */
2775 obj->known = (obj->oclass == AMULET_CLASS)
2776 ? obj->known
2777 /* default is "on" for types which don't use it */
2778 : !objects[otyp].oc_uses_known;
2779 obj->quan = oquan ? oquan : 1L;
2780 obj->corpsenm = NON_PM; /* suppress statue and figurine details */
2781 /* but suppressing fruit details leads to "bad fruit #0" */
2782 if (obj->otyp == SLIME_MOLD)
2783 obj->spe = g.context.current_fruit;
2784 }
2785 return obj;
2786 }
2787
2788 /* obj sanity check: check objects inside container */
2789 static void
check_contained(struct obj * container,const char * mesg)2790 check_contained(struct obj* container, const char *mesg)
2791 {
2792 struct obj *obj;
2793 /* big enough to work with, not too big to blow out stack in recursion */
2794 char mesgbuf[40], nestedmesg[120];
2795
2796 if (!Has_contents(container))
2797 return;
2798 /* change "invent sanity" to "contained invent sanity"
2799 but leave "nested contained invent sanity" as is */
2800 if (!strstri(mesg, "contained"))
2801 mesg = strcat(strcpy(mesgbuf, "contained "), mesg);
2802
2803 for (obj = container->cobj; obj; obj = obj->nobj) {
2804 /* catch direct cycle to avoid unbounded recursion */
2805 if (obj == container)
2806 panic("failed sanity check: container holds itself");
2807 if (obj->where != OBJ_CONTAINED)
2808 insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *) 0);
2809 else if (obj->ocontainer != container)
2810 impossible("%s obj %s in container %s, not %s", mesg,
2811 fmt_ptr((genericptr_t) obj),
2812 fmt_ptr((genericptr_t) obj->ocontainer),
2813 fmt_ptr((genericptr_t) container));
2814 if (obj->globby)
2815 check_glob(obj, mesg);
2816
2817 if (Has_contents(obj)) {
2818 /* catch most likely indirect cycle; we won't notice if
2819 parent is present when something comes before it, or
2820 notice more deeply embedded cycles (grandparent, &c) */
2821 if (obj->cobj == container)
2822 panic("failed sanity check: container holds its parent");
2823 /* change "contained... sanity" to "nested contained... sanity"
2824 and "nested contained..." to "nested nested contained..." */
2825 Strcpy(nestedmesg, "nested ");
2826 copynchars(eos(nestedmesg), mesg, (int) sizeof nestedmesg
2827 - (int) strlen(nestedmesg) - 1);
2828 /* recursively check contents */
2829 check_contained(obj, nestedmesg);
2830 }
2831 }
2832 }
2833
2834 /* called when 'obj->globby' is set so we don't recheck it here */
2835 static void
check_glob(struct obj * obj,const char * mesg)2836 check_glob(struct obj* obj, const char *mesg)
2837 {
2838 #define LOWEST_GLOB GLOB_OF_GRAY_OOZE
2839 #define HIGHEST_GLOB GLOB_OF_BLACK_PUDDING
2840 if (obj->quan != 1L || obj->owt == 0
2841 || obj->otyp < LOWEST_GLOB || obj->otyp > HIGHEST_GLOB
2842 /* a partially eaten glob could have any non-zero weight but an
2843 intact one should weigh an exact multiple of base weight (20) */
2844 || ((obj->owt % objects[obj->otyp].oc_weight) != 0 && !obj->oeaten)) {
2845 char mesgbuf[BUFSZ], globbuf[QBUFSZ];
2846
2847 Sprintf(globbuf, " glob %d,quan=%ld,owt=%u ",
2848 obj->otyp, obj->quan, obj->owt);
2849 mesg = strsubst(strcpy(mesgbuf, mesg), " obj ", globbuf);
2850 insane_object(obj, ofmt0, mesg,
2851 (obj->where == OBJ_MINVENT) ? obj->ocarry : 0);
2852 }
2853 }
2854
2855 /* check an object in hero's or monster's inventory which has worn mask set */
2856 static void
sanity_check_worn(struct obj * obj)2857 sanity_check_worn(struct obj* obj)
2858 {
2859 #if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG)
2860 static unsigned long wearbits[] = {
2861 W_ARM, W_ARMC, W_ARMH, W_ARMS, W_ARMG, W_ARMF, W_ARMU,
2862 W_WEP, W_QUIVER, W_SWAPWEP, W_AMUL, W_RINGL, W_RINGR, W_TOOL,
2863 W_SADDLE, W_BALL, W_CHAIN, 0
2864 /* [W_ART,W_ARTI are property bits for items which aren't worn] */
2865 };
2866 char maskbuf[60];
2867 const char *what;
2868 unsigned long owornmask, allmask = 0L;
2869 boolean embedded = FALSE;
2870 int i, n = 0;
2871
2872 /* use owornmask for testing and bit twiddling, but use original
2873 obj->owornmask for printing */
2874 owornmask = obj->owornmask;
2875 /* figure out how many bits are set, and also which are viable */
2876 for (i = 0; wearbits[i]; ++i) {
2877 if ((owornmask & wearbits[i]) != 0L)
2878 ++n;
2879 allmask |= wearbits[i];
2880 }
2881 if (obj == uskin) {
2882 /* embedded dragon scales have an extra bit set;
2883 make sure it's set, then suppress it */
2884 embedded = TRUE;
2885 if ((owornmask & (W_ARM | I_SPECIAL)) == (W_ARM | I_SPECIAL))
2886 owornmask &= ~I_SPECIAL;
2887 else
2888 n = 0, owornmask = ~0; /* force insane_object("bogus") below */
2889 }
2890 if (n == 2 && carried(obj)
2891 && obj == uball && (owornmask & W_BALL) != 0L
2892 && (owornmask & W_WEAPONS) != 0L) {
2893 /* chained ball can be wielded/alt-wielded/quivered; if so,
2894 pretend it's not chained in order to check the weapon pointer
2895 (we've already verified the ball pointer by successfully passing
2896 the if-condition to get here...) */
2897 owornmask &= ~W_BALL;
2898 n = 1;
2899 }
2900 if (n > 1) {
2901 /* multiple bits set */
2902 Sprintf(maskbuf, "worn mask (multiple) 0x%08lx", obj->owornmask);
2903 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2904 }
2905 if ((owornmask & ~allmask) != 0L
2906 || (carried(obj) && (owornmask & W_SADDLE) != 0L)) {
2907 /* non-wearable bit(s) set */
2908 Sprintf(maskbuf, "worn mask (bogus)) 0x%08lx", obj->owornmask);
2909 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2910 }
2911 if (n == 1 && (carried(obj) || (owornmask & (W_BALL | W_CHAIN)) != 0L)) {
2912 what = 0;
2913 /* verify that obj in hero's invent (or ball/chain elsewhere)
2914 with owornmask of W_foo is the object pointed to by ufoo */
2915 switch (owornmask) {
2916 case W_ARM:
2917 if (obj != (embedded ? uskin : uarm))
2918 what = embedded ? "skin" : "suit";
2919 break;
2920 case W_ARMC:
2921 if (obj != (embedded ? uskin : uarmc))
2922 what = embedded ? "skin" : "cloak";
2923 break;
2924 case W_ARMH:
2925 if (obj != uarmh)
2926 what = "helm";
2927 break;
2928 case W_ARMS:
2929 if (obj != uarms)
2930 what = "shield";
2931 break;
2932 case W_ARMG:
2933 if (obj != uarmg)
2934 what = "gloves";
2935 break;
2936 case W_ARMF:
2937 if (obj != uarmf)
2938 what = "boots";
2939 break;
2940 case W_ARMU:
2941 if (obj != uarmu)
2942 what = "shirt";
2943 break;
2944 case W_WEP:
2945 if (obj != uwep)
2946 what = "primary weapon";
2947 break;
2948 case W_QUIVER:
2949 if (obj != uquiver)
2950 what = "quiver";
2951 break;
2952 case W_SWAPWEP:
2953 if (obj != uswapwep)
2954 what = u.twoweap ? "secondary weapon" : "alternate weapon";
2955 break;
2956 case W_AMUL:
2957 if (obj != uamul)
2958 what = "amulet";
2959 break;
2960 case W_RINGL:
2961 if (obj != uleft)
2962 what = "left ring";
2963 break;
2964 case W_RINGR:
2965 if (obj != uright)
2966 what = "right ring";
2967 break;
2968 case W_TOOL:
2969 if (obj != ublindf)
2970 what = "blindfold";
2971 break;
2972 /* case W_SADDLE: */
2973 case W_BALL:
2974 if (obj != uball)
2975 what = "ball";
2976 break;
2977 case W_CHAIN:
2978 if (obj != uchain)
2979 what = "chain";
2980 break;
2981 default:
2982 break;
2983 }
2984 if (what) {
2985 Sprintf(maskbuf, "worn mask 0x%08lx != %s", obj->owornmask, what);
2986 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2987 }
2988 }
2989 if (n == 1 && (carried(obj) || (owornmask & (W_BALL | W_CHAIN)) != 0L
2990 || mcarried(obj))) {
2991 /* check for items worn in invalid slots; practically anything can
2992 be wielded/alt-wielded/quivered, so tests on those are limited */
2993 what = 0;
2994 if (owornmask & W_ARMOR) {
2995 if (obj->oclass != ARMOR_CLASS)
2996 what = "armor";
2997 if (embedded && !Is_dragon_armor(obj))
2998 what = "skin";
2999 } else if (owornmask & W_WEAPONS) {
3000 /* monsters don't maintain alternate weapon or quiver */
3001 if (mcarried(obj) && (owornmask & (W_SWAPWEP | W_QUIVER)) != 0L)
3002 what = (owornmask & W_SWAPWEP) != 0L ? "monst alt weapon?"
3003 : "monst quiver?";
3004 /* hero can quiver gold but not wield it (hence not alt-wield
3005 it either); also catches monster wielding gold */
3006 else if (obj->oclass == COIN_CLASS
3007 && (owornmask & (W_WEP | W_SWAPWEP)) != 0L)
3008 what = (owornmask & W_WEP) != 0L ? "weapon" : "alt weapon";
3009 } else if (owornmask & W_AMUL) {
3010 if (obj->oclass != AMULET_CLASS)
3011 what = "amulet";
3012 } else if (owornmask & W_RING) {
3013 if (obj->oclass != RING_CLASS && obj->otyp != MEAT_RING)
3014 what = "ring";
3015 } else if (owornmask & W_TOOL) {
3016 if (obj->otyp != BLINDFOLD && obj->otyp != TOWEL
3017 && obj->otyp != LENSES)
3018 what = "blindfold";
3019 } else if (owornmask & W_BALL) {
3020 if (obj->oclass != BALL_CLASS)
3021 what = "chained ball";
3022 } else if (owornmask & W_CHAIN) {
3023 if (obj->oclass != CHAIN_CLASS)
3024 what = "chain";
3025 } else if (owornmask & W_SADDLE) {
3026 if (obj->otyp != SADDLE)
3027 what = "saddle";
3028 }
3029 if (what) {
3030 char oclassname[30];
3031 struct monst *mon = mcarried(obj) ? obj->ocarry : 0;
3032
3033 /* if we've found a potion worn in the amulet slot,
3034 this yields "worn (potion amulet)" */
3035 Strcpy(oclassname, def_oc_syms[(uchar) obj->oclass].name);
3036 Sprintf(maskbuf, "worn (%s %s)", makesingular(oclassname), what);
3037 insane_object(obj, ofmt0, maskbuf, mon);
3038 }
3039 }
3040 #else /* not (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || DEBUG) */
3041 /* dummy use of obj to avoid "arg not used" complaint */
3042 if (!obj)
3043 insane_object(obj, ofmt0, "<null>", (struct monst *) 0);
3044 #endif
3045 }
3046
3047 /*
3048 * wrapper to make "near this object" convenient
3049 */
3050 struct obj *
obj_nexto(struct obj * otmp)3051 obj_nexto(struct obj* otmp)
3052 {
3053 if (!otmp) {
3054 impossible("obj_nexto: wasn't given an object to check");
3055 return (struct obj *) 0;
3056 }
3057 return obj_nexto_xy(otmp, otmp->ox, otmp->oy, TRUE);
3058 }
3059
3060 /*
3061 * looks for objects of a particular type next to x, y
3062 * skips over oid if found (lets us avoid ourselves if
3063 * we're looking for a second type of an existing object)
3064 *
3065 * TODO: return a list of all objects near us so we can more
3066 * reliably predict which one we want to 'find' first
3067 */
3068 struct obj *
obj_nexto_xy(struct obj * obj,int x,int y,boolean recurs)3069 obj_nexto_xy(struct obj* obj, int x, int y, boolean recurs)
3070 {
3071 struct obj *otmp;
3072 int fx, fy, ex, ey, otyp = obj->otyp;
3073 short dx, dy;
3074
3075 /* check under our "feet" first */
3076 otmp = sobj_at(otyp, x, y);
3077 while (otmp) {
3078 /* don't be clever and find ourselves */
3079 if (otmp != obj && mergable(otmp, obj))
3080 return otmp;
3081 otmp = nxtobj(otmp, otyp, TRUE);
3082 }
3083
3084 if (!recurs)
3085 return (struct obj *) 0;
3086
3087 /* search in a random order */
3088 dx = (rn2(2) ? -1 : 1);
3089 dy = (rn2(2) ? -1 : 1);
3090 ex = x - dx;
3091 ey = y - dy;
3092
3093 for (fx = ex; abs(fx - ex) < 3; fx += dx) {
3094 for (fy = ey; abs(fy - ey) < 3; fy += dy) {
3095 /* 0, 0 was checked above */
3096 if (isok(fx, fy) && (fx != x || fy != y)) {
3097 if ((otmp = obj_nexto_xy(obj, fx, fy, FALSE)) != 0)
3098 return otmp;
3099 }
3100 }
3101 }
3102 return (struct obj *) 0;
3103 }
3104
3105 /*
3106 * Causes one object to absorb another, increasing
3107 * weight accordingly. Frees obj2; obj1 remains and
3108 * is returned.
3109 */
3110 struct obj *
obj_absorb(struct obj ** obj1,struct obj ** obj2)3111 obj_absorb(struct obj** obj1, struct obj** obj2)
3112 {
3113 struct obj *otmp1, *otmp2;
3114 int o1wt, o2wt;
3115 long agetmp;
3116
3117 /* don't let people dumb it up */
3118 if (obj1 && obj2) {
3119 otmp1 = *obj1;
3120 otmp2 = *obj2;
3121 if (otmp1 && otmp2 && otmp1 != otmp2) {
3122 globby_bill_fixup(otmp1, otmp2);
3123 if (otmp1->bknown != otmp2->bknown)
3124 otmp1->bknown = otmp2->bknown = 0;
3125 if (otmp1->rknown != otmp2->rknown)
3126 otmp1->rknown = otmp2->rknown = 0;
3127 if (otmp1->greased != otmp2->greased)
3128 otmp1->greased = otmp2->greased = 0;
3129 if (otmp1->orotten || otmp2->orotten)
3130 otmp1->orotten = otmp2->orotten = 1;
3131 o1wt = otmp1->oeaten ? otmp1->oeaten : otmp1->owt;
3132 o2wt = otmp2->oeaten ? otmp2->oeaten : otmp2->owt;
3133 /* averaging the relative ages is less likely to overflow
3134 than averaging the absolute ages directly */
3135 agetmp = (((g.moves - otmp1->age) * o1wt
3136 + (g.moves - otmp2->age) * o2wt)
3137 / (o1wt + o2wt));
3138 otmp1->age = g.moves - agetmp; /* conv. relative back to absolute */
3139 otmp1->owt += o2wt;
3140 if (otmp1->oeaten || otmp2->oeaten)
3141 otmp1->oeaten = o1wt + o2wt;
3142 otmp1->quan = 1L;
3143 obj_extract_self(otmp2);
3144 dealloc_obj(otmp2);
3145 *obj2 = (struct obj *) 0;
3146 return otmp1;
3147 }
3148 }
3149
3150 impossible("obj_absorb: not called with two actual objects");
3151 return (struct obj *) 0;
3152 }
3153
3154 /*
3155 * Causes the heavier object to absorb the lighter object in
3156 * most cases, but if one object is OBJ_FREE and the other is
3157 * on the floor, the floor object goes first.
3158 *
3159 * wrapper for obj_absorb so that floor_effects works more
3160 * cleanly (since we don't know which we want to stay around)
3161 */
3162 struct obj *
obj_meld(struct obj ** obj1,struct obj ** obj2)3163 obj_meld(struct obj** obj1, struct obj** obj2)
3164 {
3165 struct obj *otmp1, *otmp2, *result = 0;
3166 int ox, oy;
3167
3168 if (obj1 && obj2) {
3169 otmp1 = *obj1;
3170 otmp2 = *obj2;
3171 if (otmp1 && otmp2 && otmp1 != otmp2) {
3172 ox = oy = 0;
3173 /*
3174 * FIXME?
3175 * If one of the objects is free because it's being dropped,
3176 * we should really finish a full drop and then absorb/meld
3177 * if it survives the flooreffects(). Then lighter-melds-into-
3178 * heavier will be true even when heavier is the one dropped.
3179 *
3180 * [Also, what about when one of the globs is on the shore
3181 * and we drop the other into adjacent pool or vice versa?]
3182 */
3183 if (!(otmp2->where == OBJ_FLOOR && otmp1->where == OBJ_FREE)
3184 && (otmp1->owt > otmp2->owt
3185 || (otmp1->owt == otmp2->owt && rn2(2)))) {
3186 if (otmp2->where == OBJ_FLOOR)
3187 ox = otmp2->ox, oy = otmp2->oy;
3188 result = obj_absorb(obj1, obj2);
3189 } else {
3190 if (otmp1->where == OBJ_FLOOR)
3191 ox = otmp1->ox, oy = otmp1->oy;
3192 result = obj_absorb(obj2, obj1);
3193 }
3194 /* callers really ought to take care of this; glob melding is
3195 a bookkeeping issue rather than a display one */
3196 if (ox && cansee(ox, oy))
3197 newsym(ox, oy);
3198 }
3199 } else {
3200 impossible("obj_meld: not called with two actual objects");
3201 }
3202 return result;
3203 }
3204
3205 /* give a message if hero notices two globs merging [used to be in pline.c] */
3206 void
pudding_merge_message(struct obj * otmp,struct obj * otmp2)3207 pudding_merge_message(struct obj* otmp, struct obj* otmp2)
3208 {
3209 boolean visible = (cansee(otmp->ox, otmp->oy)
3210 || cansee(otmp2->ox, otmp2->oy)),
3211 onfloor = (otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR),
3212 inpack = (carried(otmp) || carried(otmp2));
3213
3214 /* the player will know something happened inside his own inventory */
3215 if ((!Blind && visible) || inpack) {
3216 if (Hallucination) {
3217 if (onfloor) {
3218 You_see("parts of the floor melting!");
3219 } else if (inpack) {
3220 Your("pack reaches out and grabs something!");
3221 }
3222 /* even though we can see where they should be,
3223 * they'll be out of our view (minvent or container)
3224 * so don't actually show anything */
3225 } else if (onfloor || inpack) {
3226 boolean adj = ((otmp->ox != u.ux || otmp->oy != u.uy)
3227 && (otmp2->ox != u.ux || otmp2->oy != u.uy));
3228
3229 pline("The %s%s coalesce%s.",
3230 (onfloor && adj) ? "adjacent " : "",
3231 makeplural(obj_typename(otmp->otyp)),
3232 inpack ? " inside your pack" : "");
3233 }
3234 } else {
3235 You_hear("a faint sloshing sound.");
3236 }
3237 }
3238
3239 /* The algorithm that determines where a thiefstone will be keyed to. */
3240 void
choose_thiefstone_loc(coord * cc)3241 choose_thiefstone_loc(coord *cc)
3242 {
3243 /* Choose a suitable location on the current level.
3244 * Prefers, in this order: vaults, closets, spaces with containers on them.
3245 * Failing this, will try to find a suitable walkable space, preferring
3246 * floor to any other terrain type.
3247 * The interior of a shop is always considered unsuitable.
3248 * Trapped spaces are considered unsuitable unless no other space can be
3249 * found. */
3250
3251 /* try vault... */
3252 struct mkroom* croom = search_special(VAULT);
3253 if (croom) {
3254 somexy(croom, cc);
3255 return;
3256 }
3257 /* No vault? No luck. Scan all spaces on the level, assess each one and
3258 * give it a "quality" score for how good it would be as a possible stash
3259 * location. This is not particularly biased towards where players would
3260 * want to put stashes.
3261 * The algorithm for choosing a spot is as follows:
3262 * 1. Assess a space and get a "quality" score.
3263 * 2. If the quality of this space equals the current maximum known quality,
3264 * increment N, the number of spaces known to have this score, and select
3265 * it with probability 1/N.
3266 * 3. If the quality of this space is better than any other space, select
3267 * it and set N = 1.
3268 * The whole thing works because for any space with the current maximum
3269 * quality, assuming M such spaces exist, the chance of being selected is
3270 * 1/N * N/N+1 * N+1/N+2 * ... * M-1/M = 1/M.
3271 */
3272 int x, y;
3273 int max_quality = -1;
3274 int nmax = 0;
3275 cc->x = cc->y = -1;
3276 for (x = 1; x < COLNO; x++) {
3277 for (y = 1; y < ROWNO; y++) {
3278 int quality = 0;
3279 if (*in_rooms(x, y, SHOPBASE)) {
3280 quality -= 100;
3281 }
3282 if (levl[x][y].typ == ROOM || levl[x][y].typ == CORR ||
3283 levl[x][y].typ == SCORR) {
3284 /* other terrain might be walkable but we don't want to put it
3285 * on another feature */
3286 quality += 2;
3287 if (!t_at(x,y)) {
3288 quality += 7;
3289 }
3290 if ((levl[x][y].typ == CORR || levl[x][y].typ == SCORR)
3291 && levl[x][y].is_niche) {
3292 quality += 20;
3293 }
3294 if (container_at(x, y, FALSE)) {
3295 quality += 15;
3296 }
3297 }
3298 if (levl[x][y].typ == STAIRS) {
3299 /* Absolute last resort: even if an entire level has no
3300 * walkable terrain, there are probably stairs.
3301 */
3302 quality += 1;
3303 }
3304 /* TODO: favor non-joined rooms */
3305 /* TODO: examine surrounding spaces and give quality boost to
3306 * a space that has few walkable neighbors */
3307 if (quality > 0) {
3308 if (quality == max_quality) {
3309 nmax++;
3310 if (!rn2(nmax)) {
3311 cc->x = x;
3312 cc->y = y;
3313 }
3314 } else if (quality > max_quality) {
3315 nmax = 1;
3316 cc->x = x;
3317 cc->y = y;
3318 max_quality = quality;
3319 }
3320 }
3321 }
3322 }
3323 if (cc->x < 0 || cc->y < 0) {
3324 impossible("choose_thiefstone_loc: couldn't find a good space");
3325 cc->x = 1;
3326 cc->y = 1;
3327 }
3328 }
3329
3330 /* Set up the data associated with a thiefstone. (This involves both selecting
3331 * its keyed location and recording that location in the stone.) */
3332 static void
init_thiefstone(struct obj * stone)3333 init_thiefstone(struct obj *stone)
3334 {
3335 curse(stone); /* always generated cursed */
3336
3337 if (In_endgame(&u.uz)) {
3338 /* stones that generate in the endgame won't do anything */
3339 stone->keyed_ledger = THIEFSTONE_LEDGER_CANCELLED;
3340 return;
3341 }
3342
3343 stone->keyed_ledger = ledger_no(&u.uz);
3344 if (!thiefstone_ledger_valid(stone)) {
3345 impossible("init_thiefstone: invalid ledger number %d", stone->keyed_ledger);
3346 }
3347 coord cc;
3348 choose_thiefstone_loc(&cc);
3349 set_keyed_loc(stone, cc.x, cc.y);
3350 /* also put a chest here, but only at level creation; wishing or polypiling
3351 * thiefstones should not spontaneously create chests */
3352 if (g.in_mklev && !container_at(cc.x, cc.y, FALSE)) {
3353 mksobj_at(CHEST, cc.x, cc.y, TRUE, FALSE);
3354 }
3355 }
3356
3357 /* Object material probabilities. */
3358 /* for objects which are normally iron or metal */
3359 static const struct icp metal_materials[] = {
3360 {74, 0}, /* default to base type, iron or metal */
3361 { 5, IRON},
3362 { 5, WOOD},
3363 { 5, SILVER},
3364 { 3, COPPER},
3365 { 3, MITHRIL},
3366 { 1, GOLD},
3367 { 1, BONE},
3368 { 1, GLASS},
3369 { 1, PLATINUM},
3370 { 1, PLASTIC}
3371 };
3372
3373 /* for objects which are normally wooden */
3374 static const struct icp wood_materials[] = {
3375 {80, WOOD},
3376 {10, MINERAL},
3377 { 5, IRON},
3378 { 3, BONE},
3379 { 1, COPPER},
3380 { 0, GOLD}, /* can exist in certain special levels but not randomly
3381 * generated */
3382 { 1, SILVER}
3383 };
3384
3385 /* for objects which are normally cloth */
3386 static const struct icp cloth_materials[] = {
3387 {80, CLOTH},
3388 {10, LEATHER},
3389 { 7, PLASTIC},
3390 { 3, PAPER}
3391 };
3392
3393 /* for objects which are normally leather */
3394 static const struct icp leather_materials[] = {
3395 {76, LEATHER},
3396 {17, CLOTH},
3397 { 7, PLASTIC},
3398 };
3399
3400 /* for objects of dwarvish make */
3401 static const struct icp dwarvish_materials[] = {
3402 {85, IRON},
3403 {10, MITHRIL},
3404 { 2, COPPER},
3405 { 1, SILVER},
3406 { 1, GOLD},
3407 { 1, PLATINUM}
3408 };
3409
3410 /* for objects of orcish make - no valuables */
3411 static const struct icp crude_materials[] = {
3412 {60, 0}, /* use base */
3413 {20, IRON},
3414 { 8, BONE},
3415 { 7, WOOD},
3416 { 5, MINERAL}
3417 };
3418
3419 /* for armor-y objects of elven make - no iron!
3420 * Does not cover clothy items; those use the regular cloth probs. */
3421 static const struct icp elven_materials[] = {
3422 {60, 0}, /* use base material */
3423 {20, WOOD},
3424 {10, COPPER},
3425 { 5, MITHRIL},
3426 { 3, SILVER},
3427 { 2, GOLD}
3428 };
3429
3430 /* Reflectable items - for the shield of reflection; anything that can hold a
3431 * polish. Amulets also arbitrarily use this list. */
3432 static const struct icp shiny_materials[] = {
3433 {30, SILVER},
3434 {22, COPPER},
3435 {12, GOLD},
3436 {12, IRON}, /* stainless steel */
3437 {10, GLASS},
3438 { 7, MITHRIL},
3439 { 5, METAL}, /* aluminum, or similar */
3440 { 2, PLATINUM}
3441 };
3442
3443 /* for bells and other tools, especially instruments, which are normally copper
3444 * or metal. Wood and glass in other lists precludes us from using those. */
3445 static const struct icp resonant_materials[] = {
3446 {55, 0}, /* use base material */
3447 {25, COPPER},
3448 { 6, SILVER},
3449 { 5, IRON},
3450 { 5, MITHRIL},
3451 { 3, GOLD},
3452 { 1, PLATINUM}
3453 };
3454
3455 /* for horns, currently. */
3456 static const struct icp horn_materials[] = {
3457 {70, BONE},
3458 {10, COPPER},
3459 { 8, MITHRIL},
3460 { 5, WOOD},
3461 { 5, SILVER},
3462 { 2, GOLD}
3463 };
3464
3465 /* hacks for specific objects... not great because it's a lot of data, but it's
3466 * a relatively clean solution */
3467 static const struct icp statue_materials[] = {
3468 {95, MINERAL},
3469 { 4, COPPER},
3470 { 1, GOLD}
3471 };
3472 static const struct icp figurine_materials[] = {
3473 {45, MINERAL},
3474 {35, WOOD},
3475 {10, PLASTIC},
3476 { 5, METAL},
3477 { 4, COPPER},
3478 { 1, GOLD}
3479 };
3480 static const struct icp elvenhelm_materials[] = {
3481 {70, LEATHER},
3482 {20, COPPER},
3483 {10, WOOD}
3484 };
3485 static const struct icp bow_materials[] = {
3486 /* assumes all bows will be wood by default, fairly safe assumption */
3487 {75, WOOD},
3488 { 7, IRON},
3489 { 5, MITHRIL},
3490 { 4, COPPER},
3491 { 4, BONE},
3492 { 2, SILVER},
3493 { 2, PLASTIC},
3494 { 1, GOLD}
3495 };
3496
3497 /* Return the appropriate above list for a given object, or NULL if there isn't
3498 * an appropriate list. */
3499 const struct icp*
material_list(struct obj * obj)3500 material_list(struct obj* obj)
3501 {
3502 unsigned short otyp = obj->otyp;
3503 int default_material = objects[otyp].oc_material;
3504
3505 /* Cases for specific object types. */
3506 switch (otyp) {
3507 /* Special exceptions to the whole randomized materials system - where
3508 * we ALWAYS want an object to use its base material regardless of
3509 * other cases in this function - go here.
3510 * Return NULL so that init_obj_material and valid_obj_material both
3511 * work properly. */
3512 case BULLWHIP:
3513 case WORM_TOOTH:
3514 case CRYSKNIFE:
3515 case ELVEN_BOOTS:
3516 case LEATHER_DRUM:
3517 case DRUM_OF_EARTHQUAKE:
3518 case LAND_MINE:
3519 case TOWEL:
3520 case MUMMY_WRAPPING:
3521 case AMULET_OF_YENDOR:
3522 case FAKE_AMULET_OF_YENDOR:
3523 return NULL;
3524 /* Any other cases for specific object types go here. */
3525 case SHIELD_OF_REFLECTION:
3526 return shiny_materials;
3527 case BOW:
3528 case ELVEN_BOW:
3529 case ORCISH_BOW:
3530 case YUMI:
3531 case BOOMERANG: /* wooden base, similar shape */
3532 return bow_materials;
3533 case ELVEN_HELM:
3534 return elvenhelm_materials;
3535 case BELL:
3536 case BUGLE:
3537 case LANTERN:
3538 case OIL_LAMP:
3539 case MAGIC_LAMP:
3540 case PEA_WHISTLE:
3541 case MAGIC_WHISTLE:
3542 case FLUTE:
3543 case MAGIC_FLUTE:
3544 case HARP:
3545 case MAGIC_HARP:
3546 return resonant_materials;
3547 case TOOLED_HORN:
3548 case FIRE_HORN:
3549 case FROST_HORN:
3550 case HORN_OF_PLENTY:
3551 return horn_materials;
3552 case STATUE:
3553 if (Is_medusa_level(&u.uz) && g.in_mklev) {
3554 /* All statues generated with the Medusa level must be stone. */
3555 return NULL;
3556 }
3557 return statue_materials;
3558 case FIGURINE:
3559 return figurine_materials;
3560 default:
3561 break;
3562 }
3563
3564 /* Otherwise, select an appropriate list, or return NULL if no appropriate
3565 * list exists. */
3566 if (is_elven_obj(obj) && default_material != CLOTH) {
3567 return elven_materials;
3568 }
3569 else if (is_dwarvish_obj(obj) && default_material != CLOTH) {
3570 return dwarvish_materials;
3571 }
3572 else if (is_orcish_obj(obj) && default_material != CLOTH) {
3573 return crude_materials;
3574 }
3575 else if (obj->oclass == AMULET_CLASS) {
3576 /* could use metal_materials too */
3577 return shiny_materials;
3578 }
3579 else if (obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS
3580 || obj->oclass == TOOL_CLASS) {
3581 if (default_material == IRON || default_material == METAL) {
3582 return metal_materials;
3583 }
3584 else if (default_material == WOOD) {
3585 return wood_materials;
3586 }
3587 else if (default_material == CLOTH) {
3588 return cloth_materials;
3589 } else if (default_material == LEATHER) {
3590 return leather_materials;
3591 }
3592 }
3593 return NULL;
3594 }
3595
3596 /* Initialize the material field of an object, possibly randomizing it from the
3597 * above lists. */
3598 void
init_obj_material(struct obj * obj)3599 init_obj_material(struct obj* obj)
3600 {
3601 const struct icp* materials = material_list(obj);
3602
3603 /* always set the material to its base, this is the default for objects
3604 * which do not have a list */
3605 set_material(obj, objects[obj->otyp].oc_material);
3606
3607 if (materials) {
3608 int i = rnd(100);
3609 while (i > 0) {
3610 if (i <= materials->iprob)
3611 break;
3612 i -= materials->iprob;
3613 materials++;
3614 }
3615 /* Only set the new material if:
3616 * 1) it is not marked as invalid for this specific object
3617 * 2) iclass is non-zero (a zero indicates base material should be used)
3618 */
3619 if (!invalid_obj_material(obj, materials->iclass)
3620 && materials->iclass != 0) {
3621 set_material(obj, materials->iclass);
3622 }
3623 }
3624 }
3625
3626 /* Return TRUE iff an object-material combination is specifically *invalid*,
3627 * usually a bad or illogical material combination that is OK according to the
3628 * material lists, but shouldn't exist in practice, such as a glass digging
3629 * tool. This avoids having to create new lists for those specific items which
3630 * are basically the same as the regular list but excluding one or two
3631 * materials.
3632 * This should be treated as subsidiary to valid_obj_material. */
3633 static boolean
invalid_obj_material(struct obj * obj,uchar mat)3634 invalid_obj_material(struct obj *obj, uchar mat)
3635 {
3636 int oclass = obj->oclass;
3637
3638 /* flimsy/brittle digging tools... */
3639 if (is_pick(obj) && (mat == PLASTIC || mat == GLASS)) {
3640 return TRUE;
3641 }
3642
3643 /* paper weapons and armor... */
3644 if ((oclass == WEAPON_CLASS || oclass == ARMOR_CLASS) && mat == PAPER) {
3645 return TRUE;
3646 }
3647
3648 return FALSE;
3649 }
3650
3651 /* Return TRUE if mat is a valid material for a given object of obj's type
3652 * (whether a random object of this type could generate as that material). */
3653 boolean
valid_obj_material(struct obj * obj,uchar mat)3654 valid_obj_material(struct obj *obj, uchar mat)
3655 {
3656 if (obj->oartifact) {
3657 /* shenanigans possible here, ignore them */
3658 return TRUE;
3659 }
3660
3661 /* if it is what it's defined as in objects.c, always valid, don't bother
3662 * with lists */
3663 if (objects[obj->otyp].oc_material == mat) {
3664 return TRUE;
3665 }
3666 else {
3667 if (invalid_obj_material(obj, mat)) {
3668 return FALSE;
3669 }
3670 const struct icp* materials = material_list(obj);
3671
3672 if (materials) {
3673 int i = 100; /* guarantee going through everything */
3674 while (i > 0) {
3675 if (materials->iclass == mat)
3676 return TRUE;
3677 i -= materials->iprob;
3678 materials++;
3679 }
3680 }
3681 /* no valid materials in list, or no valid list */
3682 return FALSE;
3683 }
3684 }
3685
3686 /* Change the object's material, and any properties derived from it.
3687 * This includes weight, and erosion/erodeproofing (i.e. materials which
3688 * can't corrode will not be generated corroded or corrode-proofed).
3689 */
3690 void
set_material(struct obj * otmp,uchar material)3691 set_material(struct obj *otmp, uchar material)
3692 {
3693 if (!valid_obj_material(otmp, material)) {
3694 impossible("setting material of %s to invalid material %d",
3695 OBJ_NAME(objects[otmp->otyp]), material);
3696 }
3697 otmp->material = material;
3698 otmp->owt = weight(otmp);
3699 if ((otmp->oeroded) && !is_rustprone(otmp) && !is_flammable(otmp))
3700 otmp->oeroded = 0;
3701 if ((otmp->oeroded2) && !is_corrodeable(otmp) && !is_rottable(otmp))
3702 otmp->oeroded2 = 0;
3703 if (otmp->oerodeproof && !is_damageable(otmp) && (otmp->material != GLASS))
3704 otmp->oerodeproof = FALSE;
3705 }
3706
3707 /*mkobj.c*/
3708