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