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 pline("
\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;
1293 boolean canseeit, many, menorah, need_newsym, need_invupdate;
1297 menorah = obj->otyp == CANDELABRUM_OF_INVOCATION;
1298 many = menorah ? obj->spe > 1 : obj->quan > 1L;
1300 /* timeout while away */
1301 if (timeout != monstermoves) {
1302 long how_long = monstermoves - timeout;
1304 if (how_long >= obj->age) {
1306 end_burn(obj, FALSE);
1309 obj->spe = 0; /* no more candles */
1310 obj->owt = weight(obj);
1311 } else if (Is_candle(obj) || obj->otyp == POT_OIL) {
1312 /* get rid of candles and burning oil potions;
1313 we know this object isn't carried by hero,
1314 nor is it migrating */
1315 obj_extract_self(obj);
1316 obfree(obj, (struct obj *) 0);
1317 obj = (struct obj *) 0;
1321 obj->age -= how_long;
1322 begin_burn(obj, TRUE);
1327 /* only interested in INVENT, FLOOR, and MINVENT */
1328 if (get_obj_location(obj, &x, &y, 0)) {
1329 canseeit = !Blind && cansee(x, y);
1330 /* set `whose[]' to be "Your " or "Fred's " or "The goblin's " */
1331 (void) Shk_Your(whose, obj);
1335 need_newsym = need_invupdate = FALSE;
1337 /* obj->age is the age remaining at this point. */
1338 switch (obj->otyp) {
1340 /* this should only be called when we run out */
1342 switch (obj->where) {
1344 need_invupdate = TRUE;
1348 pline("%spotion of oil has burnt away.", whose);
1350 pline("%s
\83I
\83C
\83\8b\82Í
\94R
\82¦
\82Â
\82«
\82½
\81D", whose);
1354 You_see("a burning potion of oil go out.");
1356 You("
\83I
\83C
\83\8b\82Ì
\89Î
\82ª
\8fÁ
\82¦
\82½
\82Ì
\82ð
\8c©
\82½
\81D");
1361 end_burn(obj, FALSE); /* turn off light source */
1365 /* clear migrating obj's destination code before obfree
1366 to avoid false complaint of deleting worn item */
1367 if (obj->where == OBJ_MIGRATING)
1368 obj->owornmask = 0L;
1369 obj_extract_self(obj);
1370 obfree(obj, (struct obj *) 0);
1372 obj = (struct obj *) 0;
1377 switch ((int) obj->age) {
1382 if (obj->otyp == BRASS_LANTERN)
1383 lantern_message(obj);
1385 see_lamp_flicker(obj,
1387 obj->age == 50L ? " considerably" : "");
1389 obj->age == 50L ? "
\8c\83\82µ
\82" : "");
1395 if (obj->otyp == BRASS_LANTERN)
1396 lantern_message(obj);
1398 switch (obj->where) {
1402 pline("%s seems about to go out.", Yname2(obj));
1404 pline("%s
\82Í
\8d¡
\82É
\82à
\8fÁ
\82¦
\82»
\82¤
\82¾
\81D", Yname2(obj));
1408 You_see("%s about to go out.", an(xname(obj)));
1410 pline("%s
\82ª
\8fÁ
\82¦
\82©
\82¯
\82Ä
\82¢
\82é
\82Ì
\82ª
\8c©
\82¦
\82½
\81D", an(xname(obj)));
1418 /* even if blind you'll know if holding it */
1419 if (canseeit || obj->where == OBJ_INVENT) {
1420 switch (obj->where) {
1422 need_invupdate = TRUE;
1425 if (obj->otyp == BRASS_LANTERN)
1427 pline("%slantern has run out of power.", whose);
1429 pline("%s
\83\89\83\93\83^
\83\93\82Ì
\97Í
\82ð
\8eg
\82¢
\90Ø
\82Á
\82½
\81D", whose);
1432 pline("%s has gone out.", Yname2(obj));
1434 pline("%s
\82Í
\8fÁ
\82¦
\82½
\81D", Yname2(obj));
1437 if (obj->otyp == BRASS_LANTERN)
1439 You_see("a lantern run out of power.");
1441 You("
\83\89\83\93\83^
\83\93\82ª
\8fÁ
\82¦
\82é
\82Ì
\82ð
\8c©
\82½
\81D");
1444 You_see("%s go out.", an(xname(obj)));
1446 You("%s
\82ª
\8fÁ
\82¦
\82é
\82Ì
\82ð
\8c©
\82½
\81D", an(xname(obj)));
1450 end_burn(obj, FALSE);
1455 * Someone added fuel to the lamp while it was
1456 * lit. Just fall through and let begin burn
1457 * handle the new age.
1463 begin_burn(obj, TRUE);
1467 case CANDELABRUM_OF_INVOCATION:
1473 switch (obj->where) {
1477 pline("%s%scandle%s getting short.", whose,
1478 menorah ? "candelabrum's " : "",
1479 many ? "s are" : " is");
1481 pline("%s%s
\82ë
\82¤
\82»
\82
\82Í
\92Z
\82
\82È
\82Á
\82½
\81D", whose,
1482 menorah ? "
\90C
\91ä
\82Ì" : "");
1487 You_see("%scandle%s getting short.",
1488 menorah ? "a candelabrum's " : many ? "some "
1492 You("%s
\82ë
\82¤
\82»
\82
\82ª
\92Z
\82
\82È
\82é
\82Ì
\82ð
\8c©
\82½
\81D",
1493 menorah ? "
\90C
\91ä
\82Ì" : "");
1501 switch (obj->where) {
1505 pline("%s%scandle%s flame%s flicker%s low!", whose,
1506 menorah ? "candelabrum's " : "", many ? "s'" : "'s",
1507 many ? "s" : "", many ? "" : "s");
1509 pline("%s%s
\82ë
\82¤
\82»
\82
\82Ì
\89\8a\82Í
\93_
\96Å
\82µ
\81C
\88Ã
\82
\82È
\82Á
\82½
\81I", whose,
1510 menorah ? "
\90C
\91ä
\82Ì" : "");
1515 You_see("%scandle%s flame%s flicker low!",
1516 menorah ? "a candelabrum's " : many ? "some "
1518 many ? "s'" : "'s", many ? "s" : "");
1520 You("%s
\82ë
\82¤
\82»
\82
\82Ì
\89\8a\82ª
\93_
\96Å
\82µ
\81C
\88Ã
\82
\82È
\82é
\82Ì
\82ð
\8c©
\82½
\81I",
1521 menorah ? "
\90C
\91ä
\82Ì" : "");
1528 /* we know even if blind and in our inventory */
1529 if (canseeit || obj->where == OBJ_INVENT) {
1531 switch (obj->where) {
1533 need_invupdate = TRUE;
1537 pline("%scandelabrum's flame%s.", whose,
1538 many ? "s die" : " dies");
1540 pline("%s
\90C
\91ä
\82Ì
\89\8a\82Í
\8fÁ
\82¦
\82½
\81D", whose);
1545 You_see("a candelabrum's flame%s die.",
1548 You("
\90C
\91ä
\82Ì
\89\8a\82ª
\8fÁ
\82¦
\82é
\82Ì
\82ð
\8c©
\82½
\81D");
1553 switch (obj->where) {
1555 /* no need_invupdate for update_inventory() necessary;
1556 useupall() -> freeinv() handles it */
1560 pline("%s %s consumed!", Yname2(obj),
1561 many ? "are" : "is");
1563 pline("%s
\82Í
\94R
\82¦
\82Â
\82«
\82½
\81I", Yname2(obj));
1568 You see some wax candles consumed!
1569 You see a wax candle consumed!
1572 You_see("%s%s consumed!", many ? "some " : "",
1573 many ? xname(obj) : an(xname(obj)));
1575 You("%s
\82ª
\94R
\82¦
\82Â
\82«
\82é
\82Ì
\82ð
\8c©
\82½
\81I", xname(obj));
1584 ? (many ? "They shriek!" : "It shrieks!")
1585 : Blind ? "" : (many ? "Their flames die."
1586 : "Its flame dies."));
1588 pline(Hallucination ? "
\82»
\82ê
\82Í
\8bà
\90Ø
\82è
\90º
\82ð
\82 \82°
\82½
\81I"
1590 : "
\89\8a\82Í
\8fÁ
\82¦
\82½
\81D");
1594 end_burn(obj, FALSE);
1598 obj->owt = weight(obj);
1603 /* clear migrating obj's destination code
1604 so obfree won't think this item is worn */
1605 if (obj->where == OBJ_MIGRATING)
1606 obj->owornmask = 0L;
1607 obj_extract_self(obj);
1608 obfree(obj, (struct obj *) 0);
1610 obj = (struct obj *) 0;
1612 break; /* case [age ==] 0 */
1616 * Someone added fuel (candles) to the menorah while
1617 * it was lit. Just fall through and let begin burn
1618 * handle the new age.
1623 if (obj && obj->age)
1624 begin_burn(obj, TRUE);
1625 break; /* case [otyp ==] candelabrum|tallow_candle|wax_candle */
1628 impossible("burn_object: unexpeced obj %s", xname(obj));
1638 * Start a burn timeout on the given object. If not "already lit" then
1639 * create a light source for the vision system. There had better not
1640 * be a burn already running on the object.
1642 * Magic lamps stay lit as long as there's a genie inside, so don't start
1646 * potions of oil, lamps & candles:
1647 * age = # of turns of fuel left
1651 * spe = 0 not lightable, 1 lightable forever
1653 * age = # of turns of fuel left
1654 * spe = # of candles
1656 * Once the burn begins, the age will be set to the amount of fuel
1657 * remaining _once_the_burn_finishes_. If the burn is terminated
1658 * early then fuel is added back.
1660 * This use of age differs from the use of age for corpses and eggs.
1661 * For the latter items, age is when the object was created, so we
1662 * know when it becomes "bad".
1664 * This is a "silent" routine - it should not print anything out.
1667 begin_burn(obj, already_lit)
1669 boolean already_lit;
1673 boolean do_timer = TRUE;
1675 if (obj->age == 0 && obj->otyp != MAGIC_LAMP && !artifact_light(obj))
1678 switch (obj->otyp) {
1686 radius = 1; /* very dim light */
1691 /* magic times are 150, 100, 50, 25, and 0 */
1692 if (obj->age > 150L)
1693 turns = obj->age - 150L;
1694 else if (obj->age > 100L)
1695 turns = obj->age - 100L;
1696 else if (obj->age > 50L)
1697 turns = obj->age - 50L;
1698 else if (obj->age > 25L)
1699 turns = obj->age - 25L;
1704 case CANDELABRUM_OF_INVOCATION:
1707 /* magic times are 75, 15, and 0 */
1709 turns = obj->age - 75L;
1710 else if (obj->age > 15L)
1711 turns = obj->age - 15L;
1714 radius = candle_light_range(obj);
1718 /* [ALI] Support artifact light sources */
1719 if (artifact_light(obj)) {
1722 radius = arti_light_radius(obj);
1724 impossible("begin burn: unexpected %s", xname(obj));
1731 if (start_timer(turns, TIMER_OBJECT, BURN_OBJECT, obj_to_any(obj))) {
1734 if (carried(obj) && !already_lit)
1740 if (carried(obj) && !already_lit)
1744 if (obj->lamplit && !already_lit) {
1747 if (get_obj_location(obj, &x, &y, CONTAINED_TOO | BURIED_TOO))
1748 new_light_source(x, y, radius, LS_OBJECT, obj_to_any(obj));
1750 impossible("begin_burn: can't get obj position");
1755 * Stop a burn timeout on the given object if timer attached. Darken
1759 end_burn(obj, timer_attached)
1761 boolean timer_attached;
1763 if (!obj->lamplit) {
1764 impossible("end_burn: obj %s not lit", xname(obj));
1768 if (obj->otyp == MAGIC_LAMP || artifact_light(obj))
1769 timer_attached = FALSE;
1771 if (!timer_attached) {
1772 /* [DS] Cleanup explicitly, since timer cleanup won't happen */
1773 del_light_source(LS_OBJECT, obj_to_any(obj));
1775 if (obj->where == OBJ_INVENT)
1777 } else if (!stop_timer(BURN_OBJECT, obj_to_any(obj)))
1778 impossible("end_burn: obj %s not timed!", xname(obj));
1782 * Cleanup a burning object if timer stopped.
1785 cleanup_burn(arg, expire_time)
1789 struct obj *obj = arg->a_obj;
1790 if (!obj->lamplit) {
1791 impossible("cleanup_burn: obj %s not lit", xname(obj));
1795 del_light_source(LS_OBJECT, obj_to_any(obj));
1797 /* restore unused time */
1798 obj->age += expire_time - monstermoves;
1802 if (obj->where == OBJ_INVENT)
1814 /* no lightning if not the air level or too often, even then */
1815 if (!Is_airlevel(&u.uz) || rn2(8))
1818 /* the number of strikes is 8-log2(nstrike) */
1819 for (nstrike = rnd(64); nstrike <= 64; nstrike *= 2) {
1824 } while (++count < 100 && levl[x][y].typ != CLOUD);
1829 if (dirx != 0 || diry != 0)
1830 buzz(-15, /* "monster" LIGHTNING spell */
1831 8, x, y, dirx, diry);
1835 if (levl[u.ux][u.uy].typ == CLOUD) {
1836 /* Inside a cloud during a thunder storm is deafening. */
1837 /* Even if already deaf, we sense the thunder's vibrations. */
1839 pline("Kaboom!!! Boom!! Boom!!");
1841 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");
1842 incr_itimeout(&HDeaf, rn1(20, 30));
1843 context.botl = TRUE;
1844 if (!u.uinvulnerable) {
1848 multi_reason = "hiding from thunderstorm";
1850 multi_reason = "
\97\8b\82Ì
\97\92\82ð
\94ð
\82¯
\82Ä
\82¢
\82é
\8e\9e\82É";
1855 You_hear("a rumbling noise.");
1857 You_hear("
\97\8b\82Ì
\89¹
\82ð
\95·
\82¢
\82½
\81D");
1860 /* -------------------------------------------------------------------------
1863 * Generic Timeout Functions.
1868 * boolean start_timer(long timeout,short kind,short func_index,
1870 * Start a timer of kind 'kind' that will expire at time
1871 * monstermoves+'timeout'. Call the function at 'func_index'
1872 * in the timeout table using argument 'arg'. Return TRUE if
1873 * a timer was started. This places the timer on a list ordered
1874 * "sooner" to "later". If an object, increment the object's
1877 * long stop_timer(short func_index, anything *arg)
1878 * Stop a timer specified by the (func_index, arg) pair. This
1879 * assumes that such a pair is unique. Return the time the
1880 * timer would have gone off. If no timer is found, return 0.
1881 * If an object, decrement the object's timer count.
1883 * long peek_timer(short func_index, anything *arg)
1884 * Return time specified timer will go off (0 if no such timer).
1886 * void run_timers(void)
1887 * Call timers that have timed out.
1890 * void save_timers(int fd, int mode, int range)
1891 * Save all timers of range 'range'. Range is either global
1892 * or local. Global timers follow game play, local timers
1893 * are saved with a level. Object and monster timers are
1894 * saved using their respective id's instead of pointers.
1896 * void restore_timers(int fd, int range, boolean ghostly, long adjust)
1897 * Restore timers of range 'range'. If from a ghost pile,
1898 * adjust the timeout by 'adjust'. The object and monster
1899 * ids are not restored until later.
1901 * void relink_timers(boolean ghostly)
1902 * Relink all object and monster timers that had been saved
1903 * using their object's or monster's id number.
1906 * void obj_move_timers(struct obj *src, struct obj *dest)
1907 * Reassign all timers from src to dest.
1909 * void obj_split_timers(struct obj *src, struct obj *dest)
1910 * Duplicate all timers assigned to src and attach them to dest.
1912 * void obj_stop_timers(struct obj *obj)
1913 * Stop all timers attached to obj.
1915 * boolean obj_has_timer(struct obj *object, short timer_type)
1916 * Check whether object has a timer of type timer_type.
1919 STATIC_DCL const char *FDECL(kind_name, (SHORT_P));
1920 STATIC_DCL void FDECL(print_queue, (winid, timer_element *));
1921 STATIC_DCL void FDECL(insert_timer, (timer_element *));
1922 STATIC_DCL timer_element *FDECL(remove_timer,
1923 (timer_element **, SHORT_P, ANY_P *));
1924 STATIC_DCL void FDECL(write_timer, (int, timer_element *));
1925 STATIC_DCL boolean FDECL(mon_is_local, (struct monst *));
1926 STATIC_DCL boolean FDECL(timer_is_local, (timer_element *));
1927 STATIC_DCL int FDECL(maybe_write_timer, (int, int, BOOLEAN_P));
1929 /* ordered timer list */
1930 static timer_element *timer_base; /* "active" */
1931 static unsigned long timer_id = 1;
1933 /* If defined, then include names when printing out the timer queue */
1934 #define VERBOSE_TIMER
1937 timeout_proc f, cleanup;
1938 #ifdef VERBOSE_TIMER
1940 #define TTAB(a, b, c) \
1945 #define TTAB(a, b, c) \
1952 /* table of timeout functions */
1953 static const ttable timeout_funcs[NUM_TIME_FUNCS] = {
1954 TTAB(rot_organic, (timeout_proc) 0, "rot_organic"),
1955 TTAB(rot_corpse, (timeout_proc) 0, "rot_corpse"),
1956 TTAB(revive_mon, (timeout_proc) 0, "revive_mon"),
1957 TTAB(burn_object, cleanup_burn, "burn_object"),
1958 TTAB(hatch_egg, (timeout_proc) 0, "hatch_egg"),
1959 TTAB(fig_transform, (timeout_proc) 0, "fig_transform"),
1960 TTAB(melt_ice_away, (timeout_proc) 0, "melt_ice_away")
1964 STATIC_OVL const char *
1982 print_queue(win, base)
1984 timer_element *base;
1986 timer_element *curr;
1990 putstr(win, 0, " <empty>");
1992 putstr(win, 0, "timeout id kind call");
1993 for (curr = base; curr; curr = curr->next) {
1994 #ifdef VERBOSE_TIMER
1995 Sprintf(buf, " %4ld %4ld %-6s %s(%s)", curr->timeout,
1996 curr->tid, kind_name(curr->kind),
1997 timeout_funcs[curr->func_index].name,
1998 fmt_ptr((genericptr_t) curr->arg.a_void));
2000 Sprintf(buf, " %4ld %4ld %-6s #%d(%s)", curr->timeout,
2001 curr->tid, kind_name(curr->kind), curr->func_index,
2002 fmt_ptr((genericptr_t) curr->arg.a_void));
2004 putstr(win, 0, buf);
2014 const char *propname;
2016 int i, p, count, longestlen, ln, specindx = 0;
2018 win = create_nhwindow(NHW_MENU); /* corner text window */
2022 Sprintf(buf, "Current time = %ld.", monstermoves);
2023 putstr(win, 0, buf);
2025 putstr(win, 0, "Active timeout queue:");
2027 print_queue(win, timer_base);
2030 * check every one; the majority can't obtain temporary timeouts in
2031 * normal play but those can be forced via the #wizintrinsic command.
2033 count = longestlen = 0;
2034 for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) {
2035 p = propertynames[i].prop_num;
2036 intrinsic = u.uprops[p].intrinsic;
2037 if (intrinsic & TIMEOUT) {
2039 if ((ln = (int) strlen(propname)) > longestlen)
2042 if (specindx == 0 && p == FIRE_RES)
2047 putstr(win, 0, "No timed properties.");
2049 putstr(win, 0, "Timed properties:");
2051 for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) {
2052 p = propertynames[i].prop_num;
2053 intrinsic = u.uprops[p].intrinsic;
2054 if (intrinsic & TIMEOUT) {
2055 if (specindx > 0 && i >= specindx) {
2056 putstr(win, 0, " -- settable via #wizinstrinc only --");
2059 /* timeout value can be up to 16777215 (0x00ffffff) but
2060 width of 4 digits should result in values lining up
2061 almost all the time (if/when they don't, it won't
2062 look nice but the information will still be accurate) */
2063 Sprintf(buf, " %*s %4ld", -longestlen, propname,
2064 (intrinsic & TIMEOUT));
2065 putstr(win, 0, buf);
2069 display_nhwindow(win, FALSE);
2070 destroy_nhwindow(win);
2076 timer_sanity_check()
2078 timer_element *curr;
2080 /* this should be much more complete */
2081 for (curr = timer_base; curr; curr = curr->next)
2082 if (curr->kind == TIMER_OBJECT) {
2083 struct obj *obj = curr->arg.a_obj;
2085 if (obj->timed == 0) {
2086 pline("timer sanity: untimed obj %s, timer %ld",
2087 fmt_ptr((genericptr_t) obj), curr->tid);
2093 * Pick off timeout elements from the global queue and call their functions.
2094 * Do this until their time is less than or equal to the move count.
2099 timer_element *curr;
2102 * Always use the first element. Elements may be added or deleted at
2103 * any time. The list is ordered, we are done when the first element
2106 while (timer_base && timer_base->timeout <= monstermoves) {
2108 timer_base = curr->next;
2110 if (curr->kind == TIMER_OBJECT)
2111 (curr->arg.a_obj)->timed--;
2112 (*timeout_funcs[curr->func_index].f)(&curr->arg, curr->timeout);
2113 free((genericptr_t) curr);
2118 * Start a timer. Return TRUE if successful.
2121 start_timer(when, kind, func_index, arg)
2129 if (func_index < 0 || func_index >= NUM_TIME_FUNCS)
2130 panic("start_timer");
2132 gnu = (timer_element *) alloc(sizeof(timer_element));
2133 (void) memset((genericptr_t)gnu, 0, sizeof(timer_element));
2135 gnu->tid = timer_id++;
2136 gnu->timeout = monstermoves + when;
2138 gnu->needs_fixup = 0;
2139 gnu->func_index = func_index;
2143 if (kind == TIMER_OBJECT) /* increment object's timed count */
2144 (arg->a_obj)->timed++;
2146 /* should check for duplicates and fail if any */
2151 * Remove the timer from the current list and free it up. Return the time
2152 * remaining until it would have gone off, 0 if not found.
2155 stop_timer(func_index, arg)
2159 timer_element *doomed;
2162 doomed = remove_timer(&timer_base, func_index, arg);
2165 timeout = doomed->timeout;
2166 if (doomed->kind == TIMER_OBJECT)
2167 (arg->a_obj)->timed--;
2168 if (timeout_funcs[doomed->func_index].cleanup)
2169 (*timeout_funcs[doomed->func_index].cleanup)(arg, timeout);
2170 free((genericptr_t) doomed);
2171 return (timeout - monstermoves);
2177 * Find the timeout of specified timer; return 0 if none.
2180 peek_timer(type, arg)
2184 timer_element *curr;
2186 for (curr = timer_base; curr; curr = curr->next) {
2187 if (curr->func_index == type && curr->arg.a_void == arg->a_void)
2188 return curr->timeout;
2194 * Move all object timers from src to dest, leaving src untimed.
2197 obj_move_timers(src, dest)
2198 struct obj *src, *dest;
2201 timer_element *curr;
2203 for (count = 0, curr = timer_base; curr; curr = curr->next)
2204 if (curr->kind == TIMER_OBJECT && curr->arg.a_obj == src) {
2205 curr->arg.a_obj = dest;
2209 if (count != src->timed)
2210 panic("obj_move_timers");
2215 * Find all object timers and duplicate them for the new object "dest".
2218 obj_split_timers(src, dest)
2219 struct obj *src, *dest;
2221 timer_element *curr, *next_timer = 0;
2223 for (curr = timer_base; curr; curr = next_timer) {
2224 next_timer = curr->next; /* things may be inserted */
2225 if (curr->kind == TIMER_OBJECT && curr->arg.a_obj == src) {
2226 (void) start_timer(curr->timeout - monstermoves, TIMER_OBJECT,
2227 curr->func_index, obj_to_any(dest));
2233 * Stop all timers attached to this object. We can get away with this because
2234 * all object pointers are unique.
2237 obj_stop_timers(obj)
2240 timer_element *curr, *prev, *next_timer = 0;
2242 for (prev = 0, curr = timer_base; curr; curr = next_timer) {
2243 next_timer = curr->next;
2244 if (curr->kind == TIMER_OBJECT && curr->arg.a_obj == obj) {
2246 prev->next = curr->next;
2248 timer_base = curr->next;
2249 if (timeout_funcs[curr->func_index].cleanup)
2250 (*timeout_funcs[curr->func_index].cleanup)(&curr->arg,
2252 free((genericptr_t) curr);
2261 * Check whether object has a timer of type timer_type.
2264 obj_has_timer(object, timer_type)
2268 long timeout = peek_timer(timer_type, obj_to_any(object));
2270 return (boolean) (timeout != 0L);
2274 * Stop all timers of index func_index at this spot.
2278 spot_stop_timers(x, y, func_index)
2282 timer_element *curr, *prev, *next_timer = 0;
2283 long where = (((long) x << 16) | ((long) y));
2285 for (prev = 0, curr = timer_base; curr; curr = next_timer) {
2286 next_timer = curr->next;
2287 if (curr->kind == TIMER_LEVEL && curr->func_index == func_index
2288 && curr->arg.a_long == where) {
2290 prev->next = curr->next;
2292 timer_base = curr->next;
2293 if (timeout_funcs[curr->func_index].cleanup)
2294 (*timeout_funcs[curr->func_index].cleanup)(&curr->arg,
2296 free((genericptr_t) curr);
2304 * When is the spot timer of type func_index going to expire?
2305 * Returns 0L if no such timer.
2308 spot_time_expires(x, y, func_index)
2312 timer_element *curr;
2313 long where = (((long) x << 16) | ((long) y));
2315 for (curr = timer_base; curr; curr = curr->next) {
2316 if (curr->kind == TIMER_LEVEL && curr->func_index == func_index
2317 && curr->arg.a_long == where)
2318 return curr->timeout;
2324 spot_time_left(x, y, func_index)
2328 long expires = spot_time_expires(x, y, func_index);
2329 return (expires > 0L) ? expires - monstermoves : 0L;
2332 /* Insert timer into the global queue */
2337 timer_element *curr, *prev;
2339 for (prev = 0, curr = timer_base; curr; prev = curr, curr = curr->next)
2340 if (curr->timeout >= gnu->timeout)
2350 STATIC_OVL timer_element *
2351 remove_timer(base, func_index, arg)
2352 timer_element **base;
2356 timer_element *prev, *curr;
2358 for (prev = 0, curr = *base; curr; prev = curr, curr = curr->next)
2359 if (curr->func_index == func_index && curr->arg.a_void == arg->a_void)
2364 prev->next = curr->next;
2373 write_timer(fd, timer)
2375 timer_element *timer;
2380 switch (timer->kind) {
2383 /* assume no pointers in arg */
2384 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
2388 if (timer->needs_fixup)
2389 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
2391 /* replace object pointer with id */
2392 arg_save.a_obj = timer->arg.a_obj;
2393 timer->arg = zeroany;
2394 timer->arg.a_uint = (arg_save.a_obj)->o_id;
2395 timer->needs_fixup = 1;
2396 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
2397 timer->arg.a_obj = arg_save.a_obj;
2398 timer->needs_fixup = 0;
2403 if (timer->needs_fixup)
2404 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
2406 /* replace monster pointer with id */
2407 arg_save.a_monst = timer->arg.a_monst;
2408 timer->arg = zeroany;
2409 timer->arg.a_uint = (arg_save.a_monst)->m_id;
2410 timer->needs_fixup = 1;
2411 bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
2412 timer->arg.a_monst = arg_save.a_monst;
2413 timer->needs_fixup = 0;
2418 panic("write_timer");
2424 * Return TRUE if the object will stay on the level when the level is
2431 switch (obj->where) {
2439 return obj_is_local(obj->ocontainer);
2441 return mon_is_local(obj->ocarry);
2443 panic("obj_is_local");
2448 * Return TRUE if the given monster will stay on the level when the
2457 for (curr = migrating_mons; curr; curr = curr->nmon)
2460 /* `mydogs' is used during level changes, never saved and restored */
2461 for (curr = mydogs; curr; curr = curr->nmon)
2468 * Return TRUE if the timer is attached to something that will stay on the
2469 * level when the level is saved.
2472 timer_is_local(timer)
2473 timer_element *timer;
2475 switch (timer->kind) {
2481 return obj_is_local(timer->arg.a_obj);
2483 return mon_is_local(timer->arg.a_monst);
2485 panic("timer_is_local");
2490 * Part of the save routine. Count up the number of timers that would
2491 * be written. If write_it is true, actually write the timer.
2494 maybe_write_timer(fd, range, write_it)
2499 timer_element *curr;
2501 for (curr = timer_base; curr; curr = curr->next) {
2502 if (range == RANGE_GLOBAL) {
2505 if (!timer_is_local(curr)) {
2508 write_timer(fd, curr);
2514 if (timer_is_local(curr)) {
2517 write_timer(fd, curr);
2526 * Save part of the timer list. The parameter 'range' specifies either
2527 * global or level timers to save. The timer ID is saved with the global
2531 * + timeouts that follow the hero (global)
2532 * + timeouts that follow obj & monst that are migrating
2535 * + timeouts that are level specific (e.g. storms)
2536 * + timeouts that stay with the level (obj & monst)
2539 save_timers(fd, mode, range)
2540 int fd, mode, range;
2542 timer_element *curr, *prev, *next_timer = 0;
2545 if (perform_bwrite(mode)) {
2546 if (range == RANGE_GLOBAL)
2547 bwrite(fd, (genericptr_t) &timer_id, sizeof(timer_id));
2549 count = maybe_write_timer(fd, range, FALSE);
2550 bwrite(fd, (genericptr_t) &count, sizeof count);
2551 (void) maybe_write_timer(fd, range, TRUE);
2554 if (release_data(mode)) {
2555 for (prev = 0, curr = timer_base; curr; curr = next_timer) {
2556 next_timer = curr->next; /* in case curr is removed */
2558 if (!(!!(range == RANGE_LEVEL) ^ !!timer_is_local(curr))) {
2560 prev->next = curr->next;
2562 timer_base = curr->next;
2563 free((genericptr_t) curr);
2564 /* prev stays the same */
2573 * Pull in the structures from disk, but don't recalculate the object and
2577 restore_timers(fd, range, ghostly, adjust)
2579 boolean ghostly; /* restoring from a ghost level */
2580 long adjust; /* how much to adjust timeout */
2583 timer_element *curr;
2585 if (range == RANGE_GLOBAL)
2586 mread(fd, (genericptr_t) &timer_id, sizeof timer_id);
2588 /* restore elements */
2589 mread(fd, (genericptr_t) &count, sizeof count);
2590 while (count-- > 0) {
2591 curr = (timer_element *) alloc(sizeof(timer_element));
2592 mread(fd, (genericptr_t) curr, sizeof(timer_element));
2594 curr->timeout += adjust;
2599 /* to support '#stats' wizard-mode command */
2601 timer_stats(hdrfmt, hdrbuf, count, size)
2608 Sprintf(hdrbuf, hdrfmt, (long) sizeof (timer_element));
2609 *count = *size = 0L;
2610 for (te = timer_base; te; te = te->next) {
2612 *size += (long) sizeof *te;
2616 /* reset all timers that are marked for reseting */
2618 relink_timers(ghostly)
2621 timer_element *curr;
2624 for (curr = timer_base; curr; curr = curr->next) {
2625 if (curr->needs_fixup) {
2626 if (curr->kind == TIMER_OBJECT) {
2628 if (!lookup_id_mapping(curr->arg.a_uint, &nid))
2629 panic("relink_timers 1");
2631 nid = curr->arg.a_uint;
2632 curr->arg.a_obj = find_oid(nid);
2633 if (!curr->arg.a_obj)
2634 panic("cant find o_id %d", nid);
2635 curr->needs_fixup = 0;
2636 } else if (curr->kind == TIMER_MONSTER) {
2637 panic("relink_timers: no monster timer implemented");
2639 panic("relink_timers 2");