1 /*
2  *  File:       acr.cc
3  *  Summary:    Main entry point, event loop, and some initialization functions
4  *  Written by: Linley Henzell
5  *
6  *  Change History (most recent first):
7  *
8  * <18> 7/29/00         JDJ             values.h isn't included on Macs
9  * <17> 19jun2000       GDL             added Windows console support
10  * <16> 06mar2000       bwr             changes to berserk
11  * <15> 09jan2000       BCR             new Wiz command: blink
12  * <14> 10/13/99        BCR             Added auto door opening,
13  *                                       move "you have no
14  *                                       religion" to describe.cc
15  * <13> 10/11/99        BCR             Added Daniel's wizard patch
16  * <12> 10/9/99         BCR             swapped 'v' and 'V' commands,
17  *                                       added wizard help command
18  * <11> 10/7/99         BCR             haste and slow now take amulet of
19  *                                       resist slow into account
20  * <10> 9/25/99         CDL             Changes to Linux input
21  *                                       switch on command enums
22  * <9>  6/12/99         BWR             New init code, restructured
23  *                                       wiz commands, added equipment
24  *                                       listing commands
25  * <8>   6/7/99         DML             Autopickup
26  * <7>  5/30/99         JDJ             Added game_has_started.
27  * <6>  5/25/99         BWR             Changed move() to move_player()
28  * <5>  5/20/99         BWR             New berserk code, checking
29  *                                       scan_randarts for NO_TELEPORT
30  *                                       and NO_SPELLCASTING.
31  * <4>  5/12/99         BWR             Solaris support.
32  * <3>  5/09/99         JDJ             look_around no longer prints a prompt.
33  * <2>  5/08/99         JDJ             you and env are no longer arrays.
34  * <1>  -/--/--         LRH             Created
35  */
36 
37 #include "AppHdr.h"
38 
39 #include <string>
40 
41 // I don't seem to need values.h for VACPP..
42 #if !defined(__IBMCPP__) && !defined(MAC)
43 #include <limits.h>
44 #endif
45 
46 #if DEBUG
47   // this contains the DBL_MAX constant
48   #include <float.h>
49 #endif
50 
51 #include <time.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <fcntl.h>
55 #include <stdio.h>
56 
57 #ifdef DOS
58 #include <conio.h>
59 #include <file.h>
60 #endif
61 
62 #ifdef USE_UNIX_SIGNALS
63 #include <signal.h>
64 #endif
65 
66 #ifdef USE_EMX
67 #include <sys/types.h>
68 #endif
69 
70 #ifdef OS9
71 #include <stat.h>
72 #else
73 #include <sys/stat.h>
74 #endif
75 
76 #include "externs.h"
77 
78 #include "abl-show.h"
79 #include "abyss.h"
80 #include "chardump.h"
81 #include "command.h"
82 #include "debug.h"
83 #include "delay.h"
84 #include "describe.h"
85 #include "direct.h"
86 #include "dungeon.h"
87 #include "effects.h"
88 #include "fight.h"
89 #include "files.h"
90 #include "food.h"
91 #include "hiscores.h"
92 #include "initfile.h"
93 #include "invent.h"
94 #include "item_use.h"
95 #include "it_use2.h"
96 #include "it_use3.h"
97 #include "itemname.h"
98 #include "items.h"
99 #include "lev-pand.h"
100 #include "macro.h"
101 #include "misc.h"
102 #include "monplace.h"
103 #include "monstuff.h"
104 #include "mon-util.h"
105 #include "mutation.h"
106 #include "newgame.h"
107 #include "ouch.h"
108 #include "output.h"
109 #include "overmap.h"
110 #include "player.h"
111 #include "randart.h"
112 #include "religion.h"
113 #include "shopping.h"
114 #include "skills.h"
115 #include "skills2.h"
116 #include "spells1.h"
117 #include "spells3.h"
118 #include "spells4.h"
119 #include "spl-book.h"
120 #include "spl-cast.h"
121 #include "spl-util.h"
122 #include "stuff.h"
123 #include "tags.h"
124 #include "transfor.h"
125 #include "view.h"
126 #include "wpn-misc.h"
127 
128 struct crawl_environment env;
129 struct player you;
130 struct system_environment SysEnv;
131 
132 char info[ INFO_SIZE ];         // messaging queue extern'd everywhere {dlb}
133 
134 int stealth;                    // externed in view.h     // no it is not {dlb}
135 char use_colour = 1;
136 
137 FixedVector< char, NUM_STATUE_TYPES >  Visible_Statue;
138 
139 // set to true once a new game starts or an old game loads
140 bool game_has_started = false;
141 
142 // Clockwise, around the compass from north (same order as enum RUN_DIR)
143 static const struct coord_def Compass[8] =
144 {
145     {  0, -1 }, {  1, -1 }, {  1,  0 }, {  1,  1 },
146     {  0,  1 }, { -1,  1 }, { -1,  0 }, { -1, -1 },
147 };
148 
149 /*
150 
151    Functions needed:
152    New:
153    int player_speed(player you);
154    hit_player(damage, flavour, then last two ouch values, env);
155 
156 
157    Old:
158    wield(player you);
159    show_map
160    noisy()
161    losight
162 
163 */
164 
165 void (*viewwindow) (char, bool);
166 
167 /* these are all defined in view.cc: */
168 extern unsigned char (*mapch) (unsigned char);
169 extern unsigned char (*mapch2) (unsigned char);
170 unsigned char mapchar(unsigned char ldfk);
171 unsigned char mapchar2(unsigned char ldfk);
172 unsigned char mapchar3(unsigned char ldfk);
173 unsigned char mapchar4(unsigned char ldfk);
174 
175 /*
176    Function pointers are used to make switching between Linux and DOS char sets
177    possible as a runtime option (command-line -c)
178 */
179 
180 // these two are defined in view.cc. What does the player look like?
181 // (changed for shapechanging)
182 extern unsigned char your_sign;
183 extern unsigned char your_colour;
184 
185 // Functions in main module
186 static void close_door(char move_x, char move_y);
187 static void do_berserk_no_combat_penalty(void);
188 static bool initialise(void);
189 static void input(void);
190 static void move_player(char move_x, char move_y);
191 static void open_door(char move_x, char move_y);
192 
193 /*
194    It all starts here. Some initialisations are run first, then straight to
195    new_game and then input.
196 */
main(int argc,char * argv[])197 int main( int argc, char *argv[] )
198 {
199 #ifdef USE_ASCII_CHARACTERS
200     // Default to the non-ibm set when it makes sense.
201     viewwindow = &viewwindow3;
202     mapch = &mapchar3;
203     mapch2 = &mapchar4;
204 #else
205     // Use the standard ibm default
206     viewwindow = &viewwindow2;
207     mapch = &mapchar;
208     mapch2 = &mapchar2;
209 #endif
210 
211     // Load in the system environment variables
212     get_system_environment();
213 
214     // parse command line args -- look only for initfile & crawl_dir entries
215     if (!parse_args(argc, argv, true))
216     {
217         // print help
218         puts("Command line options:");
219         puts("  -name <string>   character name");
220         puts("  -race <arg>      preselect race (by letter, abbreviation, or name)");
221         puts("  -class <arg>     preselect class (by letter, abbreviation, or name)");
222         puts("  -pizza <string>  crawl pizza");
223         puts("  -plain           don't use IBM extended characters");
224         puts("  -dir <path>      crawl directory");
225         puts("  -rc <file>       init file name");
226         puts("");
227         puts("Command line options override init file options, which override");
228         puts("environment options (CRAWL_NAME, CRAWL_PIZZA, CRAWL_DIR, CRAWL_RC).");
229         puts("");
230         puts("Highscore list options: (Can now be redirected to more, etc)");
231         puts("  -scores [N]      highscore list");
232         puts("  -tscores [N]     terse highscore list");
233         puts("  -vscores [N]     verbose highscore list");
234         exit(1);
235     }
236 
237     // Read the init file
238     read_init_file();
239 
240     // now parse the args again, looking for everything else.
241     parse_args( argc, argv, false );
242 
243     if (Options.sc_entries > 0)
244     {
245         printf( " Best Crawlers -" EOL );
246         hiscores_print_list( Options.sc_entries, Options.sc_format );
247         exit(0);
248     }
249 
250 #ifdef LINUX
251     lincurses_startup();
252 #endif
253 
254 #ifdef MAC
255     init_mac();
256 #endif
257 
258 #ifdef WIN32CONSOLE
259     init_libw32c();
260 #endif
261 
262 #ifdef USE_MACROS
263     // Load macros
264     macro_init();
265 #endif
266 
267     init_overmap();             // in overmap.cc (duh?)
268     clear_ids();                // in itemname.cc
269 
270     bool game_start = initialise();
271 
272     if (game_start || Options.always_greet)
273     {
274         snprintf( info, INFO_SIZE, "Welcome, %s the %s %s.",
275                   you.your_name, species_name( you.species,you.experience_level ), you.class_name );
276 
277         mpr( info );
278 
279         // Starting messages can go here as this should only happen
280         // at the start of a new game -- bwr
281         // This message isn't appropriate for Options.always_greet
282         if (you.char_class == JOB_WANDERER && game_start)
283         {
284             int skill_levels = 0;
285             for (int i = 0; i <= NUM_SKILLS; i++)
286                 skill_levels += you.skills[ i ];
287 
288             if (skill_levels <= 2)
289             {
290                 // Demigods and Demonspawn wanderers stand to not be
291                 // able to see any of their skills at the start of
292                 // the game (one or two skills should be easily guessed
293                 // from starting equipment)... Anyways, we'll give the
294                 // player a message to warn them (and give a reason why). -- bwr
295                 mpr("You wake up in a daze, and can't recall much.");
296             }
297         }
298 
299         // These need some work -- should make sure that the god's
300         // name is metioned, else the message might be confusing.
301         switch (you.religion)
302         {
303         case GOD_ZIN:
304             simple_god_message( " says: Spread the light, my child." );
305             break;
306         case GOD_SHINING_ONE:
307             simple_god_message( " says: Smite the infidels!" );
308             break;
309         case GOD_KIKUBAAQUDGHA:
310         case GOD_YREDELEMNUL:
311         case GOD_NEMELEX_XOBEH:
312             simple_god_message( " says: Welcome..." );
313             break;
314         case GOD_XOM:
315             if (game_start)
316                 simple_god_message( " says: A new plaything!" );
317             break;
318         case GOD_VEHUMET:
319             god_speaks( you.religion, "Let it end in hellfire!");
320             break;
321         case GOD_OKAWARU:
322             simple_god_message(" says: Welcome, disciple.");
323             break;
324         case GOD_MAKHLEB:
325             god_speaks( you.religion, "Blood and souls for Makhleb!" );
326             break;
327         case GOD_SIF_MUNA:
328             simple_god_message( " whispers: I know many secrets...");
329             break;
330         case GOD_TROG:
331             simple_god_message( " says: Kill them all!" );
332             break;
333         case GOD_ELYVILON:
334             simple_god_message( " says: Go forth and aid the weak!" );
335             break;
336         default:
337             break;
338         }
339 
340         // warn player about their weapon, if unsuitable
341         wield_warning(false);
342     }
343 
344     while (true)
345     {
346         input();
347         //      cprintf("x");
348     }
349 
350     // Should never reach this stage, right?
351 
352 #ifdef LINUX
353     lincurses_shutdown();
354 #endif
355 
356 #ifdef MAC
357     deinit_mac();
358 #endif
359 
360 #ifdef USE_EMX
361     deinit_emx();
362 #endif
363 
364     return 0;
365 }                               // end main()
366 
367 #ifdef WIZARD
handle_wizard_command(void)368 static void handle_wizard_command( void )
369 {
370     int   wiz_command, i, j, tmp;
371     char  specs[256];
372 
373     // WIZ_NEVER gives protection for those who have wiz compiles,
374     // and don't want to risk their characters.
375     if (Options.wiz_mode == WIZ_NEVER)
376         return;
377 
378     if (!you.wizard)
379     {
380         mpr( "WARNING: ABOUT TO ENTER WIZARD MODE!", MSGCH_WARN );
381 
382 #ifndef SCORE_WIZARD_MODE
383         mpr( "If you continue, your game will not be scored!", MSGCH_WARN );
384 #endif
385 
386         if (!yesno( "Do you really want to enter wizard mode?", false ))
387             return;
388 
389         you.wizard = true;
390         redraw_screen();
391     }
392 
393     mpr( "Enter Wizard Command: ", MSGCH_PROMPT );
394     wiz_command = getch();
395 
396     switch (wiz_command)
397     {
398     case '?':
399         list_commands(true);        // tell it to list wizard commands
400         redraw_screen();
401         break;
402 
403     case CONTROL('G'):
404         save_ghost(true);
405         break;
406 
407     case 'x':
408         you.experience = 1 + exp_needed( 2 + you.experience_level );
409         level_change();
410         break;
411 
412     case 's':
413         you.exp_available = 20000;
414         you.redraw_experience = 1;
415         break;
416 
417     case 'S':
418         debug_set_skills();
419         break;
420 
421     case 'A':
422         debug_set_all_skills();
423         break;
424 
425     case '$':
426         you.gold += 1000;
427         you.redraw_gold = 1;
428         break;
429 
430     case 'a':
431         acquirement( OBJ_RANDOM );
432         break;
433 
434     case 'v':
435         // this command isn't very exciting... feel free to replace
436         i = prompt_invent_item( "Value of which item?", -1 );
437         if (i == PROMPT_ABORT || !is_random_artefact( you.inv[i] ))
438         {
439             canned_msg( MSG_OK );
440             break;
441         }
442         else
443         {
444             snprintf( info, INFO_SIZE, "randart val: %d", randart_value( you.inv[i] ) );
445             mpr( info );
446         }
447         break;
448 
449     case '+':
450         i = prompt_invent_item( "Make an artefact out of which item?", -1 );
451         if (i == PROMPT_ABORT)
452         {
453             canned_msg( MSG_OK );
454             break;
455         }
456 
457         // set j == equipment slot of chosen item, remove old randart benefits
458         for (j = 0; j < NUM_EQUIP; j++)
459         {
460             if (you.equip[j] == i)
461             {
462                 if (j == EQ_WEAPON)
463                     you.wield_change = true;
464 
465                 if (is_random_artefact( you.inv[i] ))
466                     unuse_randart( i );
467 
468                 break;
469             }
470         }
471 
472         make_item_randart( you.inv[i] );
473 
474         // if equiped, apply new randart benefits
475         if (j != NUM_EQUIP)
476             use_randart( i );
477 
478         item_name( you.inv[i], DESC_INVENTORY_EQUIP, info );
479         mpr( info );
480         break;
481 
482     case '|':
483         // create all unrand arts
484         for (tmp = 1; tmp < NO_UNRANDARTS; tmp++)
485         {
486             int islot = get_item_slot();
487             if (islot == NON_ITEM)
488                 break;
489 
490             make_item_unrandart( mitm[islot], tmp );
491 
492             mitm[ islot ].quantity = 1;
493             set_ident_flags( mitm[ islot ], ISFLAG_IDENT_MASK );
494 
495             move_item_to_grid( &islot, you.x_pos, you.y_pos );
496         }
497 
498         // create all fixed artefacts
499         for (tmp = SPWPN_SINGING_SWORD; tmp <= SPWPN_STAFF_OF_WUCAD_MU; tmp++)
500         {
501             int islot = get_item_slot();
502             if (islot == NON_ITEM)
503                 break;
504 
505             if (make_item_fixed_artefact( mitm[ islot ], false, tmp ))
506             {
507                 mitm[ islot ].quantity = 1;
508                 item_colour( mitm[ islot ] );
509                 set_ident_flags( mitm[ islot ], ISFLAG_IDENT_MASK );
510 
511                 move_item_to_grid( &islot, you.x_pos, you.y_pos );
512             }
513         }
514         break;
515 
516     case 'B':
517         if (you.level_type != LEVEL_ABYSS)
518             banished( DNGN_ENTER_ABYSS );
519         else
520         {
521             grd[you.x_pos][you.y_pos] = DNGN_EXIT_ABYSS;
522             down_stairs(true, you.your_level);
523             untag_followers();
524         }
525         break;
526 
527     case 'g':
528         debug_add_skills();
529         break;
530 
531     case 'G':
532         // Genocide... "unsummon" all the monsters from the level.
533         for (int mon = 0; mon < MAX_MONSTERS; mon++)
534         {
535             struct monsters *monster = &menv[mon];
536 
537             if (monster->type == -1)
538                 continue;
539 
540             monster_die(monster, KILL_RESET, 0);
541 
542         }
543         break;
544 
545     case 'h':
546         you.rotting = 0;
547         you.poison = 0;
548         you.disease = 0;
549         set_hp( abs(you.hp_max), false );
550         set_hunger( 5000 + abs(you.hunger), true );
551         break;
552 
553     case 'H':
554         you.rotting = 0;
555         you.poison = 0;
556         you.disease = 0;
557         inc_hp( 10, true );
558         set_hp( you.hp_max, false );
559         set_hunger( 12000, true );
560         you.redraw_hit_points = 1;
561         break;
562 
563     case 'b':
564         blink();            // wizards can always blink
565         break;
566 
567     case '\"':
568     case '~':
569         level_travel(0);
570         break;
571 
572     case 'd':
573     case 'D':
574         level_travel(1);
575         break;
576 
577     case 'u':
578     case 'U':
579         level_travel(-1);
580         break;
581 
582     case '%':
583     case 'o':
584         create_spec_object();
585         break;
586 
587     case 't':
588         tweak_object();
589         break;
590 
591     case 'm':
592         create_spec_monster();
593         break;
594 
595     case 'M':
596         create_spec_monster_name();
597         break;
598 
599     case 'r':
600         debug_change_species();
601         break;
602 
603     case '>':
604         grd[you.x_pos][you.y_pos] = DNGN_STONE_STAIRS_DOWN_I;
605         break;
606 
607     case '<':
608         grd[you.x_pos][you.y_pos] = DNGN_ROCK_STAIRS_UP;
609         break;
610 
611     case 'p':
612         grd[you.x_pos][you.y_pos] = DNGN_ENTER_PANDEMONIUM;
613         break;
614 
615     case 'l':
616         grd[you.x_pos][you.y_pos] = DNGN_ENTER_LABYRINTH;
617         break;
618 
619     case 'i':
620         mpr( "You feel a rush of knowledge." );
621         for (i = 0; i < ENDOFPACK; i++)
622         {
623             if (is_valid_item( you.inv[i] ))
624             {
625                 set_ident_type( you.inv[i].base_type, you.inv[i].sub_type,
626                                 ID_KNOWN_TYPE );
627 
628                 set_ident_flags( you.inv[i], ISFLAG_IDENT_MASK );
629             }
630         }
631         you.wield_change = true;
632         break;
633 
634     case 'I':
635         mpr( "You feel a rush of antiknowledge." );
636         for (i = 0; i < ENDOFPACK; i++)
637         {
638             if (is_valid_item( you.inv[i] ))
639             {
640                 set_ident_type( you.inv[i].base_type, you.inv[i].sub_type,
641                                 ID_UNKNOWN_TYPE );
642 
643                 unset_ident_flags( you.inv[i], ISFLAG_IDENT_MASK );
644             }
645         }
646         you.wield_change = true;
647         break;
648 
649     case 'X':
650         Xom_acts(true, 20, true);
651         break;
652 
653     case 'z':
654         cast_spec_spell();
655         break;              /* cast spell by number */
656 
657     case 'Z':
658         cast_spec_spell_name();
659         break;              /* cast spell by name */
660 
661     case '(':
662         mpr( "Create which feature (by number)? ", MSGCH_PROMPT );
663         get_input_line( specs, sizeof( specs ) );
664 
665         if (specs[0] != '\0')
666             grd[you.x_pos][you.y_pos] = atoi(specs);
667         break;
668 
669     case ']':
670         if (!debug_add_mutation())
671             mpr( "Failure to give mutation." );
672         break;
673 
674     case '[':
675         demonspawn();
676         break;
677 
678     case ':':
679         j = 0;
680         for (i = 0; i < 20; i++)
681         {
682             if (you.branch_stairs[i] == 0)
683                 continue;
684 
685             snprintf( info, INFO_SIZE, "Branch %2d is on level %2d",
686                      i, you.branch_stairs[i] + 1 );
687 
688             mpr(info);
689         }
690         break;
691 
692     case '{':
693         magic_mapping(99, 100);
694         break;
695 
696     case '^':
697         {
698             int old_piety = you.piety;
699 
700             gain_piety(50);
701             snprintf( info, INFO_SIZE, "Congratulations, your piety went from %d to %d!",
702                     old_piety, you.piety);
703             mpr(info);
704         }
705         break;
706 
707     case '=':
708         snprintf( info, INFO_SIZE,
709                   "Cost level: %d  Skill points: %d  Next cost level: %d",
710                   you.skill_cost_level, you.total_skill_points,
711                   skill_cost_needed( you.skill_cost_level + 1 ) );
712 
713         mpr( info );
714         break;
715 
716     case '_':
717         debug_get_religion();
718         break;
719 
720     case '\'':
721         for (i = 0; i < MAX_ITEMS; i++)
722         {
723             if (mitm[i].link == NON_ITEM)
724                 continue;
725 
726             snprintf( info, INFO_SIZE, "item:%3d link:%3d cl:%3d ty:%3d pl:%3d pl2:%3d sp:%3ld q:%3d",
727                      i, mitm[i].link,
728                      mitm[i].base_type, mitm[i].sub_type,
729                      mitm[i].plus, mitm[i].plus2, mitm[i].special,
730                      mitm[i].quantity );
731 
732             mpr(info);
733         }
734 
735         strcpy(info, "igrid:");
736         mpr(info);
737 
738         for (i = 0; i < GXM; i++)
739         {
740             for (j = 0; j < GYM; j++)
741             {
742                 if (igrd[i][j] != NON_ITEM)
743                 {
744                     snprintf( info, INFO_SIZE, "%3d at (%2d,%2d), cl:%3d ty:%3d pl:%3d pl2:%3d sp:%3ld q:%3d",
745                              igrd[i][j], i, j,
746                              mitm[i].base_type, mitm[i].sub_type,
747                              mitm[i].plus, mitm[i].plus2, mitm[i].special,
748                              mitm[i].quantity );
749 
750                     mpr(info);
751                 }
752             }
753         }
754         break;
755 
756     default:
757         mpr("Not a Wizard Command.");
758         break;
759     }
760 }
761 #endif
762 
763 // This function creates "equivalence classes" so that undiscovered
764 // traps and secret doors aren't running stopping points.
base_grid_type(char grid)765 static char base_grid_type( char grid )
766 {
767     // Don't stop for undiscovered traps:
768     if (grid == DNGN_UNDISCOVERED_TRAP)
769         return (DNGN_FLOOR);
770 
771     // Or secret doors (which currently always look like rock walls):
772     if (grid == DNGN_SECRET_DOOR)
773         return (DNGN_ROCK_WALL);
774 
775     return (grid);
776 }
777 
778 // Set up the front facing array for detecting terrain based stops
set_run_check(int index,int dir)779 static void set_run_check( int index, int dir )
780 {
781     you.run_check[index].dx = Compass[dir].x;
782     you.run_check[index].dy = Compass[dir].y;
783 
784     const int targ_x = you.x_pos + Compass[dir].x;
785     const int targ_y = you.y_pos + Compass[dir].y;
786 
787     you.run_check[index].grid = base_grid_type( grd[ targ_x ][ targ_y ] );
788 }
789 
790 // Set up the running variables for the current run.
start_running(int dir,char mode)791 static void start_running( int dir, char mode )
792 {
793     if (dir == RDIR_REST)
794     {
795         you.run_x = 0;
796         you.run_y = 0;
797         you.running = mode;
798         return;
799     }
800 
801     ASSERT( dir >= 0 && dir <= 7 );
802 
803     you.run_x = Compass[dir].x;
804     you.run_y = Compass[dir].y;
805     you.running = mode;
806 
807     // Get the compass point to the left/right of intended travel:
808     const int left  = (dir - 1 < 0) ? 7 : (dir - 1);
809     const int right = (dir + 1 > 7) ? 0 : (dir + 1);
810 
811     // Record the direction and starting tile type for later reference:
812     set_run_check( 0, left );
813     set_run_check( 1, dir );
814     set_run_check( 2, right );
815 }
816 
817 // Returns true if one of the front three grids has changed.
check_stop_running(void)818 static bool check_stop_running( void )
819 {
820     if (env.cgrid[you.x_pos + you.run_x][you.y_pos + you.run_y] != EMPTY_CLOUD)
821         return (true);
822 
823     if (mgrd[you.x_pos + you.run_x][you.y_pos + you.run_y] != NON_MONSTER)
824         return (true);
825 
826     for (int i = 0; i < 3; i++)
827     {
828         const int targ_x = you.x_pos + you.run_check[i].dx;
829         const int targ_y = you.y_pos + you.run_check[i].dy;
830         const int targ_grid = base_grid_type( grd[ targ_x ][ targ_y ] );
831 
832         if (you.run_check[i].grid != targ_grid)
833             return (true);
834     }
835 
836     return (false);
837 }
838 
839 
840 /*
841    This function handles the player's input. It's called from main(), from
842    inside an endless loop.
843  */
input(void)844 static void input(void)
845 {
846 
847     bool its_quiet;             //jmf: for silence messages
848     FixedVector < int, 2 > plox;
849     char move_x = 0;
850     char move_y = 0;
851 
852     int keyin = 0;
853 
854 #ifdef LINUX
855     // Stuff for the Unix keypad kludge
856     bool running = false;
857     bool opening = false;
858 #endif
859 
860     you.shield_blocks = 0;              // no blocks this round
861 
862     you.time_taken = player_speed();
863 
864 #ifdef LINUX
865     update_screen();
866 #else
867     window( 1, 1, 80, get_number_of_lines() );
868 #endif
869 
870     textcolor(LIGHTGREY);
871 
872     set_redraw_status( REDRAW_LINE_2_MASK | REDRAW_LINE_3_MASK );
873     print_stats();
874 
875     if (you.paralysis)
876     {
877         keyin = '.';            // end of if you.paralysis == 0
878     }
879     else
880     {
881         handle_delay();
882 
883         gotoxy(18, 9);
884 
885         if (you_are_delayed())
886             keyin = '.';
887         else
888         {
889 
890             if (you.running > 0)
891             {
892                 keyin = 128;
893 
894                 move_x = you.run_x;
895                 move_y = you.run_y;
896 
897                 if (kbhit())
898                 {
899                     you.running = 0;
900                     goto gutch;
901                 }
902 
903                 if (you.run_x == 0 && you.run_y == 0)
904                 {
905                     you.running--;
906                     keyin = '.';
907                 }
908             }
909             else
910             {
911 
912 #if DEBUG_DIAGNOSTICS
913                 // save hunger at start of round
914                 // for use with hunger "delta-meter" in  output.cc
915                 you.old_hunger = you.hunger;
916 #endif
917 
918 #if DEBUG_ITEM_SCAN
919                 debug_item_scan();
920 #endif
921 
922               gutch:
923                 flush_input_buffer( FLUSH_BEFORE_COMMAND );
924                 keyin = getch_with_command_macros();
925             }
926 
927             mesclr();
928 
929 #ifdef LINUX
930             // Kludging running and opening as two character sequences
931             // for Unix systems.  This is an easy way out... all the
932             // player has to do is find a termcap and numlock setting
933             // that will get curses the numbers from the keypad.  This
934             // will hopefully be easy.
935 
936             if (keyin == '*')
937             {
938                 opening = true;
939                 keyin = getch();
940             }
941             else if (keyin == '/')
942             {
943                 running = true;
944                 keyin = getch();
945             }
946 
947             // Translate keypad codes into command enums
948             keyin = key_to_command(keyin);
949 #else
950             // Old DOS keypad support
951             if (keyin == 0)     // ALT also works - see ..\KEYTEST.CPP
952             {
953                 keyin = getch();
954                 switch (keyin)
955                 {
956                 case 'O': move_x = -1; move_y =  1; break;
957                 case 'P': move_x =  0; move_y =  1; break;
958                 case 'I': move_x =  1; move_y = -1; break;
959                 case 'H': move_x =  0; move_y = -1; break;
960                 case 'G': move_x = -1; move_y = -1; break;
961                 case 'K': move_x = -1; move_y =  0; break;
962                 case 'Q': move_x =  1; move_y =  1; break;
963                 case 'M': move_x =  1; move_y =  0; break;
964 
965                 case 119: open_door(-1, -1); move_x = 0; move_y = 0; break;
966                 case 141: open_door( 0, -1); move_x = 0; move_y = 0; break;
967                 case 132: open_door( 1, -1); move_x = 0; move_y = 0; break;
968                 case 116: open_door( 1,  0); move_x = 0; move_y = 0; break;
969                 case 118: open_door( 1,  1); move_x = 0; move_y = 0; break;
970                 case 145: open_door( 0,  1); move_x = 0; move_y = 0; break;
971                 case 117: open_door(-1,  1); move_x = 0; move_y = 0; break;
972                 case 115: open_door(-1,  0); move_x = 0; move_y = 0; break;
973 
974                 case 76:
975                 case 'S':
976                     keyin = '.';
977                     goto get_keyin_again;
978                 }
979 
980                 keyin = 128;
981             }
982 #endif
983         }
984     }
985 
986     if (keyin != 128)
987     {
988         move_x = 0;
989         move_y = 0;
990         you.turn_is_over = 0;
991     }
992 
993 #ifndef LINUX
994   get_keyin_again:
995 #endif //jmf: just stops an annoying gcc warning
996 
997 
998 
999     switch (keyin)
1000     {
1001     case CONTROL('Y'):
1002     case CMD_OPEN_DOOR_UP_RIGHT:
1003         open_door(-1, -1); move_x = 0; move_y = 0; break;
1004 
1005     case CONTROL('K'):
1006     case CMD_OPEN_DOOR_UP:
1007         open_door( 0, -1); move_x = 0; move_y = 0; break;
1008 
1009     case CONTROL('U'):
1010     case CMD_OPEN_DOOR_UP_LEFT:
1011         open_door( 1, -1); move_x = 0; move_y = 0; break;
1012 
1013     case CONTROL('L'):
1014     case CMD_OPEN_DOOR_RIGHT:
1015         open_door( 1,  0); move_x = 0; move_y = 0; break;
1016 
1017     case CONTROL('N'):
1018     case CMD_OPEN_DOOR_DOWN_RIGHT:
1019         open_door( 1,  1); move_x = 0; move_y = 0; break;
1020 
1021     case CONTROL('J'):
1022     case CMD_OPEN_DOOR_DOWN:
1023         open_door( 0,  1); move_x = 0; move_y = 0; break;
1024 
1025     case CONTROL('B'):
1026     case CMD_OPEN_DOOR_DOWN_LEFT:
1027         open_door(-1,  1); move_x = 0; move_y = 0; break;
1028 
1029     case CONTROL('H'):
1030     case CMD_OPEN_DOOR_LEFT:
1031         open_door(-1,  0); move_x = 0; move_y = 0; break;
1032 
1033     case 'b': case CMD_MOVE_DOWN_LEFT:  move_x = -1; move_y =  1; break;
1034     case 'j': case CMD_MOVE_DOWN:       move_y =  1; move_x =  0; break;
1035     case 'u': case CMD_MOVE_UP_RIGHT:   move_x =  1; move_y = -1; break;
1036     case 'k': case CMD_MOVE_UP:         move_y = -1; move_x =  0; break;
1037     case 'y': case CMD_MOVE_UP_LEFT:    move_y = -1; move_x = -1; break;
1038     case 'h': case CMD_MOVE_LEFT:       move_x = -1; move_y =  0; break;
1039     case 'n': case CMD_MOVE_DOWN_RIGHT: move_y =  1; move_x =  1; break;
1040     case 'l': case CMD_MOVE_RIGHT:      move_x =  1; move_y =  0; break;
1041 
1042     case CMD_REST:
1043         // Yes this is backwards, but everyone here is used to using
1044         // straight 5s for long rests... might need to define a roguelike
1045         // rest key and get people switched over. -- bwr
1046 
1047 #ifdef LINUX
1048         if (!running && !opening)
1049             start_running( RDIR_REST, 100 );
1050         else
1051         {
1052             search_around();
1053             move_x = 0;
1054             move_y = 0;
1055             you.turn_is_over = 1;
1056         }
1057 #endif
1058         break;
1059 
1060     case 'B': case CMD_RUN_DOWN_LEFT:
1061         start_running( RDIR_DOWN_LEFT, 2 ); break;
1062 
1063     case 'J': case CMD_RUN_DOWN:
1064         start_running( RDIR_DOWN, 2 ); break;
1065 
1066     case 'U': case CMD_RUN_UP_RIGHT:
1067         start_running( RDIR_UP_RIGHT, 2 ); break;
1068 
1069     case 'K': case CMD_RUN_UP:
1070         start_running( RDIR_UP, 2 ); break;
1071 
1072     case 'Y': case CMD_RUN_UP_LEFT:
1073         start_running( RDIR_UP_LEFT, 2 ); break;
1074 
1075     case 'H': case CMD_RUN_LEFT:
1076         start_running( RDIR_LEFT, 2 ); break;
1077 
1078     case 'N': case CMD_RUN_DOWN_RIGHT:
1079         start_running( RDIR_DOWN_RIGHT, 2 ); break;
1080 
1081     case 'L': case CMD_RUN_RIGHT:
1082         start_running( RDIR_RIGHT, 2 ); break;
1083 
1084 #ifdef LINUX
1085         // taken care of via key -> command mapping
1086 #else
1087         // Old DOS keypad support
1088     case '1': start_running( RDIR_DOWN_LEFT, 2 ); break;
1089     case '2': start_running( RDIR_DOWN, 2 ); break;
1090     case '9': start_running( RDIR_UP_RIGHT, 2 ); break;
1091     case '8': start_running( RDIR_UP, 2 ); break;
1092     case '7': start_running( RDIR_UP_LEFT, 2 ); break;
1093     case '4': start_running( RDIR_LEFT, 2 ); break;
1094     case '3': start_running( RDIR_DOWN_RIGHT, 2 ); break;
1095     case '6': start_running( RDIR_RIGHT, 2 ); break;
1096     case '5': start_running( RDIR_REST, 100 ); break;
1097 
1098 #endif
1099 
1100     case CONTROL('A'):
1101     case CMD_TOGGLE_AUTOPICKUP:
1102         autopickup_on = !autopickup_on;
1103         strcpy(info, "Autopickup is now ");
1104         strcat(info, (autopickup_on) ? "on" : "off");
1105         strcat(info, ".");
1106         mpr(info);
1107         break;
1108 
1109     case '<':
1110     case CMD_GO_UPSTAIRS:
1111         if (grd[you.x_pos][you.y_pos] == DNGN_ENTER_SHOP)
1112         {
1113             shop();
1114             break;
1115         }
1116         else if ((grd[you.x_pos][you.y_pos] < DNGN_STONE_STAIRS_UP_I
1117                     || grd[you.x_pos][you.y_pos] > DNGN_ROCK_STAIRS_UP)
1118                 && (grd[you.x_pos][you.y_pos] < DNGN_RETURN_FROM_ORCISH_MINES
1119                     || grd[you.x_pos][you.y_pos] >= 150))
1120         {
1121             mpr( "You can't go up here!" );
1122             break;
1123         }
1124 
1125         tag_followers();  // only those beside us right now can follow
1126         start_delay( DELAY_ASCENDING_STAIRS,
1127                      1 + (you.burden_state > BS_UNENCUMBERED) );
1128         break;
1129 
1130     case '>':
1131     case CMD_GO_DOWNSTAIRS:
1132         if ((grd[you.x_pos][you.y_pos] < DNGN_ENTER_LABYRINTH
1133                 || grd[you.x_pos][you.y_pos] > DNGN_ROCK_STAIRS_DOWN)
1134             && grd[you.x_pos][you.y_pos] != DNGN_ENTER_HELL
1135             && ((grd[you.x_pos][you.y_pos] < DNGN_ENTER_DIS
1136                     || grd[you.x_pos][you.y_pos] > DNGN_TRANSIT_PANDEMONIUM)
1137                 && grd[you.x_pos][you.y_pos] != DNGN_STONE_ARCH)
1138             && !(grd[you.x_pos][you.y_pos] >= DNGN_ENTER_ORCISH_MINES
1139                 && grd[you.x_pos][you.y_pos] < DNGN_RETURN_FROM_ORCISH_MINES))
1140         {
1141             mpr( "You can't go down here!" );
1142             break;
1143         }
1144 
1145         tag_followers();  // only those beside us right now can follow
1146         start_delay( DELAY_DESCENDING_STAIRS,
1147                      1 + (you.burden_state > BS_UNENCUMBERED),
1148                      you.your_level );
1149         break;
1150 
1151     case 'O':
1152     case CMD_DISPLAY_OVERMAP:
1153         display_overmap();
1154         break;
1155 
1156     case 'o':
1157     case CMD_OPEN_DOOR:
1158         open_door(0, 0);
1159         break;
1160     case 'c':
1161     case CMD_CLOSE_DOOR:
1162         close_door(0, 0);
1163         break;
1164 
1165     case 'd':
1166     case CMD_DROP:
1167         drop();
1168         break;
1169 
1170     case 'D':
1171     case CMD_BUTCHER:
1172         butchery();
1173         break;
1174 
1175     case 'i':
1176     case CMD_DISPLAY_INVENTORY:
1177         get_invent(-1);
1178         break;
1179 
1180     case 'I':
1181     case CMD_OBSOLETE_INVOKE:
1182         // We'll leave this message in for a while.  Eventually, this
1183         // might be some special for of inventory command, or perhaps
1184         // actual god invocations will be split to here from abilities. -- bwr
1185         mpr( "This command is now 'E'voke wielded item.", MSGCH_WARN );
1186         break;
1187 
1188     case 'E':
1189     case CMD_EVOKE:
1190         if (!evoke_wielded())
1191             flush_input_buffer( FLUSH_ON_FAILURE );
1192         break;
1193 
1194     case 'g':
1195     case ',':
1196     case CMD_PICKUP:
1197         pickup();
1198         break;
1199 
1200     case ';':
1201     case CMD_INSPECT_FLOOR:
1202         item_check(';');
1203         break;
1204 
1205     case 'w':
1206     case CMD_WIELD_WEAPON:
1207         wield_weapon(false);
1208         break;
1209 
1210     case 't':
1211     case CMD_THROW:
1212         throw_anything();
1213         break;
1214 
1215     case 'f':
1216     case CMD_FIRE:
1217         shoot_thing();
1218         break;
1219 
1220     case 'W':
1221     case CMD_WEAR_ARMOUR:
1222         wear_armour();
1223         break;
1224 
1225     case 'T':
1226     case CMD_REMOVE_ARMOUR:
1227         {
1228             int index=0;
1229 
1230             if (armour_prompt("Take off which item?", &index))
1231                 takeoff_armour(index);
1232         }
1233         break;
1234 
1235     case 'R':
1236     case CMD_REMOVE_JEWELLERY:
1237         remove_ring();
1238         break;
1239     case 'P':
1240     case CMD_WEAR_JEWELLERY:
1241         puton_ring();
1242         break;
1243 
1244     case '=':
1245     case CMD_ADJUST_INVENTORY:
1246         adjust();
1247         return;
1248 
1249     case 'M':
1250     case CMD_MEMORISE_SPELL:
1251         if (!learn_spell())
1252             flush_input_buffer( FLUSH_ON_FAILURE );
1253         break;
1254 
1255     case 'z':
1256     case CMD_ZAP_WAND:
1257         zap_wand();
1258         break;
1259 
1260     case 'e':
1261     case CMD_EAT:
1262         eat_food();
1263         break;
1264 
1265     case 'a':
1266     case CMD_USE_ABILITY:
1267         if (!activate_ability())
1268             flush_input_buffer( FLUSH_ON_FAILURE );
1269         break;
1270 
1271     case 'A':
1272     case CMD_DISPLAY_MUTATIONS:
1273         display_mutations();
1274         redraw_screen();
1275         break;
1276 
1277     case 'v':
1278     case CMD_EXAMINE_OBJECT:
1279         original_name();
1280         break;
1281 
1282     case 'p':
1283     case CMD_PRAY:
1284         pray();
1285         break;
1286 
1287     case '^':
1288     case CMD_DISPLAY_RELIGION:
1289         describe_god( you.religion, true );
1290         redraw_screen();
1291         break;
1292 
1293     case '.':
1294     case CMD_MOVE_NOWHERE:
1295         search_around();
1296         move_x = 0;
1297         move_y = 0;
1298         you.turn_is_over = 1;
1299         break;
1300 
1301     case 'q':
1302     case CMD_QUAFF:
1303         drink();
1304         break;
1305 
1306     case 'r':
1307     case CMD_READ:
1308         read_scroll();
1309         break;
1310 
1311     case 'x':
1312     case CMD_LOOK_AROUND:
1313         mpr("Move the cursor around to observe a square.", MSGCH_PROMPT);
1314         mpr("Press '?' for a monster description.", MSGCH_PROMPT);
1315 
1316         struct dist lmove;
1317         look_around( lmove, true );
1318         break;
1319 
1320     case 's':
1321     case CMD_SEARCH:
1322         search_around();
1323         you.turn_is_over = 1;
1324         break;
1325 
1326     case 'Z':
1327     case CMD_CAST_SPELL:
1328         /* randart wpns */
1329         if (scan_randarts(RAP_PREVENT_SPELLCASTING))
1330         {
1331             mpr("Something interferes with your magic!");
1332             flush_input_buffer( FLUSH_ON_FAILURE );
1333             break;
1334         }
1335 
1336         if (!cast_a_spell())
1337             flush_input_buffer( FLUSH_ON_FAILURE );
1338         break;
1339 
1340     case '\'':
1341     case CMD_WEAPON_SWAP:
1342         wield_weapon(true);
1343         break;
1344 
1345     case 'X':
1346     case CMD_DISPLAY_MAP:
1347 #if (!DEBUG_DIAGNOSTICS)
1348         if (you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_ABYSS)
1349         {
1350             mpr("It would help if you knew where you were, first.");
1351             break;
1352         }
1353 #endif
1354         plox[0] = 0;
1355         show_map(plox);
1356         redraw_screen();
1357         break;
1358 
1359     case '\\':
1360     case CMD_DISPLAY_KNOWN_OBJECTS:
1361         check_item_knowledge(); //nothing = check_item_knowledge();
1362         redraw_screen();
1363         break;
1364 
1365 #ifdef ALLOW_DESTROY_ITEM_COMMAND
1366     case CONTROL('D'):
1367     case CMD_DESTROY_ITEM:
1368         cmd_destroy_item();
1369         break;
1370 #endif
1371 
1372     case CONTROL('P'):
1373     case CMD_REPLAY_MESSAGES:
1374         replay_messages();
1375         redraw_screen();
1376         break;
1377 
1378     case CONTROL('R'):
1379     case CMD_REDRAW_SCREEN:
1380         redraw_screen();
1381         break;
1382 
1383     case CONTROL('X'):
1384     case CMD_SAVE_GAME_NOW:
1385         mpr("Saving game... please wait.");
1386         save_game(true);
1387         break;
1388 
1389 #ifdef USE_UNIX_SIGNALS
1390     case CONTROL('Z'):
1391     case CMD_SUSPEND_GAME:
1392         // CTRL-Z suspend behaviour is implemented here,
1393         // because we want to have CTRL-Y available...
1394         // and unfortuantely they tend to be stuck together.
1395         clrscr();
1396         lincurses_shutdown();
1397         kill(0, SIGTSTP);
1398         lincurses_startup();
1399         redraw_screen();
1400         break;
1401 #endif
1402 
1403     case '?':
1404     case CMD_DISPLAY_COMMANDS:
1405         list_commands(false);
1406         redraw_screen();
1407         break;
1408 
1409     case 'C':
1410     case CMD_EXPERIENCE_CHECK:
1411         snprintf( info, INFO_SIZE, "You are a level %d %s %s.", you.experience_level,
1412                 species_name(you.species,you.experience_level), you.class_name);
1413         mpr(info);
1414 
1415         if (you.experience_level < 27)
1416         {
1417             int xp_needed = (exp_needed(you.experience_level+2) - you.experience) + 1;
1418             snprintf( info, INFO_SIZE, "Level %d requires %ld experience (%d point%s to go!)",
1419                     you.experience_level + 1,
1420                     exp_needed(you.experience_level + 2) + 1,
1421                     xp_needed,
1422                     (xp_needed > 1) ? "s" : "");
1423             mpr(info);
1424         }
1425         else
1426         {
1427             mpr( "I'm sorry, level 27 is as high as you can go." );
1428             mpr( "With the way you've been playing, I'm surprised you got this far." );
1429         }
1430 
1431         if (you.real_time != -1)
1432         {
1433             const time_t curr = you.real_time + (time(NULL) - you.start_time);
1434             char buff[200];
1435 
1436             make_time_string( curr, buff, sizeof(buff) );
1437 
1438             snprintf( info, INFO_SIZE, "Play time: %s (%ld turns)",
1439                       buff, you.num_turns );
1440 
1441             mpr( info );
1442         }
1443         break;
1444 
1445 
1446     case '!':
1447     case CMD_SHOUT:
1448         yell();                 /* in effects.cc */
1449         break;
1450 
1451     case '@':
1452     case CMD_DISPLAY_CHARACTER_STATUS:
1453         display_char_status();
1454         break;
1455 
1456     case 'm':
1457     case CMD_DISPLAY_SKILLS:
1458         show_skills();
1459         redraw_screen();
1460         break;
1461 
1462     case '#':
1463     case CMD_CHARACTER_DUMP:
1464         char name_your[kNameLen+1];
1465 
1466         strncpy(name_your, you.your_name, kNameLen);
1467         name_your[kNameLen] = '\0';
1468         if (dump_char( name_your, false ))
1469             strcpy(info, "Char dumped successfully.");
1470         else
1471             strcat(info, "Char dump unsuccessful! Sorry about that.");
1472         mpr(info);
1473         break;
1474 
1475 #ifdef USE_MACROS
1476     case '`':
1477     case CMD_MACRO_ADD:
1478         macro_add_query();
1479         break;
1480     case '~':
1481     case CMD_MACRO_SAVE:
1482         mpr("Saving macros.");
1483         macro_save();
1484         break;
1485 #endif
1486 
1487     case ')':
1488     case CMD_LIST_WEAPONS:
1489         list_weapons();
1490         return;
1491 
1492     case ']':
1493     case CMD_LIST_ARMOUR:
1494         list_armour();
1495         return;
1496 
1497     case '"':
1498     case CMD_LIST_JEWELLERY:
1499         list_jewellery();
1500         return;
1501 
1502 #ifdef WIZARD
1503     case CONTROL('W'):
1504     case CMD_WIZARD:
1505     case '&':
1506         handle_wizard_command();
1507         break;
1508 #endif
1509 
1510     case 'S':
1511     case CMD_SAVE_GAME:
1512         if (yesno("Save game and exit?", false))
1513             save_game(true);
1514         break;
1515 
1516     case 'Q':
1517     case CMD_QUIT:
1518         quit_game();
1519         break;
1520 
1521     case 'V':
1522     case CMD_GET_VERSION:
1523         version();
1524         break;
1525 
1526     case 128:   // Can't use this char -- it's the special value 128
1527         break;
1528 
1529     default:
1530     case CMD_NO_CMD:
1531         mpr("Unknown command.");
1532         break;
1533 
1534     }
1535 
1536 #ifdef LINUX
1537     // New Unix keypad stuff
1538     if (running)
1539     {
1540         int dir = -1;
1541 
1542         // XXX: ugly hack to interface this with the new running code. -- bwr
1543         for (int i = 0; i < 8; i++)
1544         {
1545             if (Compass[i].x == move_x && Compass[i].y == move_y)
1546             {
1547                 dir = i;
1548                 break;
1549             }
1550         }
1551 
1552         if (dir != -1)
1553         {
1554             start_running( dir, 2 );
1555             move_x = 0;
1556             move_y = 0;
1557         }
1558     }
1559     else if (opening)
1560     {
1561         open_door(move_x, move_y);
1562         move_x = 0;
1563         move_y = 0;
1564     }
1565 #endif
1566 
1567     if (move_x != 0 || move_y != 0)
1568         move_player(move_x, move_y);
1569     else if (you.turn_is_over)      // we did something other than move/attack
1570         do_berserk_no_combat_penalty();
1571 
1572     if (!you.turn_is_over)
1573     {
1574         viewwindow(1, false);
1575         return;
1576     }
1577 
1578     if (you.num_turns != -1)
1579         you.num_turns++;
1580 
1581     //if (random2(10) < you.skills [SK_TRAPS_DOORS] + 2) search_around();
1582 
1583     stealth = check_stealth();
1584 
1585 #if 0
1586     // too annoying for regular diagnostics
1587     snprintf( info, INFO_SIZE, "stealth: %d", stealth );
1588     mpr( info, MSGCH_DIAGNOSTICS );
1589 #endif
1590 
1591     if (you.special_wield != SPWLD_NONE)
1592         special_wielded();
1593 
1594     if (one_chance_in(10))
1595     {
1596         // this is instantaneous
1597         if (player_teleport() > 0 && one_chance_in(100 / player_teleport()))
1598             you_teleport2( true );
1599         else if (you.level_type == LEVEL_ABYSS && one_chance_in(30))
1600             you_teleport2( false, true ); // to new area of the Abyss
1601     }
1602 
1603     if (env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD)
1604         in_a_cloud();
1605 
1606     if (you.duration[DUR_REPEL_UNDEAD] > 1)
1607         you.duration[DUR_REPEL_UNDEAD]--;
1608 
1609     if (you.duration[DUR_REPEL_UNDEAD] == 4)
1610     {
1611         mpr( "Your holy aura is starting to fade.", MSGCH_DURATION );
1612         you.duration[DUR_REPEL_UNDEAD] -= random2(3);
1613     }
1614 
1615     if (you.duration[DUR_REPEL_UNDEAD] == 1)
1616     {
1617         mpr( "Your holy aura fades away.", MSGCH_DURATION );
1618         you.duration[DUR_REPEL_UNDEAD] = 0;
1619     }
1620 
1621     // paradox: it both lasts longer & does more damage overall if you're
1622     //          moving slower.
1623     // rationalisation: I guess it gets rubbed off/falls off/etc if you
1624     //          move around more.
1625     if (you.duration[DUR_LIQUID_FLAMES] > 0)
1626         you.duration[DUR_LIQUID_FLAMES]--;
1627 
1628     if (you.duration[DUR_LIQUID_FLAMES] != 0)
1629     {
1630         const int res_fire = player_res_fire();
1631 
1632         mpr( "You are covered in liquid flames!", MSGCH_WARN );
1633         scrolls_burn(8, OBJ_SCROLLS);
1634 
1635         if (res_fire > 0)
1636         {
1637             ouch( (((random2avg(9, 2) + 1) * you.time_taken) /
1638                     (1 + (res_fire * res_fire))) / 10, 0, KILLED_BY_BURNING );
1639         }
1640 
1641         if (res_fire <= 0)
1642         {
1643             ouch(((random2avg(9, 2) + 1) * you.time_taken) / 10, 0,
1644                                                 KILLED_BY_BURNING);
1645         }
1646 
1647         if (res_fire < 0)
1648         {
1649             ouch(((random2avg(9, 2) + 1) * you.time_taken) / 10, 0,
1650                                                 KILLED_BY_BURNING);
1651         }
1652 
1653         if (you.duration[DUR_CONDENSATION_SHIELD] > 0)
1654         {
1655             mpr("Your icy shield dissipates!", MSGCH_DURATION);
1656             you.duration[DUR_CONDENSATION_SHIELD] = 0;
1657             you.redraw_armour_class = 1;
1658         }
1659     }
1660 
1661     if (you.duration[DUR_ICY_ARMOUR] > 1)
1662     {
1663         you.duration[DUR_ICY_ARMOUR]--;
1664         //scrolls_burn(4, OBJ_POTIONS);
1665     }
1666     else if (you.duration[DUR_ICY_ARMOUR] == 1)
1667     {
1668         mpr("Your icy armour evaporates.", MSGCH_DURATION);
1669         you.redraw_armour_class = 1;     // is this needed? 2apr2000 {dlb}
1670         you.duration[DUR_ICY_ARMOUR] = 0;
1671     }
1672 
1673     if (you.duration[DUR_REPEL_MISSILES] > 1)
1674     {
1675         you.duration[DUR_REPEL_MISSILES]--;
1676         if (you.duration[DUR_REPEL_MISSILES] == 6)
1677         {
1678             mpr("Your repel missiles spell is about to expire...", MSGCH_DURATION);
1679             if (coinflip())
1680                 you.duration[DUR_REPEL_MISSILES]--;
1681         }
1682     }
1683     else if (you.duration[DUR_REPEL_MISSILES] == 1)
1684     {
1685         mpr("You feel less protected from missiles.", MSGCH_DURATION);
1686         you.duration[DUR_REPEL_MISSILES] = 0;
1687     }
1688 
1689     if (you.duration[DUR_DEFLECT_MISSILES] > 1)
1690     {
1691         you.duration[DUR_DEFLECT_MISSILES]--;
1692         if (you.duration[DUR_DEFLECT_MISSILES] == 6)
1693         {
1694             mpr("Your deflect missiles spell is about to expire...", MSGCH_DURATION);
1695             if (coinflip())
1696                 you.duration[DUR_DEFLECT_MISSILES]--;
1697         }
1698     }
1699     else if (you.duration[DUR_DEFLECT_MISSILES] == 1)
1700     {
1701         mpr("You feel less protected from missiles.", MSGCH_DURATION);
1702         you.duration[DUR_DEFLECT_MISSILES] = 0;
1703     }
1704 
1705     if (you.duration[DUR_REGENERATION] > 1)
1706     {
1707         you.duration[DUR_REGENERATION]--;
1708 
1709         if (you.duration[DUR_REGENERATION] == 6)
1710         {
1711             mpr("Your skin is crawling a little less now.", MSGCH_DURATION);
1712             if (coinflip())
1713                 you.duration[DUR_REGENERATION]--;
1714         }
1715     }
1716     else if (you.duration[DUR_REGENERATION] == 1)
1717     {
1718         mpr("Your skin stops crawling.", MSGCH_DURATION);
1719         you.duration[DUR_REGENERATION] = 0;
1720     }
1721 
1722     if (you.duration[DUR_PRAYER] > 1)
1723         you.duration[DUR_PRAYER]--;
1724     else if (you.duration[DUR_PRAYER] == 1)
1725     {
1726         god_speaks(you.religion, "Your prayer is over.");
1727         you.duration[DUR_PRAYER] = 0;
1728     }
1729 
1730 
1731     //jmf: more flexible weapon branding code
1732     if (you.duration[DUR_WEAPON_BRAND] > 1)
1733         you.duration[DUR_WEAPON_BRAND]--;
1734     else if (you.duration[DUR_WEAPON_BRAND] == 1)
1735     {
1736         const int wpn = you.equip[EQ_WEAPON];
1737         const int temp_effect = get_weapon_brand( you.inv[wpn] );
1738 
1739         you.duration[DUR_WEAPON_BRAND] = 0;
1740 
1741         char str_pass[ITEMNAME_SIZE];
1742 
1743         set_item_ego_type( you.inv[wpn], OBJ_WEAPONS, SPWPN_NORMAL );
1744         in_name(wpn, DESC_CAP_YOUR, str_pass);
1745         strncpy(info, str_pass, INFO_SIZE);
1746 
1747         switch (temp_effect)
1748         {
1749         case SPWPN_VORPAL:
1750             if (damage_type(you.inv[you.equip[EQ_WEAPON]].base_type,
1751                      you.inv[you.equip[EQ_WEAPON]].sub_type) != DVORP_CRUSHING)
1752             {
1753                 strcat(info, " seems blunter.");
1754             }
1755             else
1756             {
1757                 //jmf: for Maxwell's Silver Hammer
1758                 strcat(info, " feels lighter.");
1759             }
1760             break;
1761 
1762         case SPWPN_FLAMING:
1763             strcat(info, " goes out.");
1764             break;
1765         case SPWPN_FREEZING:
1766             strcat(info, " stops glowing.");
1767             break;
1768         case SPWPN_VENOM:
1769             strcat(info, " stops dripping with poison.");
1770             break;
1771         case SPWPN_DRAINING:
1772             strcat(info, " stops crackling.");
1773             break;
1774         case SPWPN_DISTORTION:
1775             strcat( info, " seems straighter." );
1776             miscast_effect( SPTYP_TRANSLOCATION, 9, 90, 100, "a distortion effect" );
1777             break;
1778         default:
1779             strcat(info, " seems inexplicably less special.");
1780             break;
1781         }
1782 
1783         //you.attribute[ATTR_WEAPON_BRAND] = 0;
1784         mpr(info, MSGCH_DURATION);
1785         you.wield_change = true;
1786     }
1787 
1788     if (you.duration[DUR_BREATH_WEAPON] > 1)
1789         you.duration[DUR_BREATH_WEAPON]--;
1790     else if (you.duration[DUR_BREATH_WEAPON] == 1)
1791     {
1792         mpr("You have got your breath back.", MSGCH_RECOVERY);
1793         you.duration[DUR_BREATH_WEAPON] = 0;
1794     }
1795 
1796     if (you.duration[DUR_TRANSFORMATION] > 1)
1797     {
1798         you.duration[DUR_TRANSFORMATION]--;
1799 
1800         if (you.duration[DUR_TRANSFORMATION] == 10)
1801         {
1802             mpr("Your transformation is almost over.", MSGCH_DURATION);
1803             you.duration[DUR_TRANSFORMATION] -= random2(3);
1804         }
1805     }
1806     else if (you.duration[DUR_TRANSFORMATION] == 1)
1807     {
1808         untransform();
1809         you.duration[DUR_BREATH_WEAPON] = 0;
1810     }
1811 
1812     if (you.duration[DUR_SWIFTNESS] > 1)
1813     {
1814         you.duration[DUR_SWIFTNESS]--;
1815         if (you.duration[DUR_SWIFTNESS] == 6)
1816         {
1817             mpr("You start to feel a little slower.", MSGCH_DURATION);
1818             if (coinflip())
1819                 you.duration[DUR_SWIFTNESS]--;
1820         }
1821     }
1822     else if (you.duration[DUR_SWIFTNESS] == 1)
1823     {
1824         mpr("You feel sluggish.", MSGCH_DURATION);
1825         you.duration[DUR_SWIFTNESS] = 0;
1826     }
1827 
1828     if (you.duration[DUR_INSULATION] > 1)
1829     {
1830         you.duration[DUR_INSULATION]--;
1831         if (you.duration[DUR_INSULATION] == 6)
1832         {
1833             mpr("You start to feel a little less insulated.", MSGCH_DURATION);
1834             if (coinflip())
1835                 you.duration[DUR_INSULATION]--;
1836         }
1837     }
1838     else if (you.duration[DUR_INSULATION] == 1)
1839     {
1840         mpr("You feel conductive.", MSGCH_DURATION);
1841         you.duration[DUR_INSULATION] = 0;
1842     }
1843 
1844     if (you.duration[DUR_STONEMAIL] > 1)
1845     {
1846         you.duration[DUR_STONEMAIL]--;
1847         if (you.duration[DUR_STONEMAIL] == 6)
1848         {
1849             mpr("Your scaley stone armour is starting to flake away.", MSGCH_DURATION);
1850             you.redraw_armour_class = 1;
1851             if (coinflip())
1852                 you.duration[DUR_STONEMAIL]--;
1853         }
1854     }
1855     else if (you.duration[DUR_STONEMAIL] == 1)
1856     {
1857         mpr("Your scaley stone armour disappears.", MSGCH_DURATION);
1858         you.duration[DUR_STONEMAIL] = 0;
1859         you.redraw_armour_class = 1;
1860         burden_change();
1861     }
1862 
1863     if (you.duration[DUR_FORESCRY] > 1) //jmf: added
1864         you.duration[DUR_FORESCRY]--;
1865     else if (you.duration[DUR_FORESCRY] == 1)
1866     {
1867         mpr("You feel firmly rooted in the present.", MSGCH_DURATION);
1868         you.duration[DUR_FORESCRY] = 0;
1869         you.redraw_evasion = 1;
1870     }
1871 
1872     if (you.duration[DUR_SEE_INVISIBLE] > 1)    //jmf: added
1873         you.duration[DUR_SEE_INVISIBLE]--;
1874     else if (you.duration[DUR_SEE_INVISIBLE] == 1)
1875     {
1876         you.duration[DUR_SEE_INVISIBLE] = 0;
1877 
1878         if (!player_see_invis())
1879             mpr("Your eyesight blurs momentarily.", MSGCH_DURATION);
1880     }
1881 
1882     if (you.duration[DUR_SILENCE] > 0)  //jmf: cute message handled elsewhere
1883         you.duration[DUR_SILENCE]--;
1884 
1885     if (you.duration[DUR_CONDENSATION_SHIELD] > 1)
1886     {
1887         you.duration[DUR_CONDENSATION_SHIELD]--;
1888 
1889         scrolls_burn( 1, OBJ_POTIONS );
1890 
1891         if (player_res_cold() < 0)
1892         {
1893             mpr( "You feel very cold." );
1894             ouch( 2 + random2avg(13, 2), 0, KILLED_BY_FREEZING );
1895         }
1896     }
1897     else if (you.duration[DUR_CONDENSATION_SHIELD] == 1)
1898     {
1899         you.duration[DUR_CONDENSATION_SHIELD] = 0;
1900         mpr("Your icy shield evaporates.", MSGCH_DURATION);
1901         you.redraw_armour_class = 1;
1902     }
1903 
1904     if (you.duration[DUR_STONESKIN] > 1)
1905         you.duration[DUR_STONESKIN]--;
1906     else if (you.duration[DUR_STONESKIN] == 1)
1907     {
1908         mpr("Your skin feels tender.", MSGCH_DURATION);
1909         you.redraw_armour_class = 1;
1910         you.duration[DUR_STONESKIN] = 0;
1911     }
1912 
1913     if (you.duration[DUR_GLAMOUR] > 1)  //jmf: actually GLAMOUR_RELOAD, like
1914         you.duration[DUR_GLAMOUR]--;    //     the breath weapon delay
1915     else if (you.duration[DUR_GLAMOUR] == 1)
1916     {
1917         you.duration[DUR_GLAMOUR] = 0;
1918         //FIXME: cute message or not?
1919     }
1920 
1921     if (you.duration[DUR_TELEPORT] > 1)
1922         you.duration[DUR_TELEPORT]--;
1923     else if (you.duration[DUR_TELEPORT] == 1)
1924     {
1925         // only to a new area of the abyss sometimes (for abyss teleports)
1926         you_teleport2( true, one_chance_in(5) );
1927         you.duration[DUR_TELEPORT] = 0;
1928     }
1929 
1930     if (you.duration[DUR_CONTROL_TELEPORT] > 1)
1931     {
1932         you.duration[DUR_CONTROL_TELEPORT]--;
1933 
1934         if (you.duration[DUR_CONTROL_TELEPORT] == 6)
1935         {
1936             mpr("You start to feel a little uncertain.", MSGCH_DURATION);
1937             if (coinflip())
1938                 you.duration[DUR_CONTROL_TELEPORT]--;
1939         }
1940     }
1941     else if (you.duration[DUR_CONTROL_TELEPORT] == 1)
1942     {
1943         mpr("You feel uncertain.", MSGCH_DURATION);
1944         you.duration[DUR_CONTROL_TELEPORT] = 0;
1945         you.attribute[ATTR_CONTROL_TELEPORT]--;
1946     }
1947 
1948     if (you.duration[DUR_RESIST_POISON] > 1)
1949     {
1950         you.duration[DUR_RESIST_POISON]--;
1951         if (you.duration[DUR_RESIST_POISON] == 6)
1952         {
1953             mpr("Your poison resistance is about to expire.", MSGCH_DURATION);
1954             if (coinflip())
1955                 you.duration[DUR_RESIST_POISON]--;
1956         }
1957     }
1958     else if (you.duration[DUR_RESIST_POISON] == 1)
1959     {
1960         mpr("Your poison resistance expires.", MSGCH_DURATION);
1961         you.duration[DUR_RESIST_POISON] = 0;
1962     }
1963 
1964     if (you.duration[DUR_DEATH_CHANNEL] > 1)
1965     {
1966         you.duration[DUR_DEATH_CHANNEL]--;
1967         if (you.duration[DUR_DEATH_CHANNEL] == 6)
1968         {
1969             mpr("Your unholy channel is weakening.", MSGCH_DURATION);
1970             if (coinflip())
1971                 you.duration[DUR_DEATH_CHANNEL]--;
1972         }
1973     }
1974     else if (you.duration[DUR_DEATH_CHANNEL] == 1)
1975     {
1976         mpr("Your unholy channel expires.", MSGCH_DURATION);    // Death channel wore off
1977         you.duration[DUR_DEATH_CHANNEL] = 0;
1978     }
1979 
1980     if (you.duration[DUR_SHUGGOTH_SEED_RELOAD] > 0)     //jmf: added
1981         you.duration[DUR_SHUGGOTH_SEED_RELOAD]--;
1982 
1983     if (you.duration[DUR_INFECTED_SHUGGOTH_SEED] > 1)
1984         you.duration[DUR_INFECTED_SHUGGOTH_SEED]--;
1985     else if (you.duration[DUR_INFECTED_SHUGGOTH_SEED] == 1)
1986     {
1987         //jmf: use you.max_hp instead? or would that be too evil?
1988         you.duration[DUR_INFECTED_SHUGGOTH_SEED] = 0;
1989         mpr("A horrible thing bursts from your chest!", MSGCH_WARN);
1990         ouch(1 + you.hp / 2, 0, KILLED_BY_SHUGGOTH);
1991         make_shuggoth(you.x_pos, you.y_pos, 1 + you.hp / 2);
1992     }
1993 
1994     if (you.invis > 1)
1995     {
1996         you.invis--;
1997 
1998         if (you.invis == 6)
1999         {
2000             mpr("You flicker for a moment.", MSGCH_DURATION);
2001             if (coinflip())
2002                 you.invis--;
2003         }
2004     }
2005     else if (you.invis == 1)
2006     {
2007         mpr("You flicker back into view.", MSGCH_DURATION);
2008         you.invis = 0;
2009     }
2010 
2011     if (you.conf > 0)
2012         reduce_confuse_player(1);
2013 
2014     if (you.paralysis > 1)
2015         you.paralysis--;
2016     else if (you.paralysis == 1)
2017     {
2018         mpr("You can move again.", MSGCH_DURATION);
2019         you.paralysis = 0;
2020     }
2021 
2022     if (you.exhausted > 1)
2023         you.exhausted--;
2024     else if (you.exhausted == 1)
2025     {
2026         mpr("You feel less fatigued.", MSGCH_DURATION);
2027         you.exhausted = 0;
2028     }
2029 
2030     dec_slow_player();
2031     dec_haste_player();
2032 
2033     if (you.might > 1)
2034         you.might--;
2035     else if (you.might == 1)
2036     {
2037         mpr("You feel a little less mighty now.", MSGCH_DURATION);
2038         you.might = 0;
2039         modify_stat(STAT_STRENGTH, -5, true);
2040     }
2041 
2042     if (you.berserker > 1)
2043         you.berserker--;
2044     else if (you.berserker == 1)
2045     {
2046         mpr( "You are no longer berserk.", MSGCH_DURATION );
2047         you.berserker = 0;
2048 
2049         //jmf: guilty for berserking /after/ berserk
2050         naughty( NAUGHTY_STIMULANTS, 6 + random2(6) );
2051 
2052         //
2053         // Sometimes berserk leaves us physically drained
2054         //
2055 
2056         // chance of passing out:
2057         //     - mutation gives a large plus in order to try and
2058         //       avoid the mutation being a "death sentence" to
2059         //       certain characters.
2060         //     - knowing the spell gives an advantage just
2061         //       so that people who have invested 3 spell levels
2062         //       are better off than the casual potion drinker...
2063         //       this should make it a bit more interesting for
2064         //       Crusaders again.
2065         //     - similarly for the amulet
2066         int chance = 10 + you.mutation[MUT_BERSERK] * 25
2067                         + (wearing_amulet( AMU_RAGE ) ? 10 : 0)
2068                         + (player_has_spell( SPELL_BERSERKER_RAGE ) ? 5 : 0);
2069 
2070         // Note the beauty of Trog!  They get an extra save that's at
2071         // the very least 20% and goes up to 100%.
2072         if (you.berserk_penalty == NO_BERSERK_PENALTY
2073             || (you.religion == GOD_TROG && you.piety > random2(150))
2074             || !one_chance_in( chance ))
2075         {
2076             mpr("You are exhausted.");
2077         }
2078         else
2079         {
2080             mpr("You pass out from exhaustion.", MSGCH_WARN);
2081             you.paralysis += roll_dice( 1, 4 );
2082         }
2083 
2084         // this resets from an actual penalty or from NO_BERSERK_PENALTY
2085         you.berserk_penalty = 0;
2086 
2087         int dur = 12 + roll_dice( 2, 12 );
2088         you.exhausted += dur;
2089         slow_player( dur );
2090 
2091         make_hungry(700, true);
2092 
2093         if (you.hunger < 50)
2094             you.hunger = 50;
2095 
2096         calc_hp();
2097     }
2098 
2099     if (you.confusing_touch > 1)
2100         you.confusing_touch--;
2101     else if (you.confusing_touch == 1)
2102     {
2103         snprintf( info, INFO_SIZE, "Your %s stop glowing.", your_hand(true) );
2104         mpr( info, MSGCH_DURATION );
2105         you.confusing_touch = 0;
2106     }
2107 
2108     if (you.sure_blade > 1)
2109         you.sure_blade--;
2110     else if (you.sure_blade == 1)
2111     {
2112         mpr("The bond with your blade fades away.", MSGCH_DURATION);
2113         you.sure_blade = 0;
2114     }
2115 
2116     if (you.levitation > 1)
2117     {
2118         if (you.species != SP_KENKU || you.experience_level < 15)
2119             you.levitation--;
2120 
2121         if (player_equip_ego_type( EQ_BOOTS, SPARM_LEVITATION ))
2122             you.levitation = 2;
2123 
2124         if (you.levitation == 10)
2125         {
2126             mpr("You are starting to lose your buoyancy!", MSGCH_DURATION);
2127             you.levitation -= random2(6);
2128 
2129             if (you.duration[DUR_CONTROLLED_FLIGHT] > 0)
2130                 you.duration[DUR_CONTROLLED_FLIGHT] = you.levitation;
2131         }
2132     }
2133     else if (you.levitation == 1)
2134     {
2135         mpr("You float gracefully downwards.", MSGCH_DURATION);
2136         you.levitation = 0;
2137         burden_change();
2138         you.duration[DUR_CONTROLLED_FLIGHT] = 0;
2139 
2140         if (grd[you.x_pos][you.y_pos] == DNGN_LAVA
2141             || grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER
2142             || grd[you.x_pos][you.y_pos] == DNGN_SHALLOW_WATER)
2143         {
2144             if (you.species == SP_MERFOLK
2145                 && grd[you.x_pos][you.y_pos] != DNGN_LAVA)
2146             {
2147                 mpr("You dive into the water and return to your normal form.");
2148                 merfolk_start_swimming();
2149             }
2150 
2151             if (grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER)
2152                 fall_into_a_pool(true, grd[you.x_pos][you.y_pos]);
2153         }
2154     }
2155 
2156     if (you.rotting > 0)
2157     {
2158         // XXX: Mummies have an ability (albeit an expensive one) that
2159         // can fix rotted HPs now... it's probably impossible for them
2160         // to even start rotting right now, but that could be changed. -- bwr
2161         if (you.species == SP_MUMMY)
2162             you.rotting = 0;
2163         else if (random2(20) <= (you.rotting - 1))
2164         {
2165             mpr("You feel your flesh rotting away.", MSGCH_WARN);
2166             ouch(1, 0, KILLED_BY_ROTTING);
2167             rot_hp(1);
2168             you.rotting--;
2169         }
2170     }
2171 
2172     // ghoul rotting is special, but will deduct from you.rotting
2173     // if it happens to be positive - because this is placed after
2174     // the "normal" rotting check, rotting attacks can be somewhat
2175     // more painful on ghouls - reversing order would make rotting
2176     // attacks somewhat less painful, but that seems wrong-headed {dlb}:
2177     if (you.species == SP_GHOUL)
2178     {
2179         if (one_chance_in(400))
2180         {
2181             mpr("You feel your flesh rotting away.", MSGCH_WARN);
2182             ouch(1, 0, KILLED_BY_ROTTING);
2183             rot_hp(1);
2184 
2185             if (you.rotting > 0)
2186                 you.rotting--;
2187         }
2188     }
2189 
2190     dec_disease_player();
2191 
2192     if (you.poison > 0)
2193     {
2194         if (random2(5) <= (you.poison - 1))
2195         {
2196             if (you.poison > 10 && random2(you.poison) >= 8)
2197             {
2198                 ouch(random2(10) + 5, 0, KILLED_BY_POISON);
2199                 mpr("You feel extremely sick.", MSGCH_DANGER);
2200             }
2201             else if (you.poison > 5 && coinflip())
2202             {
2203                 ouch((coinflip()? 3 : 2), 0, KILLED_BY_POISON);
2204                 mpr("You feel very sick.", MSGCH_WARN);
2205             }
2206             else
2207             {
2208                 // the poison running through your veins.");
2209                 ouch(1, 0, KILLED_BY_POISON);
2210                 mpr("You feel sick.");
2211             }
2212 
2213             if ((you.hp == 1 && one_chance_in(3)) || one_chance_in(8))
2214                 reduce_poison_player(1);
2215         }
2216     }
2217 
2218     if (you.deaths_door)
2219     {
2220         if (you.hp > allowed_deaths_door_hp())
2221         {
2222             mpr("Your life is in your own hands once again.", MSGCH_DURATION);
2223             you.paralysis += 5 + random2(5);
2224             confuse_player( 10 + random2(10) );
2225             you.hp_max--;
2226             deflate_hp(you.hp_max, false);
2227             you.deaths_door = 0;
2228         }
2229         else
2230             you.deaths_door--;
2231 
2232         if (you.deaths_door == 10)
2233         {
2234             mpr("Your time is quickly running out!", MSGCH_DURATION);
2235             you.deaths_door -= random2(6);
2236         }
2237         if (you.deaths_door == 1)
2238         {
2239             mpr("Your life is in your own hands again!", MSGCH_DURATION);
2240             more();
2241         }
2242     }
2243 
2244     const int food_use = player_hunger_rate();
2245 
2246     if (food_use > 0 && you.hunger >= 40)
2247         make_hungry( food_use, true );
2248 
2249     // XXX: using an int tmp to fix the fact that hit_points_regeneration
2250     // is only an unsigned char and is thus likely to overflow. -- bwr
2251     int tmp = static_cast< int >( you.hit_points_regeneration );
2252 
2253     if (you.hp < you.hp_max && !you.disease && !you.deaths_door)
2254         tmp += player_regen();
2255 
2256     while (tmp >= 100)
2257     {
2258         if (you.hp >= you.hp_max - 1
2259             && you.running && you.run_x == 0 && you.run_y == 0)
2260         {
2261             you.running = 0;
2262         }
2263 
2264         inc_hp(1, false);
2265         tmp -= 100;
2266     }
2267 
2268     ASSERT( tmp >= 0 && tmp < 100 );
2269     you.hit_points_regeneration = static_cast< unsigned char >( tmp );
2270 
2271     // XXX: Doing the same as the above, although overflow isn't an
2272     // issue with magic point regeneration, yet. -- bwr
2273     tmp = static_cast< int >( you.magic_points_regeneration );
2274 
2275     if (you.magic_points < you.max_magic_points)
2276         tmp += 7 + you.max_magic_points / 2;
2277 
2278     while (tmp >= 100)
2279     {
2280         if (you.magic_points >= you.max_magic_points - 1
2281             && you.running && you.run_x == 0 && you.run_y == 0)
2282         {
2283             you.running = 0;
2284         }
2285 
2286         inc_mp(1, false);
2287         tmp -= 100;
2288     }
2289 
2290     ASSERT( tmp >= 0 && tmp < 100 );
2291     you.magic_points_regeneration = static_cast< unsigned char >( tmp );
2292 
2293     viewwindow(1, true);
2294 
2295     handle_monsters();
2296 
2297     ASSERT(you.time_taken >= 0);
2298     // make sure we don't overflow
2299     ASSERT(DBL_MAX - you.elapsed_time > you.time_taken);
2300 
2301     you.elapsed_time += you.time_taken;
2302 
2303     if (you.synch_time <= you.time_taken)
2304     {
2305         handle_time(200 + (you.time_taken - you.synch_time));
2306         you.synch_time = 200;
2307     }
2308     else
2309     {
2310         you.synch_time -= you.time_taken;
2311     }
2312 
2313     manage_clouds();
2314 
2315     if (you.fire_shield > 0)
2316         manage_fire_shield();
2317 
2318     // There used to be signs of intent to have statues as some sort
2319     // of more complex state machine... I'm boiling them down to bare
2320     // basics for now.  -- bwr
2321     if (Visible_Statue[ STATUE_SILVER ])
2322     {
2323         if ((!you.invis && one_chance_in(3)) || one_chance_in(5))
2324         {
2325             char wc[30];
2326 
2327             weird_colours( random2(256), wc );
2328             snprintf(info, INFO_SIZE, "The silver statue's eyes glow %s.", wc);
2329             mpr( info, MSGCH_WARN );
2330 
2331             create_monster( summon_any_demon((coinflip() ? DEMON_COMMON
2332                                                          : DEMON_LESSER)),
2333                                      ENCH_ABJ_V, BEH_HOSTILE,
2334                                      you.x_pos, you.y_pos,
2335                                      MHITYOU, 250 );
2336         }
2337 
2338         Visible_Statue[ STATUE_SILVER ] = 0;
2339     }
2340 
2341     if (Visible_Statue[ STATUE_ORANGE_CRYSTAL ])
2342     {
2343         if ((!you.invis && coinflip()) || one_chance_in(4))
2344         {
2345             mpr("A hostile presence attacks your mind!", MSGCH_WARN);
2346 
2347             miscast_effect( SPTYP_DIVINATION, random2(15), random2(150), 100,
2348                             "an orange crystal statue" );
2349         }
2350 
2351         Visible_Statue[ STATUE_ORANGE_CRYSTAL ] = 0;
2352     }
2353 
2354     // food death check:
2355     if (you.is_undead != US_UNDEAD && you.hunger <= 500)
2356     {
2357         if (!you.paralysis && one_chance_in(40))
2358         {
2359             mpr("You lose consciousness!", MSGCH_FOOD);
2360             you.paralysis += 5 + random2(8);
2361 
2362             if (you.paralysis > 13)
2363                 you.paralysis = 13;
2364         }
2365 
2366         if (you.hunger <= 100)
2367         {
2368             mpr( "You have starved to death.", MSGCH_FOOD );
2369             ouch( -9999, 0, KILLED_BY_STARVATION );
2370         }
2371     }
2372 
2373     //jmf: added silence messages
2374     its_quiet = silenced(you.x_pos, you.y_pos);
2375 
2376     if (you.attribute[ATTR_WAS_SILENCED] != its_quiet)
2377     {
2378         if (its_quiet)
2379         {
2380             if (random2(30))
2381                 mpr("You are enveloped in profound silence.", MSGCH_WARN);
2382             else
2383                 mpr("The dungeon seems quiet ... too quiet!", MSGCH_WARN);
2384         }
2385         else
2386         {
2387             mpr("Your hearing returns.", MSGCH_RECOVERY);
2388         }
2389 
2390         you.attribute[ATTR_WAS_SILENCED] = its_quiet;
2391     }
2392 
2393     viewwindow(1, false);
2394 
2395     if (you.paralysis > 0 && any_messages())
2396         more();
2397 
2398     // place normal dungeon monsters,  but not in player LOS
2399     if (you.level_type == LEVEL_DUNGEON
2400         && !player_in_branch( BRANCH_ECUMENICAL_TEMPLE )
2401         && one_chance_in((you.char_direction == DIR_DESCENDING) ? 240 : 10))
2402     {
2403         int prox = (one_chance_in(10) ? PROX_NEAR_STAIRS
2404                                       : PROX_AWAY_FROM_PLAYER);
2405 
2406         // The rules change once the player has picked up the Orb...
2407         if (you.char_direction == DIR_ASCENDING)
2408             prox = (one_chance_in(10) ? PROX_CLOSE_TO_PLAYER : PROX_ANYWHERE);
2409 
2410         mons_place( WANDERING_MONSTER, BEH_HOSTILE, MHITNOT, false,
2411                     50, 50, LEVEL_DUNGEON, prox );
2412     }
2413 
2414     // place Abyss monsters.
2415     if (you.level_type == LEVEL_ABYSS && one_chance_in(5))
2416     {
2417         mons_place( WANDERING_MONSTER, BEH_HOSTILE, MHITNOT, false,
2418                     50, 50, LEVEL_ABYSS, PROX_ANYWHERE );
2419     }
2420 
2421     // place Pandemonium monsters
2422     if (you.level_type == LEVEL_PANDEMONIUM && one_chance_in(50))
2423         pandemonium_mons();
2424 
2425     // No monsters in the Labyrinth,  or Ecumenical Temple
2426     return;
2427 }
2428 
2429 /*
2430    Opens doors and handles some aspects of untrapping. If either move_x or
2431    move_y are non-zero,  the pair carries a specific direction for the door
2432    to be opened (eg if you type ctrl - dir).
2433  */
open_door(char move_x,char move_y)2434 static void open_door(char move_x, char move_y)
2435 {
2436     struct dist door_move;
2437     int dx, dy;             // door x, door y
2438 
2439     door_move.dx = move_x;
2440     door_move.dy = move_y;
2441 
2442     if (move_x || move_y)
2443     {
2444         // convenience
2445         dx = you.x_pos + move_x;
2446         dy = you.y_pos + move_y;
2447 
2448         const int mon = mgrd[dx][dy];
2449 
2450         if (mon != NON_MONSTER && !mons_has_ench( &menv[mon], ENCH_SUBMERGED ))
2451         {
2452             you_attack(mgrd[dx][dy], true);
2453             you.turn_is_over = 1;
2454 
2455             if (you.berserk_penalty != NO_BERSERK_PENALTY)
2456                 you.berserk_penalty = 0;
2457 
2458             return;
2459         }
2460 
2461         if (grd[dx][dy] >= DNGN_TRAP_MECHANICAL && grd[dx][dy] <= DNGN_TRAP_III)
2462         {
2463             if (env.cgrid[dx][dy] != EMPTY_CLOUD)
2464             {
2465                 mpr("You can't get to that trap right now.");
2466                 return;
2467             }
2468 
2469             disarm_trap(door_move);
2470             return;
2471         }
2472 
2473     }
2474     else
2475     {
2476         mpr("Which direction?", MSGCH_PROMPT);
2477         direction( door_move, DIR_DIR );
2478         if (!door_move.isValid)
2479             return;
2480 
2481         // convenience
2482         dx = you.x_pos + door_move.dx;
2483         dy = you.y_pos + door_move.dy;
2484     }
2485 
2486     if (grd[dx][dy] == DNGN_CLOSED_DOOR)
2487     {
2488         int skill = you.dex + (you.skills[SK_TRAPS_DOORS] + you.skills[SK_STEALTH]) / 2;
2489 
2490         if (one_chance_in(skill) && !silenced(you.x_pos, you.y_pos))
2491         {
2492             mpr( "As you open the door, it creaks loudly!" );
2493             noisy( 10, you.x_pos, you.y_pos );
2494         }
2495         else
2496         {
2497             mpr( player_is_levitating() ? "You reach down and open the door."
2498                                         : "You open the door." );
2499         }
2500 
2501         grd[dx][dy] = DNGN_OPEN_DOOR;
2502         you.turn_is_over = 1;
2503     }
2504     else
2505     {
2506         mpr("You swing at nothing.");
2507         make_hungry(3, true);
2508         you.turn_is_over = 1;
2509     }
2510 }                               // end open_door()
2511 
2512 /*
2513    Similar to open_door. Can you spot the difference?
2514  */
close_door(char door_x,char door_y)2515 static void close_door(char door_x, char door_y)
2516 {
2517     struct dist door_move;
2518     int dx, dy;             // door x, door y
2519 
2520     door_move.dx = door_x;
2521     door_move.dy = door_y;
2522 
2523     if (!(door_x || door_y))
2524     {
2525         mpr("Which direction?", MSGCH_PROMPT);
2526         direction( door_move, DIR_DIR );
2527         if (!door_move.isValid)
2528             return;
2529     }
2530 
2531     if (door_move.dx == 0 && door_move.dy == 0)
2532     {
2533         mpr("You can't close doors on yourself!");
2534         return;
2535     }
2536 
2537     // convenience
2538     dx = you.x_pos + door_move.dx;
2539     dy = you.y_pos + door_move.dy;
2540 
2541     if (grd[dx][dy] == DNGN_OPEN_DOOR)
2542     {
2543         if (mgrd[dx][dy] != NON_MONSTER)
2544         {
2545             // Need to make sure that turn_is_over = 1 if creature is invisible
2546             mpr("There's a creature in the doorway!");
2547             door_move.dx = 0;
2548             door_move.dy = 0;
2549             return;
2550         }
2551 
2552         if (igrd[dx][dy] != NON_ITEM)
2553         {
2554             mpr("There's something blocking the doorway.");
2555             door_move.dx = 0;
2556             door_move.dy = 0;
2557             return;
2558         }
2559 
2560         int skill = you.dex + (you.skills[SK_TRAPS_DOORS] + you.skills[SK_STEALTH]) / 2;
2561 
2562         if (one_chance_in(skill) && !silenced(you.x_pos, you.y_pos))
2563         {
2564             mpr("As you close the door, it creaks loudly!");
2565             noisy( 10, you.x_pos, you.y_pos );
2566         }
2567         else
2568         {
2569             mpr( player_is_levitating() ? "You reach down and close the door."
2570                                         : "You close the door." );
2571         }
2572 
2573         grd[dx][dy] = DNGN_CLOSED_DOOR;
2574         you.turn_is_over = 1;
2575     }
2576     else
2577     {
2578         mpr("There isn't anything that you can close there!");
2579     }
2580 }                               // end open_door()
2581 
2582 
2583 // initialise whole lot of stuff...
2584 // returns true if a new character
initialise(void)2585 static bool initialise(void)
2586 {
2587     bool ret;
2588 
2589     int i = 0, j = 0;           // counter variables {dlb}
2590 
2591     your_sign = '@';
2592     your_colour = LIGHTGREY;
2593 
2594     // system initialisation stuff:
2595     textbackground(0);
2596 
2597 #ifdef DOS
2598     directvideo = 1;
2599 #endif
2600 
2601 #ifdef USE_EMX
2602     init_emx();
2603 #endif
2604 
2605     srandom(time(NULL));
2606     srand(time(NULL));
2607     cf_setseed();               // required for stuff::coinflip()
2608 
2609     mons_init(mcolour);          // this needs to be way up top {dlb}
2610     init_playerspells();        // this needs to be way up top {dlb}
2611 
2612     clrscr();
2613 
2614     // init item array:
2615     for (i = 1; i < MAX_ITEMS; i++)
2616         init_item( i );
2617 
2618     // empty messaging string
2619     strcpy(info, "");
2620 
2621     for (i = 0; i < MAX_MONSTERS; i++)
2622     {
2623         menv[i].type = -1;
2624         menv[i].speed_increment = 10;
2625         menv[i].flags = 0;
2626         menv[i].behaviour = BEH_SLEEP;
2627 
2628         menv[i].foe = NON_MONSTER;
2629         menv[i].attitude = ATT_HOSTILE;
2630 
2631         for (j = 0; j < NUM_MON_ENCHANTS; j++)
2632             menv[i].enchantment[j] = ENCH_NONE;
2633 
2634         for (j = 0; j < NUM_MONSTER_SLOTS; j++)
2635             menv[i].inv[j] = NON_ITEM;
2636 
2637         menv[i].number = 0;
2638     }
2639 
2640     for (i = 0; i < GXM; i++)
2641     {
2642         for (j = 0; j < GYM; j++)
2643         {
2644             igrd[i][j] = NON_ITEM;
2645             mgrd[i][j] = NON_MONSTER;
2646             env.map[i][j] = 0;
2647         }
2648     }
2649 
2650     for (i = 0; i < 50; i++)
2651     {
2652         you.unique_creatures[i] = 0;
2653         you.unique_items[i] = UNIQ_NOT_EXISTS;
2654     }
2655 
2656     for (i = 0; i < NUM_STATUE_TYPES; i++)
2657         Visible_Statue[i] = 0;
2658 
2659     // initialize tag system before we try loading anything!
2660     tag_init();
2661 
2662     // sets up a new game:
2663     bool newc = new_game();
2664     ret = newc;  // newc will be mangled later so we'll take a copy --bwr
2665 
2666     if (!newc)
2667         restore_game();
2668 
2669     game_has_started = true;
2670 
2671     calc_hp();
2672     calc_mp();
2673 
2674     load( 82, (newc ? LOAD_START_GAME : LOAD_RESTART_GAME), false, 0,
2675           you.where_are_you );
2676 
2677 #if DEBUG_DIAGNOSTICS
2678     // Debug compiles display a lot of "hidden" information, so we auto-wiz
2679     you.wizard = true;
2680 #endif
2681 
2682     init_properties();
2683     burden_change();
2684     make_hungry(0,true);
2685 
2686     you.redraw_strength = 1;
2687     you.redraw_intelligence = 1;
2688     you.redraw_dexterity = 1;
2689     you.redraw_armour_class = 1;
2690     you.redraw_evasion = 1;
2691     you.redraw_experience = 1;
2692     you.redraw_gold = 1;
2693     you.wield_change = true;
2694 
2695     you.start_time = time( NULL );      // start timer on session
2696 
2697     draw_border();
2698     new_level();
2699 
2700     // set vision radius to player's current vision
2701     setLOSRadius( you.current_vision );
2702     viewwindow(1, false);   // This just puts the view up for the first turn.
2703     item();
2704 
2705     return (ret);
2706 }
2707 
2708 // An attempt to tone down berserk a little bit. -- bwross
2709 //
2710 // This function does the accounting for not attacking while berserk
2711 // This gives a triangluar number function for the additional penalty
2712 // Turn:    1  2  3   4   5   6   7   8
2713 // Penalty: 1  3  6  10  15  21  28  36
2714 //
2715 // Total penalty (including the standard one during upkeep is:
2716 //          2  5  9  14  20  27  35  44
2717 //
do_berserk_no_combat_penalty(void)2718 static void do_berserk_no_combat_penalty(void)
2719 {
2720     // Butchering/eating a corpse will maintain a blood rage.
2721     const int delay = current_delay_action();
2722     if (delay == DELAY_BUTCHER || delay == DELAY_EAT)
2723         return;
2724 
2725     if (you.berserk_penalty == NO_BERSERK_PENALTY)
2726         return;
2727 
2728     if (you.berserker)
2729     {
2730         you.berserk_penalty++;
2731 
2732         switch (you.berserk_penalty)
2733         {
2734         case 2:
2735             mpr("You feel a strong urge to attack something.", MSGCH_DURATION);
2736             break;
2737         case 4:
2738             mpr("You feel your anger subside.", MSGCH_DURATION);
2739             break;
2740         case 6:
2741             mpr("Your blood rage is quickly leaving you.", MSGCH_DURATION);
2742             break;
2743         }
2744 
2745         // I do these three separately, because the might and
2746         // haste counters can be different.
2747         you.berserker -= you.berserk_penalty;
2748         if (you.berserker < 1)
2749             you.berserker = 1;
2750 
2751         you.might -= you.berserk_penalty;
2752         if (you.might < 1)
2753             you.might = 1;
2754 
2755         you.haste -= you.berserk_penalty;
2756         if (you.haste < 1)
2757             you.haste = 1;
2758     }
2759     return;
2760 }                               // end do_berserk_no_combat_penalty()
2761 
2762 
2763 // Called when the player moves by walking/running. Also calls
2764 // attack function and trap function etc when necessary.
move_player(char move_x,char move_y)2765 static void move_player(char move_x, char move_y)
2766 {
2767     bool attacking = false;
2768     bool moving = true;         // used to prevent eventual movement (swap)
2769 
2770     int i;
2771     bool trap_known;
2772 
2773     if (you.conf)
2774     {
2775         if (!one_chance_in(3))
2776         {
2777             move_x = random2(3) - 1;
2778             move_y = random2(3) - 1;
2779         }
2780 
2781         const int new_targ_x = you.x_pos + move_x;
2782         const int new_targ_y = you.y_pos + move_y;
2783         const unsigned char new_targ_grid = grd[ new_targ_x ][ new_targ_y ];
2784 
2785         if (new_targ_grid < MINMOVE)
2786         {
2787             you.turn_is_over = 1;
2788             mpr("Ouch!");
2789             return;
2790         }
2791 
2792         if (new_targ_grid == DNGN_LAVA
2793             && you.duration[DUR_CONDENSATION_SHIELD] > 0)
2794         {
2795             mpr("Your icy shield dissipates!", MSGCH_DURATION);
2796             you.duration[DUR_CONDENSATION_SHIELD] = 0;
2797             you.redraw_armour_class = 1;
2798         }
2799 
2800         if ((new_targ_grid == DNGN_LAVA
2801                 || new_targ_grid == DNGN_DEEP_WATER
2802                 || new_targ_grid == DNGN_SHALLOW_WATER)
2803              && !player_is_levitating())
2804         {
2805             if (you.species == SP_MERFOLK && new_targ_grid != DNGN_LAVA)
2806             {
2807                 mpr("You stumble into the water and return to your normal form.");
2808                 merfolk_start_swimming();
2809             }
2810 
2811             if (new_targ_grid != DNGN_SHALLOW_WATER)
2812                 fall_into_a_pool( false, new_targ_grid );
2813 
2814             you.turn_is_over = 1;
2815             do_berserk_no_combat_penalty();
2816             return;
2817         }
2818     }                           // end of if you.conf
2819 
2820     if (you.running > 0 && you.running != 2 && check_stop_running())
2821     {
2822         you.running = 0;
2823         move_x = 0;
2824         move_y = 0;
2825         you.turn_is_over = 0;
2826         return;
2827     }
2828 
2829     const int targ_x = you.x_pos + move_x;
2830     const int targ_y = you.y_pos + move_y;
2831     const unsigned char old_grid   =  grd[ you.x_pos ][ you.y_pos ];
2832     const unsigned char targ_grid  =  grd[ targ_x ][ targ_y ];
2833     const unsigned char targ_monst = mgrd[ targ_x ][ targ_y ];
2834 
2835     if (targ_monst != NON_MONSTER)
2836     {
2837         struct monsters *mon = &menv[targ_monst];
2838 
2839         if (mons_has_ench( mon, ENCH_SUBMERGED ))
2840             goto break_out;
2841 
2842         // you can swap places with a friendly monster if you
2843         // can see it and you're not confused
2844         if (mons_friendly( mon ) && player_monster_visible( mon ) && !you.conf)
2845         {
2846             if (!swap_places( mon ))
2847                 moving = false;
2848 
2849             goto break_out;
2850         }
2851 
2852         you_attack( targ_monst, true );
2853         you.turn_is_over = 1;
2854 
2855         // we don't want to create a penalty if there isn't
2856         // supposed to be one
2857         if (you.berserk_penalty != NO_BERSERK_PENALTY)
2858             you.berserk_penalty = 0;
2859 
2860         attacking = true;
2861     }
2862 
2863   break_out:
2864     if (targ_grid == DNGN_LAVA && you.duration[DUR_CONDENSATION_SHIELD] > 0)
2865     {
2866         mpr("Your icy shield dissipates!", MSGCH_DURATION);
2867         you.duration[DUR_CONDENSATION_SHIELD] = 0;
2868         you.redraw_armour_class = 1;
2869     }
2870 
2871     // Handle dangerous tiles
2872     if ((targ_grid == DNGN_LAVA
2873             || targ_grid == DNGN_DEEP_WATER
2874             || targ_grid == DNGN_SHALLOW_WATER)
2875         && !attacking && !player_is_levitating() && moving)
2876     {
2877         // Merfold automatically enter deep water... every other case
2878         // we ask for confirmation.
2879         if (you.species == SP_MERFOLK && targ_grid != DNGN_LAVA)
2880         {
2881             // Only mention diving if we just entering the water.
2882             if (!player_in_water())
2883             {
2884                 mpr("You dive into the water and return to your normal form.");
2885                 merfolk_start_swimming();
2886             }
2887         }
2888         else if (targ_grid != DNGN_SHALLOW_WATER)
2889         {
2890             bool enter = yesno("Do you really want to step there?", false);
2891 
2892             if (enter)
2893             {
2894                 fall_into_a_pool( false, targ_grid );
2895                 you.turn_is_over = 1;
2896                 do_berserk_no_combat_penalty();
2897                 return;
2898             }
2899             else
2900             {
2901                 canned_msg(MSG_OK);
2902                 return;
2903             }
2904         }
2905     }
2906 
2907     if (!attacking && targ_grid >= MINMOVE && moving)
2908     {
2909         if (targ_grid == DNGN_UNDISCOVERED_TRAP
2910                 && random2(you.skills[SK_TRAPS_DOORS] + 1) > 3)
2911         {
2912             strcpy(info, "Wait a moment, ");
2913             strcat(info, you.your_name);
2914             strcat(info, "! Do you really want to step there?");
2915             mpr(info, MSGCH_WARN);
2916             more();
2917             you.turn_is_over = 0;
2918 
2919             i = trap_at_xy( targ_x, targ_y );
2920             if (i != -1)
2921                 grd[ targ_x ][ targ_y ] = trap_category(env.trap[i].type);
2922             return;
2923         }
2924 
2925         you.x_pos += move_x;
2926         you.y_pos += move_y;
2927 
2928         if (targ_grid == DNGN_SHALLOW_WATER && !player_is_levitating())
2929         {
2930             if (you.species != SP_MERFOLK)
2931             {
2932                 if (one_chance_in(3) && !silenced(you.x_pos, you.y_pos))
2933                 {
2934                     mpr("Splash!");
2935                     noisy( 10, you.x_pos, you.y_pos );
2936                 }
2937 
2938                 you.time_taken *= 13 + random2(8);
2939                 you.time_taken /= 10;
2940 
2941                 if (old_grid != DNGN_SHALLOW_WATER)
2942                 {
2943                     mpr( "You enter the shallow water. "
2944                          "Moving in this stuff is going to be slow." );
2945 
2946                     if (you.invis)
2947                         mpr( "And don't expect to remain undetected." );
2948                 }
2949             }
2950             else if (old_grid != DNGN_SHALLOW_WATER
2951                     && old_grid != DNGN_DEEP_WATER)
2952             {
2953                 mpr("You return to your normal form as you enter the water.");
2954                 merfolk_start_swimming();
2955             }
2956         }
2957 
2958         move_x = 0;
2959         move_y = 0;
2960 
2961         you.time_taken *= player_movement_speed();
2962         you.time_taken /= 10;
2963 
2964         you.turn_is_over = 1;
2965         item_check(0);
2966 
2967         if (targ_grid >= DNGN_TRAP_MECHANICAL
2968                                 && targ_grid <= DNGN_UNDISCOVERED_TRAP)
2969         {
2970             if (targ_grid == DNGN_UNDISCOVERED_TRAP)
2971             {
2972                 i = trap_at_xy(you.x_pos, you.y_pos);
2973                 if (i != -1)
2974                     grd[ you.x_pos ][ you.y_pos ] = trap_category(env.trap[i].type);
2975                 trap_known = false;
2976             }
2977             else
2978             {
2979                 trap_known = true;
2980             }
2981 
2982             i = trap_at_xy( you.x_pos, you.y_pos );
2983             if (i != -1)
2984             {
2985                 if (player_is_levitating()
2986                     && trap_category(env.trap[i].type) == DNGN_TRAP_MECHANICAL)
2987                 {
2988                     goto out_of_traps;      // can fly over mechanical traps
2989                 }
2990 
2991                 handle_traps(env.trap[i].type, i, trap_known);
2992             }
2993         }                       // end of if another grd == trap
2994     }
2995 
2996   out_of_traps:
2997     // BCR - Easy doors single move
2998     if (targ_grid == DNGN_CLOSED_DOOR && Options.easy_open)
2999         open_door(move_x, move_y);
3000     else if (targ_grid <= MINMOVE)
3001     {
3002         you.running = 0;
3003         move_x = 0;
3004         move_y = 0;
3005         you.turn_is_over = 0;
3006     }
3007 
3008     if (you.running == 2)
3009         you.running = 1;
3010 
3011     if (you.level_type == LEVEL_ABYSS
3012             && (you.x_pos <= 15 || you.x_pos >= (GXM - 16)
3013                     || you.y_pos <= 15 || you.y_pos >= (GYM - 16)))
3014     {
3015         area_shift();
3016         you.pet_target = MHITNOT;
3017 
3018 #if DEBUG_DIAGNOSTICS
3019         mpr( "Shifting.", MSGCH_DIAGNOSTICS );
3020         int igly = 0;
3021         int ig2 = 0;
3022 
3023         for (igly = 0; igly < MAX_ITEMS; igly++)
3024         {
3025             if (is_valid_item( mitm[igly] ))
3026                 ig2++;
3027         }
3028 
3029         snprintf( info, INFO_SIZE, "Number of items present: %d", ig2 );
3030         mpr( info, MSGCH_DIAGNOSTICS );
3031 
3032         ig2 = 0;
3033         for (igly = 0; igly < MAX_MONSTERS; igly++)
3034         {
3035             if (menv[igly].type != -1)
3036                 ig2++;
3037         }
3038 
3039         snprintf( info, INFO_SIZE, "Number of monsters present: %d", ig2 );
3040         mpr( info, MSGCH_DIAGNOSTICS );
3041 
3042         snprintf( info, INFO_SIZE, "Number of clouds present: %d", env.cloud_no );
3043         mpr( info, MSGCH_DIAGNOSTICS );
3044 #endif
3045     }
3046 
3047     if (!attacking)
3048     {
3049         do_berserk_no_combat_penalty();
3050     }
3051 }                               // end move_player()
3052