OSDN Git Service

shrink mine
[nethackexpress/trunk.git] / src / allmain.c
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
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
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
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
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
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
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*/