void rehumanize(void) { /* You can't revert back while unchanging */ if (Unchanging && (u.mh < 1)) { killer_format = NO_KILLER_PREFIX; killer = "killed while stuck in creature form"; done(DIED); } if (emits_light(youmonst.data)) del_light_source(level, LS_MONSTER, &youmonst); polyman("You return to %s form!", urace.adj); if (u.uhp < 1) { char kbuf[256]; sprintf(kbuf, "reverting to unhealthy %s form", urace.adj); killer_format = KILLED_BY; killer = kbuf; done(DIED); } if (!uarmg) selftouch("No longer petrify-resistant, you"); nomul(0, NULL); iflags.botl = 1; vision_full_recalc = 1; encumber_msg(); }
void exercise(int i, boolean inc_or_dec) { if (i == A_INT || i == A_CHA) return; /* can't exercise these */ /* no physical exercise while polymorphed; the body's temporary */ if (Upolyd && i != A_WIS) return; if (abs(AEXE(i)) < AVAL) { /* * Law of diminishing returns (Part I): * * Gain is harder at higher attribute values. * 79% at "3" --> 0% at "18" * Loss is even at all levels (50%). * * Note: *YES* ACURR is the right one to use. */ AEXE(i) += (inc_or_dec) ? (rn2(19) > ACURR(i)) : -rn2(2); } if (moves > 0 && (i == A_STR || i == A_CON)) encumber_msg(); }
static void post_init_tasks(void) { encumber_msg(); /* in case they auto-picked up something */ u.uz0.dlevel = u.uz.dlevel; prev_hp_notify = uhp(); /* prepare for the first move */ pre_move_tasks(FALSE); }
/* adjust an attribute; return true if change is made, false otherwise */ // int msgflg; /* positive => no message, zero => message, and */ // /* negative => conditional (msg if change made) */ bool adjattrib(int ndx, int incr, int msgflg) { if (Fixed_abil || !incr) return false; if ((ndx == A_INT || ndx == A_WIS) && uarmh && uarmh->otyp == DUNCE_CAP) { if (msgflg == 0) Your("cap constricts briefly, then relaxes again."); return false; } if (incr > 0) { if ((AMAX(ndx) >= ATTRMAX(ndx)) && (ACURR(ndx) >= AMAX(ndx))) { if (msgflg == 0 && flags.verbose) pline("You're already as %s as you can get.", plusattr[ndx]); ABASE(ndx) = AMAX(ndx) = ATTRMAX(ndx); /* just in case */ return false; } ABASE(ndx) += incr; if(ABASE(ndx) > AMAX(ndx)) { incr = ABASE(ndx) - AMAX(ndx); AMAX(ndx) += incr; if(AMAX(ndx) > ATTRMAX(ndx)) AMAX(ndx) = ATTRMAX(ndx); ABASE(ndx) = AMAX(ndx); } } else { if (ABASE(ndx) <= ATTRMIN(ndx)) { if (msgflg == 0 && flags.verbose) pline("You're already as %s as you can get.", minusattr[ndx]); ABASE(ndx) = ATTRMIN(ndx); /* just in case */ return false; } ABASE(ndx) += incr; if(ABASE(ndx) < ATTRMIN(ndx)) { incr = ABASE(ndx) - ATTRMIN(ndx); ABASE(ndx) = ATTRMIN(ndx); AMAX(ndx) += incr; if(AMAX(ndx) < ATTRMIN(ndx)) AMAX(ndx) = ATTRMIN(ndx); } } if (msgflg <= 0) You_feel("%s%s!", (incr > 1 || incr < -1) ? "very ": "", (incr > 0) ? plusattr[ndx] : minusattr[ndx]); if (moves > 1 && (ndx == A_STR || ndx == A_CON)) (void)encumber_msg(); return true; }
void redist_attr (void) { int i, tmp; for(i = 0; i < A_MAX; i++) { if (i==A_INT || i==A_WIS) continue; /* Polymorphing doesn't change your mind */ tmp = AMAX(i); AMAX(i) += (rn2(5)-2); if (AMAX(i) > ATTRMAX(i)) AMAX(i) = ATTRMAX(i); if (AMAX(i) < ATTRMIN(i)) AMAX(i) = ATTRMIN(i); ABASE(i) = ABASE(i) * AMAX(i) / tmp; /* ABASE(i) > ATTRMAX(i) is impossible */ if (ABASE(i) < ATTRMIN(i)) ABASE(i) = ATTRMIN(i); } (void)encumber_msg(); }
void restore_attrib (void) { int i; for(i = 0; i < A_MAX; i++) { /* all temporary losses/gains */ if(ATEMP(i) && ATIME(i)) { if(!(--(ATIME(i)))) { /* countdown for change */ ATEMP(i) += ATEMP(i) > 0 ? -1 : 1; if(ATEMP(i)) /* reset timer */ ATIME(i) = 100 / ACURR(A_CON); } } } (void)encumber_msg(); }
void rehumanize (void) { /* You can't revert back while unchanging */ if (Unchanging && (u.mh < 1)) { killer = killed_by_const(KM_WHILE_STUCK_IN_CREATURE_FORM); done(DIED); } if (emits_light(youmonst.data)) del_light_source(LS_MONSTER, (void *)&youmonst); polyman("return to %s form!", urace.adj); if (u.uhp < 1) { char kbuf[256]; sprintf(kbuf, "reverting to unhealthy %s form", urace.adj); fprintf(stderr, "TODO killer = %s\n", kbuf); done(DIED); } if (!uarmg) selftouch("No longer petrify-resistant, you"); nomul(0); vision_full_recalc = 1; (void) encumber_msg(); }
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 1 if polymorph successful */ int polymon(int mntmp) { boolean sticky = sticks(youmonst.data) && u.ustuck && !u.uswallow, was_blind = !!Blind, dochange = FALSE; boolean could_pass_walls = Passes_walls; int mlvl; if (mvitals[mntmp].mvflags & G_GENOD) { /* allow G_EXTINCT */ pline("You feel rather %s-ish.",mons[mntmp].mname); exercise(A_WIS, TRUE); return 0; } /* KMH, conduct */ u.uconduct.polyselfs++; if (!Upolyd) { /* Human to monster; save human stats */ u.macurr = u.acurr; u.mamax = u.amax; u.mfemale = flags.female; } else { /* Monster to monster; restore human stats, to be * immediately changed to provide stats for the new monster */ u.acurr = u.macurr; u.amax = u.mamax; flags.female = u.mfemale; } if (youmonst.m_ap_type) { /* stop mimicking immediately */ if (multi < 0) unmul(""); } else if (mons[mntmp].mlet != S_MIMIC) { /* as in polyman() */ youmonst.m_ap_type = M_AP_NOTHING; } if (is_male(&mons[mntmp])) { if (flags.female) dochange = TRUE; } else if (is_female(&mons[mntmp])) { if (!flags.female) dochange = TRUE; } else if (!is_neuter(&mons[mntmp]) && mntmp != u.ulycn) { if (!rn2(10)) dochange = TRUE; } if (dochange) { flags.female = !flags.female; pline("You %s %s%s!", (u.umonnum != mntmp) ? "turn into a" : "feel like a new", (is_male(&mons[mntmp]) || is_female(&mons[mntmp])) ? "" : flags.female ? "female " : "male ", mons[mntmp].mname); } else { if (u.umonnum != mntmp) pline("You turn into %s!", an(mons[mntmp].mname)); else pline("You feel like a new %s!", mons[mntmp].mname); } if (Stoned && poly_when_stoned(&mons[mntmp])) { /* poly_when_stoned already checked stone golem genocide */ pline("You turn to stone!"); mntmp = PM_STONE_GOLEM; Stoned = 0; delayed_killer = 0; } u.mtimedone = rn1(500, 500); u.umonnum = mntmp; set_uasmon(); /* New stats for monster, to last only as long as polymorphed. * Currently only strength gets changed. */ if (strongmonst(&mons[mntmp])) ABASE(A_STR) = AMAX(A_STR) = STR18(100); if (Stone_resistance && Stoned) { /* [email protected] */ Stoned = 0; delayed_killer = 0; pline("You no longer seem to be petrifying."); } if (Sick_resistance && Sick) { make_sick(0L, NULL, FALSE, SICK_ALL); pline("You no longer feel sick."); } if (Slimed) { if (flaming(youmonst.data)) { pline("The slime burns away!"); Slimed = 0L; iflags.botl = 1; } else if (mntmp == PM_GREEN_SLIME) { /* do it silently */ Slimed = 0L; iflags.botl = 1; } } if (nohands(youmonst.data)) Glib = 0; /* mlvl = adj_lev(&mons[mntmp]); * We can't do the above, since there's no such thing as an * "experience level of you as a monster" for a polymorphed character. */ mlvl = (int)mons[mntmp].mlevel; if (youmonst.data->mlet == S_DRAGON && mntmp >= PM_GRAY_DRAGON) { u.mhmax = In_endgame(&u.uz) ? (8*mlvl) : (4*mlvl + dice(mlvl,4)); } else if (is_golem(youmonst.data)) { u.mhmax = golemhp(mntmp); } else { if (!mlvl) u.mhmax = rnd(4); else u.mhmax = dice(mlvl, 8); if (is_home_elemental(&u.uz, &mons[mntmp])) u.mhmax *= 3; } u.mh = u.mhmax; if (u.ulevel < mlvl) { /* Low level characters can't become high level monsters for long */ u.mtimedone = u.mtimedone * u.ulevel / mlvl; } if (uskin && mntmp != armor_to_dragon(uskin->otyp)) skinback(FALSE); break_armor(); drop_weapon(1); if (hides_under(youmonst.data)) u.uundetected = OBJ_AT(u.ux, u.uy); else if (youmonst.data->mlet == S_EEL) u.uundetected = is_pool(level, u.ux, u.uy); else u.uundetected = 0; if (u.utraptype == TT_PIT) { if (could_pass_walls && !Passes_walls) { u.utrap = rn1(6,2); } else if (!could_pass_walls && Passes_walls) { u.utrap = 0; } } if (was_blind && !Blind) { /* previous form was eyeless */ Blinded = 1L; make_blinded(0L, TRUE); /* remove blindness */ } newsym(u.ux,u.uy); /* Change symbol */ if (!sticky && !u.uswallow && u.ustuck && sticks(youmonst.data)) u.ustuck = 0; else if (sticky && !sticks(youmonst.data)) uunstick(); if (u.usteed) { if (touch_petrifies(u.usteed->data) && !Stone_resistance && rnl(3)) { char buf[BUFSZ]; pline("No longer petrifying-resistant, you touch %s.", mon_nam(u.usteed)); sprintf(buf, "riding %s", an(u.usteed->data->mname)); instapetrify(buf); } if (!can_ride(u.usteed)) dismount_steed(DISMOUNT_POLY); } if (flags.verbose) { static const char use_thec[] = "Use the command #%s to %s."; static const char monsterc[] = "monster"; if (can_breathe(youmonst.data)) pline(use_thec,monsterc,"use your breath weapon"); if (attacktype(youmonst.data, AT_SPIT)) pline(use_thec,monsterc,"spit venom"); if (youmonst.data->mlet == S_NYMPH) pline(use_thec,monsterc,"remove an iron ball"); if (attacktype(youmonst.data, AT_GAZE)) pline(use_thec,monsterc,"gaze at monsters"); if (is_hider(youmonst.data)) pline(use_thec,monsterc,"hide"); if (is_were(youmonst.data)) pline(use_thec,monsterc,"summon help"); if (webmaker(youmonst.data)) pline(use_thec,monsterc,"spin a web"); if (u.umonnum == PM_GREMLIN) pline(use_thec,monsterc,"multiply in a fountain"); if (is_unicorn(youmonst.data)) pline(use_thec,monsterc,"use your horn"); if (is_mind_flayer(youmonst.data)) pline(use_thec,monsterc,"emit a mental blast"); if (youmonst.data->msound == MS_SHRIEK) /* worthless, actually */ pline(use_thec,monsterc,"shriek"); if (lays_eggs(youmonst.data) && flags.female) pline(use_thec,"sit","lay an egg"); } /* you now know what an egg of your type looks like */ if (lays_eggs(youmonst.data)) { learn_egg_type(u.umonnum); /* make queen bees recognize killer bee eggs */ learn_egg_type(egg_type_from_parent(u.umonnum, TRUE)); } find_ac(); if ((!Levitation && !u.ustuck && !Flying && (is_pool(level, u.ux,u.uy) || is_lava(level, u.ux,u.uy))) || (Underwater && !Swimming)) spoteffects(TRUE); if (Passes_walls && u.utrap && u.utraptype == TT_INFLOOR) { u.utrap = 0; pline("The rock seems to no longer trap you."); } else if (likes_lava(youmonst.data) && u.utrap && u.utraptype == TT_LAVA) { u.utrap = 0; pline("The lava now feels soothing."); } if (amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data)) { if (Punished) { pline("You slip out of the iron chain."); unpunish(); } } if (u.utrap && (u.utraptype == TT_WEB || u.utraptype == TT_BEARTRAP) && (amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data) || (youmonst.data->msize <= MZ_SMALL && u.utraptype == TT_BEARTRAP))) { pline("You are no longer stuck in the %s.", u.utraptype == TT_WEB ? "web" : "bear trap"); /* probably should burn webs too if PM_FIRE_ELEMENTAL */ u.utrap = 0; } if (webmaker(youmonst.data) && u.utrap && u.utraptype == TT_WEB) { pline("You orient yourself on the web."); u.utrap = 0; } iflags.botl = 1; vision_full_recalc = 1; see_monsters(); exercise(A_CON, FALSE); exercise(A_WIS, TRUE); encumber_msg(); return 1; }
static void newman(void) { int tmp, oldlvl; tmp = u.uhpmax; oldlvl = u.ulevel; u.ulevel = u.ulevel + rn1(5, -2); if (u.ulevel > 127 || u.ulevel < 1) { /* level went below 0? */ u.ulevel = oldlvl; /* restore old level in case they lifesave */ goto dead; } if (u.ulevel > MAXULEV) u.ulevel = MAXULEV; /* If your level goes down, your peak level goes down by the same amount so that you can't simply use blessed full healing to undo the decrease. But if your level goes up, your peak level does *not* undergo the same adjustment; you might end up losing out on the chance to regain some levels previously lost to other causes. */ if (u.ulevel < oldlvl) u.ulevelmax -= (oldlvl - u.ulevel); if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel; if (!rn2(10)) change_sex(); adjabil(oldlvl, (int)u.ulevel); reset_rndmonst(NON_PM); /* new monster generation criteria */ /* random experience points for the new experience level */ u.uexp = rndexp(FALSE); /* u.uhpmax * u.ulevel / oldlvl: proportionate hit points to new level * -10 and +10: don't apply proportionate HP to 10 of a starting * character's hit points (since a starting character's hit points * are not on the same scale with hit points obtained through level * gain) * 9 - rn2(19): random change of -9 to +9 hit points */ u.uhpmax = ((u.uhpmax - 10) * (long)u.ulevel / oldlvl + 10) + (9 - rn2(19)); u.uhp = u.uhp * (long)u.uhpmax/tmp; tmp = u.uenmax; u.uenmax = u.uenmax * (long)u.ulevel / oldlvl + 9 - rn2(19); if (u.uenmax < 0) u.uenmax = 0; u.uen = (tmp ? u.uen * (long)u.uenmax / tmp : u.uenmax); redist_attr(); u.uhunger = rn1(500,500); if (Sick) make_sick(0L, NULL, FALSE, SICK_ALL); Stoned = 0; delayed_killer = 0; if (u.uhp <= 0 || u.uhpmax <= 0) { if (Polymorph_control) { if (u.uhp <= 0) u.uhp = 1; if (u.uhpmax <= 0) u.uhpmax = 1; } else { dead: /* we come directly here if their experience level went to 0 or less */ pline("Your new form doesn't seem healthy enough to survive."); killer_format = KILLED_BY_AN; killer="unsuccessful polymorph"; done(DIED); newuhs(FALSE); return; /* lifesaved */ } } newuhs(FALSE); polyman("You feel like a new %s!", (flags.female && urace.individual.f) ? urace.individual.f : (urace.individual.m) ? urace.individual.m : urace.noun); if (Slimed) { pline("Your body transforms, but there is still slime on you."); Slimed = 10L; } iflags.botl = 1; see_monsters(); encumber_msg(); }
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; int last_dnum = -1; int i; bzero(u_stat.plname, sizeof(u_stat.plname)); strncpy(u_stat.plname, plname, sizeof(u_stat.plname) - 1); if( (mcast_socket = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ) { pline("socket: %s", strerror(errno)); } else { memset(&mcast_addr, 0, sizeof(mcast_addr)); mcast_addr.sin_family = AF_INET; mcast_addr.sin_addr.s_addr = inet_addr("225.0.0.37"); mcast_addr.sin_port = htons(12345); const struct in_addr localhost_addr = { .s_addr = htonl(INADDR_LOOPBACK) }; if( setsockopt(mcast_socket, IPPROTO_IP, IP_MULTICAST_IF, &localhost_addr, sizeof(localhost_addr)) == -1 ) pline("setsockopt: %s", strerror(errno)); } 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(); #ifdef WIZARD if (wizard) add_debug_extended_commands(); #endif (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 */ if ( #ifdef WIZARD !wizard && #endif mcast_socket >= 0 /* && !flags.run */ ) { u_stat.race = *urace.adj; u_stat.gender = *genders[Upolyd ? u.mfemale : flags.female].adj; strncpy(u_stat.class, ((Upolyd ? u.mfemale : flags.female) && urole.name.f) ? urole.name.f : urole.name.m, 3); u_stat.status = STATUS_ACTIVE; u_stat.align = u.ualign.type; u_stat.have = *(char *) &u.uhave; u_stat.hp = u.uhp; u_stat.hpmax = u.uhpmax; u_stat.pow = u.uen; u_stat.powmax = u.uenmax; u_stat.ac = u.uac; u_stat.ulevel = u.ulevel; u_stat.dlevel = depth(&u.uz); u_stat.wishes = u.uconduct.wishes; u_stat.prayers = u.uconduct.gnostic; u_stat.deaths = u.umortality; u_stat.moves = moves; if( last_dnum != u.uz.dnum ) { bzero(u_stat.dungeon_or_death, sizeof(u_stat.dungeon_or_death)); strncpy(u_stat.dungeon_or_death, dungeons[u.uz.dnum].dname, sizeof(u_stat.dungeon_or_death) - 1); last_dnum = u.uz.dnum; } /* report all stats */ sendto(mcast_socket, &u_stat, sizeof(u_stat), 0, (struct sockaddr *) &mcast_addr, (socklen_t) sizeof(mcast_addr)); }
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); } } }
/* Stop riding the current steed */ void dismount_steed(int reason) { struct monst *mtmp; struct obj *otmp; coord cc; const char *verb = "fall"; boolean repair_leg_damage = TRUE; unsigned save_utrap = u.utrap; boolean have_spot = landing_spot(&cc, reason, 0); mtmp = u.usteed; /* make a copy of steed pointer */ /* Sanity check */ if (!mtmp) /* Just return silently */ return; /* Check the reason for dismounting */ otmp = which_armor(mtmp, os_saddle); switch (reason) { case DISMOUNT_THROWN: verb = "are thrown"; case DISMOUNT_FELL: pline("You %s off of %s!", verb, mon_nam(mtmp)); if (!have_spot) have_spot = landing_spot(&cc, reason, 1); losehp(rn1(10, 10), "killed in a riding accident"); set_wounded_legs(LEFT_SIDE, (int)LWounded_legs + rn1(5, 5)); set_wounded_legs(RIGHT_SIDE, (int)RWounded_legs + rn1(5, 5)); repair_leg_damage = FALSE; break; case DISMOUNT_POLY: pline("You can no longer ride %s.", mon_nam(u.usteed)); if (!have_spot) have_spot = landing_spot(&cc, reason, 1); break; case DISMOUNT_ENGULFED: /* caller displays message */ break; case DISMOUNT_BONES: /* hero has just died... */ break; case DISMOUNT_GENERIC: /* no messages, just make it so */ break; case DISMOUNT_BYCHOICE: default: if (otmp && otmp->cursed) { pline("You can't. The saddle %s cursed.", otmp->bknown ? "is" : "seems to be"); otmp->bknown = TRUE; return; } if (!have_spot) { pline("You can't. There isn't anywhere for you to stand."); return; } if (!mtmp->mnamelth) { pline("You've been through the dungeon on %s with no name.", an(mtmp->data->mname)); if (Hallucination) pline("It felt good to get out of the rain."); } else pline("You dismount %s.", mon_nam(mtmp)); } /* While riding these refer to the steed's legs so after dismounting they refer to the player's legs once again. */ if (repair_leg_damage) LWounded_legs = RWounded_legs = 0; /* Release the steed and saddle */ u.usteed = 0; u.ugallop = 0L; /* Set player and steed's position. Try moving the player first unless we're in the midst of creating a bones file. */ if (reason == DISMOUNT_BONES) { /* move the steed to an adjacent square */ if (enexto(&cc, level, u.ux, u.uy, mtmp->data)) rloc_to(mtmp, cc.x, cc.y); else /* evidently no room nearby; move steed elsewhere */ rloc(mtmp, FALSE); return; } if (!DEADMONSTER(mtmp)) { place_monster(mtmp, u.ux, u.uy); if (!Engulfed && !u.ustuck && have_spot) { const struct permonst *mdat = mtmp->data; /* The steed may drop into water/lava */ if (!is_flyer(mdat) && !is_floater(mdat) && !is_clinger(mdat)) { if (is_pool(level, u.ux, u.uy)) { if (!Underwater) pline("%s falls into the %s!", Monnam(mtmp), surface(u.ux, u.uy)); if (!is_swimmer(mdat) && !amphibious(mdat)) { killed(mtmp); adjalign(-1); } } else if (is_lava(level, u.ux, u.uy)) { pline("%s is pulled into the lava!", Monnam(mtmp)); if (!likes_lava(mdat)) { killed(mtmp); adjalign(-1); } } } /* Steed dismounting consists of two steps: being moved to another square, and descending to the floor. We have functions to do each of these activities, but they're normally called individually and include an attempt to look at or pick up the objects on the floor: teleds() --> spoteffects() --> pickup() float_down() --> pickup() We use this kludge to make sure there is only one such attempt. Clearly this is not the best way to do it. A full fix would involve having these functions not call pickup() at all, instead calling them first and calling pickup() afterwards. But it would take a lot of work to keep this change from having any unforseen side effects (for instance, you would no longer be able to walk onto a square with a hole, and autopickup before falling into the hole). */ /* [ALI] No need to move the player if the steed died. */ if (!DEADMONSTER(mtmp)) { /* Keep steed here, move the player to cc; teleds() clears u.utrap */ in_steed_dismounting = TRUE; teleds(cc.x, cc.y, TRUE); in_steed_dismounting = FALSE; /* Put your steed in your trap */ if (save_utrap) mintrap(mtmp); } /* Couldn't... try placing the steed */ } else if (enexto(&cc, level, u.ux, u.uy, mtmp->data)) { /* Keep player here, move the steed to cc */ rloc_to(mtmp, cc.x, cc.y); /* Player stays put */ /* Otherwise, kill the steed */ } else { killed(mtmp); adjalign(-1); } } /* Return the player to the floor */ if (reason != DISMOUNT_ENGULFED) { in_steed_dismounting = TRUE; float_down(0L); in_steed_dismounting = FALSE; encumber_msg(); turnstate.vision_full_recalc = TRUE; } else /* polearms behave differently when not mounted */ if (uwep && is_pole(uwep)) u.bashmsg = FALSE; return; }
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(); } }