root/trunk/src/dungeon.c

Revision 901, 39.4 kB (checked in by takkaria, 20 hours ago)

Add the IMPAIR_HP and IMPAIR_MANA, and change the regeneration algorithm:

  • Food level only affects HP regeneration
  • HP/mana impairment means halving the rate of regeneration.
Line 
1 /*
2  * File: dungeon.c
3  * Purpose: The game core bits, shared across platforms.
4  *
5  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6  *
7  * This work is free software; you can redistribute it and/or modify it
8  * under the terms of either:
9  *
10  * a) the GNU General Public License as published by the Free Software
11  *    Foundation, version 2, or
12  *
13  * b) the "Angband licence":
14  *    This software may be copied and distributed for educational, research,
15  *    and not for profit purposes provided that this copyright and statement
16  *    are included in all such copies.  Other copyrights may also apply.
17  */
18 #include "angband.h"
19 #include "tvalsval.h"
20 #include "z-file.h"
21 #include "cmds.h"
22 #include "game-event.h"
23
24
25 /*
26  * Sense the inventory
27  */
28 static void sense_inventory(void)
29 {
30         int i;
31
32         int plev = p_ptr->lev;
33
34         int feel;
35
36         object_type *o_ptr;
37
38         char o_name[80];
39
40         unsigned int rate;
41
42
43         /* No ID when resting or confused */
44         if (p_ptr->resting) return;
45         if (p_ptr->timed[TMD_CONFUSED]) return;
46
47
48         /* Get improvement rate */
49         if (cp_ptr->flags & CF_PSEUDO_ID_IMPROV)
50                 rate = cp_ptr->sense_base / (plev * plev + cp_ptr->sense_div);
51         else
52                 rate = cp_ptr->sense_base / (plev + cp_ptr->sense_div);
53
54         if (!one_in_(rate)) return;
55
56
57         /* Check everything */
58         for (i = 0; i < INVEN_TOTAL; i++)
59         {
60                 bool okay = FALSE;
61                 bool heavy = ((cp_ptr->flags & CF_PSEUDO_ID_HEAVY) ? TRUE : FALSE);
62
63                 o_ptr = &inventory[i];
64
65                 /* Skip empty slots */
66                 if (!o_ptr->k_idx) continue;
67
68                 /* Valid "tval" codes */
69                 switch (o_ptr->tval)
70                 {
71                         case TV_SHOT:
72                         case TV_ARROW:
73                         case TV_BOLT:
74                         case TV_BOW:
75                         case TV_DIGGING:
76                         case TV_HAFTED:
77                         case TV_POLEARM:
78                         case TV_SWORD:
79                         case TV_BOOTS:
80                         case TV_GLOVES:
81                         case TV_HELM:
82                         case TV_CROWN:
83                         case TV_SHIELD:
84                         case TV_CLOAK:
85                         case TV_SOFT_ARMOR:
86                         case TV_HARD_ARMOR:
87                         case TV_DRAG_ARMOR:
88                         {
89                                 okay = TRUE;
90                                 break;
91                         }
92                 }
93
94                 /* Skip non-sense machines */
95                 if (!okay) continue;
96
97                 /* It is known, no information needed */
98                 if (object_known_p(o_ptr)) continue;
99
100
101                 /* It has already been sensed, do not sense it again */
102                 if (o_ptr->ident & IDENT_SENSE)
103                 {
104                         /* Small chance of wielded, sensed items getting complete ID */
105                         if (!o_ptr->name1 && (i >= INVEN_WIELD) && one_in_(1000))
106                                 do_ident_item(i, o_ptr);
107
108                         continue;
109                 }
110
111                 /* Occasional failure on inventory items */
112                 if ((i < INVEN_WIELD) && one_in_(5)) continue;
113
114
115
116                 /* It's already been pseudo-ID'd */
117                 if (o_ptr->pseudo &&
118                     o_ptr->pseudo != INSCRIP_INDESTRUCTIBLE) continue;
119
120                 /* Indestructible objects are either excellent or terrible */
121                 if (o_ptr->pseudo == INSCRIP_INDESTRUCTIBLE)
122                         heavy = TRUE;
123
124                 /* Check for a feeling */
125                 feel = (heavy ? object_pseudo_heavy(o_ptr) : object_pseudo_light(o_ptr));
126
127                 /* Skip non-feelings */
128                 if (!feel) continue;
129
130                 /* Stop everything */
131                 disturb(0, 0);
132
133                 /* Average pseudo-ID means full ID */
134                 if (feel == INSCRIP_AVERAGE)
135                 {
136                         do_ident_item(i, o_ptr);
137                 }
138                 else
139                 {
140                         object_desc(o_name, sizeof(o_name), o_ptr, FALSE, ODESC_BASE);
141
142                         if (i >= INVEN_WIELD)
143                         {
144                                 message_format(MSG_PSEUDOID, 0, "You feel the %s (%c) you are %s %s %s...",
145                                            o_name, index_to_label(i), describe_use(i),
146                                            ((o_ptr->number == 1) ? "is" : "are"),
147                                            inscrip_text[feel - INSCRIP_NULL]);
148                         }
149                         else
150                         {
151                                 message_format(MSG_PSEUDOID, 0, "You feel the %s (%c) in your pack %s %s...",
152                                            o_name, index_to_label(i),
153                                            ((o_ptr->number == 1) ? "is" : "are"),
154                                            inscrip_text[feel - INSCRIP_NULL]);
155                         }
156
157                         /* Sense the object */
158                         o_ptr->pseudo = feel;
159
160                         /* The object has been "sensed" */
161                         o_ptr->ident |= (IDENT_SENSE);
162                 }
163
164
165                 /* Set squelch flag as appropriate */
166                 if (i < INVEN_WIELD)
167                         p_ptr->notice |= PN_SQUELCH;
168
169
170                 /* Combine / Reorder the pack (later) */
171                 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
172
173                 /* Redraw stuff */
174                 p_ptr->redraw |= (PR_INVEN | PR_EQUIP);
175         }
176 }
177
178
179
180 /*
181  * Regenerate hit points
182  */
183 static void regenhp(int percent)
184 {
185         s32b new_chp, new_chp_frac;
186         int old_chp;
187
188         /* Save the old hitpoints */
189         old_chp = p_ptr->chp;
190
191         /* Extract the new hitpoints */
192         new_chp = ((long)p_ptr->mhp) * percent + PY_REGEN_HPBASE;
193         p_ptr->chp += (s16b)(new_chp >> 16);   /* div 65536 */
194
195         /* check for overflow */
196         if ((p_ptr->chp < 0) && (old_chp > 0)) p_ptr->chp = MAX_SHORT;
197         new_chp_frac = (new_chp & 0xFFFF) + p_ptr->chp_frac;    /* mod 65536 */
198         if (new_chp_frac >= 0x10000L)
199         {
200                 p_ptr->chp_frac = (u16b)(new_chp_frac - 0x10000L);
201                 p_ptr->chp++;
202         }
203         else
204         {
205                 p_ptr->chp_frac = (u16b)new_chp_frac;
206         }
207
208         /* Fully healed */
209         if (p_ptr->chp >= p_ptr->mhp)
210         {
211                 p_ptr->chp = p_ptr->mhp;
212                 p_ptr->chp_frac = 0;
213         }
214
215         /* Notice changes */
216         if (old_chp != p_ptr->chp)
217         {
218                 /* Redraw */
219                 p_ptr->redraw |= (PR_HP);
220         }
221 }
222
223
224 /*
225  * Regenerate mana points
226  */
227 static void regenmana(int percent)
228 {
229         s32b new_mana, new_mana_frac;
230         int old_csp;
231
232         old_csp = p_ptr->csp;
233         new_mana = ((long)p_ptr->msp) * percent + PY_REGEN_MNBASE;
234         p_ptr->csp += (s16b)(new_mana >> 16);   /* div 65536 */
235         /* check for overflow */
236         if ((p_ptr->csp < 0) && (old_csp > 0))
237         {
238                 p_ptr->csp = MAX_SHORT;
239         }
240         new_mana_frac = (new_mana & 0xFFFF) + p_ptr->csp_frac;  /* mod 65536 */
241         if (new_mana_frac >= 0x10000L)
242         {
243                 p_ptr->csp_frac = (u16b)(new_mana_frac - 0x10000L);
244                 p_ptr->csp++;
245         }
246         else
247         {
248                 p_ptr->csp_frac = (u16b)new_mana_frac;
249         }
250
251         /* Must set frac to zero even if equal */
252         if (p_ptr->csp >= p_ptr->msp)
253         {
254                 p_ptr->csp = p_ptr->msp;
255                 p_ptr->csp_frac = 0;
256         }
257
258         /* Redraw mana */
259         if (old_csp != p_ptr->csp)
260         {
261                 /* Redraw */
262                 p_ptr->redraw |= (PR_MANA);
263         }
264 }
265
266
267
268
269
270
271 /*
272  * Regenerate the monsters (once per 100 game turns)
273  *
274  * XXX XXX XXX Should probably be done during monster turns.
275  */
276 static void regen_monsters(void)
277 {
278         int i, frac;
279
280         /* Regenerate everyone */
281         for (i = 1; i < mon_max; i++)
282         {
283                 /* Check the i'th monster */
284                 monster_type *m_ptr = &mon_list[i];
285                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
286
287                 /* Skip dead monsters */
288                 if (!m_ptr->r_idx) continue;
289
290                 /* Allow regeneration (if needed) */
291                 if (m_ptr->hp < m_ptr->maxhp)
292                 {
293                         /* Hack -- Base regeneration */
294                         frac = m_ptr->maxhp / 100;
295
296                         /* Hack -- Minimal regeneration rate */
297                         if (!frac) frac = 1;
298
299                         /* Hack -- Some monsters regenerate quickly */
300                         if (r_ptr->flags[1] & (RF1_REGENERATE)) frac *= 2;
301
302                         /* Hack -- Regenerate */
303                         m_ptr->hp += frac;
304
305                         /* Do not over-regenerate */
306                         if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
307
308                         /* Redraw (later) if needed */
309                         if (p_ptr->health_who == i) p_ptr->redraw |= (PR_HEALTH);
310                 }
311         }
312 }
313
314
315 /*
316  * If player has inscribed the object with "!!", let him know when it's
317  * recharged. -LM-
318  * Also inform player when first item of a stack has recharged. -HK-
319  */
320 static void recharged_notice(const object_type *o_ptr, bool all)
321 {
322         char o_name[120];
323
324         cptr s;
325
326         /* No inscription */
327         if (!o_ptr->note) return;
328
329         /* Find a '!' */
330         s = strchr(quark_str(o_ptr->note), '!');
331
332         /* Process notification request */
333         while (s)
334         {
335                 /* Find another '!' */
336                 if (s[1] == '!')
337                 {
338                         /* Describe (briefly) */
339                         object_desc(o_name, sizeof(o_name), o_ptr, FALSE, ODESC_BASE);
340
341                         /* Disturb the player */
342                         disturb(0, 0);
343
344                         /* Notify the player */
345                         if (o_ptr->number > 1)
346                         {
347                                 if (all) msg_format("Your %s have recharged.", o_name);
348                                 else msg_format("One of your %s has recharged.", o_name);
349                         }
350
351                         /* Artifacts */
352                         else if (o_ptr->name1)
353                         {
354                                 msg_format("The %s has recharged.", o_name);
355                         }
356
357                         /* Single, non-artifact items */
358                         else msg_format("Your %s has recharged.", o_name);
359
360                         /* Done */
361                         return;
362                 }
363
364                 /* Keep looking for '!'s */
365                 s = strchr(s + 1, '!');
366         }
367 }
368
369
370 /*
371  * Recharge activatable objects in the player's equipment
372  * and rods in the inventory and on the ground.
373  */
374 static void recharge_objects(void)
375 {
376         int i;
377
378         int charged = 0;
379
380         object_type *o_ptr;
381         object_kind *k_ptr;
382
383
384         /* Process equipment */
385         for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
386         {
387                 /* Get the object */
388                 o_ptr = &inventory[i];
389
390                 /* Skip non-objects */
391                 if (!o_ptr->k_idx) continue;
392
393                 /* Recharge activatable objects */
394                 if (o_ptr->timeout > 0 && !(o_ptr->tval == TV_LITE && !artifact_p(o_ptr)))
395                 {
396                         /* Recharge */
397                         o_ptr->timeout--;
398
399                         /* Notice changes */
400                         if (!o_ptr->timeout) charged++;
401
402                         /* Message if item is recharged, if inscribed with "!!" */
403                         if (!o_ptr->timeout) recharged_notice(o_ptr, TRUE);
404                 }
405         }
406
407         /* Notice changes */
408         if (charged)
409         {
410                 /* Window stuff */
411                 p_ptr->redraw |= (PR_EQUIP);
412         }
413
414         charged = 0;
415
416         /* Recharge rods */
417         for (i = 0; i < INVEN_PACK; i++)
418         {
419                 o_ptr = &inventory[i];
420                 k_ptr = &k_info[o_ptr->k_idx];
421
422                 /* Skip non-objects */
423                 if (!o_ptr->k_idx) continue;
424
425                 /* Examine all charging rods */
426                 if ((o_ptr->tval == TV_ROD) && (o_ptr->timeout))
427                 {
428                         /* Determine how many rods are charging */
429                         int temp = (o_ptr->timeout + (k_ptr->time_base - 1)) / k_ptr->time_base;
430                         if (temp > o_ptr->number) temp = o_ptr->number;
431
432                         /* Decrease timeout by that number */
433                         o_ptr->timeout -= temp;
434
435                         /* Boundary control */
436                         if (o_ptr->timeout < 0) o_ptr->timeout = 0;
437
438                         /* Update if any rods are recharged */
439                         if (temp > (o_ptr->timeout + (k_ptr->time_base - 1)) / k_ptr->time_base)
440                         {
441                                 /* Update window */
442                                 charged++;
443
444                                 /* Message if whole stack is recharged, if inscribed with "!!" */
445                                 if (!o_ptr->timeout) recharged_notice(o_ptr, TRUE);
446                                 /* Message if first in a stack is recharged, if inscribed with "!!" -HK- */
447                                 else if (temp == o_ptr->number) recharged_notice(o_ptr, FALSE);
448                         }
449                 }
450         }
451
452         /* Notice changes */
453         if (charged)
454         {
455                 /* Combine pack */
456                 p_ptr->notice |= (PN_COMBINE);
457
458                 /* Redraw stuff */
459                 p_ptr->redraw |= (PR_INVEN);
460         }
461
462
463         /*** Process Objects ***/
464
465         /* Process objects */
466         for (i = 1; i < o_max; i++)
467         {
468                 /* Get the object */
469                 o_ptr = &o_list[i];
470
471                 /* Skip dead objects */
472                 if (!o_ptr->k_idx) continue;
473
474                 /* Recharge rods on the ground */
475                 if ((o_ptr->tval == TV_ROD) && o_ptr->timeout)
476                 {
477                         /* Charge it */
478                         o_ptr->timeout -= o_ptr->number;
479
480                         /* Boundary control */
481                         if (o_ptr->timeout < 0) o_ptr->timeout = 0;
482                 }
483         }
484 }
485
486
487 static void play_ambient_sound(void)
488 {
489         /* Town sound */
490         if (p_ptr->depth == 0)
491         {
492                 /* Hack - is it daytime or nighttime? */
493                 if (turn % (10L * TOWN_DAWN) < TOWN_DAWN / 2)
494                 {
495                         /* It's day. */
496                         sound(MSG_AMBIENT_DAY);
497                 }
498                 else
499                 {
500                         /* It's night. */
501                         sound(MSG_AMBIENT_NITE);
502                 }
503                
504         }
505
506         /* Dungeon level 1-20 */
507         else if (p_ptr->depth <= 20)
508         {
509                 sound(MSG_AMBIENT_DNG1);
510         }
511
512         /* Dungeon level 21-40 */
513         else if (p_ptr->depth <= 40)
514         {
515                 sound(MSG_AMBIENT_DNG2);
516         }
517
518         /* Dungeon level 41-60 */
519         else if (p_ptr->depth <= 60)
520         {
521                 sound(MSG_AMBIENT_DNG3);
522         }
523
524         /* Dungeon level 61-80 */
525         else if (p_ptr->depth <= 80)
526         {
527                 sound(MSG_AMBIENT_DNG4);
528         }
529
530         /* Dungeon level 80- */
531         else 
532         {
533                 sound(MSG_AMBIENT_DNG5);
534         }
535 }
536
537 /*
538  * Helper for process_world -- decrement p_ptr->timed[] fields.
539  */
540 static void decrease_timeouts(void)
541 {
542         int adjust = (adj_con_fix[p_ptr->stat_ind[A_CON]] + 1);
543         int i;
544
545         /* Decrement all effects that can be done simply */
546         for (i = 0; i < TMD_MAX; i++)
547         {
548                 int decr = 1;
549                 if (!p_ptr->timed[i])
550                         continue;
551
552                 switch (i)
553                 {
554                         case TMD_CUT:
555                         {
556                                 /* Hack -- check for truly "mortal" wound */
557                                 decr = (p_ptr->timed[i] > 1000) ? 0 : adjust;
558                                 break;
559                         }
560
561                         case TMD_POISONED:
562                         case TMD_STUN:
563                         {
564                                 decr = adjust;
565                                 break;
566                         }
567                 }
568                 /* Decrement the effect */
569                 dec_timed(i, decr);
570         }
571
572         return;
573 }
574
575
576 /*
577  * Handle certain things once every 10 game turns
578  */
579 static void process_world(void)
580 {
581         int i;
582
583         int regen_amount;
584
585         object_type *o_ptr;
586
587         /* Every 10 game turns */
588         if (turn % 10) return;
589
590
591         /*** Check the Time and Load ***/
592
593         /* Play an ambient sound at regular intervals. */
594         if (!(turn % ((10L * TOWN_DAWN) / 4)))
595         {
596                 play_ambient_sound();
597         }
598
599         /*** Handle the "town" (stores and sunshine) ***/
600
601         /* While in town */
602         if (!p_ptr->depth)
603         {
604                 /* Hack -- Daybreak/Nighfall in town */
605                 if (!(turn % ((10L * TOWN_DAWN) / 2)))
606                 {
607                         bool dawn;
608
609                         /* Check for dawn */
610                         dawn = (!(turn % (10L * TOWN_DAWN)));
611
612                         /* Day breaks */
613                         if (dawn)
614                                 msg_print("The sun has risen.");
615
616                         /* Night falls */
617                         else
618                                 msg_print("The sun has fallen.");
619
620                         /* Illuminate */
621                         town_illuminate(dawn);
622                 }
623         }
624
625
626         /* While in the dungeon */
627         else
628         {
629                 /*** Update the Stores ***/
630
631                 /* Update the stores once a day (while in dungeon) */
632                 if (!(turn % (10L * STORE_TURNS)))
633                 {
634                         int n;
635
636                         /* Message */
637                         if (cheat_xtra) msg_print("Updating Shops...");
638
639                         /* Maintain each shop (except home) */
640                         for (n = 0; n < MAX_STORES; n++)
641                         {
642                                 /* Skip the home */
643                                 if (n == STORE_HOME) continue;
644
645                                 /* Maintain */
646                                 store_maint(n);
647                         }
648
649                         /* Sometimes, shuffle the shop-keepers */
650                         if (one_in_(STORE_SHUFFLE))
651                         {
652                                 /* Message */
653                                 if (cheat_xtra) msg_print("Shuffling a Shopkeeper...");
654
655                                 /* Pick a random shop (except home) */
656                                 while (1)
657                                 {
658                                         n = randint0(MAX_STORES);
659                                         if (n != STORE_HOME) break;
660                                 }
661
662                                 /* Shuffle it */
663                                 store_shuffle(n);
664                         }
665
666                         /* Message */
667                         if (cheat_xtra) msg_print("Done.");
668                 }
669         }
670
671
672         /*** Process the monsters ***/
673
674         /* Check for creature generation */
675         if (one_in_(MAX_M_ALLOC_CHANCE))
676         {
677                 /* Make a new monster */
678                 (void)alloc_monster(MAX_SIGHT + 5, FALSE, p_ptr->depth);
679         }
680
681         /* Hack -- Check for creature regeneration */
682         if (!(turn % 100)) regen_monsters();
683
684
685         /*** Damage over Time ***/
686
687         /* Take damage from poison */
688         if (p_ptr->timed[TMD_POISONED])
689         {
690                 /* Take damage */
691                 take_hit(1, "poison");
692         }
693
694         /* Take damage from cuts */
695         if (p_ptr->timed[TMD_CUT])
696         {
697                 /* Mortal wound or Deep Gash */
698                 if (p_ptr->timed[TMD_CUT] > 200)
699                         i = 3;
700
701                 /* Severe cut */
702                 else if (p_ptr->timed[TMD_CUT] > 100)
703                         i = 2;
704
705                 /* Other cuts */
706                 else
707                         i = 1;
708
709                 /* Take damage */
710                 take_hit(i, "a fatal wound");
711         }
712
713
714         /*** Check the Food, and Regenerate ***/
715
716         /* Digest normally */
717         if (p_ptr->food < PY_FOOD_MAX)
718         {
719                 /* Every 100 game turns */
720                 if (!(turn % 100))
721                 {
722                         /* Basic digestion rate based on speed */
723                         i = extract_energy[p_ptr->pspeed] * 2;
724
725                         /* Regeneration takes more food */
726                         if (p_ptr->regenerate) i += 30;
727
728                         /* Slow digestion takes less food */
729                         if (p_ptr->slow_digest) i -= 10;
730
731                         /* Minimal digestion */
732                         if (i < 1) i = 1;
733
734                         /* Digest some food */
735                         (void)set_food(p_ptr->food - i);
736                 }
737         }
738
739         /* Digest quickly when gorged */
740         else
741         {
742                 /* Digest a lot of food */
743                 (void)set_food(p_ptr->food - 100);
744         }
745
746         /* Getting Faint */
747         if (p_ptr->food < PY_FOOD_FAINT)
748         {
749                 /* Faint occasionally */
750                 if (!p_ptr->timed[TMD_PARALYZED] && one_in_(10))
751                 {
752                         /* Message */
753                         msg_print("You faint from the lack of food.");
754                         disturb(1, 0);
755
756                         /* Hack -- faint (bypass free action) */
757                         (void)inc_timed(TMD_PARALYZED, 1 + randint0(5));
758                 }
759         }
760
761
762         /* Starve to death (slowly) */
763         if (p_ptr->food < PY_FOOD_STARVE)
764         {
765                 /* Calculate damage */
766                 i = (PY_FOOD_STARVE - p_ptr->food) / 10;
767
768                 /* Take damage */
769                 take_hit(i, "starvation");
770         }
771
772         /** Regenerate HP **/
773
774         /* Default regeneration */
775         if (p_ptr->food >= PY_FOOD_WEAK)
776                 regen_amount = PY_REGEN_NORMAL;
777         else if (p_ptr->food < PY_FOOD_STARVE)
778                 regen_amount = 0;
779         else if (p_ptr->food < PY_FOOD_FAINT)
780                 regen_amount = PY_REGEN_FAINT;
781         else /* if (p_ptr->food < PY_FOOD_WEAK) */
782                 regen_amount = PY_REGEN_WEAK;
783
784         /* Various things speed up regeneration */
785         if (p_ptr->regenerate)
786                 regen_amount *= 2;
787         if (p_ptr->searching || p_ptr->resting)
788                 regen_amount *= 2;
789
790         /* Some things slow it down */
791         if (p_ptr->impair_hp)
792                 regen_amount /= 2;
793
794         /* Various things interfere with physical healing */
795         if (p_ptr->timed[TMD_PARALYZED]) regen_amount = 0;
796         if (p_ptr->timed[TMD_POISONED]) regen_amount = 0;
797         if (p_ptr->timed[TMD_STUN]) regen_amount = 0;
798         if (p_ptr->timed[TMD_CUT]) regen_amount = 0;
799
800         /* Regenerate Hit Points if needed */
801         if (p_ptr->chp < p_ptr->mhp)
802                 regenhp(regen_amount);
803
804
805         /** Regenerate SP **/
806
807         /* Default regeneration */
808         regen_amount = PY_REGEN_NORMAL;
809
810         /* Various things speed up regeneration */
811         if (p_ptr->regenerate)
812                 regen_amount *= 2;
813         if (p_ptr->searching || p_ptr->resting)
814                 regen_amount *= 2;
815
816         /* Some things slow it down */
817         if (p_ptr->impair_mana)
818                 regen_amount /= 2;
819
820         /* Regenerate mana */
821         if (p_ptr->csp < p_ptr->msp)
822                 regenmana(regen_amount);
823
824
825
826         /*** Timeout Various Things ***/
827
828         decrease_timeouts();
829
830
831
832         /*** Process Light ***/
833
834         /* Check for light being wielded */
835         o_ptr = &inventory[INVEN_LITE];
836
837         /* Burn some fuel in the current lite */
838         if (o_ptr->tval == TV_LITE)
839         {
840                 u32b f1, f2, f3;
841                 bool burn_fuel = TRUE;
842
843                 /* Get the object flags */
844                 object_flags(o_ptr, &f1, &f2, &f3);
845
846                 /* Turn off the wanton burning of light during the day in the town */
847                 if (!p_ptr->depth && ((turn % (10L * TOWN_DAWN)) < ((10L * TOWN_DAWN) / 2)))
848                         burn_fuel = FALSE;
849
850                 /* If the light has the NO_FUEL flag, well... */
851                 if (f3 & TR3_NO_FUEL)
852                     burn_fuel = FALSE;
853
854                 /* Use some fuel (except on artifacts, or during the day) */
855                 if (burn_fuel && o_ptr->timeout > 0)
856                 {
857                         /* Decrease life-span */
858                         o_ptr->timeout--;
859
860                         /* Hack -- notice interesting fuel steps */
861                         if ((o_ptr->timeout < 100) || (!(o_ptr->timeout % 100)))
862                         {
863                                 /* Redraw stuff */
864                                 p_ptr->redraw |= (PR_EQUIP);
865                         }
866
867                         /* Hack -- Special treatment when blind */
868                         if (p_ptr->timed[TMD_BLIND])
869                         {
870                                 /* Hack -- save some light for later */
871                                 if (o_ptr->timeout == 0) o_ptr->timeout++;
872                         }
873
874                         /* The light is now out */
875                         else if (o_ptr->timeout == 0)
876                         {
877                                 disturb(0, 0);
878                                 msg_print("Your light has gone out!");
879                         }