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