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 14STATIC_DCL void NDECL(do_positionbar); 15#endif 16 17#ifdef OVL0 18 19void 20moveloop() 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 429void 430stop_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 450void 451display_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 479void 480newgame() 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 */ 546void 547welcome(new_game) 548boolean 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 576STATIC_DCL void 577do_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