1 /*	SCCS Id: @(#)allmain.c	3.4	2003/04/02	*/
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 /* various code that was replicated in *main.c */
6 
7 #include "hack.h"
8 
9 #ifndef NO_SIGNAL
10 #include <signal.h>
11 #endif
12 
13 #ifdef POSITIONBAR
14 STATIC_DCL void NDECL(do_positionbar);
15 #endif
16 
17 #ifdef OVL0
18 
19 void
moveloop()20 moveloop()
21 {
22 #if defined(MICRO) || defined(WIN32)
23     char ch;
24     int abort_lev;
25 #endif
26     int moveamt = 0, wtcap = 0, change = 0;
27     boolean didmove = FALSE, monscanmove = FALSE;
28 
29     flags.moonphase = phase_of_the_moon();
30     if(flags.moonphase == FULL_MOON) {
31 	You("are lucky!  Full moon tonight.");
32 	change_luck(1);
33     } else if(flags.moonphase == NEW_MOON) {
34 	pline("Be careful!  New moon tonight.");
35     }
36     flags.friday13 = friday_13th();
37     if (flags.friday13) {
38 	pline("Watch out!  Bad things can happen on Friday the 13th.");
39 	change_luck(-1);
40     }
41 
42     initrack();
43 
44 
45     /* Note:  these initializers don't do anything except guarantee that
46 	    we're linked properly.
47     */
48     decl_init();
49     monst_init();
50     monstr_init();	/* monster strengths */
51     objects_init();
52 
53 #ifdef WIZARD
54     if (wizard) add_debug_extended_commands();
55 #endif
56 
57     (void) encumber_msg(); /* in case they auto-picked up something */
58 
59     u.uz0.dlevel = u.uz.dlevel;
60     youmonst.movement = NORMAL_SPEED;	/* give the hero some movement points */
61 
62     for(;;) {
63 	get_nh_event();
64 #ifdef POSITIONBAR
65 	do_positionbar();
66 #endif
67 
68 	didmove = flags.move;
69 	if(didmove) {
70 	    /* actual time passed */
71 	    youmonst.movement -= NORMAL_SPEED;
72 
73 	    do { /* hero can't move this turn loop */
74 		wtcap = encumber_msg();
75 
76 		flags.mon_moving = TRUE;
77 		do {
78 		    monscanmove = movemon();
79 		    if (youmonst.movement > NORMAL_SPEED)
80 			break;	/* it's now your turn */
81 		} while (monscanmove);
82 		flags.mon_moving = FALSE;
83 
84 		if (!monscanmove && youmonst.movement < NORMAL_SPEED) {
85 		    /* both you and the monsters are out of steam this round */
86 		    /* set up for a new turn */
87 		    struct monst *mtmp;
88 		    mcalcdistress();	/* adjust monsters' trap, blind, etc */
89 
90 		    /* reallocate movement rations to monsters */
91 		    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
92 			mtmp->movement += mcalcmove(mtmp);
93 
94 		    if(!rn2(u.uevent.udemigod ? 25 :
95 			    (depth(&u.uz) > depth(&stronghold_level)) ? 50 : 70))
96 			(void) makemon((struct permonst *)0, 0, 0, NO_MM_FLAGS);
97 
98 		    /* calculate how much time passed. */
99 #ifdef STEED
100 		    if (u.usteed && u.umoved) {
101 			/* your speed doesn't augment steed's speed */
102 			moveamt = mcalcmove(u.usteed);
103 		    } else
104 #endif
105 		    {
106 			moveamt = youmonst.data->mmove;
107 
108 			if (Very_fast) {	/* speed boots or potion */
109 			    /* average movement is 1.67 times normal */
110 			    moveamt += NORMAL_SPEED / 2;
111 			    if (rn2(3) == 0) moveamt += NORMAL_SPEED / 2;
112 			} else if (Fast) {
113 			    /* average movement is 1.33 times normal */
114 			    if (rn2(3) != 0) moveamt += NORMAL_SPEED / 2;
115 			}
116 		    }
117 
118 		    switch (wtcap) {
119 			case UNENCUMBERED: break;
120 			case SLT_ENCUMBER: moveamt -= (moveamt / 4); break;
121 			case MOD_ENCUMBER: moveamt -= (moveamt / 2); break;
122 			case HVY_ENCUMBER: moveamt -= ((moveamt * 3) / 4); break;
123 			case EXT_ENCUMBER: moveamt -= ((moveamt * 7) / 8); break;
124 			default: break;
125 		    }
126 
127 		    youmonst.movement += moveamt;
128 		    if (youmonst.movement < 0) youmonst.movement = 0;
129 		    settrack();
130 
131 		    monstermoves++;
132 		    moves++;
133 
134 		    /********************************/
135 		    /* once-per-turn things go here */
136 		    /********************************/
137 
138 		    if (flags.bypasses) clear_bypasses();
139 		    if(Glib) glibr();
140 		    nh_timeout();
141 		    run_regions();
142 
143 		    if (u.ublesscnt)  u.ublesscnt--;
144 		    if(flags.time && !flags.run)
145 			flags.botl = 1;
146 
147 		    /* One possible result of prayer is healing.  Whether or
148 		     * not you get healed depends on your current hit points.
149 		     * If you are allowed to regenerate during the prayer, the
150 		     * end-of-prayer calculation messes up on this.
151 		     * Another possible result is rehumanization, which requires
152 		     * that encumbrance and movement rate be recalculated.
153 		     */
154 		    if (u.uinvulnerable) {
155 			/* for the moment at least, you're in tiptop shape */
156 			wtcap = UNENCUMBERED;
157 		    } else if (Upolyd && youmonst.data->mlet == S_EEL && !is_pool(u.ux,u.uy) && !Is_waterlevel(&u.uz)) {
158 			if (u.mh > 1) {
159 			    u.mh--;
160 			    flags.botl = 1;
161 			} else if (u.mh < 1)
162 			    rehumanize();
163 		    } else if (Upolyd && u.mh < u.mhmax) {
164 			if (u.mh < 1)
165 			    rehumanize();
166 			else if (Regeneration ||
167 				    (wtcap < MOD_ENCUMBER && !(moves%20))) {
168 			    flags.botl = 1;
169 			    u.mh++;
170 			}
171 		    } else if (u.uhp < u.uhpmax &&
172 			 (wtcap < MOD_ENCUMBER || !u.umoved || Regeneration)) {
173 			if (u.ulevel > 9 && !(moves % 3)) {
174 			    int heal, Con = (int) ACURR(A_CON);
175 
176 			    if (Con <= 12) {
177 				heal = 1;
178 			    } else {
179 				heal = rnd(Con);
180 				if (heal > u.ulevel-9) heal = u.ulevel-9;
181 			    }
182 			    flags.botl = 1;
183 			    u.uhp += heal;
184 			    if(u.uhp > u.uhpmax)
185 				u.uhp = u.uhpmax;
186 			} else if (Regeneration ||
187 			     (u.ulevel <= 9 &&
188 			      !(moves % ((MAXULEV+12) / (u.ulevel+2) + 1)))) {
189 			    flags.botl = 1;
190 			    u.uhp++;
191 			}
192 		    }
193 
194 		    /* moving around while encumbered is hard work */
195 		    if (wtcap > MOD_ENCUMBER && u.umoved) {
196 			if(!(wtcap < EXT_ENCUMBER ? moves%30 : moves%10)) {
197 			    if (Upolyd && u.mh > 1) {
198 				u.mh--;
199 			    } else if (!Upolyd && u.uhp > 1) {
200 				u.uhp--;
201 			    } else {
202 				You("pass out from exertion!");
203 				exercise(A_CON, FALSE);
204 				fall_asleep(-10, FALSE);
205 			    }
206 			}
207 		    }
208 
209 		    if ((u.uen < u.uenmax) &&
210 			((wtcap < MOD_ENCUMBER &&
211 			  (!(moves%((MAXULEV + 8 - u.ulevel) *
212 				    (Role_if(PM_WIZARD) ? 3 : 4) / 6))))
213 			 || Energy_regeneration)) {
214 			u.uen += rn1((int)(ACURR(A_WIS) + ACURR(A_INT)) / 15 + 1,1);
215 			if (u.uen > u.uenmax)  u.uen = u.uenmax;
216 			flags.botl = 1;
217 		    }
218 
219 		    if(!u.uinvulnerable) {
220 			if(Teleportation && !rn2(85)) {
221 			    xchar old_ux = u.ux, old_uy = u.uy;
222 			    tele();
223 			    if (u.ux != old_ux || u.uy != old_uy) {
224 				if (!next_to_u()) {
225 				    check_leash(old_ux, old_uy);
226 				}
227 #ifdef REDO
228 				/* clear doagain keystrokes */
229 				pushch(0);
230 				savech(0);
231 #endif
232 			    }
233 			}
234 			/* delayed change may not be valid anymore */
235 			if ((change == 1 && !Polymorph) ||
236 			    (change == 2 && u.ulycn == NON_PM))
237 			    change = 0;
238 			if(Polymorph && !rn2(100))
239 			    change = 1;
240 			else if (u.ulycn >= LOW_PM && !Upolyd &&
241 				 !rn2(80 - (20 * night())))
242 			    change = 2;
243 			if (change && !Unchanging) {
244 			    if (multi >= 0) {
245 				if (occupation)
246 				    stop_occupation();
247 				else
248 				    nomul(0);
249 				if (change == 1) polyself(FALSE);
250 				else you_were();
251 				change = 0;
252 			    }
253 			}
254 		    }
255 
256 		    if(Searching && multi >= 0) (void) dosearch0(1);
257 		    dosounds();
258 		    do_storms();
259 		    gethungry();
260 		    age_spells();
261 		    exerchk();
262 		    invault();
263 		    if (u.uhave.amulet) amulet();
264 		    if (!rn2(40+(int)(ACURR(A_DEX)*3)))
265 			u_wipe_engr(rnd(3));
266 		    if (u.uevent.udemigod && !u.uinvulnerable) {
267 			if (u.udg_cnt) u.udg_cnt--;
268 			if (!u.udg_cnt) {
269 			    intervene();
270 			    u.udg_cnt = rn1(200, 50);
271 			}
272 		    }
273 		    restore_attrib();
274 		    /* underwater and waterlevel vision are done here */
275 		    if (Is_waterlevel(&u.uz))
276 			movebubbles();
277 		    else if (Underwater)
278 			under_water(0);
279 		    /* vision while buried done here */
280 		    else if (u.uburied) under_ground(0);
281 
282 		    /* when immobile, count is in turns */
283 		    if(multi < 0) {
284 			if (++multi == 0) {	/* finished yet? */
285 			    unmul((char *)0);
286 			    /* if unmul caused a level change, take it now */
287 			    if (u.utotype) deferred_goto();
288 			}
289 		    }
290 		}
291 	    } while (youmonst.movement<NORMAL_SPEED); /* hero can't move loop */
292 
293 	    /******************************************/
294 	    /* once-per-hero-took-time things go here */
295 	    /******************************************/
296 
297 
298 	} /* actual time passed */
299 
300 	/****************************************/
301 	/* once-per-player-input things go here */
302 	/****************************************/
303 
304 	find_ac();
305 	if(!flags.mv || Blind) {
306 	    /* redo monsters if hallu or wearing a helm of telepathy */
307 	    if (Hallucination) {	/* update screen randomly */
308 		see_monsters();
309 		see_objects();
310 		see_traps();
311 		if (u.uswallow) swallowed(0);
312 	    } else if (Unblind_telepat) {
313 		see_monsters();
314 	    } else if (Warning || Warn_of_mon)
315 	     	see_monsters();
316 
317 	    if (vision_full_recalc) vision_recalc(0);	/* vision! */
318 	}
319 	if(flags.botl || flags.botlx) bot();
320 
321 	flags.move = 1;
322 
323 	if(multi >= 0 && occupation) {
324 #if defined(MICRO) || defined(WIN32)
325 	    abort_lev = 0;
326 	    if (kbhit()) {
327 		if ((ch = Getchar()) == ABORT)
328 		    abort_lev++;
329 # ifdef REDO
330 		else
331 		    pushch(ch);
332 # endif /* REDO */
333 	    }
334 	    if (!abort_lev && (*occupation)() == 0)
335 #else
336 	    if ((*occupation)() == 0)
337 #endif
338 		occupation = 0;
339 	    if(
340 #if defined(MICRO) || defined(WIN32)
341 		   abort_lev ||
342 #endif
343 		   monster_nearby()) {
344 		stop_occupation();
345 		reset_eat();
346 	    }
347 #if defined(MICRO) || defined(WIN32)
348 	    if (!(++occtime % 7))
349 		display_nhwindow(WIN_MAP, FALSE);
350 #endif
351 	    continue;
352 	}
353 
354 	if ((u.uhave.amulet || Clairvoyant) &&
355 	    !In_endgame(&u.uz) && !BClairvoyant &&
356 	    !(moves % 15) && !rn2(2))
357 		do_vicinity_map();
358 
359 	if(u.utrap && u.utraptype == TT_LAVA) {
360 	    if(!is_lava(u.ux,u.uy))
361 		u.utrap = 0;
362 	    else if (!u.uinvulnerable) {
363 		u.utrap -= 1<<8;
364 		if(u.utrap < 1<<8) {
365 		    killer_format = KILLED_BY;
366 		    killer = "molten lava";
367 		    You("sink below the surface and die.");
368 		    done(DISSOLVED);
369 		} else if(didmove && !u.umoved) {
370 		    Norep("You sink deeper into the lava.");
371 		    u.utrap += rnd(4);
372 		}
373 	    }
374 	}
375 
376 #ifdef WIZARD
377 	if (iflags.sanity_check)
378 	    sanity_check();
379 #endif
380 
381 #ifdef CLIPPING
382 	/* just before rhack */
383 	cliparound(u.ux, u.uy);
384 #endif
385 
386 	u.umoved = FALSE;
387 
388 	if (multi > 0) {
389 	    lookaround();
390 	    if (!multi) {
391 		/* lookaround may clear multi */
392 		flags.move = 0;
393 		if (flags.time) flags.botl = 1;
394 		continue;
395 	    }
396 	    if (flags.mv) {
397 		if(multi < COLNO && !--multi)
398 		    flags.travel = iflags.travel1 = flags.mv = flags.run = 0;
399 		domove();
400 	    } else {
401 		--multi;
402 		rhack(save_cm);
403 	    }
404 	} else if (multi == 0) {
405 #ifdef MAIL
406 	    ckmailstatus();
407 #endif
408 	    rhack((char *)0);
409 	}
410 	if (u.utotype)		/* change dungeon level */
411 	    deferred_goto();	/* after rhack() */
412 	/* !flags.move here: multiple movement command stopped */
413 	else if (flags.time && (!flags.move || !flags.mv))
414 	    flags.botl = 1;
415 
416 	if (vision_full_recalc) vision_recalc(0);	/* vision! */
417 	/* when running in non-tport mode, this gets done through domove() */
418 	if ((!flags.run || iflags.runmode == RUN_TPORT) &&
419 		(multi && (!flags.travel ? !(multi % 7) : !(moves % 7L)))) {
420 	    if (flags.time && flags.run) flags.botl = 1;
421 	    display_nhwindow(WIN_MAP, FALSE);
422 	}
423     }
424 }
425 
426 #endif /* OVL0 */
427 #ifdef OVL1
428 
429 void
stop_occupation()430 stop_occupation()
431 {
432 	if(occupation) {
433 		if (!maybe_finished_meal(TRUE))
434 		    You("stop %s.", occtxt);
435 		occupation = 0;
436 		flags.botl = 1; /* in case u.uhs changed */
437 /* fainting stops your occupation, there's no reason to sync.
438 		sync_hunger();
439 */
440 #ifdef REDO
441 		nomul(0);
442 		pushch(0);
443 #endif
444 	}
445 }
446 
447 #endif /* OVL1 */
448 #ifdef OVLB
449 
450 void
display_gamewindows()451 display_gamewindows()
452 {
453     WIN_MESSAGE = create_nhwindow(NHW_MESSAGE);
454     WIN_STATUS = create_nhwindow(NHW_STATUS);
455     WIN_MAP = create_nhwindow(NHW_MAP);
456     WIN_INVEN = create_nhwindow(NHW_MENU);
457 
458 #ifdef MAC
459     /*
460      * This _is_ the right place for this - maybe we will
461      * have to split display_gamewindows into create_gamewindows
462      * and show_gamewindows to get rid of this ifdef...
463      */
464 	if ( ! strcmp ( windowprocs . name , "mac" ) ) {
465 	    SanePositions ( ) ;
466 	}
467 #endif
468 
469     /*
470      * The mac port is not DEPENDENT on the order of these
471      * displays, but it looks a lot better this way...
472      */
473     display_nhwindow(WIN_STATUS, FALSE);
474     display_nhwindow(WIN_MESSAGE, FALSE);
475     clear_glyph_buffer();
476     display_nhwindow(WIN_MAP, FALSE);
477 }
478 
479 void
newgame()480 newgame()
481 {
482 	int i;
483 
484 #ifdef MFLOPPY
485 	gameDiskPrompt();
486 #endif
487 
488 	flags.ident = 1;
489 
490 	for (i = 0; i < NUMMONS; i++)
491 		mvitals[i].mvflags = mons[i].geno & G_NOCORPSE;
492 
493 	init_objects();		/* must be before u_init() */
494 
495 	flags.pantheon = -1;	/* role_init() will reset this */
496 	role_init();		/* must be before init_dungeons(), u_init(),
497 				 * and init_artifacts() */
498 
499 	init_dungeons();	/* must be before u_init() to avoid rndmonst()
500 				 * creating odd monsters for any tins and eggs
501 				 * in hero's initial inventory */
502 	init_artifacts();	/* before u_init() in case $WIZKIT specifies
503 				 * any artifacts */
504 	u_init();
505 
506 #ifndef NO_SIGNAL
507 	(void) signal(SIGINT, (SIG_RET_TYPE) done1);
508 #endif
509 #ifdef NEWS
510 	if(iflags.news) display_file(NEWS, FALSE);
511 #endif
512 	load_qtlist();	/* load up the quest text info */
513 /*	quest_init();*/	/* Now part of role_init() */
514 
515 	mklev();
516 	u_on_upstairs();
517 	vision_reset();		/* set up internals for level (after mklev) */
518 	check_special_room(FALSE);
519 
520 	flags.botlx = 1;
521 
522 	/* Move the monster from under you or else
523 	 * makedog() will fail when it calls makemon().
524 	 *			- ucsfcgl!kneller
525 	 */
526 	if(MON_AT(u.ux, u.uy)) mnexto(m_at(u.ux, u.uy));
527 	(void) makedog();
528 	docrt();
529 
530 	if (flags.legacy) {
531 		flush_screen(1);
532 		com_pager(1);
533 	}
534 
535 #ifdef INSURANCE
536 	save_currentstate();
537 #endif
538 	program_state.something_worth_saving++;	/* useful data now exists */
539 
540 	/* Success! */
541 	welcome(TRUE);
542 	return;
543 }
544 
545 /* show "welcome [back] to nethack" message at program startup */
546 void
welcome(new_game)547 welcome(new_game)
548 boolean new_game;	/* false => restoring an old game */
549 {
550     char buf[BUFSZ];
551     boolean currentgend = Upolyd ? u.mfemale : flags.female;
552 
553     /*
554      * The "welcome back" message always describes your innate form
555      * even when polymorphed or wearing a helm of opposite alignment.
556      * Alignment is shown unconditionally for new games; for restores
557      * it's only shown if it has changed from its original value.
558      * Sex is shown for new games except when it is redundant; for
559      * restores it's only shown if different from its original value.
560      */
561     *buf = '\0';
562     if (new_game || u.ualignbase[A_ORIGINAL] != u.ualignbase[A_CURRENT])
563 	Sprintf(eos(buf), " %s", align_str(u.ualignbase[A_ORIGINAL]));
564     if (!urole.name.f &&
565 	    (new_game ? (urole.allow & ROLE_GENDMASK) == (ROLE_MALE|ROLE_FEMALE) :
566 	     currentgend != flags.initgend))
567 	Sprintf(eos(buf), " %s", genders[currentgend].adj);
568 
569     pline(new_game ? "%s %s, welcome to NetHack!  You are a%s %s %s."
570 		   : "%s %s, the%s %s %s, welcome back to NetHack!",
571 	  Hello((struct monst *) 0), plname, buf, urace.adj,
572 	  (currentgend && urole.name.f) ? urole.name.f : urole.name.m);
573 }
574 
575 #ifdef POSITIONBAR
576 STATIC_DCL void
do_positionbar()577 do_positionbar()
578 {
579 	static char pbar[COLNO];
580 	char *p;
581 
582 	p = pbar;
583 	/* up stairway */
584 	if (upstair.sx &&
585 	   (glyph_to_cmap(level.locations[upstair.sx][upstair.sy].glyph) ==
586 	    S_upstair ||
587  	    glyph_to_cmap(level.locations[upstair.sx][upstair.sy].glyph) ==
588 	    S_upladder)) {
589 		*p++ = '<';
590 		*p++ = upstair.sx;
591 	}
592 	if (sstairs.sx &&
593 	   (glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph) ==
594 	    S_upstair ||
595  	    glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph) ==
596 	    S_upladder)) {
597 		*p++ = '<';
598 		*p++ = sstairs.sx;
599 	}
600 
601 	/* down stairway */
602 	if (dnstair.sx &&
603 	   (glyph_to_cmap(level.locations[dnstair.sx][dnstair.sy].glyph) ==
604 	    S_dnstair ||
605  	    glyph_to_cmap(level.locations[dnstair.sx][dnstair.sy].glyph) ==
606 	    S_dnladder)) {
607 		*p++ = '>';
608 		*p++ = dnstair.sx;
609 	}
610 	if (sstairs.sx &&
611 	   (glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph) ==
612 	    S_dnstair ||
613  	    glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph) ==
614 	    S_dnladder)) {
615 		*p++ = '>';
616 		*p++ = sstairs.sx;
617 	}
618 
619 	/* hero location */
620 	if (u.ux) {
621 		*p++ = '@';
622 		*p++ = u.ux;
623 	}
624 	/* fence post */
625 	*p = 0;
626 
627 	update_positionbar(pbar);
628 }
629 #endif
630 
631 #endif /* OVLB */
632 
633 /*allmain.c*/
634