1 /* NetHack 3.6 timeout.c $NHDT-Date: 1505214876 2017/09/12 11:14:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.75 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2018. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2018 */
9 /* JNetHack may be freely redistributed. See license for details. */
12 #include "lev.h" /* for checking save modes */
14 STATIC_DCL void NDECL(stoned_dialogue);
15 STATIC_DCL void NDECL(vomiting_dialogue);
16 STATIC_DCL void NDECL(choke_dialogue);
17 STATIC_DCL void NDECL(levitation_dialogue);
18 STATIC_DCL void NDECL(slime_dialogue);
19 STATIC_DCL void NDECL(slip_or_trip);
20 STATIC_DCL void FDECL(see_lamp_flicker, (struct obj *, const char *));
21 STATIC_DCL void FDECL(lantern_message, (struct obj *));
22 STATIC_DCL void FDECL(cleanup_burn, (ANY_P *, long));
24 /* used by wizard mode #timeout and #wizintrinsic; order by 'interest'
25 for timeout countdown, where most won't occur in normal play */
26 /*JP
\83E
\83B
\83U
\81[
\83h
\83\82\81[
\83h
\82Å
\82µ
\82©
\8eg
\82í
\82ê
\82È
\82¢
\82æ
\82¤
\82È
\82Ì
\82Å
\96|
\96ó
\82µ
\82È
\82¢ */
27 const struct propname {
29 const char *prop_name;
31 { INVULNERABLE, "invulnerable" },
32 { STONED, "petrifying" },
33 { SLIMED, "becoming slime" },
34 { STRANGLED, "strangling" },
35 { SICK, "fatally sick" },
36 { STUNNED, "stunned" },
37 { CONFUSION, "confused" },
38 { HALLUC, "hallucinating" },
39 { BLINDED, "blinded" },
41 { VOMITING, "vomiting" },
42 { GLIB, "slippery fingers" },
43 { WOUNDED_LEGS, "wounded legs" },
45 { TELEPORT, "teleporting" },
46 { POLYMORPH, "polymorphing" },
47 { LEVITATION, "levitating" },
48 { FAST, "very fast" }, /* timed 'FAST' is very fast */
49 { CLAIRVOYANT, "clairvoyant" },
50 { DETECT_MONSTERS, "monster detection" },
51 { SEE_INVIS, "see invisible" },
52 { INVIS, "invisible" },
53 /* properties beyond here don't have timed values during normal play,
54 so there's no much point in trying to order them sensibly;
55 they're either on or off based on equipment, role, actions, &c */
56 { FIRE_RES, "fire resistance" },
57 { COLD_RES, "cold resistance" },
58 { SLEEP_RES, "sleep resistance" },
59 { DISINT_RES, "disintegration resistance" },
60 { SHOCK_RES, "shock resistance" },
61 { POISON_RES, "poison resistance" },
62 { ACID_RES, "acid resistance" },
63 { STONE_RES, "stoning resistance" },
64 { DRAIN_RES, "drain resistance" },
65 { SICK_RES, "sickness resistance" },
66 { ANTIMAGIC, "magic resistance" },
67 { HALLUC_RES, "hallucination resistance" },
68 { FUMBLING, "fumbling" },
69 { HUNGER, "voracious hunger" },
70 { TELEPAT, "telepathic" },
71 { WARNING, "warning" },
72 { WARN_OF_MON, "warn: monster type or class" },
73 { WARN_UNDEAD, "warn: undead" },
74 { SEARCHING, "searching" },
75 { INFRAVISION, "infravision" },
76 { ADORNED, "adorned (+/- Cha)" },
77 { DISPLACED, "displaced" },
78 { STEALTH, "stealthy" },
79 { AGGRAVATE_MONSTER, "monster aggravation" },
80 { CONFLICT, "conflict" },
81 { JUMPING, "jumping" },
82 { TELEPORT_CONTROL, "teleport control" },
84 { WWALKING, "water walking" },
85 { SWIMMING, "swimming" },
86 { MAGICAL_BREATHING, "magical breathing" },
87 { PASSES_WALLS, "pass thru walls" },
88 { SLOW_DIGESTION, "slow digestion" },
89 { HALF_SPDAM, "half spell damage" },
90 { HALF_PHDAM, "half physical damage" },
91 { REGENERATION, "HP regeneration" },
92 { ENERGY_REGENERATION, "energy regeneration" },
93 { PROTECTION, "extra protection" },
94 { PROT_FROM_SHAPE_CHANGERS, "protection from shape changers" },
95 { POLYMORPH_CONTROL, "polymorph control" },
96 { UNCHANGING, "unchanging" },
97 { REFLECTING, "reflecting" },
98 { FREE_ACTION, "free action" },
99 { FIXED_ABIL, "fixed abilites" },
100 { LIFESAVED, "life will be saved" },
104 /* He is being petrified - dialogue by inmet!tower */
105 static NEARDATA const char *const stoned_texts[] = {
107 "You are slowing down.", /* 5 */
108 "Your limbs are stiffening.", /* 4 */
109 "Your limbs have turned to stone.", /* 3 */
110 "You have turned to stone.", /* 2 */
111 "You are a statue." /* 1 */
113 "
\82 \82È
\82½
\82Í
\82Ì
\82ë
\82
\82È
\82Á
\82½
\81D", /* 5 */
114 "
\82 \82È
\82½
\82Ì
\8eè
\91«
\82Í
\8dd
\92¼
\82µ
\82½
\81D", /* 4 */
115 "
\82 \82È
\82½
\82Ì
\8eè
\91«
\82Í
\90Î
\89»
\82µ
\82½
\81D", /* 3 */
116 "
\82 \82È
\82½
\82Í
\90Î
\82É
\82È
\82Á
\82½
\81D", /* 2 */
117 "
\82 \82È
\82½
\82Í
\92¤
\91\9c\82É
\82È
\82Á
\82½
\81D" /* 1 */
124 register long i = (Stoned & TIMEOUT);
126 if (i > 0L && i <= SIZE(stoned_texts)) {
129 Strcpy(buf, stoned_texts[SIZE(stoned_texts) - i]);
131 if (nolimbs(youmonst.data) && strstri(buf, "limbs"))
132 (void) strsubst(buf, "limbs", "extremities");
134 if (nolimbs(youmonst.data) && strstri(buf, "
\8eè
\91«"))
135 (void) strsubst(buf, "
\8eè
\91«", "
\90æ
\92[");
140 case 5: /* slowing down */
145 case 4: /* limbs stiffening */
146 /* just one move left to save oneself so quit fiddling around;
147 don't stop attempt to eat tin--might be lizard or acidic */
153 case 3: /* limbs turned to stone */
155 nomul(-3); /* can't move anymore */
157 multi_reason = "getting stoned";
159 multi_reason = "
\90Î
\89»
\82µ
\82Â
\82Â
\82 \82é
\8e\9e\82É";
160 nomovemsg = You_can_move_again; /* not unconscious */
163 if ((HDeaf & TIMEOUT) > 0L && (HDeaf & TIMEOUT) < 5L)
164 set_itimeout(&HDeaf, 5L); /* avoid Hear_again at tail end */
168 exercise(A_DEX, FALSE);
171 /* hero is getting sicker and sicker prior to vomiting */
172 static NEARDATA const char *const vomiting_texts[] = {
174 "are feeling mildly nauseated.", /* 14 */
175 "feel slightly confused.", /* 11 */
176 "can't seem to think straight.", /* 8 */
177 "feel incredibly sick.", /* 5 */
178 "are about to vomit." /* 2 */
180 "
\82¿
\82å
\82Á
\82Æ
\93f
\82«
\8bC
\82ª
\82µ
\82½
\81D", /* 14 */
181 "
\8f
\82µ
\8d¬
\97\90\82µ
\82½
\81D", /* 11 */
182 "
\82Ü
\82Æ
\82à
\82É
\8ev
\8dl
\82Å
\82«
\82È
\82
\82È
\82Á
\82½
\81D", /* 8 */
183 "
\82Æ
\82Ä
\82à
\8bC
\95ª
\82ª
\88«
\82
\82È
\82Á
\82½
\81D", /* 5 */
184 "
\93Ë
\91R
\9aq
\93f
\82µ
\82½
\81D" /* 2 */
192 long v = (Vomiting & TIMEOUT);
194 /* note: nhtimeout() hasn't decremented timed properties for the
195 current turn yet, so we use Vomiting-1 here */
196 switch ((int) (v - 1L)) {
198 txt = vomiting_texts[0];
201 txt = vomiting_texts[1];
204 make_stunned((HStun & TIMEOUT) + (long) d(2, 4), FALSE);
205 if (!Popeye(VOMITING))
209 make_confused((HConfusion & TIMEOUT) + (long) d(2, 4), FALSE);
214 txt = vomiting_texts[2];
217 txt = vomiting_texts[3];
220 txt = vomiting_texts[4];
221 if (cantvomit(youmonst.data))
223 txt = "gag uncontrollably.";
225 txt = "
\8bC
\95ª
\82Ì
\88«
\82³
\82ª
\97}
\82¦
\82ç
\82ê
\82È
\82
\82È
\82Á
\82½
\81D";
226 else if (Hallucination)
227 /* "hurl" is short for "hurl chunks" which is slang for
228 relatively violent vomiting... */
230 txt = "are about to hurl!";
232 txt = "
\83\8a\83o
\81[
\83X
\90¡
\91O
\82¾
\81I";
236 if (!cantvomit(youmonst.data)) {
238 /* case 2 used to be "You suddenly vomit!" but it wasn't sudden
239 since you've just been through the earlier messages of the
240 countdown, and it was still possible to move around between
241 that message and "You can move again." (from vomit()'s
242 nomul(-2)) with no intervening message; give one here to
243 have more specific point at which hero became unable to move
244 [vomit() issues its own message for the cantvomit() case
245 and for the FAINTING-or-worse case where stomach is empty] */
246 if (u.uhs < FAINTING)
248 You("%s!", !Hallucination ? "vomit" : "hurl chunks");
250 You("%s
\81I", !Hallucination ? "
\93f
\82¢
\82½" : "
\83\8a\83o
\81[
\83X
\82µ
\82½");
259 exercise(A_CON, FALSE);
262 static NEARDATA const char *const choke_texts[] = {
264 "You find it hard to breathe.",
265 "You're gasping for air.",
266 "You can no longer breathe.",
267 "You're turning %s.",
270 "
\82 \82È
\82½
\82Í
\8cÄ
\8bz
\82ª
\8d¢
\93ï
\82É
\82È
\82Á
\82½
\81D",
271 "
\82 \82È
\82½
\82Í
\8bê
\82µ
\82
\82Ä
\82 \82¦
\82¢
\82¾
\81D",
272 "
\82 \82È
\82½
\82Í
\82à
\82¤
\8cÄ
\8bz
\82ª
\82Å
\82«
\82È
\82¢
\81D",
273 "
\82 \82È
\82½
\82Í%s
\82È
\82Á
\82½
\81D",
274 "
\82 \82È
\82½
\82Í
\92\82\91§
\82µ
\82½
\81D"
278 static NEARDATA const char *const choke_texts2[] = {
280 "Your %s is becoming constricted.",
281 "Your blood is having trouble reaching your brain.",
282 "The pressure on your %s increases.",
283 "Your consciousness is fading.",
286 "
\82 \82È
\82½
\82Ì%s
\82Í
\8di
\82ß
\82Â
\82¯
\82ç
\82ê
\82½
\81D",
287 "
\8c\8c\89t
\82Ì
\82ß
\82®
\82è
\82ª
\88«
\82
\82È
\82Á
\82½
\81D",
288 "%s
\82Ì
\88³
\97Í
\82ª
\8d\82\82
\82È
\82Á
\82½
\81D",
289 "
\88Ó
\8e¯
\82ª
\89\93\82
\82È
\82Á
\82Ä
\82«
\82½
\81D",
290 "
\82 \82È
\82½
\82Í
\92\82\91§
\82µ
\82½
\81D"
297 register long i = (Strangled & TIMEOUT);
299 if (i > 0 && i <= SIZE(choke_texts)) {
300 if (Breathless || !rn2(50))
301 pline(choke_texts2[SIZE(choke_texts2) - i], body_part(NECK));
303 const char *str = choke_texts[SIZE(choke_texts) - i];
307 pline(str, hcolor(NH_BLUE));
309 pline(str, jconj_adj(hcolor(NH_BLUE)));
314 exercise(A_STR, FALSE);
317 static NEARDATA const char *const levi_texts[] = {
318 #if 0 /*JP*//* %s
\82Í
\8eg
\82í
\82È
\82¢ */
319 "You float slightly lower.",
320 "You wobble unsteadily %s the %s."
322 "
\82 \82È
\82½
\82Ì
\95\82\82«
\8bï
\8d\87\82Í
\8f
\82µ
\92á
\82
\82È
\82Á
\82½
\81D",
323 "
\82 \82È
\82½
\82Í
\82®
\82ç
\82®
\82ç
\97h
\82ê
\82Í
\82¶
\82ß
\82½
\81D"
328 levitation_dialogue()
330 /* -1 because the last message comes via float_down() */
331 long i = (((HLevitation & TIMEOUT) - 1L) / 2L);
336 if (!ACCESSIBLE(levl[u.ux][u.uy].typ)
337 && !is_pool_or_lava(u.ux,u.uy))
340 if (((HLevitation & TIMEOUT) % 2L) && i > 0L && i <= SIZE(levi_texts)) {
341 const char *s = levi_texts[SIZE(levi_texts) - i];
343 #if 0 /*JP*//* %s
\82Í
\8eg
\82Á
\82Ä
\82¢
\82È
\82¢
\82Ì
\82Å
\92P
\8f\83\89» */
345 boolean danger = (is_pool_or_lava(u.ux, u.uy)
346 && !Is_waterlevel(&u.uz));
348 pline(s, danger ? "over" : "in",
349 danger ? surface(u.ux, u.uy) : "air");
356 static NEARDATA const char *const slime_texts[] = {
358 "You are turning a little %s.", /* 5 */
359 "Your limbs are getting oozy.", /* 4 */
360 "Your skin begins to peel away.", /* 3 */
361 "You are turning into %s.", /* 2 */
362 "You have become %s." /* 1 */
364 "
\8f
\82µ%s
\82È
\82Á
\82½
\81D", /* 5 */
365 "
\8eè
\91«
\82ª
\97n
\82¯
\82Í
\82¶
\82ß
\82½
\81D", /* 4 */
366 "
\94§
\82ª
\82Ç
\82ë
\82Ç
\82ë
\82É
\82È
\82Á
\82Ä
\82«
\82½
\81D", /* 3 */
367 "%s
\82É
\82È
\82è
\82Í
\82¶
\82ß
\82½
\81D", /* 2 */
368 "%s
\82É
\82È
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D", /* 1 */
375 register long i = (Slimed & TIMEOUT) / 2L;
377 if (((Slimed & TIMEOUT) % 2L) && i >= 0L && i < SIZE(slime_texts)) {
380 Strcpy(buf, slime_texts[SIZE(slime_texts) - i - 1L]);
382 if (nolimbs(youmonst.data) && strstri(buf, "limbs"))
383 (void) strsubst(buf, "limbs", "extremities");
385 if (nolimbs(youmonst.data) && strstri(buf, "
\8eè
\91«"))
386 (void) strsubst(buf, "
\8eè
\91«", "
\90æ
\92[");
389 if (index(buf, '%')) {
390 if (i == 4L) { /* "you are turning green" */
391 if (!Blind) /* [what if you're already green?] */
393 pline(buf, hcolor(NH_GREEN));
395 pline(buf, jconj_adj(hcolor(NH_GREEN)));
399 an(Hallucination ? rndmonnam(NULL) : "green slime"));
401 Hallucination ? rndmonnam(NULL) : "
\97Î
\83X
\83\89\83C
\83\80");
405 if (i == 3L) { /* limbs becoming oozy */
406 HFast = 0L; /* lose intrinsic speed */
412 if (i == 2L && (HDeaf & TIMEOUT) > 0L && (HDeaf & TIMEOUT) < 5L)
413 set_itimeout(&HDeaf, 5L); /* avoid Hear_again at tail end */
414 exercise(A_DEX, FALSE);
422 make_slimed(0L, "The slime that covers you is burned away!");
424 make_slimed(0L, "
\82 \82È
\82½
\82ð
\95¢
\82Á
\82Ä
\82¢
\82½
\83X
\83\89\83C
\83\80\82Í
\8fÄ
\82¯
\97\8e\82¿
\82½
\81I");
428 /* Intrinsic Passes_walls is temporary when your god is trying to fix
429 all troubles and then TROUBLE_STUCK_IN_WALL calls safe_teleds() but
430 it can't find anywhere to place you. If that happens you get a small
431 value for (HPasses_walls & TIMEOUT) to move somewhere yourself.
432 Message given is "you feel much slimmer" as a joke hint that you can
433 move between things which are closely packed--like the substance of
435 static NEARDATA const char *const phaze_texts[] = {
437 "You start to feel bloated.",
438 "You are feeling rather flabby.",
440 "
\82 \82È
\82½
\82Í
\96c
\82ç
\82Ý
\82Í
\82¶
\82ß
\82½
\8bC
\82ª
\82·
\82é
\81D",
441 "
\82 \82È
\82½
\82Í
\8f
\82µ
\82½
\82é
\82ñ
\82¾
\8bC
\82ª
\82·
\82é
\81D",
448 long i = ((HPasses_walls & TIMEOUT) / 2L);
450 if (EPasses_walls || (HPasses_walls & ~TIMEOUT))
453 if (((HPasses_walls & TIMEOUT) % 2L) && i > 0L && i <= SIZE(phaze_texts))
454 pline1(phaze_texts[SIZE(phaze_texts) - i]);
460 register struct prop *upp;
464 int baseluck = (flags.moonphase == FULL_MOON) ? 1 : 0;
469 if (u.uluck != baseluck
470 && moves % ((u.uhave.amulet || u.ugangr) ? 300 : 600) == 0) {
471 /* Cursed luckstones stop bad luck from timing out; blessed luckstones
472 * stop good luck from timing out; normal luckstones stop both;
473 * neither is stopped if you don't have a luckstone.
474 * Luck is based at 0 usually, +1 if a full moon and -1 on Friday 13th
476 register int time_luck = stone_luck(FALSE);
477 boolean nostone = !carrying(LUCKSTONE) && !stone_luck(TRUE);
479 if (u.uluck > baseluck && (nostone || time_luck < 0))
481 else if (u.uluck < baseluck && (nostone || time_luck > 0))
485 return; /* things past this point could kill you */
494 if (HLevitation & TIMEOUT)
495 levitation_dialogue();
496 if (HPasses_walls & TIMEOUT)
498 if (u.mtimedone && !--u.mtimedone) {
500 u.mtimedone = rnd(100 * youmonst.data->mlevel + 1);
501 else if (is_were(youmonst.data))
502 you_unwere(FALSE); /* if polycontrl, asks whether to rehumanize */
509 /* Dissipate spell-based protection. */
511 if (--u.usptime == 0 && u.uspellprot) {
512 u.usptime = u.uspmtime;
517 Norep("The %s haze around you %s.", hcolor(NH_GOLDEN),
518 u.uspellprot ? "becomes less dense" : "disappears");
520 Norep("
\82 \82È
\82½
\82Ì
\89ñ
\82è
\82Ì%s
\96¶
\82Í%s
\81D", hcolor(NH_GOLDEN),
521 u.uspellprot ? "
\8fÁ
\82¦
\82Í
\82¶
\82ß
\82½" : "
\8fÁ
\82¦
\82½");
527 if (--u.ugallop == 0L && u.usteed)
529 pline("%s stops galloping.", Monnam(u.usteed));
531 pline("%s
\82Í
\91¬
\8bì
\82¯
\82ð
\82â
\82ß
\82½
\81D", Monnam(u.usteed));
534 for (upp = u.uprops; upp < u.uprops + SIZE(u.uprops); upp++)
535 if ((upp->intrinsic & TIMEOUT) && !(--upp->intrinsic & TIMEOUT)) {
536 kptr = find_delayed_killer((int) (upp - u.uprops));
537 switch (upp - u.uprops) {
539 if (kptr && kptr->name[0]) {
540 killer.format = kptr->format;
542 Strcpy(killer.name, kptr->name);
544 Sprintf(killer.name, "%s
\82Ì
\8dU
\8c\82\82Å", kptr->name);
548 killer.format = NO_KILLER_PREFIX;
549 Strcpy(killer.name, "killed by petrification");
551 killer.format = KILLED_BY;
552 Strcpy(killer.name, "
\90Î
\89»
\8dU
\8c\82\82Å");
555 dealloc_killer(kptr);
556 /* (unlike sliming, you aren't changing form here) */
560 if (kptr && kptr->name[0]) {
561 killer.format = kptr->format;
562 Strcpy(killer.name, kptr->name);
564 killer.format = NO_KILLER_PREFIX;
566 Strcpy(killer.name, "turned into green slime");
568 Strcpy(killer.name, "
\97Î
\83X
\83\89\83C
\83\80\82É
\82È
\82Á
\82½");
570 dealloc_killer(kptr);
571 /* involuntarily break "never changed form" conduct */
572 u.uconduct.polyselfs++;
576 make_vomiting(0L, TRUE);
580 You("die from your illness.");
582 You("
\95a
\8bC
\82Å
\8e\80\82ñ
\82¾
\81D");
583 if (kptr && kptr->name[0]) {
584 killer.format = kptr->format;
585 Strcpy(killer.name, kptr->name);
587 killer.format = KILLED_BY_AN;
588 killer.name[0] = 0; /* take the default */
590 dealloc_killer(kptr);
592 if ((m_idx = name_to_mon(killer.name)) >= LOW_PM) {
593 if (type_is_pname(&mons[m_idx])) {
594 killer.format = KILLED_BY;
595 } else if (mons[m_idx].geno & G_UNIQ) {
596 Strcpy(killer.name, the(killer.name));
597 killer.format = KILLED_BY;
606 You_feel("yourself slowing down%s.",
607 Fast ? " a bit" : "");
609 You("%s
\92x
\82
\82È
\82Á
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D",
610 Fast ? "
\82¿
\82å
\82Á
\82Æ" : "");
614 /* So make_confused works properly */
615 set_itimeout(&HConfusion, 1L);
616 make_confused(0L, TRUE);
621 set_itimeout(&HStun, 1L);
622 make_stunned(0L, TRUE);
627 set_itimeout(&Blinded, 1L);
628 make_blinded(0L, TRUE);
633 set_itimeout(&HDeaf, 1L);
641 if (!Invis && !BInvis && !Blind) {
644 ? "are no longer invisible."
645 : "can no longer see through yourself.");
648 ? "
\82à
\82¤
\93§
\96¾
\82Å
\82Í
\82È
\82¢
\81D"
649 : "
\93§
\82«
\82Æ
\82¨
\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
655 set_mimic_blocking(); /* do special mimic handling */
656 see_monsters(); /* make invis mons appear */
657 newsym(u.ux, u.uy); /* make self appear */
667 make_totter(0L, TRUE);
672 set_itimeout(&HHallucination, 1L);
673 (void) make_hallucinated(0L, TRUE, 0L);
678 if (unconscious() || Sleep_resistance) {
679 incr_itimeout(&HSleepy, rnd(100));
684 You("
\96°
\82è
\82É
\97\8e\82¿
\82½
\81D");
686 fall_asleep(-sleeptime, TRUE);
687 incr_itimeout(&HSleepy, sleeptime + rnd(100));
691 (void) float_down(I_SPECIAL | TIMEOUT, 0L);
697 You_feel("hemmed in again.");
699 You_feel("
\82Ü
\82½
\95Â
\82¶
\8d\9e\82ß
\82ç
\82ê
\82½
\82æ
\82¤
\82¾
\81D");
702 pline("You're back to your %s self again.",
703 !Upolyd ? "normal" : "unusual");
705 pline("
\82 \82È
\82½
\82Í
\8dÄ
\82Ñ
\92Ê
\8fí%s
\82Ì
\8fó
\91Ô
\82É
\82È
\82Á
\82½
\81D",
706 !Upolyd ? "" : "
\82Å
\82Í
\82È
\82¢");
711 killer.format = KILLED_BY;
714 (u.uburied) ? "suffocation" : "strangulation");
717 (u.uburied) ? "
\92\82\91§
\82µ
\82Ä" : "
\8eñ
\82ð
\8di
\82ß
\82ç
\82ê
\82Ä");
720 /* must be declining to die in explore|wizard mode;
721 treat like being cured of strangulation by prayer */
722 if (uamul && uamul->otyp == AMULET_OF_STRANGULATION) {
724 Your("amulet vanishes!");
726 Your("
\96\82\8f\9c\82¯
\82Í
\8fÁ
\82¦
\82½
\81I");
731 /* call this only when a move took place. */
732 /* otherwise handle fumbling msgs locally. */
733 if (u.umoved && !Levitation) {
737 multi_reason = "fumbling";
739 multi_reason = "
\82Ö
\82Ü
\82ð
\82µ
\82½
\8c\84\82É";
741 /* The more you are carrying the more likely you
742 * are to make noise when you fumble. Adjustments
743 * to this number must be thoroughly play tested.
745 if ((inv_weight() > -500)) {
747 You("make a lot of noise!");
749 You("
\91å
\82«
\82È
\89¹
\82ð
\82½
\82Ä
\82½
\81I");
753 /* from outside means slippery ice; don't reset
754 counter if that's the only fumble reason */
755 HFumbling &= ~FROMOUTSIDE;
757 incr_itimeout(&HFumbling, rnd(20));
759 case DETECT_MONSTERS:
769 fall_asleep(how_long, wakeup_msg)
776 multi_reason = "sleeping";
778 multi_reason = "
\96°
\82è
\82Ì
\82³
\82È
\82©
\82É";
779 /* generally don't notice sounds while sleeping */
780 if (wakeup_msg && multi == how_long) {
781 /* caller can follow with a direct call to Hear_again() if
782 there's a need to override this when wakeup_msg is true */
783 incr_itimeout(&HDeaf, how_long);
785 afternmv = Hear_again; /* this won't give any messages */
787 /* early wakeup from combat won't be possible until next monster turn */
788 u.usleep = monstermoves;
790 nomovemsg = wakeup_msg ? "You wake up." : You_can_move_again;
792 nomovemsg = wakeup_msg ? "
\96Ú
\82ð
\8ao
\82Ü
\82µ
\82½
\81D" : You_can_move_again;
795 /* Attach an egg hatch timeout to the given egg.
796 * when = Time to hatch, usually only passed if re-creating an
797 * existing hatch timer. Pass 0L for random hatch time.
800 attach_egg_hatch_timeout(egg, when)
806 /* stop previous timer, if any */
807 (void) stop_timer(HATCH_EGG, obj_to_any(egg));
810 * Decide if and when to hatch the egg. The old hatch_it() code tried
811 * once a turn from age 151 to 200 (inclusive), hatching if it rolled
812 * a number x, 1<=x<=age, where x>150. This yields a chance of
813 * hatching > 99.9993%. Mimic that here.
816 for (i = (MAX_EGG_HATCH_TIME - 50) + 1; i <= MAX_EGG_HATCH_TIME; i++)
824 (void) start_timer(when, TIMER_OBJECT, HATCH_EGG, obj_to_any(egg));
828 /* prevent an egg from ever hatching */
833 /* stop previous timer, if any */
834 (void) stop_timer(HATCH_EGG, obj_to_any(egg));
837 /* timer callback routine: hatch the given egg */
839 hatch_egg(arg, timeout)
844 struct monst *mon, *mon2;
847 boolean yours, silent, knows_egg = FALSE;
848 boolean cansee_hatchspot = FALSE;
849 int i, mnum, hatchcount = 0;
852 /* sterilized while waiting */
853 if (egg->corpsenm == NON_PM)
856 mon = mon2 = (struct monst *) 0;
857 mnum = big_to_little(egg->corpsenm);
858 /* The identity of one's father is learned, not innate */
859 yours = (egg->spe || (!flags.female && carried(egg) && !rn2(2)));
860 silent = (timeout != monstermoves); /* hatched while away */
862 /* only can hatch when in INVENT, FLOOR, MINVENT */
863 if (get_obj_location(egg, &x, &y, 0)) {
864 hatchcount = rnd((int) egg->quan);
865 cansee_hatchspot = cansee(x, y) && !silent;
866 if (!(mons[mnum].geno & G_UNIQ)
867 && !(mvitals[mnum].mvflags & (G_GENOD | G_EXTINCT))) {
868 for (i = hatchcount; i > 0; i--) {
869 if (!enexto(&cc, x, y, &mons[mnum])
870 || !(mon = makemon(&mons[mnum], cc.x, cc.y, NO_MINVENT)))
872 /* tame if your own egg hatches while you're on the
873 same dungeon level, or any dragon egg which hatches
874 while it's in your inventory */
875 if ((yours && !silent)
876 || (carried(egg) && mon->data->mlet == S_DRAGON)) {
877 if (tamedog(mon, (struct obj *) 0)) {
878 if (carried(egg) && mon->data->mlet != S_DRAGON)
882 if (mvitals[mnum].mvflags & G_EXTINCT)
883 break; /* just made last one */
884 mon2 = mon; /* in case makemon() fails on 2nd egg */
889 egg->quan -= (long) hatchcount;
893 * We could possibly hatch while migrating, but the code isn't
896 } else if (obj->where == OBJ_MIGRATING) {
898 * We can do several things. The first ones that come to
900 * + Create the hatched monster then place it on the migrating
901 * mons list. This is tough because all makemon() is made
902 * to place the monster as well. Makemon() also doesn't lend
903 * itself well to splitting off a "not yet placed" subroutine.
904 * + Mark the egg as hatched, then place the monster when we
905 * place the migrating objects.
906 * + Or just kill any egg which gets sent to another level.
907 * Falling is the usual reason such transportation occurs.
909 cansee_hatchspot = FALSE;
915 char monnambuf[BUFSZ], carriedby[BUFSZ];
916 boolean siblings = (hatchcount > 1), redraw = FALSE;
918 if (cansee_hatchspot) {
919 /* [bug? m_monnam() yields accurate monster type
920 regardless of hallucination] */
922 Sprintf(monnambuf, "%s%s", siblings ? "some " : "",
923 siblings ? makeplural(m_monnam(mon)) : an(m_monnam(mon)));
925 Sprintf(monnambuf, "%s%s", siblings ? "
\82¢
\82
\82Â
\82©
\82Ì" : "",
928 /* we don't learn the egg type here because learning
929 an egg type requires either seeing the egg hatch
930 or being familiar with the egg already,
931 as well as being able to see the resulting
932 monster, checked below
935 switch (egg->where) {
937 knows_egg = TRUE; /* true even if you are blind */
938 if (!cansee_hatchspot)
940 You_feel("%s %s from your pack!", something,
941 locomotion(mon->data, "drop"));
943 pline("
\89½
\82©
\82ª
\82 \82È
\82½
\82Ì
\94w
\95\89\82¢
\91Ü
\82©
\82ç%s
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D",
944 jpast(locomotion(mon->data, "
\97\8e\82¿
\82é")));
948 You_see("%s %s out of your pack!", monnambuf,
949 locomotion(mon->data, "drop"));
951 You("%s
\82ª
\82 \82È
\82½
\82Ì
\94w
\95\89\82¢
\91Ü
\82©
\82ç%s
\82Ì
\82ð
\8c©
\82½
\81D", monnambuf,
952 jpast(locomotion(mon->data, "
\97\8e\82¿
\82é")));
956 pline("%s cries sound like \"%s%s\"",
957 siblings ? "Their" : "Its",
958 flags.female ? "mommy" : "daddy", egg->spe ? "." : "?");
960 pline("
\82»
\82ê
\82Í
\81w%s%s
\81x
\82Æ
\96Â
\82¢
\82Ä
\82¢
\82é
\82æ
\82¤
\82¾
\81D",
961 flags.female ? "
\83}
\83}" : "
\83p
\83p", egg->spe ? "" : "
\81H");
963 } else if (mon->data->mlet == S_DRAGON && !Deaf) {
965 verbalize("Gleep!"); /* Mything eggs :-) */
967 verbalize("
\83u
\83H
\81[
\81I"); /* Mything eggs :-) */
973 if (cansee_hatchspot) {
976 You_see("%s hatch.", monnambuf);
978 You("%s
\82ª
\97\91\82©
\82ç
\82©
\82¦
\82é
\82Ì
\82ð
\8c©
\82½
\81D", monnambuf);
979 redraw = TRUE; /* update egg's map location */
984 if (cansee_hatchspot) {
985 /* egg carrying monster might be invisible */
988 && (!mon2->wormno || cansee(mon2->mx, mon2->my))) {
990 Sprintf(carriedby, "%s pack",
991 s_suffix(a_monnam(mon2)));
993 Sprintf(carriedby, "%s
\82Ì
\94w
\95\89\82¢
\91Ü
\82©
\82ç",
997 } else if (is_pool(mon->mx, mon->my)) {
999 Strcpy(carriedby, "empty water");
1001 Strcpy(carriedby, "
\89½
\82à
\82È
\82¢
\90\85\92\86\82©
\82ç");
1004 Strcpy(carriedby, "thin air");
1006 Strcpy(carriedby, "
\89½
\82à
\82È
\82¢
\8bó
\8aÔ
\82©
\82ç");
1009 You_see("%s %s out of %s!", monnambuf,
1010 locomotion(mon->data, "drop"), carriedby);
1012 You("%s
\82ª%s%s
\82Ì
\82ð
\8c©
\82½
\81D", monnambuf, carriedby,
1013 locomotion(mon->data, "
\97\8e\82¿
\82é"));
1022 impossible("egg hatched where? (%d)", (int) egg->where);
1026 if (cansee_hatchspot && knows_egg)
1027 learn_egg_type(mnum);
1029 if (egg->quan > 0) {
1030 /* still some eggs left */
1031 /* Instead of ordinary egg timeout use a short one */
1032 attach_egg_hatch_timeout(egg, (long) rnd(12));
1033 } else if (carried(egg)) {
1036 /* free egg here because we use it above */
1037 obj_extract_self(egg);
1038 obfree(egg, (struct obj *) 0);
1045 /* Learn to recognize eggs of the given type. */
1047 learn_egg_type(mnum)
1050 /* baby monsters hatch from grown-up eggs */
1051 mnum = little_to_big(mnum);
1052 mvitals[mnum].mvflags |= MV_KNOWS_EGG;
1053 /* we might have just learned about other eggs being carried */
1057 /* Attach a fig_transform timeout to the given figurine. */
1059 attach_fig_transform_timeout(figurine)
1060 struct obj *figurine;
1064 /* stop previous timer, if any */
1065 (void) stop_timer(FIG_TRANSFORM, obj_to_any(figurine));
1068 * Decide when to transform the figurine.
1070 i = rnd(9000) + 200;
1071 /* figurine will transform */
1072 (void) start_timer((long) i, TIMER_OBJECT, FIG_TRANSFORM,
1073 obj_to_any(figurine));
1076 /* give a fumble message */
1080 struct obj *otmp = vobj_at(u.ux, u.uy), *otmp2;
1083 boolean on_foot = TRUE;
1087 if (otmp && on_foot && !u.uinwater && is_pool(u.ux, u.uy))
1090 if (otmp && on_foot) { /* trip over something in particular */
1092 If there is only one item, it will have just been named
1093 during the move, so refer to by via pronoun; otherwise,
1094 if the top item has been or can be seen, refer to it by
1095 name; if not, look for rocks to trip over; trip over
1096 anonymous "something" if there aren't any rocks.
1099 what = (iflags.last_msg == PLNMSG_ONE_ITEM_HERE)
1100 ? ((otmp->quan == 1L) ? "it"
1101 : Hallucination ? "they" : "them")
1102 : (otmp->dknown || !Blind)
1104 : ((otmp2 = sobj_at(ROCK, u.ux, u.uy)) == 0
1106 : (otmp2->quan == 1L ? "a rock" : "some rocks"));
1108 what = (iflags.last_msg == PLNMSG_ONE_ITEM_HERE)
1110 : (otmp->dknown || !Blind)
1112 : ((otmp2 = sobj_at(ROCK, u.ux, u.uy)) == 0
1116 if (Hallucination) {
1117 what = strcpy(buf, what);
1118 buf[0] = highc(buf[0]);
1120 pline("Egads! %s bite%s your %s!", what,
1121 (!otmp || otmp->quan == 1L) ? "s" : "", body_part(FOOT));
1123 pline("
\82®
\82í
\82\9f\81I%s
\82ª%s
\82É
\8a\9a\82Ý
\82Â
\82¢
\82½
\81I", what, body_part(FOOT));
1127 You("trip over %s.", what);
1129 You("%s
\82É
\82Â
\82Ü
\82Ã
\82¢
\82½
\81D", what);
1131 if (!uarmf && otmp->otyp == CORPSE
1132 && touch_petrifies(&mons[otmp->corpsenm]) && !Stone_resistance) {
1134 Sprintf(killer.name, "tripping over %s corpse",
1135 an(mons[otmp->corpsenm].mname));
1137 Sprintf(killer.name, "%s
\82Ì
\8e\80\91Ì
\82É
\82Â
\82Ü
\82Ã
\82¢
\82Ä",
1138 mons[otmp->corpsenm].mname);
1140 instapetrify(killer.name);
1142 } else if (rn2(3) && is_ice(u.ux, u.uy)) {
1144 pline("%s %s%s on the ice.",
1145 u.usteed ? upstart(x_monnam(u.usteed,
1146 (has_mname(u.usteed)) ? ARTICLE_NONE
1148 (char *) 0, SUPPRESS_SADDLE, FALSE))
1150 rn2(2) ? "slip" : "slide", on_foot ? "" : "s");
1152 pline("%s
\82Í
\95X
\82Ì
\8fã
\82Å
\8a\8a\82Á
\82½
\81D",
1153 u.usteed ? upstart(x_monnam(u.usteed,
1154 (has_mname(u.usteed)) ? ARTICLE_NONE
1156 (char *) 0, SUPPRESS_SADDLE, FALSE))
1164 You("trip over your own %s.",
1165 Hallucination ? "elbow" : makeplural(body_part(FOOT)));
1167 You("
\8e©
\95ª
\82Ì%s
\82ð
\93¥
\82ñ
\82Å
\82Â
\82Ü
\82Ã
\82¢
\82½
\81D",
1168 Hallucination ? "
\95I" : body_part(FOOT));
1174 Hallucination ? "on a banana peel" : "and nearly fall");
1176 You("%s
\81D", Hallucination ?
1177 "
\83o
\83i
\83i
\82Ì
\94ç
\82Å
\8a\8a\82Á
\82½" : "
\8a\8a\82Á
\82Ä
\93]
\82Ñ
\82»
\82¤
\82É
\82È
\82Á
\82½");
1184 You("
\82¶
\82½
\82Î
\82½
\82µ
\82½
\81D");
1190 You("
\82æ
\82ë
\82ß
\82¢
\82½
\81D");
1197 Your("%s slip out of the stirrups.",
1198 makeplural(body_part(FOOT)));
1200 You("
\82 \82Ô
\82Ý
\82ð
\93¥
\82Ý
\8aO
\82µ
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D");
1205 You("let go of the reins.");
1207 You("
\8eè
\8dj
\82ð
\95ú
\82µ
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D");
1211 You("bang into the saddle-horn.");
1213 You("
\83T
\83h
\83\8b\83z
\81[
\83\93\82É
\82Ô
\82Â
\82©
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D");
1217 You("slide to one side of the saddle.");
1219 You("
\82·
\82×
\82Á
\82Ä
\88Æ
\82Ì
\95Ð
\91¤
\82É
\82¸
\82ê
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D");
1222 dismount_steed(DISMOUNT_FELL);
1227 /* Print a lamp flicker message with tailer. */
1229 see_lamp_flicker(obj, tailer)
1233 switch (obj->where) {
1237 pline("%s flickers%s.", Yname2(obj), tailer);
1239 pline("%s
\82Í%s
\93_
\96Å
\82µ
\82½
\81D", Yname2(obj), tailer);
1243 You_see("%s flicker%s.", an(xname(obj)), tailer);
1245 You("%s
\82ª%s
\93_
\96Å
\82·
\82é
\82Ì
\82ð
\8c©
\82½
\81D", an(xname(obj)), tailer);
1250 /* Print a dimming message for brass lanterns. */
1252 lantern_message(obj)
1255 /* from adventure */
1256 switch (obj->where) {
1259 Your("lantern is getting dim.");
1261 Your("
\83\89\83\93\83^
\83\93\82Í
\88Ã
\82
\82È
\82Á
\82Ä
\82«
\82½
\81D");
1264 pline("Batteries have not been invented yet.");
1266 pline("
\93d
\92r
\82Í
\82Ü
\82¾
\94
\96¾
\82³
\82ê
\82Ä
\82È
\82¢
\82ñ
\82¾
\82Á
\82¯
\81D");
1270 You_see("a lantern getting dim.");
1272 pline("
\83\89\83\93\83^
\83\93\82ª
\88Ã
\82
\82È
\82Á
\82Ä
\82«
\82½
\82Ì
\82ª
\8c©
\82¦
\82½
\81D");
1276 pline("%s lantern is getting dim.", s_suffix(Monnam(obj->ocarry)));
1278 pline("%s
\82Ì
\83\89\83\93\83^
\83\93\82Í
\88Ã
\82
\82È
\82Á
\82Ä
\82«
\82½
\81D", Monnam(obj->ocarry));
1284 * Timeout callback for for objects that are burning. E.g. lamps, candles.
1285 * See begin_burn() for meanings of obj->age and obj->spe.
1288 burn_object(arg, timeout)
1292 struct obj *obj = arg->a_obj;
1294 boolean canseeit, many, menorah, need_newsym, need_invupdate;
1296 boolean canseeit, menorah, need_newsym, need_invupdate;
1301 menorah = obj->otyp == CANDELABRUM_OF_INVOCATION;
1303 many = menorah ? obj->spe > 1 : obj->quan > 1L;
1306 /* timeout while away */
1307 if (timeout != monstermoves) {
1308 long how_long = monstermoves - timeout;
1310 if (how_long >= obj->age) {
1312 end_burn(obj, FALSE);
1315 obj->spe = 0; /* no more candles */
1316 obj->owt = weight(obj);
1317 } else if (Is_candle(obj) || obj->otyp == POT_OIL) {
1318 /* get rid of candles and burning oil potions;
1319 we know this object isn't carried by hero,
1320 nor is it migrating */
1321 obj_extract_self(obj);
1322 obfree(obj, (struct obj *) 0);
1323 obj = (struct obj *) 0;
1327 obj->age -= how_long;
1328 begin_burn(obj, TRUE);
1333 /* only interested in INVENT, FLOOR, and MINVENT */
1334 if (get_obj_location(obj, &x, &y, 0)) {
1335 canseeit = !Blind && cansee(x, y);
1336 /* set `whose[]' to be "Your " or "Fred's " or "The goblin's " */
1337 (void) Shk_Your(whose, obj);
1341 need_newsym = need_invupdate = FALSE;
1343 /* obj->age is the age remaining at this point. */
1344 switch (obj->otyp) {
1346 /* this should only be called when we run out */
1348 switch (obj->where) {
1350 need_invupdate = TRUE;
1354 pline("%spotion of oil has burnt away.", whose);
1356 pline("%s
\83I
\83C
\83\8b\82Í
\94R
\82¦
\82Â
\82«
\82½
\81D", whose);
1360 You_see("a burning potion of oil go out.");
1362 You("
\83I
\83C
\83\8b\82Ì
\89Î
\82ª
\8fÁ
\82¦
\82½
\82Ì
\82ð
\8c©
\82½
\81D");
1367 end_burn(obj, FALSE); /* turn off light source */
1371 /* clear migrating obj's destination code before obfree
1372 to avoid false complaint of deleting worn item */
1373 if (obj->where == OBJ_MIGRATING)
1374 obj->owornmask = 0L;
1375 obj_extract_self(obj);
1376 obfree(obj, (struct obj *) 0);
1378 obj = (struct obj *) 0;
1383 switch ((int) obj->age) {
1388 if (obj->otyp == BRASS_LANTERN)
1389 lantern_message(obj);
1391 see_lamp_flicker(obj,
1393 obj->age == 50L ? " considerably" : "");
1395 obj->age == 50L ? "
\8c\83\82µ
\82" : "");
1401 if (obj->otyp == BRASS_LANTERN)
1402 lantern_message(obj);
1404 switch (obj->where) {
1408 pline("%s seems about to go out.", Yname2(obj));
1410 pline("%s
\82Í
\8d¡
\82É
\82à
\8fÁ
\82¦
\82»
\82¤
\82¾
\81D", Yname2(obj));
1414 You_see("%s about to go out.", an(xname(obj)));
1416 pline("%s
\82ª
\8fÁ
\82¦
\82©
\82¯
\82Ä
\82¢
\82é
\82Ì
\82ª
\8c©
\82¦
\82½
\81D", an(xname(obj)));
1424 /* even if blind you'll know if holding it */
1425 if (canseeit || obj->where == OBJ_INVENT) {
1426 switch (obj->where) {
1428 need_invupdate = TRUE;
1431 if (obj->otyp == BRASS_LANTERN)
1433 pline("%slantern has run out of power.", whose);
1435 pline("%s
\83\89\83\93\83^
\83\93\82Ì
\97Í
\82ð
\8eg
\82¢
\90Ø
\82Á
\82½
\81D", whose);
1438 pline("%s has gone out.", Yname2(obj));
1440 pline("%s
\82Í
\8fÁ
\82¦
\82½
\81D", Yname2(obj));
1443 if (obj->otyp == BRASS_LANTERN)
1445 You_see("a lantern run out of power.");
1447 You("
\83\89\83\93\83^
\83\93\82ª
\8fÁ
\82¦
\82é
\82Ì
\82ð
\8c©
\82½
\81D");
1450 You_see("%s go out.", an(xname(obj)));
1452 You("%s
\82ª
\8fÁ
\82¦
\82é
\82Ì
\82ð
\8c©
\82½
\81D", an(xname(obj)));
1456 end_burn(obj, FALSE);
1461 * Someone added fuel to the lamp while it was
1462 * lit. Just fall through and let begin burn
1463 * handle the new age.
1469 begin_burn(obj, TRUE);
1473 case CANDELABRUM_OF_INVOCATION:
1479 switch (obj->where) {
1483 pline("%s%scandle%s getting short.", whose,
1484 menorah ? "candelabrum's " : "",
1485 many ? "s are" : " is");
1487 pline("%s%s
\82ë
\82¤
\82»
\82
\82Í
\92Z
\82
\82È
\82Á
\82½
\81D", whose,
1488 menorah ? "
\90C
\91ä
\82Ì" : "");
1493 You_see("%scandle%s getting short.",
1494 menorah ? "a candelabrum's " : many ? "some "
1498 You("%s
\82ë
\82¤
\82»
\82
\82ª
\92Z
\82
\82È
\82é
\82Ì
\82ð
\8c©
\82½
\81D",
1499 menorah ? "
\90C
\91ä
\82Ì" : "");
1507 switch (obj->where) {
1511 pline("%s%scandle%s flame%s flicker%s low!", whose,
1512 menorah ? "candelabrum's " : "", many ? "s'" : "'s",
1513 many ? "s" : "", many ? "" : "s");
1515 pline("%s%s
\82ë
\82¤
\82»
\82
\82Ì
\89\8a\82Í
\93_
\96Å
\82µ
\81C
\88Ã
\82
\82È
\82Á
\82½
\81I", whose,
1516 menorah ? "
\90C
\91ä
\82Ì" : "");
1521 You_see("%scandle%s flame%s flicker low!",
1522 menorah ? "a candelabrum's " : many ? "some "
1524 many ? "s'" : "'s", many ? "s" : "");
1526 You("%s
\82ë
\82¤
\82»
\82
\82Ì
\89\8a\82ª
\93_
\96Å
\82µ
\81C
\88Ã
\82
\82È
\82é
\82Ì
\82ð
\8c©
\82½
\81I",
1527 menorah ? "
\90C
\91ä
\82Ì" : "");
1534 /* we know even if blind and in our inventory */
1535 if (canseeit || obj->where == OBJ_INVENT) {
1537 switch (obj->where) {
1539 need_invupdate = TRUE;
1543 pline("%scandelabrum's flame%s.", whose,
1544 many ? "s die" : " dies");
1546 pline("%s
\90C
\91ä
\82Ì
\89\8a\82Í
\8fÁ
\82¦
\82½
\81D", whose);
1551 You_see("a candelabrum's flame%s die.",
1554 You("
\90C
\91ä
\82Ì
\89\8a\82ª
\8fÁ
\82¦
\82é
\82Ì
\82ð
\8c©
\82½
\81D");
1559 switch (obj->where) {
1561 /* no need_invupdate for update_inventory() necessary;
1562 useupall() -> freeinv() handles it */
1566 pline("%s %s consumed!", Yname2(obj),
1567 many ? "are" : "is");
1569 pline("%s
\82Í
\94R
\82¦
\82Â
\82«
\82½
\81I", Yname2(obj));
1574 You see some wax candles consumed!
1575 You see a wax candle consumed!
1578 You_see("%s%s consumed!", many ? "some " : "",
1579 many ? xname(obj) : an(xname(obj)));
1581 You("%s
\82ª
\94R
\82¦
\82Â
\82«
\82é
\82Ì
\82ð
\8c©
\82½
\81I", xname(obj));
1590 ? (many ? "They shriek!" : "It shrieks!")
1591 : Blind ? "" : (many ? "Their flames die."
1592 : "Its flame dies."));
1594 pline(Hallucination ? "
\82»
\82ê
\82Í
\8bà
\90Ø
\82è
\90º
\82ð
\82 \82°
\82½
\81I"
1596 : "
\89\8a\82Í
\8fÁ
\82¦
\82½
\81D");
1600 end_burn(obj, FALSE);
1604 obj->owt = weight(obj);
1609 /* clear migrating obj's destination code
1610 so obfree won't think this item is worn */
1611 if (obj->where == OBJ_MIGRATING)
1612 obj->owornmask = 0L;
1613 obj_extract_self(obj);
1614 obfree(obj, (struct obj *) 0);
1616 obj = (struct obj *) 0;
1618 break; /* case [age ==] 0 */
1622 * Someone added fuel (candles) to the menorah while
1623 * it was lit. Just fall through and let begin burn
1624 * handle the new age.
1629 if (obj && obj->age)
1630 begin_burn(obj, TRUE);
1631 break; /* case [otyp ==] candelabrum|tallow_candle|wax_candle */
1634 impossible("burn_object: unexpeced obj %s", xname(obj));
1644 * Start a burn timeout on the given object. If not "already lit" then
1645 * create a light source for the vision system. There had better not
1646 * be a burn already running on the object.
1648 * Magic lamps stay lit as long as there's a genie inside, so don't start
1652 * potions of oil, lamps & candles:
1653 * age = # of turns of fuel left
1657 * spe = 0 not lightable, 1 lightable forever
1659 * age = # of turns of fuel left
1660 * spe = # of candles
1662 * Once the burn begins, the age will be set to the amount of fuel
1663 * remaining _once_the_burn_finishes_. If the burn is terminated
1664 * early then fuel is added back.
1666 * This use of age differs from the use of age for corpses and eggs.
1667 * For the latter items, age is when the object was created, so we
1668 * know when it becomes "bad".
1670 * This is a "silent" routine - it should not print anything out.
1673 begin_burn(obj, already_lit)
1675 boolean already_lit;
1679 boolean do_timer = TRUE;
1681 if (obj->age == 0 && obj->otyp != MAGIC_LAMP && !artifact_light(obj))
1684 switch (obj->otyp) {
1692 radius = 1; /* very dim light */
1697 /* magic times are 150, 100, 50, 25, and 0 */
1698 if (obj->age > 150L)
1699 turns = obj->age - 150L;
1700 else if (obj->age > 100L)
1701 turns = obj->age - 100L;
1702 else if (obj->age > 50L)
1703 turns = obj->age - 50L;
1704 else if (obj->age > 25L)
1705 turns = obj->age - 25L;
1710 case CANDELABRUM_OF_INVOCATION:
1713 /* magic times are 75, 15, and 0 */
1715 turns = obj->age - 75L;
1716 else if (obj->age > 15L)
1717 turns = obj->age - 15L;
1720 radius = candle_light_range(obj);
1724 /* [ALI] Support artifact light sources */
1725 if (artifact_light(obj)) {
1728 radius = arti_light_radius(obj);
1730 impossible("begin burn: unexpected %s", xname(obj));
1737 if (start_timer(turns, TIMER_OBJECT, BURN_OBJECT, obj_to_any(obj))) {
1740 if (carried(obj) && !already_lit)
1746 if (carried(obj) && !already_lit)
1750 if (obj->lamplit && !already_lit) {
1753 if (get_obj_location(obj, &x, &y, CONTAINED_TOO | BURIED_TOO))
1754 new_light_source(x, y, radius, LS_OBJECT, obj_to_any(obj));
1756 impossible("begin_burn: can't get obj position");
1761 * Stop a burn timeout on the given object if timer attached. Darken
1765 end_burn(obj, timer_attached)
1767 boolean timer_attached;
1769 if (!obj->lamplit) {
1770 impossible("end_burn: obj %s not lit", xname(obj));
1774 if (obj->otyp == MAGIC_LAMP || artifact_light(obj))
1775 timer_attached = FALSE;
1777 if (!timer_attached) {
1778 /* [DS] Cleanup explicitly, since timer cleanup won't happen */
1779 del_light_source(LS_OBJECT, obj_to_any(obj));
1781 if (obj->where == OBJ_INVENT)
1783 } else if (!stop_timer(BURN_OBJECT, obj_to_any(obj)))
1784 impossible("end_burn: obj %s not timed!", xname(obj));
1788 * Cleanup a burning object if timer stopped.
1791 cleanup_burn(arg, expire_time)
1795 struct obj *obj = arg->a_obj;
1796 if (!obj->lamplit) {
1797 impossible("cleanup_burn: obj %s not lit", xname(obj));
1801 del_light_source(LS_OBJECT, obj_to_any(obj));
1803 /* restore unused time */
1804 obj->age += expire_time - monstermoves;
1808 if (obj->where == OBJ_INVENT)
1820 /* no lightning if not the air level or too often, even then */
1821 if (!Is_airlevel(&u.uz) || rn2(8))
1824 /* the number of strikes is 8-log2(nstrike) */
1825 for (nstrike = rnd(64); nstrike <= 64; nstrike *= 2) {
1830 } while (++count < 100 && levl[x][y].typ != CLOUD);
1835 if (dirx != 0 || diry != 0)
1836 buzz(-15, /* "monster" LIGHTNING spell */
1837 8, x, y, dirx, diry);
1841 if (levl[u.ux][u.uy].typ == CLOUD) {
1842 /* Inside a cloud during a thunder storm is deafening. */
1843 /* Even if already deaf, we sense the thunder's vibrations. */
1845 pline("Kaboom!!! Boom!! Boom!!");
1847 pline("
\83s
\83J
\83b
\81I
\81I
\83S
\83\8d\83S
\83\8d\83S
\83\8d\83S
\83\8d\81I
\81I
\83h
\81[
\83\93\81I");
1848 incr_itimeout(&HDeaf, rn1(20, 30));
1849 context.botl = TRUE;
1850 if (!u.uinvulnerable) {
1854 multi_reason = "hiding from thunderstorm";
1856 multi_reason = "
\97\8b\82Ì
\97\92\82ð
\94ð
\82¯
\82Ä
\82¢
\82é
\8e\9e\82É";
1861 You_hear("a rumbling noise.");
1863 You_hear("
\97\8b\82Ì
\89¹
\82ð
\95·
\82¢
\82½
\81D");
1866 /* -------------------------------------------------------------------------
1869 * Generic Timeout Functions.
1874 * boolean start_timer(long timeout,short kind,short func_index,
1876 * Start a timer of kind 'kind' that will expire at time
1877 * monstermoves+'timeout'. Call the function at 'func_index'
1878 * in the timeout table using argument 'arg'. Return TRUE if
1879 * a timer was started. This places the timer on a list ordered
1880 * "sooner" to "later". If an object, increment the object's
1883 * long stop_timer(short func_index, anything *arg)
1884 * Stop a timer specified by the (func_index, arg) pair. This
1885 * assumes that such a pair is unique. Return the time the
1886 * timer would have gone off. If no timer is found, return 0.
1887 * If an object, decrement the object's timer count.
1889 * long peek_timer(short func_index, anything *arg)
1890 * Return time specified timer will go off (0 if no such timer).
1892 * void run_timers(void)
1893 * Call timers that have timed out.
1896 * void save_timers(int fd, int mode, int range)
1897 * Save all timers of range 'range'. Range is either global
1898 * or local. Global timers follow game play, local timers
1899 * are saved with a level. Object and monster timers are
1900 * saved using their respective id's instead of pointers.
1902 * void restore_timers(int fd, int range, boolean ghostly, long adjust)
1903 * Restore timers of range 'range'. If from a ghost pile,
1904 * adjust the timeout by 'adjust'. The object and monster
1905 * ids are not restored until later.
1907 * void relink_timers(boolean ghostly)
1908 * Relink all object and monster timers that had been saved
1909 * using their object's or monster's id number.
1912 * void obj_move_timers(struct obj *src, struct obj *dest)
1913 * Reassign all timers from src to dest.
1915 * void obj_split_timers(struct obj *src, struct obj *dest)
1916 * Duplicate all timers assigned to src and attach them to dest.
1918 * void obj_stop_timers(struct obj *obj)
1919 * Stop all timers attached to obj.
1921 * boolean obj_has_timer(struct obj *object, short timer_type)
1922 * Check whether object has a timer of type timer_type.
1925 STATIC_DCL const char *FDECL(kind_name, (SHORT_P));
1926 STATIC_DCL void FDECL(print_queue, (winid, timer_element *));
1927 STATIC_DCL void FDECL(insert_timer, (timer_element *));
1928 STATIC_DCL timer_element *FDECL(remove_timer,
1929 (timer_element **, SHORT_P, ANY_P *));
1930 STATIC_DCL void FDECL(write_timer, (int, timer_element *));
1931 STATIC_DCL boolean FDECL(mon_is_local, (struct monst *));
1932 STATIC_DCL boolean FDECL(timer_is_local, (timer_element *));
1933 STATIC_DCL int FDECL(maybe_write_timer, (int, int, BOOLEAN_P));
1935 /* ordered timer list */
1936 static timer_element *timer_base; /* "active" */
1937 static unsigned long timer_id = 1;
1939 /* If defined, then include names when printing out the timer queue */
1940 #define VERBOSE_TIMER
1943 timeout_proc f, cleanup;
1944 #ifdef VERBOSE_TIMER
1946 #define TTAB(a, b, c) \
1951 #define TTAB(a, b, c) \
1958 /* table of timeout functions */
1959 static const ttable timeout_funcs[NUM_TIME_FUNCS] = {
1960 TTAB(rot_organic, (timeout_proc) 0, "rot_organic"),
1961 TTAB(rot_corpse, (timeout_proc) 0, "rot_corpse"),
1962 TTAB(revive_mon, (timeout_proc) 0, "revive_mon"),
1963 TTAB(burn_object, cleanup_burn, "burn_object"),
1964 TTAB(hatch_egg, (timeout_proc) 0, "hatch_egg"),
1965 TTAB(fig_transform, (timeout_proc) 0, "fig_transform"),
1966 TTAB(melt_ice_away, (timeout_proc) 0, "melt_ice_away")
1970 STATIC_OVL const char *
1988 print_queue(win, base)
1990 timer_element *base;
1992 timer_element *curr;
1996 putstr(win, 0, " <empty>");
1998 putstr(win, 0, "timeout id kind call");
1999 for (curr = base; curr; curr = curr->next) {
2000 #ifdef VERBOSE_TIMER
2001 Sprintf(buf, " %4ld %4ld %-6s %s(%s)", curr->timeout,
2002 curr->tid, kind_name(curr->kind),
2003 timeout_funcs[curr->func_index].name,
2004 fmt_ptr((genericptr_t) curr->arg.a_void));
2006 Sprintf(buf, " %4ld %4ld %-6s #%d(%s)", curr->timeout,
2007 curr->tid, kind_name(curr->kind), curr->func_index,
2008 fmt_ptr((genericptr_t) curr->arg.a_void));
2010 putstr(win, 0, buf);
2020 const char *propname;
2022 int i, p, count, longestlen, ln, specindx = 0;
2024 win = create_nhwindow(NHW_MENU); /* corner text window */
2028 Sprintf(buf, "Current time = %ld.", monstermoves);
2029 putstr(win, 0, buf);
2031 putstr(win, 0, "Active timeout queue:");
2033 print_queue(win, timer_base);
2036 * check every one; the majority can't obtain temporary timeouts in
2037 * normal play but those can be forced via the #wizintrinsic command.
2039 count = longestlen = 0;
2040 for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) {
2041 p = propertynames[i].prop_num;
2042 intrinsic = u.uprops[p].intrinsic;
2043 if (intrinsic & TIMEOUT) {
2045 if ((ln = (int) strlen(propname)) > longestlen)
2048 if (specindx == 0 && p == FIRE_RES)
2053 putstr(win, 0, "No timed properties.");
2055 putstr(win, 0, "Timed properties:");
2057 for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) {
2058 p = propertynames[i].prop_num;
2059 intrinsic = u.uprops[p].intrinsic;
2060 if (intrinsic & TIMEOUT) {
2061 if (specindx > 0 && i >= specindx) {
2062 putstr(win, 0, " -- settable via #wizinstrinc only --");
2065 /* timeout value can be up to 16777215 (0x00ffffff) but
2066 width of 4 digits should result in values lining up
2067 almost all the time (if/when they don't, it won't
2068 look nice but the information will still be accurate) */
2069 Sprintf(buf, " %*s %4ld", -longestlen, propname,
2070 (intrinsic & TIMEOUT));
2071 putstr(win, 0, buf);
2075 display_nhwindow(win, FALSE);
2076 destroy_nhwindow(win);
2082 timer_sanity_check()
2084 timer_element *curr;
2086 /* this should be much more complete */
2087 for (curr = timer_base; curr; curr = curr->next)
2088 if (curr->kind == TIMER_OBJECT) {
2089 struct obj *obj = curr->arg.a_obj;
2091 if (obj->timed == 0) {
2092 pline("timer sanity: untimed obj %s, timer %ld",
2093 fmt_ptr((genericptr_t) obj), curr->tid);
2099 * Pick off timeout elements from the global queue and call their functions.
2100 * Do this until their time is less than or equal to the move count.
2105 timer_element *curr;
2108 * Always use the first element. Elements may be added or deleted at
2109 * any time. The list is ordered, we are done when the first element
2112 while (timer_base && timer_base->timeout <= monstermoves) {
2114 timer_base = curr->next;
2116 if (curr->kind == TIMER_OBJECT)
2117 (curr->arg.a_obj)->timed--;
2118 (*timeout_funcs[curr->func_index].f)(&curr->arg, curr->timeout);
2119 free((genericptr_t) curr);
2124 * Start a timer. Return TRUE if successful.
2127 start_timer(when, kind, func_index, arg)
2135 if (func_index < 0 || func_index >= NUM_TIME_FUNCS)
2136 panic("start_timer");
2138 gnu = (timer_element *) alloc(sizeof(timer_element));
2139 (void) memset((genericptr_t)gnu, 0, sizeof(timer_element));
2141 gnu->tid = timer_id++;
2142 gnu->timeout = monstermoves + when;
2144 gnu->needs_fixup = 0;
2145 gnu->func_index = func_index;
2149 if (kind == TIMER_OBJECT) /* increment object's timed count */
2150 (arg->a_obj)->timed++;
2152 /* should check for duplicates and fail if any */
2157 * Remove the timer from the current list and free it up. Return the time
2158 * remaining until it would have gone off, 0 if not found.
2161 stop_timer(func_index, arg)
2165 timer_element *doomed;
2168 doomed = remove_timer(&timer_base, func_index, arg);
2171 timeout = doomed->timeout;
2172 if (doomed->kind == TIMER_OBJECT)
2173 (arg->a_obj)->timed--;
2174 if (timeout_funcs[doomed->func_index].cleanup)
2175 (*timeout_funcs[doomed->func_index].cleanup)(arg, timeout);
2176 free((genericptr_t) doomed);
2177 return (timeout - monstermoves);
2183 * Find the timeout of specified timer; return 0 if none.
2186 peek_timer(type, arg)
2190 timer_element *curr;
2192 for (curr = timer_base; curr; curr = curr->next) {
2193 if (curr->func_index == type && curr->arg.a_void == arg->a_void)
2194 return curr->timeout;
2200 * Move all object timers from src to dest, leaving src untimed.
2203 obj_move_timers(src, dest)
2204 struct obj *src, *dest;
2207 timer_element *curr;
2209 for (count = 0, curr = timer_base; curr; curr = curr->next)
2210 if (curr->kind == TIMER_OBJECT && curr->arg.a_obj == src) {
2211 curr->arg.a_obj = dest;
2215 if (count != src->timed)
2216 panic("obj_move_timers");
2221 * Find all object timers and duplicate them for the new object "dest".
2224 obj_split_timers(src, dest)
2225 struct obj *src, *dest;
2227 timer_element *curr, *next_timer = 0;
2229 for (curr = timer_base; curr; curr = next_timer) {
2230 next_timer = curr->next; /* things may be inserted */
2231 if (curr->kind == TIMER_OBJECT && curr->arg.a_obj == src) {
2232 (void) start_timer(curr->timeout - monstermoves, TIMER_OBJECT,
2233 curr->func_index, obj_to_any(dest));
2239 * Stop all timers attached to this object. We can get away with this because
2240 * all object pointers are unique.
2243 obj_stop_timers(obj)
2246 timer_element *curr, *prev, *next_timer = 0;
2248 for (prev = 0, curr = timer_base; curr; curr = next_timer) {
2249 next_timer = curr->next;
2250 if (curr->kind == TIMER_OBJECT && curr->arg.a_obj == obj) {
2252 prev->next = curr->next;
2254 timer_base = curr->next;
2255 if (timeout_funcs[curr->func_index].cleanup)
2256 (*timeout_funcs[curr->func_index].cleanup)(&curr->arg,
2258 free((genericptr_t) curr);
2267 * Check whether object has a timer of type timer_type.
2270 obj_has_timer(object, timer_type)
2274 long timeout = peek_timer(timer_type, obj_to_any(object));
2276 return (boolean) (timeout != 0L);
2280 * Stop all timers of index func_index at this spot.
2284 spot_stop_timers(x, y, func_index)
2288 timer_element *curr, *prev, *next_timer = 0;
2289 long where = (((long) x << 16) | ((long) y));
2291 for (prev = 0, curr = timer_base; curr; curr = next_timer) {
2292 next_timer = curr->next;
2293 if (curr->kind == TIMER_LEVEL && curr->func_index == func_index
2294 && curr->arg.a_long == where) {
2296 prev->next = curr->next;
2298 timer_base = curr->next;
2299 if (timeout_funcs[curr->func_index].cleanup)
2300 (*timeout_funcs[curr->func_index].cleanup)(&curr->arg,
2302 free((genericptr_t) curr);
2310 * When is the spot timer of type func_index going to expire?
2311 * Returns 0L if no such timer.
2314 spot_time_expires(x, y, func_index)
2318 timer_element *curr;
2319 long where = (((long) x << 16) | ((long) y));
2321 for (curr = timer_base; curr; curr = curr->next) {
2322 if (curr->kind == TIMER_LEVEL && curr->func_index == func_index
2323 && curr->arg.a_long == where)
2324 return curr->timeout;
2330 spot_time_left(x, y, func_index)
2334 long expires = spot_time_expires(x, y, func_index);
2335 return (expires > 0L) ? expires - monstermoves : 0L;
2338 /* Insert timer into the global queue */
2343 timer_element *curr, *prev;
2345 for (prev = 0, curr = timer_base; curr; prev = curr, curr = curr->next)
2346 if (curr->timeout >= gnu->timeout)
2356 STATIC_OVL timer_element *
2357 remove_timer(base, func_index, arg)
2358 timer_element **base;
2362 timer_element *prev, *curr;
2364 for (prev = 0, curr = *base; curr; prev = curr, curr = curr->next)
2365 if (curr->func_index == func_index && curr->arg.a_void == arg->a_void)
2370 prev->next = curr->next;
2379 write_timer(fd, timer)
2381 timer_element *timer;
2386 switch (timer->kind) {
2389 /* assume no pointers in arg */
2390 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
2394 if (timer->needs_fixup)
2395 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
2397 /* replace object pointer with id */
2398 arg_save.a_obj = timer->arg.a_obj;
2399 timer->arg = zeroany;
2400 timer->arg.a_uint = (arg_save.a_obj)->o_id;
2401 timer->needs_fixup = 1;
2402 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
2403 timer->arg.a_obj = arg_save.a_obj;
2404 timer->needs_fixup = 0;
2409 if (timer->needs_fixup)
2410 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
2412 /* replace monster pointer with id */
2413 arg_save.a_monst = timer->arg.a_monst;
2414 timer->arg = zeroany;
2415 timer->arg.a_uint = (arg_save.a_monst)->m_id;
2416 timer->needs_fixup = 1;
2417 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
2418 timer->arg.a_monst = arg_save.a_monst;
2419 timer->needs_fixup = 0;
2424 panic("write_timer");
2430 * Return TRUE if the object will stay on the level when the level is
2437 switch (obj->where) {
2445 return obj_is_local(obj->ocontainer);
2447 return mon_is_local(obj->ocarry);
2449 panic("obj_is_local");
2454 * Return TRUE if the given monster will stay on the level when the
2463 for (curr = migrating_mons; curr; curr = curr->nmon)
2466 /* `mydogs' is used during level changes, never saved and restored */
2467 for (curr = mydogs; curr; curr = curr->nmon)
2474 * Return TRUE if the timer is attached to something that will stay on the
2475 * level when the level is saved.
2478 timer_is_local(timer)
2479 timer_element *timer;
2481 switch (timer->kind) {
2487 return obj_is_local(timer->arg.a_obj);
2489 return mon_is_local(timer->arg.a_monst);
2491 panic("timer_is_local");
2496 * Part of the save routine. Count up the number of timers that would
2497 * be written. If write_it is true, actually write the timer.
2500 maybe_write_timer(fd, range, write_it)
2505 timer_element *curr;
2507 for (curr = timer_base; curr; curr = curr->next) {
2508 if (range == RANGE_GLOBAL) {
2511 if (!timer_is_local(curr)) {
2514 write_timer(fd, curr);
2520 if (timer_is_local(curr)) {
2523 write_timer(fd, curr);
2532 * Save part of the timer list. The parameter 'range' specifies either
2533 * global or level timers to save. The timer ID is saved with the global
2537 * + timeouts that follow the hero (global)
2538 * + timeouts that follow obj & monst that are migrating
2541 * + timeouts that are level specific (e.g. storms)
2542 * + timeouts that stay with the level (obj & monst)
2545 save_timers(fd, mode, range)
2546 int fd, mode, range;
2548 timer_element *curr, *prev, *next_timer = 0;
2551 if (perform_bwrite(mode)) {
2552 if (range == RANGE_GLOBAL)
2553 bwrite(fd, (genericptr_t) &timer_id, sizeof(timer_id));
2555 count = maybe_write_timer(fd, range, FALSE);
2556 bwrite(fd, (genericptr_t) &count, sizeof count);
2557 (void) maybe_write_timer(fd, range, TRUE);
2560 if (release_data(mode)) {
2561 for (prev = 0, curr = timer_base; curr; curr = next_timer) {
2562 next_timer = curr->next; /* in case curr is removed */
2564 if (!(!!(range == RANGE_LEVEL) ^ !!timer_is_local(curr))) {
2566 prev->next = curr->next;
2568 timer_base = curr->next;
2569 free((genericptr_t) curr);
2570 /* prev stays the same */
2579 * Pull in the structures from disk, but don't recalculate the object and
2583 restore_timers(fd, range, ghostly, adjust)
2585 boolean ghostly; /* restoring from a ghost level */
2586 long adjust; /* how much to adjust timeout */
2589 timer_element *curr;
2591 if (range == RANGE_GLOBAL)
2592 mread(fd, (genericptr_t) &timer_id, sizeof timer_id);
2594 /* restore elements */
2595 mread(fd, (genericptr_t) &count, sizeof count);
2596 while (count-- > 0) {
2597 curr = (timer_element *) alloc(sizeof(timer_element));
2598 mread(fd, (genericptr_t) curr, sizeof(timer_element));
2600 curr->timeout += adjust;
2605 /* to support '#stats' wizard-mode command */
2607 timer_stats(hdrfmt, hdrbuf, count, size)
2614 Sprintf(hdrbuf, hdrfmt, (long) sizeof (timer_element));
2615 *count = *size = 0L;
2616 for (te = timer_base; te; te = te->next) {
2618 *size += (long) sizeof *te;
2622 /* reset all timers that are marked for reseting */
2624 relink_timers(ghostly)
2627 timer_element *curr;
2630 for (curr = timer_base; curr; curr = curr->next) {
2631 if (curr->needs_fixup) {
2632 if (curr->kind == TIMER_OBJECT) {
2634 if (!lookup_id_mapping(curr->arg.a_uint, &nid))
2635 panic("relink_timers 1");
2637 nid = curr->arg.a_uint;
2638 curr->arg.a_obj = find_oid(nid);
2639 if (!curr->arg.a_obj)
2640 panic("cant find o_id %d", nid);
2641 curr->needs_fixup = 0;
2642 } else if (curr->kind == TIMER_MONSTER) {
2643 panic("relink_timers: no monster timer implemented");
2645 panic("relink_timers 2");