1 /* NetHack 3.6 timeout.c $NHDT-Date: 1446861771 2015/11/07 02:02:51 $ $NHDT-Branch: master $:$NHDT-Revision: 1.63 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
6 #include "lev.h" /* for checking save modes */
8 STATIC_DCL void NDECL(stoned_dialogue);
9 STATIC_DCL void NDECL(vomiting_dialogue);
10 STATIC_DCL void NDECL(choke_dialogue);
11 STATIC_DCL void NDECL(slime_dialogue);
12 STATIC_DCL void NDECL(slip_or_trip);
13 STATIC_DCL void FDECL(see_lamp_flicker, (struct obj *, const char *));
14 STATIC_DCL void FDECL(lantern_message, (struct obj *));
15 STATIC_DCL void FDECL(cleanup_burn, (ANY_P *, long));
17 /* He is being petrified - dialogue by inmet!tower */
18 static NEARDATA const char *const stoned_texts[] = {
19 "You are slowing down.", /* 5 */
20 "Your limbs are stiffening.", /* 4 */
21 "Your limbs have turned to stone.", /* 3 */
22 "You have turned to stone.", /* 2 */
23 "You are a statue." /* 1 */
29 register long i = (Stoned & TIMEOUT);
31 if (i > 0L && i <= SIZE(stoned_texts)) {
34 Strcpy(buf, stoned_texts[SIZE(stoned_texts) - i]);
35 if (nolimbs(youmonst.data) && strstri(buf, "limbs"))
36 (void) strsubst(buf, "limbs", "extremities");
40 case 5: /* slowing down */
45 case 4: /* limbs stiffening */
46 /* just one move left to save oneself so quit fiddling around;
47 don't stop attempt to eat tin--might be lizard or acidic */
53 case 3: /* limbs turned to stone */
55 nomul(-3); /* can't move anymore */
56 multi_reason = "getting stoned";
57 nomovemsg = You_can_move_again; /* not unconscious */
62 exercise(A_DEX, FALSE);
65 /* He is getting sicker and sicker prior to vomiting */
66 static NEARDATA const char *const vomiting_texts[] = {
67 "are feeling mildly nauseated.", /* 14 */
68 "feel slightly confused.", /* 11 */
69 "can't seem to think straight.", /* 8 */
70 "feel incredibly sick.", /* 5 */
71 "suddenly vomit!" /* 2 */
78 long v = (Vomiting & TIMEOUT);
80 /* note: nhtimeout() hasn't decremented timed properties for the
81 current turn yet, so we use Vomiting-1 here */
82 switch ((int) (v - 1L)) {
84 txt = vomiting_texts[0];
87 txt = vomiting_texts[1];
90 make_stunned((HStun & TIMEOUT) + (long) d(2, 4), FALSE);
91 if (!Popeye(VOMITING))
95 make_confused((HConfusion & TIMEOUT) + (long) d(2, 4), FALSE);
100 txt = vomiting_texts[2];
103 txt = vomiting_texts[3];
106 txt = vomiting_texts[4];
107 if (cantvomit(youmonst.data))
108 txt = "gag uncontrolably.";
112 if (!cantvomit(youmonst.data))
121 exercise(A_CON, FALSE);
124 static NEARDATA const char *const choke_texts[] = {
125 "You find it hard to breathe.", "You're gasping for air.",
126 "You can no longer breathe.", "You're turning %s.", "You suffocate."
129 static NEARDATA const char *const choke_texts2[] = {
130 "Your %s is becoming constricted.",
131 "Your blood is having trouble reaching your brain.",
132 "The pressure on your %s increases.", "Your consciousness is fading.",
139 register long i = (Strangled & TIMEOUT);
141 if (i > 0 && i <= SIZE(choke_texts)) {
142 if (Breathless || !rn2(50))
143 pline(choke_texts2[SIZE(choke_texts2) - i], body_part(NECK));
145 const char *str = choke_texts[SIZE(choke_texts) - i];
148 pline(str, hcolor(NH_BLUE));
153 exercise(A_STR, FALSE);
156 static NEARDATA const char *const slime_texts[] = {
157 "You are turning a little %s.", /* 5 */
158 "Your limbs are getting oozy.", /* 4 */
159 "Your skin begins to peel away.", /* 3 */
160 "You are turning into %s.", /* 2 */
161 "You have become %s." /* 1 */
167 register long i = (Slimed & TIMEOUT) / 2L;
169 if (((Slimed & TIMEOUT) % 2L) && i >= 0L && i < SIZE(slime_texts)) {
172 Strcpy(buf, slime_texts[SIZE(slime_texts) - i - 1L]);
173 if (nolimbs(youmonst.data) && strstri(buf, "limbs"))
174 (void) strsubst(buf, "limbs", "extremities");
176 if (index(buf, '%')) {
177 if (i == 4L) { /* "you are turning green" */
178 if (!Blind) /* [what if you're already green?] */
179 pline(buf, hcolor(NH_GREEN));
182 an(Hallucination ? rndmonnam(NULL) : "green slime"));
186 if (i == 3L) { /* limbs becoming oozy */
187 HFast = 0L; /* lose intrinsic speed */
193 exercise(A_DEX, FALSE);
200 make_slimed(0L, "The slime that covers you is burned away!");
207 register struct prop *upp;
211 int baseluck = (flags.moonphase == FULL_MOON) ? 1 : 0;
216 if (u.uluck != baseluck
217 && moves % (u.uhave.amulet || u.ugangr ? 300 : 600) == 0) {
218 /* Cursed luckstones stop bad luck from timing out; blessed luckstones
219 * stop good luck from timing out; normal luckstones stop both;
220 * neither is stopped if you don't have a luckstone.
221 * Luck is based at 0 usually, +1 if a full moon and -1 on Friday 13th
223 register int time_luck = stone_luck(FALSE);
224 boolean nostone = !carrying(LUCKSTONE) && !stone_luck(TRUE);
226 if (u.uluck > baseluck && (nostone || time_luck < 0))
228 else if (u.uluck < baseluck && (nostone || time_luck > 0))
232 return; /* things past this point could kill you */
241 if (u.mtimedone && !--u.mtimedone) {
243 u.mtimedone = rnd(100 * youmonst.data->mlevel + 1);
250 /* Dissipate spell-based protection. */
252 if (--u.usptime == 0 && u.uspellprot) {
253 u.usptime = u.uspmtime;
257 Norep("The %s haze around you %s.", hcolor(NH_GOLDEN),
258 u.uspellprot ? "becomes less dense" : "disappears");
263 if (--u.ugallop == 0L && u.usteed)
264 pline("%s stops galloping.", Monnam(u.usteed));
267 for (upp = u.uprops; upp < u.uprops + SIZE(u.uprops); upp++)
268 if ((upp->intrinsic & TIMEOUT) && !(--upp->intrinsic & TIMEOUT)) {
269 kptr = find_delayed_killer((int) (upp - u.uprops));
270 switch (upp - u.uprops) {
272 if (kptr && kptr->name[0]) {
273 killer.format = kptr->format;
274 Strcpy(killer.name, kptr->name);
276 killer.format = NO_KILLER_PREFIX;
277 Strcpy(killer.name, "killed by petrification");
279 dealloc_killer(kptr);
280 /* (unlike sliming, you aren't changing form here) */
284 if (kptr && kptr->name[0]) {
285 killer.format = kptr->format;
286 Strcpy(killer.name, kptr->name);
288 killer.format = NO_KILLER_PREFIX;
289 Strcpy(killer.name, "turned into green slime");
291 dealloc_killer(kptr);
292 /* involuntarily break "never changed form" conduct */
293 u.uconduct.polyselfs++;
297 make_vomiting(0L, TRUE);
300 You("die from your illness.");
301 if (kptr && kptr->name[0]) {
302 killer.format = kptr->format;
303 Strcpy(killer.name, kptr->name);
305 killer.format = KILLED_BY_AN;
306 killer.name[0] = 0; /* take the default */
308 dealloc_killer(kptr);
310 if ((m_idx = name_to_mon(killer.name)) >= LOW_PM) {
311 if (type_is_pname(&mons[m_idx])) {
312 killer.format = KILLED_BY;
313 } else if (mons[m_idx].geno & G_UNIQ) {
314 Strcpy(killer.name, the(killer.name));
315 killer.format = KILLED_BY;
323 You_feel("yourself slowing down%s.",
324 Fast ? " a bit" : "");
327 /* So make_confused works properly */
328 set_itimeout(&HConfusion, 1L);
329 make_confused(0L, TRUE);
334 set_itimeout(&HStun, 1L);
335 make_stunned(0L, TRUE);
340 set_itimeout(&Blinded, 1L);
341 make_blinded(0L, TRUE);
346 set_itimeout(&HDeaf, 1L);
353 if (!Invis && !BInvis && !Blind) {
355 ? "are no longer invisible."
356 : "can no longer see through yourself.");
361 set_mimic_blocking(); /* do special mimic handling */
362 see_monsters(); /* make invis mons appear */
363 newsym(u.ux, u.uy); /* make self appear */
371 set_itimeout(&HHallucination, 1L);
372 (void) make_hallucinated(0L, TRUE, 0L);
377 if (unconscious() || Sleep_resistance) {
378 incr_itimeout(&HSleepy, rnd(100));
382 fall_asleep(-sleeptime, TRUE);
383 incr_itimeout(&HSleepy, sleeptime + rnd(100));
387 (void) float_down(I_SPECIAL | TIMEOUT, 0L);
390 killer.format = KILLED_BY;
392 (u.uburied) ? "suffocation" : "strangulation");
394 /* must be declining to die in explore|wizard mode;
395 treat like being cured of strangulation by prayer */
396 if (uamul && uamul->otyp == AMULET_OF_STRANGULATION) {
397 Your("amulet vanishes!");
402 /* call this only when a move took place. */
403 /* otherwise handle fumbling msgs locally. */
404 if (u.umoved && !Levitation) {
407 multi_reason = "fumbling";
409 /* The more you are carrying the more likely you
410 * are to make noise when you fumble. Adjustments
411 * to this number must be thoroughly play tested.
413 if ((inv_weight() > -500)) {
414 You("make a lot of noise!");
418 /* from outside means slippery ice; don't reset
419 counter if that's the only fumble reason */
420 HFumbling &= ~FROMOUTSIDE;
422 incr_itimeout(&HFumbling, rnd(20));
424 case DETECT_MONSTERS:
434 fall_asleep(how_long, wakeup_msg)
440 multi_reason = "sleeping";
441 /* generally don't notice sounds while sleeping */
442 if (wakeup_msg && multi == how_long) {
443 /* caller can follow with a direct call to Hear_again() if
444 there's a need to override this when wakeup_msg is true */
445 incr_itimeout(&HDeaf, how_long);
446 afternmv = Hear_again; /* this won't give any messages */
448 /* early wakeup from combat won't be possible until next monster turn */
449 u.usleep = monstermoves;
450 nomovemsg = wakeup_msg ? "You wake up." : You_can_move_again;
453 /* Attach an egg hatch timeout to the given egg.
454 * when = Time to hatch, usually only passed if re-creating an
455 * existing hatch timer. Pass 0L for random hatch time.
458 attach_egg_hatch_timeout(egg, when)
464 /* stop previous timer, if any */
465 (void) stop_timer(HATCH_EGG, obj_to_any(egg));
468 * Decide if and when to hatch the egg. The old hatch_it() code tried
469 * once a turn from age 151 to 200 (inclusive), hatching if it rolled
470 * a number x, 1<=x<=age, where x>150. This yields a chance of
471 * hatching > 99.9993%. Mimic that here.
474 for (i = (MAX_EGG_HATCH_TIME - 50) + 1; i <= MAX_EGG_HATCH_TIME; i++)
482 (void) start_timer(when, TIMER_OBJECT, HATCH_EGG, obj_to_any(egg));
486 /* prevent an egg from ever hatching */
491 /* stop previous timer, if any */
492 (void) stop_timer(HATCH_EGG, obj_to_any(egg));
495 /* timer callback routine: hatch the given egg */
497 hatch_egg(arg, timeout)
502 struct monst *mon, *mon2;
505 boolean yours, silent, knows_egg = FALSE;
506 boolean cansee_hatchspot = FALSE;
507 int i, mnum, hatchcount = 0;
510 /* sterilized while waiting */
511 if (egg->corpsenm == NON_PM)
514 mon = mon2 = (struct monst *) 0;
515 mnum = big_to_little(egg->corpsenm);
516 /* The identity of one's father is learned, not innate */
517 yours = (egg->spe || (!flags.female && carried(egg) && !rn2(2)));
518 silent = (timeout != monstermoves); /* hatched while away */
520 /* only can hatch when in INVENT, FLOOR, MINVENT */
521 if (get_obj_location(egg, &x, &y, 0)) {
522 hatchcount = rnd((int) egg->quan);
523 cansee_hatchspot = cansee(x, y) && !silent;
524 if (!(mons[mnum].geno & G_UNIQ)
525 && !(mvitals[mnum].mvflags & (G_GENOD | G_EXTINCT))) {
526 for (i = hatchcount; i > 0; i--) {
527 if (!enexto(&cc, x, y, &mons[mnum])
528 || !(mon = makemon(&mons[mnum], cc.x, cc.y, NO_MINVENT)))
530 /* tame if your own egg hatches while you're on the
531 same dungeon level, or any dragon egg which hatches
532 while it's in your inventory */
533 if ((yours && !silent)
534 || (carried(egg) && mon->data->mlet == S_DRAGON)) {
535 if (tamedog(mon, (struct obj *) 0)) {
536 if (carried(egg) && mon->data->mlet != S_DRAGON)
540 if (mvitals[mnum].mvflags & G_EXTINCT)
541 break; /* just made last one */
542 mon2 = mon; /* in case makemon() fails on 2nd egg */
547 egg->quan -= (long) hatchcount;
551 * We could possibly hatch while migrating, but the code isn't
554 } else if (obj->where == OBJ_MIGRATING) {
556 * We can do several things. The first ones that come to
558 * + Create the hatched monster then place it on the migrating
559 * mons list. This is tough because all makemon() is made
560 * to place the monster as well. Makemon() also doesn't lend
561 * itself well to splitting off a "not yet placed" subroutine.
562 * + Mark the egg as hatched, then place the monster when we
563 * place the migrating objects.
564 * + Or just kill any egg which gets sent to another level.
565 * Falling is the usual reason such transportation occurs.
567 cansee_hatchspot = FALSE;
573 char monnambuf[BUFSZ], carriedby[BUFSZ];
574 boolean siblings = (hatchcount > 1), redraw = FALSE;
576 if (cansee_hatchspot) {
577 Sprintf(monnambuf, "%s%s", siblings ? "some " : "",
578 siblings ? makeplural(m_monnam(mon)) : an(m_monnam(mon)));
579 /* we don't learn the egg type here because learning
580 an egg type requires either seeing the egg hatch
581 or being familiar with the egg already,
582 as well as being able to see the resulting
583 monster, checked below
586 switch (egg->where) {
588 knows_egg = TRUE; /* true even if you are blind */
589 if (!cansee_hatchspot)
590 You_feel("%s %s from your pack!", something,
591 locomotion(mon->data, "drop"));
593 You_see("%s %s out of your pack!", monnambuf,
594 locomotion(mon->data, "drop"));
596 pline("%s cries sound like \"%s%s\"",
597 siblings ? "Their" : "Its",
598 flags.female ? "mommy" : "daddy", egg->spe ? "." : "?");
599 } else if (mon->data->mlet == S_DRAGON && !Deaf) {
600 verbalize("Gleep!"); /* Mything eggs :-) */
605 if (cansee_hatchspot) {
607 You_see("%s hatch.", monnambuf);
608 redraw = TRUE; /* update egg's map location */
613 if (cansee_hatchspot) {
614 /* egg carrying monster might be invisible */
615 if (canseemon(egg->ocarry)) {
616 Sprintf(carriedby, "%s pack",
617 s_suffix(a_monnam(egg->ocarry)));
619 } else if (is_pool(mon->mx, mon->my))
620 Strcpy(carriedby, "empty water");
622 Strcpy(carriedby, "thin air");
623 You_see("%s %s out of %s!", monnambuf,
624 locomotion(mon->data, "drop"), carriedby);
632 impossible("egg hatched where? (%d)", (int) egg->where);
636 if (cansee_hatchspot && knows_egg)
637 learn_egg_type(mnum);
640 /* still some eggs left */
641 /* Instead of ordinary egg timeout use a short one */
642 attach_egg_hatch_timeout(egg, (long) rnd(12));
643 } else if (carried(egg)) {
646 /* free egg here because we use it above */
647 obj_extract_self(egg);
648 obfree(egg, (struct obj *) 0);
655 /* Learn to recognize eggs of the given type. */
660 /* baby monsters hatch from grown-up eggs */
661 mnum = little_to_big(mnum);
662 mvitals[mnum].mvflags |= MV_KNOWS_EGG;
663 /* we might have just learned about other eggs being carried */
667 /* Attach a fig_transform timeout to the given figurine. */
669 attach_fig_transform_timeout(figurine)
670 struct obj *figurine;
674 /* stop previous timer, if any */
675 (void) stop_timer(FIG_TRANSFORM, obj_to_any(figurine));
678 * Decide when to transform the figurine.
681 /* figurine will transform */
682 (void) start_timer((long) i, TIMER_OBJECT, FIG_TRANSFORM,
683 obj_to_any(figurine));
686 /* give a fumble message */
690 struct obj *otmp = vobj_at(u.ux, u.uy), *otmp2;
693 boolean on_foot = TRUE;
697 if (otmp && on_foot && !u.uinwater && is_pool(u.ux, u.uy))
700 if (otmp && on_foot) { /* trip over something in particular */
702 If there is only one item, it will have just been named
703 during the move, so refer to by via pronoun; otherwise,
704 if the top item has been or can be seen, refer to it by
705 name; if not, look for rocks to trip over; trip over
706 anonymous "something" if there aren't any rocks.
708 what = (iflags.last_msg == PLNMSG_ONE_ITEM_HERE)
709 ? ((otmp->quan == 1L) ? "it"
710 : Hallucination ? "they" : "them")
711 : (otmp->dknown || !Blind)
713 : ((otmp2 = sobj_at(ROCK, u.ux, u.uy)) == 0
715 : (otmp2->quan == 1L ? "a rock" : "some rocks"));
717 what = strcpy(buf, what);
718 buf[0] = highc(buf[0]);
719 pline("Egads! %s bite%s your %s!", what,
720 (!otmp || otmp->quan == 1L) ? "s" : "", body_part(FOOT));
722 You("trip over %s.", what);
724 if (!uarmf && otmp->otyp == CORPSE
725 && touch_petrifies(&mons[otmp->corpsenm]) && !Stone_resistance) {
726 Sprintf(killer.name, "tripping over %s corpse",
727 an(mons[otmp->corpsenm].mname));
728 instapetrify(killer.name);
730 } else if (rn2(3) && is_ice(u.ux, u.uy)) {
731 pline("%s %s%s on the ice.",
732 u.usteed ? upstart(x_monnam(u.usteed,
733 (has_mname(u.usteed)) ? ARTICLE_NONE
735 (char *) 0, SUPPRESS_SADDLE, FALSE))
737 rn2(2) ? "slip" : "slide", on_foot ? "" : "s");
742 You("trip over your own %s.",
743 Hallucination ? "elbow" : makeplural(body_part(FOOT)));
747 Hallucination ? "on a banana peel" : "and nearly fall");
759 Your("%s slip out of the stirrups.",
760 makeplural(body_part(FOOT)));
763 You("let go of the reins.");
766 You("bang into the saddle-horn.");
769 You("slide to one side of the saddle.");
772 dismount_steed(DISMOUNT_FELL);
777 /* Print a lamp flicker message with tailer. */
779 see_lamp_flicker(obj, tailer)
783 switch (obj->where) {
786 pline("%s flickers%s.", Yname2(obj), tailer);
789 You_see("%s flicker%s.", an(xname(obj)), tailer);
794 /* Print a dimming message for brass lanterns. */
800 switch (obj->where) {
802 Your("lantern is getting dim.");
804 pline("Batteries have not been invented yet.");
807 You_see("a lantern getting dim.");
810 pline("%s lantern is getting dim.", s_suffix(Monnam(obj->ocarry)));
816 * Timeout callback for for objects that are burning. E.g. lamps, candles.
817 * See begin_burn() for meanings of obj->age and obj->spe.
820 burn_object(arg, timeout)
824 struct obj *obj = arg->a_obj;
825 boolean canseeit, many, menorah, need_newsym;
829 menorah = obj->otyp == CANDELABRUM_OF_INVOCATION;
830 many = menorah ? obj->spe > 1 : obj->quan > 1L;
832 /* timeout while away */
833 if (timeout != monstermoves) {
834 long how_long = monstermoves - timeout;
836 if (how_long >= obj->age) {
838 end_burn(obj, FALSE);
841 obj->spe = 0; /* no more candles */
842 } else if (Is_candle(obj) || obj->otyp == POT_OIL) {
843 /* get rid of candles and burning oil potions;
844 we know this object isn't carried by hero,
845 nor is it migrating */
846 obj_extract_self(obj);
847 obfree(obj, (struct obj *) 0);
848 obj = (struct obj *) 0;
852 obj->age -= how_long;
853 begin_burn(obj, TRUE);
858 /* only interested in INVENT, FLOOR, and MINVENT */
859 if (get_obj_location(obj, &x, &y, 0)) {
860 canseeit = !Blind && cansee(x, y);
861 /* set `whose[]' to be "Your " or "Fred's " or "The goblin's " */
862 (void) Shk_Your(whose, obj);
868 /* obj->age is the age remaining at this point. */
871 /* this should only be called when we run out */
873 switch (obj->where) {
876 pline("%spotion of oil has burnt away.", whose);
879 You_see("a burning potion of oil go out.");
884 end_burn(obj, FALSE); /* turn off light source */
888 /* clear migrating obj's destination code before obfree
889 to avoid false complaint of deleting worn item */
890 if (obj->where == OBJ_MIGRATING)
892 obj_extract_self(obj);
893 obfree(obj, (struct obj *) 0);
895 obj = (struct obj *) 0;
900 switch ((int) obj->age) {
905 if (obj->otyp == BRASS_LANTERN)
906 lantern_message(obj);
908 see_lamp_flicker(obj,
909 obj->age == 50L ? " considerably" : "");
915 if (obj->otyp == BRASS_LANTERN)
916 lantern_message(obj);
918 switch (obj->where) {
921 pline("%s seems about to go out.", Yname2(obj));
924 You_see("%s about to go out.", an(xname(obj)));
932 /* even if blind you'll know if holding it */
933 if (canseeit || obj->where == OBJ_INVENT) {
934 switch (obj->where) {
937 if (obj->otyp == BRASS_LANTERN)
938 pline("%slantern has run out of power.", whose);
940 pline("%s has gone out.", Yname2(obj));
943 if (obj->otyp == BRASS_LANTERN)
944 You_see("a lantern run out of power.");
946 You_see("%s go out.", an(xname(obj)));
950 end_burn(obj, FALSE);
955 * Someone added fuel to the lamp while it was
956 * lit. Just fall through and let begin burn
957 * handle the new age.
963 begin_burn(obj, TRUE);
967 case CANDELABRUM_OF_INVOCATION:
973 switch (obj->where) {
976 pline("%s%scandle%s getting short.", whose,
977 menorah ? "candelabrum's " : "",
978 many ? "s are" : " is");
981 You_see("%scandle%s getting short.",
982 menorah ? "a candelabrum's " : many ? "some "
991 switch (obj->where) {
994 pline("%s%scandle%s flame%s flicker%s low!", whose,
995 menorah ? "candelabrum's " : "", many ? "s'" : "'s",
996 many ? "s" : "", many ? "" : "s");
999 You_see("%scandle%s flame%s flicker low!",
1000 menorah ? "a candelabrum's " : many ? "some "
1002 many ? "s'" : "'s", many ? "s" : "");
1008 /* we know even if blind and in our inventory */
1009 if (canseeit || obj->where == OBJ_INVENT) {
1011 switch (obj->where) {
1014 pline("%scandelabrum's flame%s.", whose,
1015 many ? "s die" : " dies");
1018 You_see("a candelabrum's flame%s die.",
1023 switch (obj->where) {
1026 pline("%s %s consumed!", Yname2(obj),
1027 many ? "are" : "is");
1031 You see some wax candles consumed!
1032 You see a wax candle consumed!
1034 You_see("%s%s consumed!", many ? "some " : "",
1035 many ? xname(obj) : an(xname(obj)));
1042 ? (many ? "They shriek!" : "It shrieks!")
1043 : Blind ? "" : (many ? "Their flames die."
1044 : "Its flame dies."));
1047 end_burn(obj, FALSE);
1055 /* clear migrating obj's destination code
1056 so obfree won't think this item is worn */
1057 if (obj->where == OBJ_MIGRATING)
1058 obj->owornmask = 0L;
1059 obj_extract_self(obj);
1060 obfree(obj, (struct obj *) 0);
1062 obj = (struct obj *) 0;
1068 * Someone added fuel (candles) to the menorah while
1069 * it was lit. Just fall through and let begin burn
1070 * handle the new age.
1075 if (obj && obj->age)
1076 begin_burn(obj, TRUE);
1081 impossible("burn_object: unexpeced obj %s", xname(obj));
1089 * Start a burn timeout on the given object. If not "already lit" then
1090 * create a light source for the vision system. There had better not
1091 * be a burn already running on the object.
1093 * Magic lamps stay lit as long as there's a genie inside, so don't start
1097 * potions of oil, lamps & candles:
1098 * age = # of turns of fuel left
1102 * spe = 0 not lightable, 1 lightable forever
1104 * age = # of turns of fuel left
1105 * spe = # of candles
1107 * Once the burn begins, the age will be set to the amount of fuel
1108 * remaining _once_the_burn_finishes_. If the burn is terminated
1109 * early then fuel is added back.
1111 * This use of age differs from the use of age for corpses and eggs.
1112 * For the latter items, age is when the object was created, so we
1113 * know when it becomes "bad".
1115 * This is a "silent" routine - it should not print anything out.
1118 begin_burn(obj, already_lit)
1120 boolean already_lit;
1124 boolean do_timer = TRUE;
1126 if (obj->age == 0 && obj->otyp != MAGIC_LAMP && !artifact_light(obj))
1129 switch (obj->otyp) {
1137 radius = 1; /* very dim light */
1142 /* magic times are 150, 100, 50, 25, and 0 */
1143 if (obj->age > 150L)
1144 turns = obj->age - 150L;
1145 else if (obj->age > 100L)
1146 turns = obj->age - 100L;
1147 else if (obj->age > 50L)
1148 turns = obj->age - 50L;
1149 else if (obj->age > 25L)
1150 turns = obj->age - 25L;
1155 case CANDELABRUM_OF_INVOCATION:
1158 /* magic times are 75, 15, and 0 */
1160 turns = obj->age - 75L;
1161 else if (obj->age > 15L)
1162 turns = obj->age - 15L;
1165 radius = candle_light_range(obj);
1169 /* [ALI] Support artifact light sources */
1170 if (artifact_light(obj)) {
1173 radius = arti_light_radius(obj);
1175 impossible("begin burn: unexpected %s", xname(obj));
1182 if (start_timer(turns, TIMER_OBJECT, BURN_OBJECT, obj_to_any(obj))) {
1185 if (carried(obj) && !already_lit)
1191 if (carried(obj) && !already_lit)
1195 if (obj->lamplit && !already_lit) {
1198 if (get_obj_location(obj, &x, &y, CONTAINED_TOO | BURIED_TOO))
1199 new_light_source(x, y, radius, LS_OBJECT, obj_to_any(obj));
1201 impossible("begin_burn: can't get obj position");
1206 * Stop a burn timeout on the given object if timer attached. Darken
1210 end_burn(obj, timer_attached)
1212 boolean timer_attached;
1214 if (!obj->lamplit) {
1215 impossible("end_burn: obj %s not lit", xname(obj));
1219 if (obj->otyp == MAGIC_LAMP || artifact_light(obj))
1220 timer_attached = FALSE;
1222 if (!timer_attached) {
1223 /* [DS] Cleanup explicitly, since timer cleanup won't happen */
1224 del_light_source(LS_OBJECT, obj_to_any(obj));
1226 if (obj->where == OBJ_INVENT)
1228 } else if (!stop_timer(BURN_OBJECT, obj_to_any(obj)))
1229 impossible("end_burn: obj %s not timed!", xname(obj));
1233 * Cleanup a burning object if timer stopped.
1236 cleanup_burn(arg, expire_time)
1240 struct obj *obj = arg->a_obj;
1241 if (!obj->lamplit) {
1242 impossible("cleanup_burn: obj %s not lit", xname(obj));
1246 del_light_source(LS_OBJECT, obj_to_any(obj));
1248 /* restore unused time */
1249 obj->age += expire_time - monstermoves;
1253 if (obj->where == OBJ_INVENT)
1265 /* no lightning if not the air level or too often, even then */
1266 if (!Is_airlevel(&u.uz) || rn2(8))
1269 /* the number of strikes is 8-log2(nstrike) */
1270 for (nstrike = rnd(64); nstrike <= 64; nstrike *= 2) {
1275 } while (++count < 100 && levl[x][y].typ != CLOUD);
1280 if (dirx != 0 || diry != 0)
1281 buzz(-15, /* "monster" LIGHTNING spell */
1282 8, x, y, dirx, diry);
1286 if (levl[u.ux][u.uy].typ == CLOUD) {
1287 /* Inside a cloud during a thunder storm is deafening. */
1288 /* Even if already deaf, we sense the thunder's vibrations. */
1289 pline("Kaboom!!! Boom!! Boom!!");
1290 incr_itimeout(&HDeaf, rn1(20, 30));
1291 if (!u.uinvulnerable) {
1294 multi_reason = "hiding from thunderstorm";
1298 You_hear("a rumbling noise.");
1301 /* -------------------------------------------------------------------------
1304 * Generic Timeout Functions.
1309 * boolean start_timer(long timeout,short kind,short func_index,
1311 * Start a timer of kind 'kind' that will expire at time
1312 * monstermoves+'timeout'. Call the function at 'func_index'
1313 * in the timeout table using argument 'arg'. Return TRUE if
1314 * a timer was started. This places the timer on a list ordered
1315 * "sooner" to "later". If an object, increment the object's
1318 * long stop_timer(short func_index, anything *arg)
1319 * Stop a timer specified by the (func_index, arg) pair. This
1320 * assumes that such a pair is unique. Return the time the
1321 * timer would have gone off. If no timer is found, return 0.
1322 * If an object, decrement the object's timer count.
1324 * long peek_timer(short func_index, anything *arg)
1325 * Return time specified timer will go off (0 if no such timer).
1327 * void run_timers(void)
1328 * Call timers that have timed out.
1331 * void save_timers(int fd, int mode, int range)
1332 * Save all timers of range 'range'. Range is either global
1333 * or local. Global timers follow game play, local timers
1334 * are saved with a level. Object and monster timers are
1335 * saved using their respective id's instead of pointers.
1337 * void restore_timers(int fd, int range, boolean ghostly, long adjust)
1338 * Restore timers of range 'range'. If from a ghost pile,
1339 * adjust the timeout by 'adjust'. The object and monster
1340 * ids are not restored until later.
1342 * void relink_timers(boolean ghostly)
1343 * Relink all object and monster timers that had been saved
1344 * using their object's or monster's id number.
1347 * void obj_move_timers(struct obj *src, struct obj *dest)
1348 * Reassign all timers from src to dest.
1350 * void obj_split_timers(struct obj *src, struct obj *dest)
1351 * Duplicate all timers assigned to src and attach them to dest.
1353 * void obj_stop_timers(struct obj *obj)
1354 * Stop all timers attached to obj.
1356 * boolean obj_has_timer(struct obj *object, short timer_type)
1357 * Check whether object has a timer of type timer_type.
1360 STATIC_DCL const char *FDECL(kind_name, (SHORT_P));
1361 STATIC_DCL void FDECL(print_queue, (winid, timer_element *));
1362 STATIC_DCL void FDECL(insert_timer, (timer_element *));
1363 STATIC_DCL timer_element *FDECL(remove_timer,
1364 (timer_element **, SHORT_P, ANY_P *));
1365 STATIC_DCL void FDECL(write_timer, (int, timer_element *));
1366 STATIC_DCL boolean FDECL(mon_is_local, (struct monst *));
1367 STATIC_DCL boolean FDECL(timer_is_local, (timer_element *));
1368 STATIC_DCL int FDECL(maybe_write_timer, (int, int, BOOLEAN_P));
1370 /* ordered timer list */
1371 static timer_element *timer_base; /* "active" */
1372 static unsigned long timer_id = 1;
1374 /* If defined, then include names when printing out the timer queue */
1375 #define VERBOSE_TIMER
1378 timeout_proc f, cleanup;
1379 #ifdef VERBOSE_TIMER
1381 #define TTAB(a, b, c) \
1386 #define TTAB(a, b, c) \
1393 /* table of timeout functions */
1394 static const ttable timeout_funcs[NUM_TIME_FUNCS] = {
1395 TTAB(rot_organic, (timeout_proc) 0, "rot_organic"),
1396 TTAB(rot_corpse, (timeout_proc) 0, "rot_corpse"),
1397 TTAB(revive_mon, (timeout_proc) 0, "revive_mon"),
1398 TTAB(burn_object, cleanup_burn, "burn_object"),
1399 TTAB(hatch_egg, (timeout_proc) 0, "hatch_egg"),
1400 TTAB(fig_transform, (timeout_proc) 0, "fig_transform"),
1401 TTAB(melt_ice_away, (timeout_proc) 0, "melt_ice_away")
1405 STATIC_OVL const char *
1423 print_queue(win, base)
1425 timer_element *base;
1427 timer_element *curr;
1431 putstr(win, 0, "<empty>");
1433 putstr(win, 0, "timeout id kind call");
1434 for (curr = base; curr; curr = curr->next) {
1435 #ifdef VERBOSE_TIMER
1436 Sprintf(buf, " %4ld %4ld %-6s %s(%s)", curr->timeout,
1437 curr->tid, kind_name(curr->kind),
1438 timeout_funcs[curr->func_index].name,
1439 fmt_ptr((genericptr_t) curr->arg.a_void));
1441 Sprintf(buf, " %4ld %4ld %-6s #%d(%s)", curr->timeout,
1442 curr->tid, kind_name(curr->kind), curr->func_index,
1443 fmt_ptr((genericptr_t) curr->arg.a_void));
1445 putstr(win, 0, buf);
1456 win = create_nhwindow(NHW_MENU); /* corner text window */
1460 Sprintf(buf, "Current time = %ld.", monstermoves);
1461 putstr(win, 0, buf);
1463 putstr(win, 0, "Active timeout queue:");
1465 print_queue(win, timer_base);
1467 display_nhwindow(win, FALSE);
1468 destroy_nhwindow(win);
1474 timer_sanity_check()
1476 timer_element *curr;
1478 /* this should be much more complete */
1479 for (curr = timer_base; curr; curr = curr->next)
1480 if (curr->kind == TIMER_OBJECT) {
1481 struct obj *obj = curr->arg.a_obj;
1482 if (obj->timed == 0) {
1483 pline("timer sanity: untimed obj %s, timer %ld",
1484 fmt_ptr((genericptr_t) obj), curr->tid);
1490 * Pick off timeout elements from the global queue and call their functions.
1491 * Do this until their time is less than or equal to the move count.
1496 timer_element *curr;
1499 * Always use the first element. Elements may be added or deleted at
1500 * any time. The list is ordered, we are done when the first element
1503 while (timer_base && timer_base->timeout <= monstermoves) {
1505 timer_base = curr->next;
1507 if (curr->kind == TIMER_OBJECT)
1508 (curr->arg.a_obj)->timed--;
1509 (*timeout_funcs[curr->func_index].f)(&curr->arg, curr->timeout);
1510 free((genericptr_t) curr);
1515 * Start a timer. Return TRUE if successful.
1518 start_timer(when, kind, func_index, arg)
1526 if (func_index < 0 || func_index >= NUM_TIME_FUNCS)
1527 panic("start_timer");
1529 gnu = (timer_element *) alloc(sizeof(timer_element));
1531 gnu->tid = timer_id++;
1532 gnu->timeout = monstermoves + when;
1534 gnu->needs_fixup = 0;
1535 gnu->func_index = func_index;
1539 if (kind == TIMER_OBJECT) /* increment object's timed count */
1540 (arg->a_obj)->timed++;
1542 /* should check for duplicates and fail if any */
1547 * Remove the timer from the current list and free it up. Return the time
1548 * remaining until it would have gone off, 0 if not found.
1551 stop_timer(func_index, arg)
1555 timer_element *doomed;
1558 doomed = remove_timer(&timer_base, func_index, arg);
1561 timeout = doomed->timeout;
1562 if (doomed->kind == TIMER_OBJECT)
1563 (arg->a_obj)->timed--;
1564 if (timeout_funcs[doomed->func_index].cleanup)
1565 (*timeout_funcs[doomed->func_index].cleanup)(arg, timeout);
1566 free((genericptr_t) doomed);
1567 return (timeout - monstermoves);
1573 * Find the timeout of specified timer; return 0 if none.
1576 peek_timer(type, arg)
1580 timer_element *curr;
1582 for (curr = timer_base; curr; curr = curr->next) {
1583 if (curr->func_index == type && curr->arg.a_void == arg->a_void)
1584 return curr->timeout;
1590 * Move all object timers from src to dest, leaving src untimed.
1593 obj_move_timers(src, dest)
1594 struct obj *src, *dest;
1597 timer_element *curr;
1599 for (count = 0, curr = timer_base; curr; curr = curr->next)
1600 if (curr->kind == TIMER_OBJECT && curr->arg.a_obj == src) {
1601 curr->arg.a_obj = dest;
1605 if (count != src->timed)
1606 panic("obj_move_timers");
1611 * Find all object timers and duplicate them for the new object "dest".
1614 obj_split_timers(src, dest)
1615 struct obj *src, *dest;
1617 timer_element *curr, *next_timer = 0;
1619 for (curr = timer_base; curr; curr = next_timer) {
1620 next_timer = curr->next; /* things may be inserted */
1621 if (curr->kind == TIMER_OBJECT && curr->arg.a_obj == src) {
1622 (void) start_timer(curr->timeout - monstermoves, TIMER_OBJECT,
1623 curr->func_index, obj_to_any(dest));
1629 * Stop all timers attached to this object. We can get away with this because
1630 * all object pointers are unique.
1633 obj_stop_timers(obj)
1636 timer_element *curr, *prev, *next_timer = 0;
1638 for (prev = 0, curr = timer_base; curr; curr = next_timer) {
1639 next_timer = curr->next;
1640 if (curr->kind == TIMER_OBJECT && curr->arg.a_obj == obj) {
1642 prev->next = curr->next;
1644 timer_base = curr->next;
1645 if (timeout_funcs[curr->func_index].cleanup)
1646 (*timeout_funcs[curr->func_index].cleanup)(&curr->arg,
1648 free((genericptr_t) curr);
1657 * Check whether object has a timer of type timer_type.
1660 obj_has_timer(object, timer_type)
1664 long timeout = peek_timer(timer_type, obj_to_any(object));
1666 return (boolean) (timeout != 0L);
1670 * Stop all timers of index func_index at this spot.
1674 spot_stop_timers(x, y, func_index)
1678 timer_element *curr, *prev, *next_timer = 0;
1679 long where = (((long) x << 16) | ((long) y));
1681 for (prev = 0, curr = timer_base; curr; curr = next_timer) {
1682 next_timer = curr->next;
1683 if (curr->kind == TIMER_LEVEL && curr->func_index == func_index
1684 && curr->arg.a_long == where) {
1686 prev->next = curr->next;
1688 timer_base = curr->next;
1689 if (timeout_funcs[curr->func_index].cleanup)
1690 (*timeout_funcs[curr->func_index].cleanup)(&curr->arg,
1692 free((genericptr_t) curr);
1700 * When is the spot timer of type func_index going to expire?
1701 * Returns 0L if no such timer.
1704 spot_time_expires(x, y, func_index)
1708 timer_element *curr;
1709 long where = (((long) x << 16) | ((long) y));
1711 for (curr = timer_base; curr; curr = curr->next) {
1712 if (curr->kind == TIMER_LEVEL && curr->func_index == func_index
1713 && curr->arg.a_long == where)
1714 return curr->timeout;
1720 spot_time_left(x, y, func_index)
1724 long expires = spot_time_expires(x, y, func_index);
1725 return (expires > 0L) ? expires - monstermoves : 0L;
1728 /* Insert timer into the global queue */
1733 timer_element *curr, *prev;
1735 for (prev = 0, curr = timer_base; curr; prev = curr, curr = curr->next)
1736 if (curr->timeout >= gnu->timeout)
1746 STATIC_OVL timer_element *
1747 remove_timer(base, func_index, arg)
1748 timer_element **base;
1752 timer_element *prev, *curr;
1754 for (prev = 0, curr = *base; curr; prev = curr, curr = curr->next)
1755 if (curr->func_index == func_index && curr->arg.a_void == arg->a_void)
1760 prev->next = curr->next;
1769 write_timer(fd, timer)
1771 timer_element *timer;
1776 switch (timer->kind) {
1779 /* assume no pointers in arg */
1780 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
1784 if (timer->needs_fixup)
1785 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
1787 /* replace object pointer with id */
1788 arg_save.a_obj = timer->arg.a_obj;
1789 timer->arg = zeroany;
1790 timer->arg.a_uint = (arg_save.a_obj)->o_id;
1791 timer->needs_fixup = 1;
1792 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
1793 timer->arg.a_obj = arg_save.a_obj;
1794 timer->needs_fixup = 0;
1799 if (timer->needs_fixup)
1800 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
1802 /* replace monster pointer with id */
1803 arg_save.a_monst = timer->arg.a_monst;
1804 timer->arg = zeroany;
1805 timer->arg.a_uint = (arg_save.a_monst)->m_id;
1806 timer->needs_fixup = 1;
1807 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
1808 timer->arg.a_monst = arg_save.a_monst;
1809 timer->needs_fixup = 0;
1814 panic("write_timer");
1820 * Return TRUE if the object will stay on the level when the level is
1827 switch (obj->where) {
1835 return obj_is_local(obj->ocontainer);
1837 return mon_is_local(obj->ocarry);
1839 panic("obj_is_local");
1844 * Return TRUE if the given monster will stay on the level when the
1853 for (curr = migrating_mons; curr; curr = curr->nmon)
1856 /* `mydogs' is used during level changes, never saved and restored */
1857 for (curr = mydogs; curr; curr = curr->nmon)
1864 * Return TRUE if the timer is attached to something that will stay on the
1865 * level when the level is saved.
1868 timer_is_local(timer)
1869 timer_element *timer;
1871 switch (timer->kind) {
1877 return obj_is_local(timer->arg.a_obj);
1879 return mon_is_local(timer->arg.a_monst);
1881 panic("timer_is_local");
1886 * Part of the save routine. Count up the number of timers that would
1887 * be written. If write_it is true, actually write the timer.
1890 maybe_write_timer(fd, range, write_it)
1895 timer_element *curr;
1897 for (curr = timer_base; curr; curr = curr->next) {
1898 if (range == RANGE_GLOBAL) {
1901 if (!timer_is_local(curr)) {
1904 write_timer(fd, curr);
1910 if (timer_is_local(curr)) {
1913 write_timer(fd, curr);
1922 * Save part of the timer list. The parameter 'range' specifies either
1923 * global or level timers to save. The timer ID is saved with the global
1927 * + timeouts that follow the hero (global)
1928 * + timeouts that follow obj & monst that are migrating
1931 * + timeouts that are level specific (e.g. storms)
1932 * + timeouts that stay with the level (obj & monst)
1935 save_timers(fd, mode, range)
1936 int fd, mode, range;
1938 timer_element *curr, *prev, *next_timer = 0;
1941 if (perform_bwrite(mode)) {
1942 if (range == RANGE_GLOBAL)
1943 bwrite(fd, (genericptr_t) &timer_id, sizeof(timer_id));
1945 count = maybe_write_timer(fd, range, FALSE);
1946 bwrite(fd, (genericptr_t) &count, sizeof count);
1947 (void) maybe_write_timer(fd, range, TRUE);
1950 if (release_data(mode)) {
1951 for (prev = 0, curr = timer_base; curr; curr = next_timer) {
1952 next_timer = curr->next; /* in case curr is removed */
1954 if (!(!!(range == RANGE_LEVEL) ^ !!timer_is_local(curr))) {
1956 prev->next = curr->next;
1958 timer_base = curr->next;
1959 free((genericptr_t) curr);
1960 /* prev stays the same */
1969 * Pull in the structures from disk, but don't recalculate the object and
1973 restore_timers(fd, range, ghostly, adjust)
1975 boolean ghostly; /* restoring from a ghost level */
1976 long adjust; /* how much to adjust timeout */
1979 timer_element *curr;
1981 if (range == RANGE_GLOBAL)
1982 mread(fd, (genericptr_t) &timer_id, sizeof timer_id);
1984 /* restore elements */
1985 mread(fd, (genericptr_t) &count, sizeof count);
1986 while (count-- > 0) {
1987 curr = (timer_element *) alloc(sizeof(timer_element));
1988 mread(fd, (genericptr_t) curr, sizeof(timer_element));
1990 curr->timeout += adjust;
1995 /* reset all timers that are marked for reseting */
1997 relink_timers(ghostly)
2000 timer_element *curr;
2003 for (curr = timer_base; curr; curr = curr->next) {
2004 if (curr->needs_fixup) {
2005 if (curr->kind == TIMER_OBJECT) {
2007 if (!lookup_id_mapping(curr->arg.a_uint, &nid))
2008 panic("relink_timers 1");
2010 nid = curr->arg.a_uint;
2011 curr->arg.a_obj = find_oid(nid);
2012 if (!curr->arg.a_obj)
2013 panic("cant find o_id %d", nid);
2014 curr->needs_fixup = 0;
2015 } else if (curr->kind == TIMER_MONSTER) {
2016 panic("relink_timers: no monster timer implemented");
2018 panic("relink_timers 2");