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