1 /* NetHack 3.6 allmain.c $NHDT-Date: 1463217182 2016/05/14 09:13:02 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.72 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* various code that was replicated in *main.c */
14 STATIC_DCL
void NDECL(do_positionbar
);
16 STATIC_DCL
void FDECL(interrupt_multi
, (const char *));
22 #if defined(MICRO) || defined(WIN32)
26 int moveamt
= 0, wtcap
= 0, change
= 0;
27 boolean monscanmove
= FALSE
;
29 /* Note: these initializers don't do anything except guarantee that
30 we're linked properly.
34 monstr_init(); /* monster strengths */
37 /* if a save file created in normal mode is now being restored in
38 explore mode, treat it as normal restore followed by 'X' command
39 to use up the save file and require confirmation for explore mode */
40 if (resuming
&& iflags
.deferred_X
)
41 (void) enter_explore_mode();
43 /* side-effects from the real world */
44 flags
.moonphase
= phase_of_the_moon();
45 if (flags
.moonphase
== FULL_MOON
) {
46 You("are lucky! Full moon tonight.");
48 } else if (flags
.moonphase
== NEW_MOON
) {
49 pline("Be careful! New moon tonight.");
51 flags
.friday13
= friday_13th();
53 pline("Watch out! Bad things can happen on Friday the 13th.");
57 if (!resuming
) { /* new game */
58 context
.rndencode
= rnd(9000);
59 set_wear((struct obj
*) 0); /* for side-effects of starting gear */
60 (void) pickup(1); /* autopickup at initial location */
61 } else { /* restore old game */
63 update_inventory(); /* for perm_invent */
65 read_engr_at(u
.ux
, u
.uy
); /* subset of pickup() */
68 update_inventory(); /* for perm_invent */
71 (void) encumber_msg(); /* in case they auto-picked up something */
72 if (defer_see_monsters
) {
73 defer_see_monsters
= FALSE
;
78 u
.uz0
.dlevel
= u
.uz
.dlevel
;
79 youmonst
.movement
= NORMAL_SPEED
; /* give the hero some movement points */
82 program_state
.in_moveloop
= 1;
85 if (program_state
.done_hup
)
94 /* actual time passed */
95 youmonst
.movement
-= NORMAL_SPEED
;
97 do { /* hero can't move this turn loop */
98 wtcap
= encumber_msg();
100 context
.mon_moving
= TRUE
;
102 monscanmove
= movemon();
103 if (youmonst
.movement
>= NORMAL_SPEED
)
104 break; /* it's now your turn */
105 } while (monscanmove
);
106 context
.mon_moving
= FALSE
;
108 if (!monscanmove
&& youmonst
.movement
< NORMAL_SPEED
) {
109 /* both you and the monsters are out of steam this round
111 /* set up for a new turn */
113 mcalcdistress(); /* adjust monsters' trap, blind, etc */
115 /* reallocate movement rations to monsters */
116 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
117 mtmp
->movement
+= mcalcmove(mtmp
);
119 if (!rn2(u
.uevent
.udemigod
121 : (depth(&u
.uz
) > depth(&stronghold_level
))
124 (void) makemon((struct permonst
*) 0, 0, 0,
127 /* calculate how much time passed. */
128 if (u
.usteed
&& u
.umoved
) {
129 /* your speed doesn't augment steed's speed */
130 moveamt
= mcalcmove(u
.usteed
);
132 moveamt
= youmonst
.data
->mmove
;
134 if (Very_fast
) { /* speed boots or potion */
135 /* gain a free action on 2/3 of turns */
137 moveamt
+= NORMAL_SPEED
;
139 /* gain a free action on 1/3 of turns */
141 moveamt
+= NORMAL_SPEED
;
149 moveamt
-= (moveamt
/ 4);
152 moveamt
-= (moveamt
/ 2);
155 moveamt
-= ((moveamt
* 3) / 4);
158 moveamt
-= ((moveamt
* 7) / 8);
164 youmonst
.movement
+= moveamt
;
165 if (youmonst
.movement
< 0)
166 youmonst
.movement
= 0;
172 /********************************/
173 /* once-per-turn things go here */
174 /********************************/
183 if (flags
.time
&& !context
.run
)
186 /* One possible result of prayer is healing. Whether or
187 * not you get healed depends on your current hit points.
188 * If you are allowed to regenerate during the prayer, the
189 * end-of-prayer calculation messes up on this.
190 * Another possible result is rehumanization, which
192 * that encumbrance and movement rate be recalculated.
194 if (u
.uinvulnerable
) {
195 /* for the moment at least, you're in tiptop shape */
196 wtcap
= UNENCUMBERED
;
197 } else if (Upolyd
&& youmonst
.data
->mlet
== S_EEL
198 && !is_pool(u
.ux
, u
.uy
)
199 && !Is_waterlevel(&u
.uz
)) {
200 /* eel out of water loses hp, same as for monsters;
201 as hp gets lower, rate of further loss slows down
203 if (u
.mh
> 1 && rn2(u
.mh
) > rn2(8)
204 && (!Half_physical_damage
|| !(moves
% 2L))) {
209 } else if (Upolyd
&& u
.mh
< u
.mhmax
) {
212 else if (Regeneration
213 || (wtcap
< MOD_ENCUMBER
&& !(moves
% 20))) {
217 interrupt_multi("You are in full health.");
219 } else if (u
.uhp
< u
.uhpmax
220 && (wtcap
< MOD_ENCUMBER
|| !u
.umoved
222 if (u
.ulevel
> 9 && !(moves
% 3)) {
223 int heal
, Con
= (int) ACURR(A_CON
);
229 if (heal
> u
.ulevel
- 9)
234 if (u
.uhp
> u
.uhpmax
)
236 if (u
.uhp
>= u
.uhpmax
)
237 interrupt_multi("You are in full health.");
238 } else if (Regeneration
241 % ((MAXULEV
+ 12) / (u
.ulevel
+ 2)
245 if (u
.uhp
>= u
.uhpmax
)
246 interrupt_multi("You are in full health.");
250 /* moving around while encumbered is hard work */
251 if (wtcap
> MOD_ENCUMBER
&& u
.umoved
) {
252 if (!(wtcap
< EXT_ENCUMBER
? moves
% 30
254 if (Upolyd
&& u
.mh
> 1) {
256 } else if (!Upolyd
&& u
.uhp
> 1) {
259 You("pass out from exertion!");
260 exercise(A_CON
, FALSE
);
261 fall_asleep(-10, FALSE
);
266 if ((u
.uen
< u
.uenmax
)
267 && ((wtcap
< MOD_ENCUMBER
268 && (!(moves
% ((MAXULEV
+ 8 - u
.ulevel
)
269 * (Role_if(PM_WIZARD
) ? 3 : 4)
270 / 6)))) || Energy_regeneration
)) {
272 (int) (ACURR(A_WIS
) + ACURR(A_INT
)) / 15 + 1, 1);
273 if (u
.uen
> u
.uenmax
)
276 if (u
.uen
>= u
.uenmax
)
277 interrupt_multi("You feel full of energy.");
280 if (!u
.uinvulnerable
) {
281 if (Teleportation
&& !rn2(85)) {
282 xchar old_ux
= u
.ux
, old_uy
= u
.uy
;
284 if (u
.ux
!= old_ux
|| u
.uy
!= old_uy
) {
286 check_leash(old_ux
, old_uy
);
288 /* clear doagain keystrokes */
293 /* delayed change may not be valid anymore */
294 if ((change
== 1 && !Polymorph
)
295 || (change
== 2 && u
.ulycn
== NON_PM
))
297 if (Polymorph
&& !rn2(100))
299 else if (u
.ulycn
>= LOW_PM
&& !Upolyd
300 && !rn2(80 - (20 * night())))
302 if (change
&& !Unchanging
) {
314 if (Searching
&& multi
>= 0)
326 if (!rn2(40 + (int) (ACURR(A_DEX
) * 3)))
328 if (u
.uevent
.udemigod
&& !u
.uinvulnerable
) {
333 u
.udg_cnt
= rn1(200, 50);
337 /* underwater and waterlevel vision are done here */
338 if (Is_waterlevel(&u
.uz
) || Is_airlevel(&u
.uz
))
340 else if (Is_firelevel(&u
.uz
))
344 /* vision while buried done here */
348 /* when immobile, count is in turns */
350 if (++multi
== 0) { /* finished yet? */
352 /* if unmul caused a level change, take it now */
358 } while (youmonst
.movement
359 < NORMAL_SPEED
); /* hero can't move loop */
361 /******************************************/
362 /* once-per-hero-took-time things go here */
363 /******************************************/
365 if (context
.bypasses
)
367 if ((u
.uhave
.amulet
|| Clairvoyant
) && !In_endgame(&u
.uz
)
368 && !BClairvoyant
&& !(moves
% 15) && !rn2(2))
369 do_vicinity_map((struct obj
*) 0);
370 if (u
.utrap
&& u
.utraptype
== TT_LAVA
)
372 /* when/if hero escapes from lava, he can't just stay there */
374 (void) pooleffects(FALSE
);
376 } /* actual time passed */
378 /****************************************/
379 /* once-per-player-input things go here */
380 /****************************************/
384 if (!context
.mv
|| Blind
) {
385 /* redo monsters if hallu or wearing a helm of telepathy */
386 if (Hallucination
) { /* update screen randomly */
392 } else if (Unblind_telepat
) {
394 } else if (Warning
|| Warn_of_mon
)
397 if (vision_full_recalc
)
398 vision_recalc(0); /* vision! */
400 if (context
.botl
|| context
.botlx
) {
407 if (multi
>= 0 && occupation
) {
408 #if defined(MICRO) || defined(WIN32)
411 if ((ch
= pgetchar()) == ABORT
)
416 if (!abort_lev
&& (*occupation
)() == 0)
418 if ((*occupation
)() == 0)
422 #if defined(MICRO) || defined(WIN32)
429 #if defined(MICRO) || defined(WIN32)
430 if (!(++occtime
% 7))
431 display_nhwindow(WIN_MAP
, FALSE
);
436 if (iflags
.sanity_check
)
440 /* just before rhack */
441 cliparound(u
.ux
, u
.uy
);
449 /* lookaround may clear multi */
456 if (multi
< COLNO
&& !--multi
)
457 context
.travel
= context
.travel1
= context
.mv
=
464 } else if (multi
== 0) {
470 if (u
.utotype
) /* change dungeon level */
471 deferred_goto(); /* after rhack() */
472 /* !context.move here: multiple movement command stopped */
473 else if (flags
.time
&& (!context
.move
|| !context
.mv
))
476 if (vision_full_recalc
)
477 vision_recalc(0); /* vision! */
478 /* when running in non-tport mode, this gets done through domove() */
479 if ((!context
.run
|| flags
.runmode
== RUN_TPORT
)
480 && (multi
&& (!context
.travel
? !(multi
% 7) : !(moves
% 7L)))) {
481 if (flags
.time
&& context
.run
)
483 display_nhwindow(WIN_MAP
, FALSE
);
492 if (!maybe_finished_meal(TRUE
))
493 You("stop %s.", occtxt
);
495 context
.botl
= 1; /* in case u.uhs changed */
498 } else if (multi
>= 0) {
504 display_gamewindows()
506 WIN_MESSAGE
= create_nhwindow(NHW_MESSAGE
);
507 #ifdef STATUS_VIA_WINDOWPORT
508 status_initialize(0);
510 WIN_STATUS
= create_nhwindow(NHW_STATUS
);
512 WIN_MAP
= create_nhwindow(NHW_MAP
);
513 WIN_INVEN
= create_nhwindow(NHW_MENU
);
514 /* in case of early quit where WIN_INVEN could be destroyed before
515 ever having been used, use it here to pacify the Qt interface */
516 start_menu(WIN_INVEN
), end_menu(WIN_INVEN
, (char *) 0);
519 /* This _is_ the right place for this - maybe we will
520 * have to split display_gamewindows into create_gamewindows
521 * and show_gamewindows to get rid of this ifdef...
523 if (!strcmp(windowprocs
.name
, "mac"))
528 * The mac port is not DEPENDENT on the order of these
529 * displays, but it looks a lot better this way...
531 #ifndef STATUS_VIA_WINDOWPORT
532 display_nhwindow(WIN_STATUS
, FALSE
);
534 display_nhwindow(WIN_MESSAGE
, FALSE
);
535 clear_glyph_buffer();
536 display_nhwindow(WIN_MAP
, FALSE
);
550 context
.stethoscope_move
= -1L;
551 context
.warnlevel
= 1;
552 context
.next_attrib_check
= 600L; /* arbitrary first setting */
553 context
.tribute
.enabled
= TRUE
; /* turn on 3.6 tributes */
554 context
.tribute
.tributesz
= sizeof(struct tribute_info
);
556 for (i
= 0; i
< NUMMONS
; i
++)
557 mvitals
[i
].mvflags
= mons
[i
].geno
& G_NOCORPSE
;
559 init_objects(); /* must be before u_init() */
561 flags
.pantheon
= -1; /* role_init() will reset this */
562 role_init(); /* must be before init_dungeons(), u_init(),
563 * and init_artifacts() */
565 init_dungeons(); /* must be before u_init() to avoid rndmonst()
566 * creating odd monsters for any tins and eggs
567 * in hero's initial inventory */
568 init_artifacts(); /* before u_init() in case $WIZKIT specifies
573 (void) signal(SIGINT
, (SIG_RET_TYPE
) done1
);
577 display_file(NEWS
, FALSE
);
579 load_qtlist(); /* load up the quest text info */
580 /* quest_init(); -- Now part of role_init() */
585 obj_delivery(FALSE
); /* finish wizkit */
586 vision_reset(); /* set up internals for level (after mklev) */
587 check_special_room(FALSE
);
589 if (MON_AT(u
.ux
, u
.uy
))
590 mnexto(m_at(u
.ux
, u
.uy
));
599 urealtime
.realtime
= 0L;
600 urealtime
.start_timing
= getnow();
604 program_state
.something_worth_saving
++; /* useful data now exists */
611 /* show "welcome [back] to nethack" message at program startup */
614 boolean new_game
; /* false => restoring an old game */
617 boolean currentgend
= Upolyd
? u
.mfemale
: flags
.female
;
620 * The "welcome back" message always describes your innate form
621 * even when polymorphed or wearing a helm of opposite alignment.
622 * Alignment is shown unconditionally for new games; for restores
623 * it's only shown if it has changed from its original value.
624 * Sex is shown for new games except when it is redundant; for
625 * restores it's only shown if different from its original value.
628 if (new_game
|| u
.ualignbase
[A_ORIGINAL
] != u
.ualignbase
[A_CURRENT
])
629 Sprintf(eos(buf
), " %s", align_str(u
.ualignbase
[A_ORIGINAL
]));
632 ? (urole
.allow
& ROLE_GENDMASK
) == (ROLE_MALE
| ROLE_FEMALE
)
633 : currentgend
!= flags
.initgend
))
634 Sprintf(eos(buf
), " %s", genders
[currentgend
].adj
);
636 pline(new_game
? "%s %s, welcome to NetHack! You are a%s %s %s."
637 : "%s %s, the%s %s %s, welcome back to NetHack!",
638 Hello((struct monst
*) 0), plname
, buf
, urace
.adj
,
639 (currentgend
&& urole
.name
.f
) ? urole
.name
.f
: urole
.name
.m
);
646 static char pbar
[COLNO
];
652 && (glyph_to_cmap(level
.locations
[upstair
.sx
][upstair
.sy
].glyph
)
654 || glyph_to_cmap(level
.locations
[upstair
.sx
][upstair
.sy
].glyph
)
660 && (glyph_to_cmap(level
.locations
[sstairs
.sx
][sstairs
.sy
].glyph
)
662 || glyph_to_cmap(level
.locations
[sstairs
.sx
][sstairs
.sy
].glyph
)
670 && (glyph_to_cmap(level
.locations
[dnstair
.sx
][dnstair
.sy
].glyph
)
672 || glyph_to_cmap(level
.locations
[dnstair
.sx
][dnstair
.sy
].glyph
)
678 && (glyph_to_cmap(level
.locations
[sstairs
.sx
][sstairs
.sy
].glyph
)
680 || glyph_to_cmap(level
.locations
[sstairs
.sx
][sstairs
.sy
].glyph
)
694 update_positionbar(pbar
);
702 if (multi
> 0 && !context
.travel
) {
704 if (flags
.verbose
&& msg
)