void moveloop() { #if defined(MICRO) || defined(WIN32) char ch; int abort_lev; #endif int moveamt = 0, wtcap = 0, change = 0; boolean didmove = FALSE, monscanmove = FALSE; flags.moonphase = phase_of_the_moon(); if(flags.moonphase == FULL_MOON) { You("are lucky! Full moon tonight."); change_luck(1); } else if(flags.moonphase == NEW_MOON) { pline("Be careful! New moon tonight."); } flags.friday13 = friday_13th(); if (flags.friday13) { pline("Watch out! Bad things can happen on Friday the 13th."); change_luck(-1); } initrack(); /* Note: these initializers don't do anything except guarantee that we're linked properly. */ decl_init(); monst_init(); monstr_init(); /* monster strengths */ objects_init(); commands_init(); (void) encumber_msg(); /* in case they auto-picked up something */ u.uz0.dlevel = u.uz.dlevel; youmonst.movement = NORMAL_SPEED; /* give the hero some movement points */ for(;;) { get_nh_event(); #ifdef POSITIONBAR do_positionbar(); #endif didmove = flags.move; if(didmove) { /* actual time passed */ youmonst.movement -= NORMAL_SPEED; do { /* hero can't move this turn loop */ wtcap = encumber_msg(); flags.mon_moving = TRUE; do { monscanmove = movemon(); if (youmonst.movement >= NORMAL_SPEED) { curmonst = &youmonst; break; /* it's now your turn */ } } while (monscanmove); flags.mon_moving = FALSE; if (!monscanmove && youmonst.movement < NORMAL_SPEED) { /* both you and the monsters are out of steam this round */ /* set up for a new turn */ struct monst *mtmp; mcalcdistress(); /* adjust monsters' trap, blind, etc */ /* reallocate movement rations to monsters */ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) mtmp->movement += mcalcmove(mtmp); if(!rn2(u.uevent.udemigod ? 25 : (depth(&u.uz) > depth(&stronghold_level)) ? 50 : 70)) (void) makemon((struct permonst *)0, 0, 0, NO_MM_FLAGS); /* calculate how much time passed. */ #ifdef STEED if (u.usteed && u.umoved) { /* your speed doesn't augment steed's speed */ moveamt = mcalcmove(u.usteed); } else #endif { moveamt = youmonst.data->mmove; if (Very_fast) { /* speed boots or potion */ /* average movement is 1.67 times normal */ moveamt += NORMAL_SPEED / 2; if (rn2(3) == 0) moveamt += NORMAL_SPEED / 2; } else if (Fast) { /* average movement is 1.33 times normal */ if (rn2(3) != 0) moveamt += NORMAL_SPEED / 2; } } switch (wtcap) { case UNENCUMBERED: break; case SLT_ENCUMBER: moveamt -= (moveamt / 4); break; case MOD_ENCUMBER: moveamt -= (moveamt / 2); break; case HVY_ENCUMBER: moveamt -= ((moveamt * 3) / 4); break; case EXT_ENCUMBER: moveamt -= ((moveamt * 7) / 8); break; default: break; } youmonst.movement += moveamt; if (youmonst.movement < 0) youmonst.movement = 0; settrack(); monstermoves++; moves++; /********************************/ /* once-per-turn things go here */ /********************************/ if (flags.bypasses) clear_bypasses(); if(Glib) glibr(); nh_timeout(); run_regions(); if (u.ublesscnt) u.ublesscnt--; if(flags.time && !flags.run) flags.botl = 1; /* One possible result of prayer is healing. Whether or * not you get healed depends on your current hit points. * If you are allowed to regenerate during the prayer, the * end-of-prayer calculation messes up on this. * Another possible result is rehumanization, which requires * that encumbrance and movement rate be recalculated. */ if (u.uinvulnerable) { /* for the moment at least, you're in tiptop shape */ wtcap = UNENCUMBERED; } else if (Upolyd && youmonst.data->mlet == S_EEL && !is_pool(u.ux,u.uy) && !Is_waterlevel(&u.uz) && !(u.uswallow && u.ustuck->data == &mons[PM_WATER_ELEMENTAL])) { if (u.mh > 1) { u.mh--; flags.botl = 1; } else if (u.mh < 1) killer_format = KILLED_BY_AN, rehumanize("inability to breathe air"); } else if (Upolyd && u.mh < u.mhmax) { if (u.mh < 1) rehumanize(0); else if (Regeneration || (wtcap < MOD_ENCUMBER && !(moves%20))) { flags.botl = 1; u.mh++; } } else if (u.uhp < u.uhpmax && (wtcap < MOD_ENCUMBER || !u.umoved || Regeneration)) { if (u.ulevel > 9 && !(moves % 3)) { int heal, Con = (int) ACURR(A_CON); if (Con <= 12) { heal = 1; } else { heal = rnd(Con); if (heal > u.ulevel-9) heal = u.ulevel-9; } flags.botl = 1; u.uhp += heal; if(u.uhp > u.uhpmax) u.uhp = u.uhpmax; } else if (Regeneration || (u.ulevel <= 9 && !(moves % ((MAXULEV+12) / (u.ulevel+2) + 1)))) { flags.botl = 1; u.uhp++; } } /* moving around while encumbered is hard work */ if (wtcap > MOD_ENCUMBER && u.umoved) { if(!(wtcap < EXT_ENCUMBER ? moves%30 : moves%10)) { if (Upolyd && u.mh > 1) { u.mh--; } else if (!Upolyd && u.uhp > 1) { u.uhp--; } else { You("pass out from exertion!"); exercise(A_CON, FALSE); fall_asleep(-10, FALSE); } } } if ((u.uen < u.uenmax) && ((wtcap < MOD_ENCUMBER && (!(moves%((MAXULEV + 8 - u.ulevel) * (Role_if(PM_WIZARD) ? 3 : 4) / 6)))) || Energy_regeneration)) { u.uen += rn1((int)(ACURR(A_WIS) + ACURR(A_INT)) / 15 + 1,1); if (u.uen > u.uenmax) u.uen = u.uenmax; flags.botl = 1; } if(!u.uinvulnerable) { if(Teleportation && !rn2(85)) { xchar old_ux = u.ux, old_uy = u.uy; tele(); if (u.ux != old_ux || u.uy != old_uy) { if (!next_to_u()) { check_leash(old_ux, old_uy); } #ifdef REDO /* clear doagain keystrokes */ pushch(0); savech(0); #endif } } /* delayed change may not be valid anymore */ if ((change == 1 && !Polymorph) || (change == 2 && u.ulycn == NON_PM)) change = 0; if(Polymorph && !rn2(100)) change = 1; else if (u.ulycn >= LOW_PM && !Upolyd && !rn2(80 - (20 * night()))) change = 2; if (change && !Unchanging) { if (multi >= 0) { if (occupation) stop_occupation(); else nomul(0); if (change == 1) polyself(FALSE); else you_were(); change = 0; } } if(u.utrap && u.utraptype == TT_LAVA) { if(!is_lava(u.ux,u.uy)) u.utrap = 0; else if (!u.uinvulnerable) { u.utrap -= 1<<8; if(u.utrap < 1<<8) { killer_format = KILLED_BY; killer = "molten lava"; You("sink below the surface and die."); done(DISSOLVED); } else if(didmove && !u.umoved) { Norep("You sink deeper into the lava."); u.utrap += rnd(4); } } } } if(Searching && multi >= 0) (void) dosearch0(1); dosounds(); /* hack - make sure damage from storms is not blamed on the player */ flags.mon_moving = TRUE; do_storms(); flags.mon_moving = FALSE; gethungry(); age_spells(); exerchk(); invault(); if (u.uhave.amulet) amulet(); if (!rn2(40+(int)(ACURR(A_DEX)*3))) u_wipe_engr(rnd(3)); if (u.uevent.udemigod && !u.uinvulnerable) { if (u.udg_cnt) u.udg_cnt--; if (!u.udg_cnt) { intervene(); u.udg_cnt = rn1(200, 50); } } restore_attrib(); /* underwater and waterlevel vision are done here */ if (Is_waterlevel(&u.uz)) movebubbles(); else if (Underwater) under_water(0); /* vision while buried done here */ else if (u.uburied) under_ground(0); /* when immobile, count is in turns */ if(multi < 0) { if (++multi == 0) { /* finished yet? */ unmul((char *)0); /* if unmul caused a level change, take it now */ if (u.utotype) deferred_goto(); } } } } while (youmonst.movement<NORMAL_SPEED); /* hero can't move loop */ /******************************************/ /* once-per-hero-took-time things go here */ /******************************************/ curmonst = &youmonst; } /* actual time passed */ /****************************************/ /* once-per-player-input things go here */ /****************************************/ find_ac(); if(!flags.mv || Blind) { /* redo monsters if hallu or wearing a helm of telepathy */ if (HHallucination && !Halluc_resistance) { /* update screen randomly */ /* see_monsters(); see_objects(); see_traps(); if (u.uswallow) swallowed(0); */ if (u.uswallow) { swallowed(1); } else if (Underwater && !Is_waterlevel(&u.uz)) { under_water(1); } else if (u.uburied) { under_ground(1); } else { register int x, y; register struct rm *lev; vision_recalc(2); /*clear_nhwindow(WIN_MAP);*/ clear_glyph_buffer(); for (x = 1; x < COLNO; x++) { lev = &levl[x][0]; for (y = 0; y < ROWNO; y++, lev++) if (lev->glyph != cmap_to_glyph(S_stone)) show_glyph(x,y,lev->glyph); } vision_recalc(0); see_monsters(); } } else if (Unblind_telepat) { see_monsters(); } else if (Warning || Warn_of_mon) see_monsters(); if (vision_full_recalc) vision_recalc(0); /* vision! */ } #ifdef REALTIME_ON_BOTL if(iflags.showrealtime) { /* Update the bottom line if the number of minutes has * changed */ if(get_realtime() / 60 != realtime_data.last_displayed_time / 60) flags.botl = 1; } #endif if(flags.botl || flags.botlx) bot(); flags.move = 1; if(multi >= 0 && occupation) { #if defined(MICRO) || defined(WIN32) abort_lev = 0; if (kbhit()) { if ((ch = Getchar()) == ABORT) abort_lev++; # ifdef REDO else pushch(ch); # endif /* REDO */ } if (!abort_lev && (*occupation)() == 0) #else if ((*occupation)() == 0) #endif occupation = 0; if( #if defined(MICRO) || defined(WIN32) abort_lev || #endif monster_nearby()) { stop_occupation(); reset_eat(); } #if defined(MICRO) || defined(WIN32) if (!(++occtime % 7)) display_nhwindow(WIN_MAP, FALSE); #endif continue; } if ((u.uhave.amulet || Clairvoyant) && !In_endgame(&u.uz) && !BClairvoyant && !(moves % 15) && !rn2(2)) do_vicinity_map(); #ifdef WIZARD if (iflags.sanity_check) sanity_check(); #endif #ifdef CLIPPING /* just before rhack */ cliparound(u.ux, u.uy); #endif u.umoved = FALSE; if (multi > 0) { lookaround(); if (!multi) { /* lookaround may clear multi */ flags.move = 0; if (flags.time) flags.botl = 1; continue; } if (flags.mv) { if(multi < COLNO && !--multi) flags.travel = iflags.travel1 = flags.mv = flags.run = 0; domove(); } else { --multi; rhack(save_cm); } } else if (multi == 0) { #ifdef MAIL ckmailstatus(); #endif rhack((char *)0); } if (u.utotype) /* change dungeon level */ deferred_goto(); /* after rhack() */ /* !flags.move here: multiple movement command stopped */ else if (flags.time && (!flags.move || !flags.mv)) flags.botl = 1; if (vision_full_recalc) vision_recalc(0); /* vision! */ /* when running in non-tport mode, this gets done through domove() */ if ((!flags.run || iflags.runmode == RUN_TPORT) && (multi && (!flags.travel ? !(multi % 7) : !(moves % 7L)))) { if (flags.time && flags.run) flags.botl = 1; display_nhwindow(WIN_MAP, FALSE); } } }
/* returns 0 if something was detected */ int food_detect(struct obj *sobj, boolean *scr_known) { struct obj *obj; struct monst *mtmp; int ct = 0, ctu = 0; boolean confused = (Confusion || (sobj && sobj->cursed)), stale; char oclass = confused ? POTION_CLASS : FOOD_CLASS; const char *what = confused ? "something" : "food"; int uw = u.uinwater; stale = clear_stale_map(oclass, 0); for (obj = level->objlist; obj; obj = obj->nobj) if (o_in(obj, oclass)) { if (obj->ox == u.ux && obj->oy == u.uy) ctu++; else ct++; } for (mtmp = level->monlist; mtmp && !ct; mtmp = mtmp->nmon) { /* no DEADMONSTER(mtmp) check needed since dmons never have inventory */ for (obj = mtmp->minvent; obj; obj = obj->nobj) if (o_in(obj, oclass)) { ct++; break; } } if (!ct && !ctu) { *scr_known = stale && !confused; if (stale) { doredraw(); pline("You sense a lack of %s nearby.", what); if (sobj && sobj->blessed) { if (!u.uedibility) pline("Your %s starts to tingle.", body_part(NOSE)); u.uedibility = 1; } } else if (sobj) { char buf[BUFSZ]; sprintf(buf, "Your %s twitches%s.", body_part(NOSE), (sobj->blessed && !u.uedibility) ? " then starts to tingle" : ""); if (sobj->blessed && !u.uedibility) { boolean savebeginner = flags.beginner; /* prevent non-delivery of */ flags.beginner = FALSE; /* message */ strange_feeling(sobj, buf); flags.beginner = savebeginner; u.uedibility = 1; } else strange_feeling(sobj, buf); } return !stale; } else if (!ct) { *scr_known = TRUE; pline("You %s %s nearby.", sobj ? "smell" : "sense", what); if (sobj && sobj->blessed) { if (!u.uedibility) pline("Your %s starts to tingle.", body_part(NOSE)); u.uedibility = 1; } } else { struct obj *temp; *scr_known = TRUE; cls(); u.uinwater = 0; for (obj = level->objlist; obj; obj = obj->nobj) if ((temp = o_in(obj, oclass)) != 0) { if (temp != obj) { temp->ox = obj->ox; temp->oy = obj->oy; } map_object(temp,1); } for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) /* no DEADMONSTER(mtmp) check needed since dmons never have inventory */ for (obj = mtmp->minvent; obj; obj = obj->nobj) if ((temp = o_in(obj, oclass)) != 0) { temp->ox = mtmp->mx; temp->oy = mtmp->my; map_object(temp,1); break; /* skip rest of this monster's inventory */ } newsym(u.ux,u.uy); if (sobj) { if (sobj->blessed) { pline("Your %s %s to tingle and you smell %s.", body_part(NOSE), u.uedibility ? "continues" : "starts", what); u.uedibility = 1; } else pline("Your %s tingles and you smell %s.", body_part(NOSE), what); } else pline("You sense %s.", what); win_pause_output(P_MAP); exercise(A_WIS, TRUE); doredraw(); u.uinwater = uw; if (Underwater) under_water(2); if (u.uburied) under_ground(2); } return 0; }
/* look for gold, on the floor or in monsters' possession */ int gold_detect(struct obj *sobj, boolean *scr_known) { struct obj *obj; struct monst *mtmp; int uw = u.uinwater; struct obj *temp; boolean stale; *scr_known = stale = clear_stale_map(COIN_CLASS, sobj->blessed ? GOLD : 0); /* look for gold carried by monsters (might be in a container) */ for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; /* probably not needed in this case but... */ if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { *scr_known = TRUE; goto outgoldmap; /* skip further searching */ } else for (obj = mtmp->minvent; obj; obj = obj->nobj) if (sobj->blessed && o_material(obj, GOLD)) { *scr_known = TRUE; goto outgoldmap; } else if (o_in(obj, COIN_CLASS)) { *scr_known = TRUE; goto outgoldmap; /* skip further searching */ } } /* look for gold objects */ for (obj = level->objlist; obj; obj = obj->nobj) { if (sobj->blessed && o_material(obj, GOLD)) { *scr_known = TRUE; if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap; } else if (o_in(obj, COIN_CLASS)) { *scr_known = TRUE; if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap; } } if (!*scr_known) { /* no gold found on floor or monster's inventory. adjust message if you have gold in your inventory */ char buf[BUFSZ]; if (youmonst.data == &mons[PM_GOLD_GOLEM]) { sprintf(buf, "You feel like a million %s!", currency(2L)); } else if (hidden_gold() || money_cnt(invent)) strcpy(buf, "You feel worried about your future financial situation."); else strcpy(buf, "You feel materially poor."); strange_feeling(sobj, buf); return 1; } /* only under me - no separate display required */ if (stale) doredraw(); pline("You notice some gold between your %s.", makeplural(body_part(FOOT))); return 0; outgoldmap: cls(); u.uinwater = 0; /* Discover gold locations. */ for (obj = level->objlist; obj; obj = obj->nobj) { if (sobj->blessed && (temp = o_material(obj, GOLD))) { if (temp != obj) { temp->ox = obj->ox; temp->oy = obj->oy; } map_object(temp,1); } else if ((temp = o_in(obj, COIN_CLASS))) { if (temp != obj) { temp->ox = obj->ox; temp->oy = obj->oy; } map_object(temp,1); } } for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; /* probably overkill here */ if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { struct obj gold; gold.otyp = GOLD_PIECE; gold.ox = mtmp->mx; gold.oy = mtmp->my; map_object(&gold,1); } else for (obj = mtmp->minvent; obj; obj = obj->nobj) if (sobj->blessed && (temp = o_material(obj, GOLD))) { temp->ox = mtmp->mx; temp->oy = mtmp->my; map_object(temp,1); break; } else if ((temp = o_in(obj, COIN_CLASS))) { temp->ox = mtmp->mx; temp->oy = mtmp->my; map_object(temp,1); break; } } newsym(u.ux,u.uy); pline("You feel very greedy, and sense gold!"); exercise(A_WIS, TRUE); win_pause_output(P_MAP); doredraw(); u.uinwater = uw; if (Underwater) under_water(2); if (u.uburied) under_ground(2); return 0; }
void moveloop() { #ifdef MICRO char ch; int abort_lev; #endif int moverate = 0; boolean didmove = 0; /* Note: these initializers don't do anything except guarantee that we're linked properly. */ decl_init(); monst_init(); monstr_init(); /* monster strengths */ objects_init(); (void) encumber_msg(); /* in case they auto-picked up something */ for(;;) { #ifdef CLIPPING cliparound(u.ux, u.uy); #endif #if defined(MAC_MPW32) && !defined(MODEL_FAR) UnloadAllSegments(); /* Marks non-resident segments as purgeable */ #endif get_nh_event(); didmove = flags.move; if(flags.move) { /* actual time passed */ #ifdef POLYSELF int oldmtimedone; #endif int wtcap; if (u.utotype) deferred_goto(); wtcap = encumber_msg(); #ifdef POLYSELF oldmtimedone = u.mtimedone; #endif #ifdef SOUNDS dosounds(); #endif if(moverate <= 0) { /* calculate how much time passed. */ int moveamt = 0; if(Fast & ~INTRINSIC) moveamt = 6; else if(Fast) moveamt = 8; else moveamt = 12; switch(wtcap) { case UNENCUMBERED: break; case SLT_ENCUMBER: moveamt = (moveamt * 4) / 3; break; case MOD_ENCUMBER: moveamt *= 2; break; case HVY_ENCUMBER: moveamt *= 4; break; default: moveamt *= 12; break; } moverate += moveamt; settrack(); } if(moverate > 0) { movemon(); /* a monster may have levteleported player -dlc */ if (u.utotype) deferred_goto(); if(!rn2(u.uevent.udemigod ? 25 : (depth(&u.uz) > depth(&stronghold_level)) ? 50 : 70)) (void) makemon((struct permonst *)0, 0, 0); ++monstermoves; remove_cadavers(&fobj); remove_cadavers(&invent); moverate -= 12; } if(Glib) glibr(); nh_timeout(); ++moves; if (u.ublesscnt) u.ublesscnt--; if(flags.time) flags.botl = 1; /* One possible result of prayer is healing. Whether or * not you get healed depends on your current hit points. * If you are allowed to regenerate during the prayer, the * end-of-prayer calculation messes up on this. */ if (u.uinvulnerable) ; else #ifdef POLYSELF if (u.mtimedone && u.mh < u.mhmax) { if (u.mh < 1) { rehumanize(); moverate = 0; } else if (Regeneration || (wtcap < MOD_ENCUMBER && !(moves%20))) { flags.botl = 1; u.mh++; } } else #endif if(u.uhp < u.uhpmax) { if(u.ulevel > 9) { int heal; if(HRegeneration || (!(moves%3) && (wtcap < MOD_ENCUMBER || !flags.mv))) { flags.botl = 1; if (ACURR(A_CON) <= 12) heal = 1; else heal = rnd((int) ACURR(A_CON)-12); if (heal > u.ulevel-9) heal = u.ulevel-9; u.uhp += heal; if(u.uhp > u.uhpmax) u.uhp = u.uhpmax; } } else if(HRegeneration || ((wtcap < MOD_ENCUMBER || !flags.mv) && (!(moves%((MAXULEV+12)/(u.ulevel+2)+1))))) { flags.botl = 1; u.uhp++; } } if (wtcap > MOD_ENCUMBER && flags.mv) { if(!(wtcap < EXT_ENCUMBER ? moves%30 : moves%10)) { if(u.uhp > 1) { u.uhp--; } else { pline("You pass out from exertion!"); exercise(A_CON, FALSE); nomul(-10); u.usleep = 1; } } } if ((u.uen < u.uenmax) && ((wtcap < MOD_ENCUMBER && (!(moves%((MAXULEV + 1 - u.ulevel) * (pl_character[0] == 'W' ? 3 : 4) / 2)))) || Energy_regeneration)) { u.uen += rn1((int)(ACURR(A_WIS) + ACURR(A_INT)) / 10 + 1,1); if (u.uen > u.uenmax) u.uen = u.uenmax; flags.botl = 1; } if(!u.uinvulnerable) { if(Teleportation && !rn2(85)) { #ifdef REDO /* clear doagain keystrokes */ pushch(0); savech(0); #endif tele(); } #ifdef POLYSELF if(Polymorph && !rn2(100)) { if (multi >= 0) { if (occupation) stop_occupation(); else nomul(0); } polyself(); moverate = 0; } else if (u.ulycn >= 0 && !rn2(80 - (20 * night()))) { if (multi >= 0) { if (occupation) stop_occupation(); else nomul(0); } you_were(); moverate = 0; } #endif } if(Searching && multi >= 0) (void) dosearch0(1); do_storms(); hatch_eggs(); burn_lamps(); gethungry(); exerchk(); invault(); amulet(); if (!rn2(40+(int)(ACURR(A_DEX)*3))) u_wipe_engr(rnd(3)); if (u.uevent.udemigod && !u.uinvulnerable) { if (u.udg_cnt) u.udg_cnt--; if (!u.udg_cnt) { intervene(); u.udg_cnt = rn1(200, 50); } } restore_attrib(); /* underwater and waterlevel vision are done here */ if (Is_waterlevel(&u.uz)) movebubbles(); else if (Underwater) under_water(0); #ifdef POLYSELF if ((oldmtimedone && !u.mtimedone) || (!oldmtimedone && u.mtimedone)) moverate = 0; #endif } if(multi < 0) { if(!++multi){ pline("%s",nomovemsg ? nomovemsg : (const char *)"You can move again."); nomovemsg = 0; u.usleep = 0; if(afternmv) (*afternmv)(); afternmv = 0; } } find_ac(); if(!flags.mv || Blind) { /* redo monsters if hallu or wearing a helm of telepathy */ if (Hallucination || (HTelepat & (WORN_HELMET|WORN_AMUL|W_ART))) see_monsters(); /* redo objects if hallucinating */ if (Hallucination) see_objects(); /* update swallowed display */ if (Hallucination && u.uswallow) swallowed(0); if (vision_full_recalc) vision_recalc(0); /* vision! */ } if(flags.botl || flags.botlx) bot(); flags.move = 1; if(multi >= 0 && occupation) { #ifdef MICRO abort_lev = 0; if (kbhit()) { if ((ch = Getchar()) == ABORT) abort_lev++; # ifdef REDO else pushch(ch); # endif /* REDO */ } if (!abort_lev && (*occupation)() == 0) #else if ((*occupation)() == 0) #endif occupation = 0; if( #ifdef MICRO abort_lev || #endif monster_nearby()) { stop_occupation(); reset_eat(); } #ifdef MICRO if (!(++occtime % 7)) display_nhwindow(WIN_MAP, FALSE); #endif continue; } if((u.uhave.amulet || Clairvoyant) && !In_endgame(&u.uz) && !(moves%15) && !rn2(2)) do_vicinity_map(); if(u.utrap && u.utraptype == TT_LAVA) { if(!is_lava(u.ux,u.uy)) u.utrap = 0; else { u.utrap -= 1<<8; if(u.utrap < 1<<8) { killer_format = KILLED_BY; killer = "molten lava"; You("sink below the surface and suffocate."); done(DROWNING); /*whatever*/ } else if(didmove && !u.umoved) { Norep("You sink deeper into the lava."); u.utrap += rnd(4); } } } u.umoved = FALSE; if(!didmove || moverate <= 0) { if(multi > 0) { lookaround(); if(!multi) { /* lookaround may clear multi */ flags.move = 0; continue; } if(flags.mv) { if(multi < COLNO && !--multi) flags.mv = flags.run = 0; domove(); } else { --multi; rhack(save_cm); } } else if(multi == 0) { #ifdef MAIL ckmailstatus(); #endif rhack(NULL); } } if (vision_full_recalc) vision_recalc(0); /* vision! */ if(multi && multi%7 == 0) display_nhwindow(WIN_MAP, FALSE); } }
void moveloop() { #if defined(MICRO) || defined(WIN32) char ch; int abort_lev; #endif int moveamt = 0, wtcap = 0, change = 0; boolean didmove = FALSE, monscanmove = FALSE; flags.moonphase = phase_of_the_moon(); if(flags.moonphase == FULL_MOON) { You("are lucky! Full moon tonight."); change_luck(1); } else if(flags.moonphase == NEW_MOON) { pline("Be careful! New moon tonight."); } flags.friday13 = friday_13th(); if (flags.friday13) { pline("Watch out! Bad things can happen on Friday the 13th."); change_luck(-1); } /* KMH -- February 2 */ flags.groundhogday = groundhog_day(); if (flags.groundhogday) pline("Happy Groundhog Day!"); initrack(); /* Note: these initializers don't do anything except guarantee that we're linked properly. */ decl_init(); monst_init(); monstr_init(); /* monster strengths */ objects_init(); #ifdef WIZARD if (wizard) add_debug_extended_commands(); #endif (void) encumber_msg(); /* in case they auto-picked up something */ if (defer_see_monsters) { defer_see_monsters = FALSE; see_monsters(); } u.uz0.dlevel = u.uz.dlevel; youmonst.movement = NORMAL_SPEED; /* give the hero some movement points */ for(;;) { get_nh_event(); #ifdef POSITIONBAR do_positionbar(); #endif didmove = flags.move; if(didmove) { /* actual time passed */ youmonst.movement -= NORMAL_SPEED; do { /* hero can't move this turn loop */ wtcap = encumber_msg(); flags.mon_moving = TRUE; do { monscanmove = movemon(); if (youmonst.movement > NORMAL_SPEED) break; /* it's now your turn */ } while (monscanmove); flags.mon_moving = FALSE; if (!monscanmove && youmonst.movement < NORMAL_SPEED) { /* both you and the monsters are out of steam this round */ /* set up for a new turn */ struct monst *mtmp; mcalcdistress(); /* adjust monsters' trap, blind, etc */ /* reallocate movement rations to monsters */ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) mtmp->movement += mcalcmove(mtmp); if(!rn2(u.uevent.udemigod ? 25 : (depth(&u.uz) > depth(&stronghold_level)) ? 50 : 70)) (void) makemon((struct permonst *)0, 0, 0, NO_MM_FLAGS); /* calculate how much time passed. */ #ifdef STEED if (u.usteed && u.umoved) { /* your speed doesn't augment steed's speed */ moveamt = mcalcmove(u.usteed); } else #endif { moveamt = youmonst.data->mmove; if (Very_fast) { /* speed boots or potion */ /* average movement is 1.67 times normal */ moveamt += NORMAL_SPEED / 2; if (rn2(3) == 0) moveamt += NORMAL_SPEED / 2; } else if (Fast) { /* average movement is 1.33 times normal */ if (rn2(3) != 0) moveamt += NORMAL_SPEED / 2; } if (tech_inuse(T_BLINK)) { /* TECH: Blinking! */ /* Case Average Variance * ------------------------- * Normal 12 0 * Fast 16 12 * V fast 20 12 * Blinking 24 12 * F & B 28 18 * V F & B 30 18 */ moveamt += NORMAL_SPEED * 2 / 3; if (rn2(3) == 0) moveamt += NORMAL_SPEED / 2; } } switch (wtcap) { case UNENCUMBERED: break; case SLT_ENCUMBER: moveamt -= (moveamt / 4); break; case MOD_ENCUMBER: moveamt -= (moveamt / 2); break; case HVY_ENCUMBER: moveamt -= ((moveamt * 3) / 4); break; case EXT_ENCUMBER: moveamt -= ((moveamt * 7) / 8); break; default: break; } youmonst.movement += moveamt; if (youmonst.movement < 0) youmonst.movement = 0; settrack(); monstermoves++; moves++; /********************************/ /* once-per-turn things go here */ /********************************/ if (flags.bypasses) clear_bypasses(); if(Glib) glibr(); nh_timeout(); run_regions(); #ifdef DUNGEON_GROWTH dgn_growths(TRUE, TRUE); #endif if (u.ublesscnt) u.ublesscnt--; if(flags.time && !flags.run) flags.botl = 1; /* One possible result of prayer is healing. Whether or * not you get healed depends on your current hit points. * If you are allowed to regenerate during the prayer, the * end-of-prayer calculation messes up on this. * Another possible result is rehumanization, which requires * that encumbrance and movement rate be recalculated. */ if (u.uinvulnerable) { /* for the moment at least, you're in tiptop shape */ wtcap = UNENCUMBERED; } else if (Upolyd && youmonst.data->mlet == S_EEL && !is_pool(u.ux,u.uy) && !Is_waterlevel(&u.uz)) { if (u.mh > 1) { u.mh--; flags.botl = 1; } else if (u.mh < 1) rehumanize(); } else if (Upolyd && u.mh < u.mhmax) { if (u.mh < 1) rehumanize(); else if (Regeneration || (wtcap < MOD_ENCUMBER && !(moves%20))) { flags.botl = 1; u.mh++; } } else if (u.uhp < u.uhpmax && (wtcap < MOD_ENCUMBER || !u.umoved || Regeneration)) { /* * KMH, balance patch -- New regeneration code * Healthstones have been added, which alter your effective * experience level and constitution (-2 cursed, +1 uncursed, * +2 blessed) for the basis of regeneration calculations. */ int efflev = u.ulevel + u.uhealbonus; int effcon = ACURR(A_CON) + u.uhealbonus; int heal = 1; if (efflev > 9 && !(moves % 3)) { if (effcon <= 12) { heal = 1; } else { heal = rnd(effcon); if (heal > efflev-9) heal = efflev-9; } flags.botl = 1; u.uhp += heal; if(u.uhp > u.uhpmax) u.uhp = u.uhpmax; } else if (Regeneration || (efflev <= 9 && !(moves % ((MAXULEV+12) / (u.ulevel+2) + 1)))) { flags.botl = 1; u.uhp++; } } if (!u.uinvulnerable && u.uen > 0 && u.uhp < u.uhpmax && tech_inuse(T_CHI_HEALING)) { u.uen--; u.uhp++; flags.botl = 1; } /* moving around while encumbered is hard work */ if (wtcap > MOD_ENCUMBER && u.umoved) { if(!(wtcap < EXT_ENCUMBER ? moves%30 : moves%10)) { if (Upolyd && u.mh > 1) { u.mh--; } else if (!Upolyd && u.uhp > 1) { u.uhp--; } else { You("pass out from exertion!"); exercise(A_CON, FALSE); fall_asleep(-10, FALSE); } } } /* KMH -- OK to regenerate if you don't move */ if ((u.uen < u.uenmax) && (Energy_regeneration || ((wtcap < MOD_ENCUMBER || !flags.mv) && (!(moves%((MAXULEV + 15 - u.ulevel) * (Role_if(PM_WIZARD) ? 3 : 4) / 6)))))) { u.uen += rn1((int)(ACURR(A_WIS) + ACURR(A_INT)) / 15 + 1,1); #ifdef WIZ_PATCH_DEBUG pline("mana was = %d now = %d",temp,u.uen); #endif if (u.uen > u.uenmax) u.uen = u.uenmax; flags.botl = 1; } if(!u.uinvulnerable) { if(Teleportation && !rn2(85)) { xchar old_ux = u.ux, old_uy = u.uy; tele(); if (u.ux != old_ux || u.uy != old_uy) { if (!next_to_u()) { check_leash(&youmonst, old_ux, old_uy, TRUE); } #ifdef REDO /* clear doagain keystrokes */ pushch(0); savech(0); #endif } } long ch = (80 - (40 * night())) / 2 * (Race_if(PM_HUMAN_WEREWOLF) ? u.ulevel * u.ulevel : 2); ch = (ch > LARGEST_INT) ? LARGEST_INT : ch; /* delayed change may not be valid anymore */ if ((change == 1 && !Polymorph) || (change == 2 && u.ulycn == NON_PM)) change = 0; if(Polymorph && !rn2(100)) change = 1; else if (u.ulycn >= LOW_PM && !Upolyd && !rn2((int)ch)) change = 2; if (change && !Unchanging) { if (multi >= 0) { if (occupation) stop_occupation(); else nomul(0); if (change == 1) polyself(FALSE); else you_were(); change = 0; } } } /* !u.uinvulnerable */ if(Searching && multi >= 0) (void) dosearch0(1); dosounds(); do_storms(); gethungry(); age_spells(); exerchk(); invault(); if (u.uhave.amulet) amulet(); if (!rn2(40+(int)(ACURR(A_DEX)*3))) u_wipe_engr(rnd(3)); if (u.uevent.udemigod && !u.uinvulnerable) { if (u.udg_cnt) u.udg_cnt--; if (!u.udg_cnt) { intervene(); u.udg_cnt = rn1(200, 50); } } restore_attrib(); /* underwater and waterlevel vision are done here */ if (Is_waterlevel(&u.uz)) movebubbles(); else if (Underwater) under_water(0); /* vision while buried done here */ else if (u.uburied) under_ground(0); /* when immobile, count is in turns */ if(multi < 0) { if (++multi == 0) { /* finished yet? */ unmul((char *)0); /* if unmul caused a level change, take it now */ if (u.utotype) deferred_goto(); } } } } while (youmonst.movement<NORMAL_SPEED); /* hero can't move loop */ /******************************************/ /* once-per-hero-took-time things go here */ /******************************************/ } /* actual time passed */ /****************************************/ /* once-per-player-input things go here */ /****************************************/ find_ac(); if(!flags.mv || Blind) { /* redo monsters if hallu or wearing a helm of telepathy */ if (Hallucination) { /* update screen randomly */ see_monsters(); see_objects(); see_traps(); if (u.uswallow) swallowed(0); } else if (Unblind_telepat) { see_monsters(); } else if (Warning || Warn_of_mon) see_monsters(); if (vision_full_recalc) vision_recalc(0); /* vision! */ } if(flags.botl || flags.botlx) bot(); flags.move = 1; if(multi >= 0 && occupation) { #if defined(MICRO) || defined(WIN32) abort_lev = 0; if (kbhit()) { if ((ch = Getchar()) == ABORT) abort_lev++; # ifdef REDO else pushch(ch); # endif /* REDO */ } if (!abort_lev && (*occupation)() == 0) #else if ((*occupation)() == 0) #endif occupation = 0; if( #if defined(MICRO) || defined(WIN32) abort_lev || #endif monster_nearby()) { stop_occupation(); reset_eat(); } #if defined(MICRO) || defined(WIN32) if (!(++occtime % 7)) display_nhwindow(WIN_MAP, FALSE); #endif continue; } if ((u.uhave.amulet || Clairvoyant) && !In_endgame(&u.uz) && !BClairvoyant && !(moves % 15) && !rn2(2)) do_vicinity_map(); if(u.utrap && u.utraptype == TT_LAVA) { if(!is_lava(u.ux,u.uy)) u.utrap = 0; else if (!u.uinvulnerable) { u.utrap -= 1<<8; if(u.utrap < 1<<8) { killer_format = KILLED_BY; killer = "molten lava"; You("sink below the surface and die."); done(DISSOLVED); } else if(didmove && !u.umoved) { Norep("You sink deeper into the lava."); u.utrap += rnd(4); } } } #ifdef WIZARD if (iflags.sanity_check) sanity_check(); #endif #ifdef CLIPPING /* just before rhack */ cliparound(u.ux, u.uy); #endif u.umoved = FALSE; if (multi > 0) { lookaround(); if (!multi) { /* lookaround may clear multi */ flags.move = 0; if (flags.time) flags.botl = 1; continue; } if (flags.mv) { if(multi < COLNO && !--multi) flags.travel = iflags.travel1 = flags.mv = flags.run = 0; domove(); } else { --multi; rhack(save_cm); } } else if (multi == 0) { #ifdef MAIL ckmailstatus(); #endif rhack((char *)0); } if (u.utotype) /* change dungeon level */ deferred_goto(); /* after rhack() */ /* !flags.move here: multiple movement command stopped */ else if (flags.time && (!flags.move || !flags.mv)) flags.botl = 1; if (vision_full_recalc) vision_recalc(0); /* vision! */ /* when running in non-tport mode, this gets done through domove() */ if ((!flags.run || iflags.runmode == RUN_TPORT) && (multi && (!flags.travel ? !(multi % 7) : !(moves % 7L)))) { if (flags.time && flags.run) flags.botl = 1; display_nhwindow(WIN_MAP, FALSE); } } }
static void you_moved(void) { int moveamt = 0, wtcap = 0, change = 0; boolean monscanmove = FALSE; /* Begin turn-tracking for delay_msg. */ if (delay_start == 0) delay_start = moves; /* actual time passed */ youmonst.movement -= NORMAL_SPEED; do { /* hero can't move this turn loop */ wtcap = encumber_msg(); calc_attr_bonus(); flags.mon_moving = TRUE; do { monscanmove = movemon(); if (youmonst.movement > NORMAL_SPEED) break; /* it's now your turn */ } while (monscanmove); flags.mon_moving = FALSE; if (!monscanmove && youmonst.movement < NORMAL_SPEED) { /* both you and the monsters are out of steam this round */ /* set up for a new turn */ struct monst *mtmp; mcalcdistress(); /* adjust monsters' trap, blind, etc */ /* reallocate movement rations to monsters */ for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) mtmp->movement += mcalcmove(mtmp); if (!rn2(u.uevent.udemigod ? 25 : (depth(&u.uz) > depth(&stronghold_level)) ? 50 : 70)) makemon(NULL, level, 0, 0, NO_MM_FLAGS); /* calculate how much time passed. */ if (u.usteed && u.umoved) { /* your speed doesn't augment steed's speed */ moveamt = mcalcmove(u.usteed); } else { moveamt = youmonst.data->mmove; if (Very_fast) { /* speed boots or potion */ /* average movement is 1.67 times normal */ moveamt += NORMAL_SPEED / 2; if (rn2(3) == 0) moveamt += NORMAL_SPEED / 2; } else if (Fast) { /* average movement is 1.33 times normal */ if (rn2(3) != 0) moveamt += NORMAL_SPEED / 2; } } switch (wtcap) { case UNENCUMBERED: break; case SLT_ENCUMBER: moveamt -= (moveamt / 4); break; case MOD_ENCUMBER: moveamt -= (moveamt / 2); break; case HVY_ENCUMBER: moveamt -= ((moveamt * 3) / 4); break; case EXT_ENCUMBER: moveamt -= ((moveamt * 7) / 8); break; default: break; } youmonst.movement += moveamt; if (youmonst.movement < 0) youmonst.movement = 0; settrack(); moves++; level->lastmoves = moves; /********************************/ /* once-per-turn things go here */ /********************************/ if (flags.bypasses) clear_bypasses(); if (Glib) glibr(); nh_timeout(); run_regions(level); dgn_growths(level, TRUE, TRUE); if (u.ublesscnt) u.ublesscnt--; iflags.botl = 1; /* One possible result of prayer is healing. Whether or * not you get healed depends on your current hit points. * If you are allowed to regenerate during the prayer, the * end-of-prayer calculation messes up on this. * Another possible result is rehumanization, which requires * that encumbrance and movement rate be recalculated. */ if (u.uinvulnerable) { /* for the moment at least, you're in tiptop shape */ wtcap = UNENCUMBERED; } else if (Upolyd && youmonst.data->mlet == S_EEL && !is_pool(level, u.ux,u.uy) && !Is_waterlevel(&u.uz)) { if (u.mh > 1) { u.mh--; iflags.botl = 1; } else if (u.mh < 1) rehumanize(); } else if (Upolyd && u.mh < u.mhmax) { if (u.mh < 1) rehumanize(); else if (Regeneration || (wtcap < MOD_ENCUMBER && !(moves%20))) { iflags.botl = 1; u.mh++; interrupt_multi("Hit points", u.mh, u.mhmax); } } else if (u.uhp < u.uhpmax && (wtcap < MOD_ENCUMBER || !u.umoved || Regeneration)) { if (u.ulevel > 9 && !(moves % 3)) { int heal, Con = (int) ACURR(A_CON); if (Con <= 12) { heal = 1; } else { heal = rnd(Con); if (heal > u.ulevel-9) heal = u.ulevel-9; } iflags.botl = 1; u.uhp += heal; if (u.uhp > u.uhpmax) u.uhp = u.uhpmax; interrupt_multi("Hit points", u.uhp, u.uhpmax); } else if (Regeneration || (u.ulevel <= 9 && !(moves % ((MAXULEV+12) / (u.ulevel+2) + 1)))) { iflags.botl = 1; u.uhp++; interrupt_multi("Hit points", u.uhp, u.uhpmax); } } /* moving around while encumbered is hard work */ if (wtcap > MOD_ENCUMBER && u.umoved) { if (!(wtcap < EXT_ENCUMBER ? moves%30 : moves%10)) { if (Upolyd && u.mh > 1) { u.mh--; } else if (!Upolyd && u.uhp > 1) { u.uhp--; } else { pline("你用力过度昏倒了!"); exercise(A_CON, FALSE); fall_asleep(-10, FALSE); } } } if ((u.uen < u.uenmax) && ((wtcap < MOD_ENCUMBER && (!(moves%((MAXULEV + 8 - u.ulevel) * (Role_if (PM_WIZARD) ? 3 : 4) / 6)))) || Energy_regeneration)) { u.uen += rn1((int)(ACURR(A_WIS) + ACURR(A_INT)) / 15 + 1,1); if (u.uen > u.uenmax) u.uen = u.uenmax; iflags.botl = 1; interrupt_multi("Magic energy", u.uen, u.uenmax); } if (!u.uinvulnerable) { if (Teleportation && !rn2(85)) { xchar old_ux = u.ux, old_uy = u.uy; tele(); if (u.ux != old_ux || u.uy != old_uy) { if (!next_to_u()) { check_leash(old_ux, old_uy); } } } /* delayed change may not be valid anymore */ if ((change == 1 && !Polymorph) || (change == 2 && u.ulycn == NON_PM)) change = 0; if (Polymorph && !rn2(100)) change = 1; else if (u.ulycn >= LOW_PM && !Upolyd && !rn2(80 - (20 * night()))) change = 2; if (change && !Unchanging) { if (multi >= 0) { if (occupation) stop_occupation(); else nomul(0, NULL); if (change == 1) polyself(FALSE); else you_were(); change = 0; } } } if (Searching && multi >= 0) dosearch0(1); dosounds(); do_storms(); gethungry(); age_spells(); exerchk(); invault(); if (u.uhave.amulet) amulet(); if (!rn2(40+(int)(ACURR(A_DEX)*3))) u_wipe_engr(rnd(3)); if (u.uevent.udemigod && !u.uinvulnerable) { if (u.udg_cnt) u.udg_cnt--; if (!u.udg_cnt) { intervene(); u.udg_cnt = rn1(200, 50); } } restore_attrib(); /* underwater and waterlevel vision are done here */ if (Is_waterlevel(&u.uz)) movebubbles(); else if (Underwater) under_water(0); /* vision while buried done here */ else if (u.uburied) under_ground(0); /* when immobile, count is in turns */ if (multi < 0) { if (++multi == 0) { /* finished yet? */ unmul(NULL); /* if unmul caused a level change, take it now */ if (u.utotype) deferred_goto(); } } } } while (youmonst.movement<NORMAL_SPEED); /* hero can't move loop */ /******************************************/ /* once-per-hero-took-time things go here */ /******************************************/ if (u.utrap && u.utraptype == TT_LAVA) handle_lava_trap(TRUE); if (iflags.hp_notify && prev_hp_notify != uhp()) { pline("%s", hp_notify_format_str(iflags.hp_notify_fmt ? iflags.hp_notify_fmt : "[HP%c%a=%h]")); prev_hp_notify = uhp(); } }